Skip to content

Commit 6527870

Browse files
committed
feat(sdk): adds partially auto-generated SDK
The OpenAPI spec is used to auto generate a cross-platform (universal) SDK that can be used to hit the REST API endpoints from both a browser and NodeJS environments. Signed-off-by: Peter Somogyvari <[email protected]>
1 parent 05a2e0b commit 6527870

File tree

26 files changed

+848
-22
lines changed

26 files changed

+848
-22
lines changed

package-lock.json

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+7-4
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
"scripts": {
55
"configure": "lerna clean --yes && lerna bootstrap && npm run build && node ./tools/generate-api-server-config.js",
66
"start:api-server": "node ./packages/bif-cmd-api-server/dist/lib/main/typescript/cmd/bif-api.js --config-file=.config.json",
7+
"generate-sdk": "openapi-generator generate -i x.json -g typescript-axios -o packages/bif-sdk/src/main/typescript/generated/openapi/typescript-axios/",
78
"tsc": "lerna exec --stream --ignore '*/*cockpit' -- tsc --project ./tsconfig.json",
8-
"clean": "lerna exec --stream --ignore '*/*cockpit' -- del-cli dist/**",
9-
"build": "npm-run-all --parallel build:frontend build:backend",
9+
"clean": "lerna exec --stream --ignore '*/*cockpit' -- del-cli dist/** && del-cli packages/bif-sdk/src/main/typescript/generated/openapi/typescript-axios/*",
10+
"build": "npm-run-all build:backend build:frontend",
1011
"build:frontend": "lerna exec --stream --scope '*/*cockpit' -- ng build --prod",
11-
"build:backend": "npm-run-all clean tsc webpack",
12+
"build:backend": "npm-run-all lint clean generate-sdk tsc webpack",
1213
"build:dev:pkg:cmd-api-server": "lerna exec --stream --scope '*/*api-server' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
14+
"build:dev:pkg:sdk": "lerna exec --stream --scope '*/*sdk' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
1315
"webpack": "npm-run-all webpack:web:dev webpack:node:dev webpack:web:prod webpack:node:prod",
1416
"webpack:web:prod": "lerna exec --stream --ignore '*/*{cockpit,server}' -- webpack --env=prod --target=web --config ../../webpack.config.js",
1517
"webpack:web:dev": "lerna exec --stream --ignore '*/*{cockpit,server}' -- webpack --env=dev --target=web --config ../../webpack.config.js",
@@ -19,7 +21,7 @@
1921
"commit": "git-cz",
2022
"setup": "lerna exec --stream --ignore '*/*cockpit' -- rm -rf node_modules package-lock.json",
2123
"lint": "lerna exec --stream --ignore '*/*cockpit' -- cross-env DEBUG= tslint --project tsconfig.json",
22-
"pretest": "npm run lint && npm run build",
24+
"pretest": "npm run build",
2325
"test": "lerna exec --stream --ignore '*/*cockpit' -- tap --timeout=600 src/test/typescript/unit/",
2426
"test-coverage": "lerna exec --stream --ignore '*/*cockpit' -- tap --timeout=600 src/test/typescript/unit/ --cov",
2527
"test-coverage-html": "lerna exec --stream --ignore '*/*cockpit' -- tap --timeout=600 src/test/typescript/unit/ --cov --coverage-report=lcov",
@@ -29,6 +31,7 @@
2931
"devDependencies": {
3032
"@commitlint/cli": "8.1.0",
3133
"@commitlint/config-conventional": "8.0.0",
34+
"@openapitools/openapi-generator-cli": "1.0.10-4.2.3",
3235
"@types/node-fetch": "2.5.4",
3336
"@types/uuid": "3.4.6",
3437
"commitizen": "4.0.3",

packages/bif-cmd-api-server/src/main/typescript/consortium/routes/create-consortium-endpoint-v1.ts

+18-17
Original file line numberDiff line numberDiff line change
@@ -35,24 +35,25 @@ export class CreateConsortiumEndpointV1 {
3535
const consortium: IConsortium = req.body;
3636
const idAlreadyExists = await this.options.storage.has(consortium.id);
3737
if (idAlreadyExists) {
38-
res.json({ success: false, message: `Consortium with ID ${consortium.id} already exists.` });
3938
res.status(400);
39+
res.json({ success: false, message: `Consortium with ID ${consortium.id} already exists.` });
40+
} else {
41+
// FIXME: We need a library handling the crypto, how about NodeJS bindings for Ursa?
42+
const privateKey = this.options.config.get('privateKey');
43+
const privateKeyBytes = Uint8Array.from(Buffer.from(privateKey, 'hex'));
44+
const consortiumJson: string = JSON.stringify(consortium);
45+
const consortiumBytesHash = Uint8Array.from(keccak256.array(consortiumJson));
46+
const signatureWrapper = secp256k1.ecdsaSign(consortiumBytesHash, privateKeyBytes);
47+
const signature = Buffer.from(signatureWrapper.signature).toString('hex');
48+
const consortiumWrapper: IConsortiumWrapper = {
49+
signature,
50+
consortiumJson,
51+
};
52+
const wrapperJson = JSON.stringify(consortiumWrapper);
53+
// tslint:disable-next-line: no-console
54+
await this.options.storage.set(consortium.id, wrapperJson);
55+
res.status(201);
56+
res.json({ success: true, consortiumWrapper });
4057
}
41-
// FIXME: We need a library handling the crypto, how about NodeJS bindings for Ursa?
42-
const privateKey = this.options.config.get('privateKey');
43-
const privateKeyBytes = Uint8Array.from(Buffer.from(privateKey, 'hex'));
44-
const consortiumJson: string = JSON.stringify(consortium);
45-
const consortiumBytesHash = Uint8Array.from(keccak256.array(consortiumJson));
46-
const signatureWrapper = secp256k1.ecdsaSign(consortiumBytesHash, privateKeyBytes);
47-
const signature = Buffer.from(signatureWrapper.signature).toString('hex');
48-
const consortiumWrapper: IConsortiumWrapper = {
49-
signature,
50-
consortiumJson,
51-
};
52-
const wrapperJson = JSON.stringify(consortiumWrapper);
53-
// tslint:disable-next-line: no-console
54-
await this.options.storage.set(consortium.id, wrapperJson);
55-
res.json({ success: true, consortiumWrapper });
56-
res.status(201);
5758
}
5859
}

packages/bif-cockpit/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@angular/router": "8.2.14",
2424
"@capacitor/core": "1.5.1",
2525
"@hyperledger-labs/bif-common": "0.2.0",
26+
"@hyperledger-labs/bif-sdk": "0.2.0",
2627
"@ionic-native/core": "5.0.0",
2728
"@ionic-native/splash-screen": "5.0.0",
2829
"@ionic-native/status-bar": "5.0.0",

packages/bif-cockpit/src/app/app.component.ts

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { SplashScreen } from '@ionic-native/splash-screen/ngx';
55
import { StatusBar } from '@ionic-native/status-bar/ngx';
66

77
import { LoggerProvider, Logger } from '@hyperledger-labs/bif-common';
8+
import { DefaultApi, Configuration } from '@hyperledger-labs/bif-sdk';
89

910
@Component({
1011
selector: 'app-root',
@@ -72,5 +73,22 @@ export class AppComponent implements OnInit {
7273
if (path !== undefined) {
7374
this.selectedIndex = this.appPages.findIndex(page => page.title.toLowerCase() === path.toLowerCase());
7475
}
76+
this.testApi();
77+
}
78+
79+
async testApi(): Promise<void> {
80+
const BIF_API_HOST = 'http://localhost:4000';
81+
const configuration = new Configuration({ basePath: BIF_API_HOST,});
82+
const api = new DefaultApi(configuration);
83+
const response = await api.apiV1ConsortiumPost({
84+
configurationEndpoint: 'domain-and-an-http-endpoint',
85+
id: 'asdf',
86+
name: 'asdf',
87+
bifNodes: [
88+
{
89+
host: 'BIF-NODE-HOST-1', publicKey: 'FAKE-PUBLIC-KEY'
90+
}
91+
]
92+
});
7593
}
7694
}

packages/bif-sdk/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `@hyperledger-labs/bif-sdk`
2+
3+
> TODO: description
4+
5+
## Usage
6+
7+
```
8+
// TODO: DEMONSTRATE API
9+
```

packages/bif-sdk/package-lock.json

+37
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/bif-sdk/package.json

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "@hyperledger-labs/bif-sdk",
3+
"version": "0.2.0",
4+
"description": "Universal library used by both front end and back end components of BIF. Aims to be a developer swiss army knife.",
5+
"main": "dist/bif-sdk.node.umd.js",
6+
"mainMinified": "dist/bif-sdk.node.umd.min.js",
7+
"browser": "dist/bif-sdk.web.umd.js",
8+
"browserMinified": "dist/bif-sdk.web.umd.min.js",
9+
"module": "dist/lib/main/typescript/index.js",
10+
"types": "dist/types/main/typescript/index.d.ts",
11+
"files": [
12+
"dist/*"
13+
],
14+
"publishConfig": {
15+
"access": "public"
16+
},
17+
"engines": {
18+
"node": ">=10",
19+
"npm": ">=6"
20+
},
21+
"repository": {
22+
"type": "git",
23+
"url": "git+https://github.com/hyperledger-labs/blockchain-integration-framework.git"
24+
},
25+
"keywords": [
26+
"Hyperledger",
27+
"Blockchain",
28+
"Interoperability",
29+
"Integration"
30+
],
31+
"author": {
32+
"name": "Peter Somogyvari",
33+
"email": "[email protected]",
34+
"url": "https://accenture.com"
35+
},
36+
"contributors": [
37+
{
38+
"name": "Please add yourself to the list of contributors",
39+
"email": "[email protected]",
40+
"url": "https://example.com"
41+
}
42+
],
43+
"license": "Apache-2.0",
44+
"bugs": {
45+
"url": "https://github.com/hyperledger-labs/blockchain-integration-framework/issues"
46+
},
47+
"homepage": "https://github.com/hyperledger-labs/blockchain-integration-framework#readme",
48+
"dependencies": {
49+
"@hyperledger-labs/bif-common": "0.2.0",
50+
"axios": "0.19.2"
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Logger, LoggerProvider } from '@hyperledger-labs/bif-common';
2+
3+
export interface IApiClientOptions {
4+
apiHost: string;
5+
apiPort: number;
6+
}
7+
8+
export class ApiClient {
9+
10+
private readonly log: Logger;
11+
12+
constructor(public readonly options: IApiClientOptions) {
13+
this.log = LoggerProvider.getOrCreate({ label: 'api-client ' });
14+
}
15+
16+
public async call(): Promise<void> {
17+
this.log.debug(`call()`);
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ApiClient } from "../api-client";
2+
3+
export interface IConsortiumServiceOptions {
4+
apiClient: ApiClient;
5+
}
6+
7+
export class ConsortiumService {
8+
constructor(public readonly options: IConsortiumServiceOptions) {
9+
}
10+
11+
async create(): Promise<void> {
12+
return;
13+
}
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
wwwroot/*.js
2+
node_modules
3+
typings
4+
dist
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# OpenAPI Generator Ignore
2+
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
3+
4+
# Use this file to prevent files from being overwritten by the generator.
5+
# The patterns follow closely to .gitignore or .dockerignore.
6+
7+
# As an example, the C# client generator defines ApiClient.cs.
8+
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
9+
#ApiClient.cs
10+
11+
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
12+
#foo/*/qux
13+
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
14+
15+
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
16+
#foo/**/qux
17+
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
18+
19+
# You can also negate patterns with an exclamation (!).
20+
# For example, you can ignore all files in a docs folder with the file extension .md:
21+
#docs/*.md
22+
# Then explicitly reverse the ignore rule for a single file:
23+
#!docs/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
4.2.3

0 commit comments

Comments
 (0)