@hahnpro/hpc-api 5.3.4 → 2024.4.0-0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -24
- package/src/index.d.ts +20 -0
- package/src/index.js +20 -0
- package/{dist → src/lib}/Queue.js +2 -7
- package/src/lib/api-base.js +6 -0
- package/src/lib/api.js +60 -0
- package/src/lib/asset.interface.js +1 -0
- package/src/lib/asset.service.d.ts +24 -0
- package/src/lib/asset.service.js +51 -0
- package/{dist → src/lib}/assettypes.service.d.ts +4 -4
- package/src/lib/assettypes.service.js +24 -0
- package/{dist → src/lib}/content.interface.js +2 -5
- package/src/lib/content.service.d.ts +23 -0
- package/src/lib/content.service.js +49 -0
- package/src/lib/data.interface.d.ts +38 -0
- package/src/lib/data.interface.js +3 -0
- package/src/lib/data.service.d.ts +27 -0
- package/src/lib/data.service.js +57 -0
- package/src/lib/endpoint.interface.js +1 -0
- package/src/lib/endpoint.service.d.ts +8 -0
- package/src/lib/endpoint.service.js +12 -0
- package/src/lib/events.interface.js +1 -0
- package/{dist → src/lib}/events.service.d.ts +2 -2
- package/src/lib/events.service.js +9 -0
- package/src/lib/flow-deployment.interface.js +1 -0
- package/{dist → src/lib}/flow-deployment.service.d.ts +15 -13
- package/src/lib/flow-deployment.service.js +68 -0
- package/src/lib/flow-function.interface.js +1 -0
- package/src/lib/flow-function.service.d.ts +11 -0
- package/src/lib/flow-function.service.js +20 -0
- package/src/lib/flow-module.interface.js +1 -0
- package/src/lib/flow-module.service.d.ts +11 -0
- package/{dist → src/lib}/flow-module.service.js +9 -12
- package/src/lib/flow.interface.js +1 -0
- package/src/lib/flow.service.d.ts +26 -0
- package/src/lib/flow.service.js +49 -0
- package/{dist → src/lib}/http.service.d.ts +12 -6
- package/src/lib/http.service.js +179 -0
- package/src/lib/label.interface.js +1 -0
- package/src/lib/label.service.d.ts +9 -0
- package/src/lib/label.service.js +15 -0
- package/src/lib/mock/api-base.mock.js +7 -0
- package/src/lib/mock/api.mock.js +199 -0
- package/{dist → src/lib}/mock/asset.mock.service.js +30 -41
- package/{dist → src/lib}/mock/assetTypes.mock.service.js +19 -27
- package/{dist → src/lib}/mock/content.mock.service.js +21 -24
- package/src/lib/mock/data.mock.service.js +93 -0
- package/{dist → src/lib}/mock/endpoint.mock.service.js +2 -6
- package/src/lib/mock/events.mock.service.js +10 -0
- package/src/lib/mock/flow-deployment.mock.service.js +118 -0
- package/{dist → src/lib}/mock/flow-functions.mock.service.js +12 -21
- package/src/lib/mock/flow-modules.mock.service.js +20 -0
- package/src/lib/mock/flow.mock.service.js +81 -0
- package/src/lib/mock/index.js +11 -0
- package/src/lib/mock/label.mock.service.js +13 -0
- package/src/lib/mock/notification.mock.service.js +7 -0
- package/src/lib/mock/secret.mock.service.js +28 -0
- package/src/lib/mock/task.mock.service.js +32 -0
- package/{dist → src/lib}/mock/timeseries.mock.service.js +40 -49
- package/{dist → src/lib}/mock/trash.mock.service.js +8 -15
- package/src/lib/mock/user.mock.service.js +10 -0
- package/{dist → src/lib}/mock/vault.mock.service.js +2 -6
- package/src/lib/notification.interface.js +1 -0
- package/src/lib/notification.service.js +6 -0
- package/src/lib/proxy.service.d.ts +11 -0
- package/{dist → src/lib}/proxy.service.js +1 -5
- package/src/lib/resource.interface.js +1 -0
- package/src/lib/schema.interface.js +1 -0
- package/src/lib/secret.interface.js +1 -0
- package/src/lib/secret.service.js +15 -0
- package/src/lib/storage.interface.js +1 -0
- package/src/lib/task.interface.js +1 -0
- package/{dist → src/lib}/task.service.d.ts +2 -2
- package/src/lib/task.service.js +19 -0
- package/src/lib/timeseries.interface.js +1 -0
- package/{dist → src/lib}/timeseries.service.d.ts +10 -8
- package/src/lib/timeseries.service.js +92 -0
- package/{dist → src/lib}/token-set.d.ts +3 -1
- package/src/lib/token-set.js +23 -0
- package/{dist → src/lib}/trash.service.js +2 -6
- package/src/lib/user-settings.interface.js +1 -0
- package/src/lib/user.service.d.ts +11 -0
- package/src/lib/user.service.js +26 -0
- package/src/lib/vault.interface.js +1 -0
- package/{dist → src/lib}/vault.service.d.ts +2 -2
- package/src/lib/vault.service.js +10 -0
- package/LICENSE +0 -21
- package/dist/api-base.js +0 -10
- package/dist/api.js +0 -62
- package/dist/asset.interface.js +0 -2
- package/dist/asset.service.d.ts +0 -24
- package/dist/asset.service.js +0 -53
- package/dist/assettypes.service.js +0 -28
- package/dist/content.service.d.ts +0 -23
- package/dist/content.service.js +0 -50
- package/dist/data.interface.d.ts +0 -31
- package/dist/data.interface.js +0 -6
- package/dist/data.service.d.ts +0 -21
- package/dist/data.service.js +0 -50
- package/dist/endpoint.interface.js +0 -2
- package/dist/endpoint.service.d.ts +0 -8
- package/dist/endpoint.service.js +0 -16
- package/dist/events.interface.js +0 -2
- package/dist/events.service.js +0 -13
- package/dist/flow-deployment.interface.js +0 -2
- package/dist/flow-deployment.service.js +0 -74
- package/dist/flow-function.interface.js +0 -2
- package/dist/flow-function.service.d.ts +0 -11
- package/dist/flow-function.service.js +0 -23
- package/dist/flow-module.interface.js +0 -2
- package/dist/flow-module.service.d.ts +0 -11
- package/dist/flow.interface.js +0 -2
- package/dist/flow.service.d.ts +0 -24
- package/dist/flow.service.js +0 -54
- package/dist/http.service.js +0 -161
- package/dist/index.d.ts +0 -20
- package/dist/index.js +0 -23
- package/dist/label.interface.js +0 -2
- package/dist/label.service.d.ts +0 -9
- package/dist/label.service.js +0 -19
- package/dist/mock/api-base.mock.js +0 -11
- package/dist/mock/api.mock.js +0 -128
- package/dist/mock/data.mock.service.js +0 -96
- package/dist/mock/events.mock.service.js +0 -14
- package/dist/mock/flow-deployment.mock.service.js +0 -142
- package/dist/mock/flow-modules.mock.service.js +0 -27
- package/dist/mock/flow.mock.service.js +0 -93
- package/dist/mock/index.js +0 -14
- package/dist/mock/label.mock.service.js +0 -17
- package/dist/mock/notification.mock.service.js +0 -11
- package/dist/mock/secret.mock.service.js +0 -31
- package/dist/mock/task.mock.service.js +0 -37
- package/dist/mock/user.mock.service.js +0 -14
- package/dist/notification.interface.js +0 -2
- package/dist/notification.service.js +0 -10
- package/dist/proxy.service.d.ts +0 -11
- package/dist/resource.interface.js +0 -2
- package/dist/schema.interface.js +0 -2
- package/dist/secret.interface.js +0 -2
- package/dist/secret.service.js +0 -19
- package/dist/storage.interface.js +0 -2
- package/dist/task.interface.js +0 -2
- package/dist/task.service.js +0 -22
- package/dist/timeseries.interface.js +0 -2
- package/dist/timeseries.service.js +0 -56
- package/dist/token-set.js +0 -23
- package/dist/user-settings.interface.js +0 -2
- package/dist/user.service.d.ts +0 -11
- package/dist/user.service.js +0 -33
- package/dist/vault.interface.js +0 -2
- package/dist/vault.service.js +0 -14
- package/{dist → src/lib}/Queue.d.ts +0 -0
- package/{dist → src/lib}/api-base.d.ts +0 -0
- package/{dist → src/lib}/api.d.ts +6 -6
- package/{dist → src/lib}/asset.interface.d.ts +0 -0
- package/{dist → src/lib}/content.interface.d.ts +0 -0
- package/{dist → src/lib}/endpoint.interface.d.ts +0 -0
- package/{dist → src/lib}/events.interface.d.ts +0 -0
- package/{dist → src/lib}/flow-deployment.interface.d.ts +1 -1
- package/{dist → src/lib}/flow-function.interface.d.ts +0 -0
- package/{dist → src/lib}/flow-module.interface.d.ts +0 -0
- package/{dist → src/lib}/flow.interface.d.ts +1 -1
- package/{dist → src/lib}/label.interface.d.ts +0 -0
- package/{dist → src/lib}/mock/api-base.mock.d.ts +0 -0
- package/{dist → src/lib}/mock/api.mock.d.ts +18 -18
- package/{dist → src/lib}/mock/asset.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/assetTypes.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/content.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/data.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/endpoint.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/events.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/flow-deployment.mock.service.d.ts +2 -2
- package/{dist → src/lib}/mock/flow-functions.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/flow-modules.mock.service.d.ts +2 -2
- package/{dist → src/lib}/mock/flow.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/index.d.ts +0 -0
- package/{dist → src/lib}/mock/label.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/notification.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/secret.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/task.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/timeseries.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/trash.mock.service.d.ts +1 -1
- package/{dist → src/lib}/mock/user.mock.service.d.ts +0 -0
- package/{dist → src/lib}/mock/vault.mock.service.d.ts +1 -1
- package/{dist → src/lib}/notification.interface.d.ts +0 -0
- package/{dist → src/lib}/notification.service.d.ts +1 -1
- /package/{dist → src/lib}/resource.interface.d.ts +0 -0
- /package/{dist → src/lib}/schema.interface.d.ts +0 -0
- /package/{dist → src/lib}/secret.interface.d.ts +0 -0
- /package/{dist → src/lib}/secret.service.d.ts +0 -0
- /package/{dist → src/lib}/storage.interface.d.ts +0 -0
- /package/{dist → src/lib}/task.interface.d.ts +0 -0
- /package/{dist → src/lib}/timeseries.interface.d.ts +0 -0
- /package/{dist → src/lib}/trash.service.d.ts +0 -0
- /package/{dist → src/lib}/user-settings.interface.d.ts +0 -0
- /package/{dist → src/lib}/vault.interface.d.ts +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { mix } from 'ts-mixer';
|
|
3
|
+
import { APIBase } from './api-base';
|
|
4
|
+
import { DataService } from './data.service';
|
|
5
|
+
import { TrashService } from './trash.service';
|
|
6
|
+
let BaseService = class BaseService extends APIBase {
|
|
7
|
+
};
|
|
8
|
+
BaseService = __decorate([
|
|
9
|
+
mix(DataService, TrashService)
|
|
10
|
+
], BaseService);
|
|
11
|
+
export class FlowDeploymentService extends BaseService {
|
|
12
|
+
constructor(httpClient) {
|
|
13
|
+
super(httpClient, '/flow/deployments');
|
|
14
|
+
}
|
|
15
|
+
// workaround as flow-deployment-service does not have a POST /many endpoint
|
|
16
|
+
addMany(dto, options = {}) {
|
|
17
|
+
const reqs = dto.map((v) => this.addOne(v, options));
|
|
18
|
+
return Promise.all(reqs);
|
|
19
|
+
}
|
|
20
|
+
updateOne(id, dto, options = { force: false }) {
|
|
21
|
+
return super.updateOne(id, dto, options);
|
|
22
|
+
}
|
|
23
|
+
getDeploymentStatistics(id, options = {}) {
|
|
24
|
+
return this.httpClient.get(`${this.basePath}/${id}/statistics`, options);
|
|
25
|
+
}
|
|
26
|
+
getDeploymentMetrics(id, range = '12h', interval = '5m', options = {}) {
|
|
27
|
+
const params = { range, interval };
|
|
28
|
+
return this.httpClient.get(`${this.basePath}/${id}/metrics`, { params, ...options });
|
|
29
|
+
}
|
|
30
|
+
getDeploymentLogs(id, options = {}) {
|
|
31
|
+
return this.httpClient.get(`${this.basePath}/${id}/logs`, options);
|
|
32
|
+
}
|
|
33
|
+
resolveReferences(id, recursive = true, types, options = {}) {
|
|
34
|
+
const params = { recursive, types: types?.join(',') ?? undefined };
|
|
35
|
+
return this.httpClient.get(`${this.basePath}/${id}/references`, { params, ...options });
|
|
36
|
+
}
|
|
37
|
+
updateStatus(id, desiredStatus, options = {}) {
|
|
38
|
+
return this.httpClient.put(`${this.basePath}/${id}/status`, { desiredStatus }, options);
|
|
39
|
+
}
|
|
40
|
+
deleteOne(id, _force, options = {}) {
|
|
41
|
+
return this.updateStatus(id, 'deleted', options);
|
|
42
|
+
}
|
|
43
|
+
async waitForRunningStatus(id, options = {}) {
|
|
44
|
+
return new Promise(async (resolve, reject) => {
|
|
45
|
+
const esId = await this.subscribeToStatus(id, (event) => {
|
|
46
|
+
if (event.type === 'message' &&
|
|
47
|
+
['running', 'deployment failed', 'deleted', 'generating failed', 'updating failed', 'upgrading failed'].includes(event.data)) {
|
|
48
|
+
this.httpClient.destroyEventSource(esId);
|
|
49
|
+
if (event.data === 'running') {
|
|
50
|
+
resolve();
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
reject(`Deployment in failed status: ${event.data}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, (event) => reject(event), options);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
addOne(dto, options = {}) {
|
|
60
|
+
return super.addOne(dto, options);
|
|
61
|
+
}
|
|
62
|
+
subscribeToStatus(id, listener, errorListener, options = {}) {
|
|
63
|
+
return this.httpClient.addEventSource(`${this.basePath}/${id}/status`, listener, errorListener, options);
|
|
64
|
+
}
|
|
65
|
+
subscribeToLogs(id, listener, errorListener, options = {}) {
|
|
66
|
+
return this.httpClient.addEventSource(`${this.basePath}/${id}/logs/subscribe`, listener, errorListener, options);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Paginated } from './data.interface';
|
|
2
|
+
import { DataService } from './data.service';
|
|
3
|
+
import { FlowFunctionDto } from './flow-function.interface';
|
|
4
|
+
import { HttpClient, TokenOption } from './http.service';
|
|
5
|
+
export declare class FlowFunctionService extends DataService<FlowFunctionDto> {
|
|
6
|
+
constructor(httpClient: HttpClient);
|
|
7
|
+
addMany(dto: any[], options?: TokenOption): Promise<FlowFunctionDto[]>;
|
|
8
|
+
getRevisions(fqn: string, options?: TokenOption): Promise<Paginated<FlowFunctionDto[]>>;
|
|
9
|
+
rollback(fqn: string, revisionId: string, options?: TokenOption): Promise<FlowFunctionDto>;
|
|
10
|
+
deleteRevision(fqn: string, revisionId: string, options?: TokenOption): Promise<any>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { DataService } from './data.service';
|
|
2
|
+
export class FlowFunctionService extends DataService {
|
|
3
|
+
constructor(httpClient) {
|
|
4
|
+
super(httpClient, '/flow/functions');
|
|
5
|
+
}
|
|
6
|
+
// workaround as flow-functions-service does not have a POST /many endpoint
|
|
7
|
+
addMany(dto, options = {}) {
|
|
8
|
+
const reqs = dto.map((v) => this.addOne(v, options));
|
|
9
|
+
return Promise.all(reqs);
|
|
10
|
+
}
|
|
11
|
+
getRevisions(fqn, options = {}) {
|
|
12
|
+
return this.httpClient.get(`${this.basePath}/${fqn}/revisions`, options);
|
|
13
|
+
}
|
|
14
|
+
rollback(fqn, revisionId, options = {}) {
|
|
15
|
+
return this.httpClient.put(`${this.basePath}/${fqn}/rollback`, { revisionId }, options);
|
|
16
|
+
}
|
|
17
|
+
deleteRevision(fqn, revisionId, options = {}) {
|
|
18
|
+
return this.httpClient.delete(`${this.basePath}/${fqn}/revisions/${revisionId}`, options);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import FormData from 'form-data';
|
|
2
|
+
import { DataService } from './data.service';
|
|
3
|
+
import { FlowModule } from './flow-module.interface';
|
|
4
|
+
import { HttpClient, TokenOption } from './http.service';
|
|
5
|
+
export declare class FlowModuleService extends DataService<FlowModule> {
|
|
6
|
+
constructor(httpClient: HttpClient);
|
|
7
|
+
deleteArtifact(name: string, version: string, options?: TokenOption): Promise<FlowModule>;
|
|
8
|
+
publish(form: FormData, options?: TokenOption): Promise<unknown>;
|
|
9
|
+
addOne(_dto: any): Promise<FlowModule>;
|
|
10
|
+
addMany(_dto: any[]): Promise<FlowModule[]>;
|
|
11
|
+
}
|
|
@@ -1,27 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.FlowModuleService = void 0;
|
|
4
|
-
const data_service_1 = require("./data.service");
|
|
5
|
-
class FlowModuleService extends data_service_1.DataService {
|
|
1
|
+
import { DataService } from './data.service';
|
|
2
|
+
export class FlowModuleService extends DataService {
|
|
6
3
|
constructor(httpClient) {
|
|
7
4
|
super(httpClient, '/flow/modules');
|
|
8
5
|
}
|
|
9
|
-
deleteArtifact(name, version) {
|
|
10
|
-
return this.httpClient.delete(`${this.basePath}/${name}/${version}
|
|
6
|
+
deleteArtifact(name, version, options = {}) {
|
|
7
|
+
return this.httpClient.delete(`${this.basePath}/${name}/${version}`, options);
|
|
11
8
|
}
|
|
12
|
-
publish(form) {
|
|
9
|
+
publish(form, options = {}) {
|
|
13
10
|
const config = {
|
|
14
|
-
headers:
|
|
11
|
+
headers: { ...form.getHeaders() },
|
|
15
12
|
maxBodyLength: Infinity,
|
|
16
13
|
maxContentLength: Infinity,
|
|
14
|
+
...options,
|
|
17
15
|
};
|
|
18
16
|
return this.httpClient.post(`${this.basePath}`, form, config);
|
|
19
17
|
}
|
|
20
|
-
addOne(
|
|
18
|
+
addOne(_dto) {
|
|
21
19
|
throw new Error('not allowed: use publish instead');
|
|
22
20
|
}
|
|
23
|
-
addMany(
|
|
21
|
+
addMany(_dto) {
|
|
24
22
|
throw new Error('not allowed: use publish instead');
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
exports.FlowModuleService = FlowModuleService;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { APIBase } from './api-base';
|
|
2
|
+
import { Paginated, RequestParameter } from './data.interface';
|
|
3
|
+
import { DataService } from './data.service';
|
|
4
|
+
import { FlowDeployment } from './flow-deployment.interface';
|
|
5
|
+
import { FlowDiagram, FlowDto } from './flow.interface';
|
|
6
|
+
import { HttpClient, TokenOption } from './http.service';
|
|
7
|
+
import { TrashService } from './trash.service';
|
|
8
|
+
interface BaseService extends DataService<FlowDto>, TrashService<FlowDto> {
|
|
9
|
+
}
|
|
10
|
+
declare class BaseService extends APIBase {
|
|
11
|
+
}
|
|
12
|
+
export declare class FlowService extends BaseService {
|
|
13
|
+
constructor(httpClient: HttpClient);
|
|
14
|
+
addMany(dto: any[], options?: TokenOption): Promise<FlowDto[]>;
|
|
15
|
+
getMany(params?: RequestParameter, options?: TokenOption): Promise<Paginated<FlowDto[]>>;
|
|
16
|
+
getOne(id: string, options?: TokenOption & {
|
|
17
|
+
[key: string]: any;
|
|
18
|
+
}): Promise<FlowDto>;
|
|
19
|
+
getFlowWithDiagram(diagramId: string, options?: TokenOption): Promise<FlowDto>;
|
|
20
|
+
getDiagramRevisions(id: string, options?: TokenOption): Promise<FlowDiagram[]>;
|
|
21
|
+
isDeploymentOnLatestDiagramVersion(depl: FlowDeployment, options?: TokenOption): Promise<boolean>;
|
|
22
|
+
getRevisions(id: string, options?: TokenOption): Promise<Paginated<FlowDto[]>>;
|
|
23
|
+
rollback(id: string, revisionId: string, options?: TokenOption): Promise<FlowDto>;
|
|
24
|
+
deleteRevision(id: string, revisionId: string, options?: TokenOption): Promise<any>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { mix } from 'ts-mixer';
|
|
3
|
+
import { APIBase } from './api-base';
|
|
4
|
+
import { DataService } from './data.service';
|
|
5
|
+
import { TrashService } from './trash.service';
|
|
6
|
+
let BaseService = class BaseService extends APIBase {
|
|
7
|
+
};
|
|
8
|
+
BaseService = __decorate([
|
|
9
|
+
mix(DataService, TrashService)
|
|
10
|
+
], BaseService);
|
|
11
|
+
export class FlowService extends BaseService {
|
|
12
|
+
constructor(httpClient) {
|
|
13
|
+
super(httpClient, '/flows');
|
|
14
|
+
}
|
|
15
|
+
// workaround as flow-service does not have a POST /many endpoint
|
|
16
|
+
addMany(dto, options = {}) {
|
|
17
|
+
const reqs = dto.map((v) => this.addOne(v, options));
|
|
18
|
+
return Promise.all(reqs);
|
|
19
|
+
}
|
|
20
|
+
getMany(params = {}, options = {}) {
|
|
21
|
+
params.populate = params.populate ? params.populate : 'none';
|
|
22
|
+
return super.getMany(params, options);
|
|
23
|
+
}
|
|
24
|
+
getOne(id, options = {}) {
|
|
25
|
+
options.populate = options.populate ? options.populate : 'none';
|
|
26
|
+
return super.getOne(id, options);
|
|
27
|
+
}
|
|
28
|
+
getFlowWithDiagram(diagramId, options = {}) {
|
|
29
|
+
return this.httpClient.get(`${this.basePath}/diagram/${diagramId}`, options);
|
|
30
|
+
}
|
|
31
|
+
getDiagramRevisions(id, options = {}) {
|
|
32
|
+
return this.httpClient.get(`${this.basePath}/${id}/diagram/revisions`, options);
|
|
33
|
+
}
|
|
34
|
+
async isDeploymentOnLatestDiagramVersion(depl, options = {}) {
|
|
35
|
+
const flowId = typeof depl.flow === 'string' ? depl.flow : depl.flow.id;
|
|
36
|
+
const diagramId = typeof depl.diagram === 'string' ? depl.diagram : depl.diagram.id;
|
|
37
|
+
const revisions = await this.getDiagramRevisions(flowId, options);
|
|
38
|
+
return revisions[revisions.length - 1].id === diagramId;
|
|
39
|
+
}
|
|
40
|
+
getRevisions(id, options = {}) {
|
|
41
|
+
return this.httpClient.get(`${this.basePath}/${id}/revisions`, options);
|
|
42
|
+
}
|
|
43
|
+
rollback(id, revisionId, options = {}) {
|
|
44
|
+
return this.httpClient.put(`${this.basePath}/${id}/rollback`, { revisionId }, options);
|
|
45
|
+
}
|
|
46
|
+
deleteRevision(id, revisionId, options = {}) {
|
|
47
|
+
return this.httpClient.delete(`${this.basePath}/${id}/revisions/${revisionId}`, options);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -2,6 +2,10 @@ import { AxiosInstance, AxiosRequestConfig, Method } from 'axios';
|
|
|
2
2
|
import EventSource from 'eventsource';
|
|
3
3
|
import { Queue } from './Queue';
|
|
4
4
|
import { TokenSet } from './token-set';
|
|
5
|
+
export type TokenOption = {
|
|
6
|
+
token?: string;
|
|
7
|
+
};
|
|
8
|
+
export type Config = TokenOption & AxiosRequestConfig;
|
|
5
9
|
export declare class HttpClient {
|
|
6
10
|
protected readonly baseURL: string;
|
|
7
11
|
protected readonly authBaseURL: string;
|
|
@@ -14,6 +18,7 @@ export declare class HttpClient {
|
|
|
14
18
|
protected readonly requestQueue: Queue;
|
|
15
19
|
private tokenSet;
|
|
16
20
|
private exchangedTokenSet;
|
|
21
|
+
private discoveredIssuers;
|
|
17
22
|
eventSourcesMap: Map<string, {
|
|
18
23
|
eventSource: EventSource;
|
|
19
24
|
listener: (event: MessageEvent) => void;
|
|
@@ -26,12 +31,12 @@ export declare class HttpClient {
|
|
|
26
31
|
size: number;
|
|
27
32
|
total: number;
|
|
28
33
|
};
|
|
29
|
-
delete: <T>(url: string, config?:
|
|
30
|
-
get: <T>(url: string, config?:
|
|
31
|
-
post: <T>(url: string, data: any, config?:
|
|
32
|
-
put: <T>(url: string, data: any, config?:
|
|
33
|
-
protected request: <T>(method: Method, url: string, config?:
|
|
34
|
-
addEventSource(url: string, listener: (event: MessageEvent) => void, errorListener?: (event: MessageEvent) => void): Promise<string>;
|
|
34
|
+
delete: <T>(url: string, config?: Config) => Promise<T>;
|
|
35
|
+
get: <T>(url: string, config?: Config) => Promise<T>;
|
|
36
|
+
post: <T>(url: string, data: any, config?: Config) => Promise<T>;
|
|
37
|
+
put: <T>(url: string, data: any, config?: Config) => Promise<T>;
|
|
38
|
+
protected request: <T>(method: Method, url: string, config?: Config, data?: any) => Promise<T>;
|
|
39
|
+
addEventSource(url: string, listener: (event: MessageEvent) => void, errorListener?: (event: MessageEvent) => void, options?: TokenOption): Promise<string>;
|
|
35
40
|
destroyEventSource(id: string): void;
|
|
36
41
|
destroyAllEventSources(): void;
|
|
37
42
|
getAccessToken: (forceRefresh?: boolean) => Promise<string>;
|
|
@@ -39,6 +44,7 @@ export declare class HttpClient {
|
|
|
39
44
|
protected discoverIssuer(uri: string): Promise<Issuer>;
|
|
40
45
|
protected requestAccessToken(additionalOpts?: {}): Promise<TokenSet>;
|
|
41
46
|
protected exchangeAccessToken(accessToken: string): Promise<TokenSet>;
|
|
47
|
+
provideExternalToken(token: string): Promise<void>;
|
|
42
48
|
}
|
|
43
49
|
interface Issuer {
|
|
44
50
|
issuer: string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { stringify } from 'querystring';
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
import EventSource from 'eventsource';
|
|
4
|
+
import { CompactSign, decodeJwt } from 'jose';
|
|
5
|
+
import { Queue } from './Queue';
|
|
6
|
+
import { TokenSet } from './token-set';
|
|
7
|
+
export class HttpClient {
|
|
8
|
+
constructor(baseURL, authBaseURL, realm, clientId, clientSecret, tokenSubject) {
|
|
9
|
+
this.baseURL = baseURL;
|
|
10
|
+
this.authBaseURL = authBaseURL;
|
|
11
|
+
this.realm = realm;
|
|
12
|
+
this.clientId = clientId;
|
|
13
|
+
this.clientSecret = clientSecret;
|
|
14
|
+
this.tokenSubject = tokenSubject;
|
|
15
|
+
this.discoveredIssuers = new Map();
|
|
16
|
+
this.eventSourcesMap = new Map();
|
|
17
|
+
this.getQueueStats = () => this.requestQueue?.getStats();
|
|
18
|
+
this.delete = (url, config) => this.request('DELETE', url, config);
|
|
19
|
+
this.get = (url, config) => this.request('GET', url, config);
|
|
20
|
+
this.post = (url, data, config) => this.request('POST', url, config, data);
|
|
21
|
+
this.put = (url, data, config) => this.request('PUT', url, config, data);
|
|
22
|
+
this.request = (method, url, config = {}, data) => {
|
|
23
|
+
return this.requestQueue.add(() => new Promise((resolve, reject) => {
|
|
24
|
+
const tokenP = config.token ? Promise.resolve(config.token) : this.getAccessToken();
|
|
25
|
+
tokenP
|
|
26
|
+
.then((token) => {
|
|
27
|
+
const headers = { Authorization: `Bearer ${token}`, ...config.headers };
|
|
28
|
+
return this.axiosInstance.request({ ...config, headers, method, url, data });
|
|
29
|
+
})
|
|
30
|
+
.then((response) => resolve(response.data))
|
|
31
|
+
.catch(reject);
|
|
32
|
+
}));
|
|
33
|
+
};
|
|
34
|
+
this.getAccessToken = async (forceRefresh = false) => {
|
|
35
|
+
let accessToken;
|
|
36
|
+
if (forceRefresh || !this.tokenSet || this.tokenSet.isExpired()) {
|
|
37
|
+
if (this.tokenSet?.provided) {
|
|
38
|
+
throw new Error('provided token is expired and cannot be refreshed, provide a new token.');
|
|
39
|
+
}
|
|
40
|
+
this.tokenSet = await this.requestAccessToken();
|
|
41
|
+
accessToken = this.tokenSet.accessToken;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
accessToken = this.tokenSet.accessToken;
|
|
45
|
+
}
|
|
46
|
+
if (this.tokenSubject) {
|
|
47
|
+
if (forceRefresh || !this.exchangedTokenSet || this.exchangedTokenSet.isExpired()) {
|
|
48
|
+
this.exchangedTokenSet = await this.exchangeAccessToken(accessToken);
|
|
49
|
+
}
|
|
50
|
+
return this.exchangedTokenSet.accessToken;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
return accessToken;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
this.axiosInstance = axios.create({ baseURL, timeout: 60000 });
|
|
57
|
+
this.authAxiosInstance = axios.create({ baseURL: authBaseURL || baseURL, timeout: 10000 });
|
|
58
|
+
this.requestQueue = new Queue({ concurrency: 1, timeout: 70000, throwOnTimeout: true });
|
|
59
|
+
}
|
|
60
|
+
async addEventSource(url, listener, errorListener, options = {}) {
|
|
61
|
+
const id = generateUUID();
|
|
62
|
+
const errListener = errorListener
|
|
63
|
+
? errorListener
|
|
64
|
+
: (event) => {
|
|
65
|
+
throw new Error(JSON.stringify(event, null, 2));
|
|
66
|
+
};
|
|
67
|
+
const token = options.token ? options.token : await this.getAccessToken();
|
|
68
|
+
const es = new EventSource(`${this.baseURL}${url}`, {
|
|
69
|
+
headers: { authorization: 'Bearer ' + token },
|
|
70
|
+
});
|
|
71
|
+
es.addEventListener('message', listener);
|
|
72
|
+
es.addEventListener('error', errListener);
|
|
73
|
+
// the listeners have to be saved otherwise they cannot be removed
|
|
74
|
+
this.eventSourcesMap.set(id, { eventSource: es, listener, errListener });
|
|
75
|
+
return id;
|
|
76
|
+
}
|
|
77
|
+
destroyEventSource(id) {
|
|
78
|
+
if (!this.eventSourcesMap.has(id)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const es = this.eventSourcesMap.get(id);
|
|
82
|
+
// close and unbind listeners so that the process quits cleanly
|
|
83
|
+
es.eventSource.close();
|
|
84
|
+
es.eventSource.removeEventListener('message', es.listener);
|
|
85
|
+
es.eventSource.removeEventListener('error', es.errListener);
|
|
86
|
+
this.eventSourcesMap.delete(id);
|
|
87
|
+
}
|
|
88
|
+
destroyAllEventSources() {
|
|
89
|
+
for (const key of this.eventSourcesMap.keys()) {
|
|
90
|
+
this.destroyEventSource(key);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
validateIssuer(issuer) {
|
|
94
|
+
if (!issuer.issuer ||
|
|
95
|
+
!issuer.grant_types_supported?.includes('client_credentials') ||
|
|
96
|
+
!issuer.token_endpoint_auth_methods_supported?.includes('client_secret_jwt')) {
|
|
97
|
+
throw new Error('Issuer does not support client_secret_jwt');
|
|
98
|
+
}
|
|
99
|
+
return issuer;
|
|
100
|
+
}
|
|
101
|
+
async discoverIssuer(uri) {
|
|
102
|
+
if (this.discoveredIssuers.has(uri)) {
|
|
103
|
+
return this.discoveredIssuers.get(uri);
|
|
104
|
+
}
|
|
105
|
+
const wellKnownUri = `${uri}/.well-known/openid-configuration`;
|
|
106
|
+
const issuerResponse = await this.authAxiosInstance.get(wellKnownUri, {
|
|
107
|
+
responseType: 'json',
|
|
108
|
+
headers: { Accept: 'application/json' },
|
|
109
|
+
});
|
|
110
|
+
const validIssuer = this.validateIssuer(issuerResponse.data);
|
|
111
|
+
this.discoveredIssuers.set(uri, validIssuer);
|
|
112
|
+
return validIssuer;
|
|
113
|
+
}
|
|
114
|
+
async requestAccessToken(additionalOpts = {}) {
|
|
115
|
+
const issuer = await this.discoverIssuer(`${this.authBaseURL}/realms/${this.realm}`);
|
|
116
|
+
const timestamp = Date.now() / 1000;
|
|
117
|
+
const audience = [...new Set([issuer.issuer, issuer.token_endpoint].filter(Boolean))];
|
|
118
|
+
const assertionPayload = {
|
|
119
|
+
iat: timestamp,
|
|
120
|
+
exp: timestamp + 60,
|
|
121
|
+
jti: generateUUID(),
|
|
122
|
+
iss: this.clientId,
|
|
123
|
+
sub: this.clientId,
|
|
124
|
+
aud: audience,
|
|
125
|
+
};
|
|
126
|
+
const supportedAlgos = issuer.token_endpoint_auth_signing_alg_values_supported;
|
|
127
|
+
const alg = issuer.token_endpoint_auth_signing_alg ??
|
|
128
|
+
(Array.isArray(supportedAlgos) && supportedAlgos.find((signAlg) => /^HS(?:256|384|512)/.test(signAlg)));
|
|
129
|
+
if (!alg) {
|
|
130
|
+
throw new Error('Issuer has to support HS256, HS384 or HS512');
|
|
131
|
+
}
|
|
132
|
+
const assertion = await new CompactSign(Buffer.from(JSON.stringify(assertionPayload)))
|
|
133
|
+
.setProtectedHeader({ alg })
|
|
134
|
+
.sign(new TextEncoder().encode(this.clientSecret));
|
|
135
|
+
const opts = {
|
|
136
|
+
client_id: this.clientId,
|
|
137
|
+
client_assertion: assertion,
|
|
138
|
+
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
|
|
139
|
+
grant_type: 'client_credentials',
|
|
140
|
+
...additionalOpts,
|
|
141
|
+
};
|
|
142
|
+
const authResponse = await this.authAxiosInstance.post(issuer.token_endpoint, stringify(opts), {
|
|
143
|
+
headers: { Accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
144
|
+
});
|
|
145
|
+
if (authResponse?.data?.access_token && authResponse.data.expires_in) {
|
|
146
|
+
return new TokenSet(authResponse.data.access_token, authResponse.data.expires_in);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
throw new Error('Invalid access token received');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async exchangeAccessToken(accessToken) {
|
|
153
|
+
if (!accessToken || !this.tokenSubject) {
|
|
154
|
+
throw new Error('Could not exchange access token');
|
|
155
|
+
}
|
|
156
|
+
const opts = {
|
|
157
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
|
|
158
|
+
subject_token: accessToken,
|
|
159
|
+
audience: this.clientId,
|
|
160
|
+
requested_token_type: 'urn:ietf:params:oauth:token-type:access_token',
|
|
161
|
+
requested_subject: this.tokenSubject,
|
|
162
|
+
};
|
|
163
|
+
return this.requestAccessToken(opts);
|
|
164
|
+
}
|
|
165
|
+
async provideExternalToken(token) {
|
|
166
|
+
const issuer = await this.discoverIssuer(`${this.authBaseURL}/realms/${this.realm}`);
|
|
167
|
+
const { iss: providedIssuer, exp } = decodeJwt(token);
|
|
168
|
+
if (issuer.issuer !== providedIssuer) {
|
|
169
|
+
throw new Error(`Provided token is not issued by currently configured issuer. Provided token issued by ${providedIssuer}, but ${issuer.issuer} is configured.`);
|
|
170
|
+
}
|
|
171
|
+
this.tokenSet = new TokenSet(token, exp - Date.now() / 1000, true);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
function generateUUID() {
|
|
175
|
+
if (typeof globalThis.crypto?.randomUUID === 'function') {
|
|
176
|
+
return globalThis.crypto.randomUUID();
|
|
177
|
+
}
|
|
178
|
+
throw new Error('randomUUID() not available in this environment. Please upgrade to Node 20+ or a modern browser.');
|
|
179
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DataService } from './data.service';
|
|
2
|
+
import { HttpClient, TokenOption } from './http.service';
|
|
3
|
+
import { Label } from './label.interface';
|
|
4
|
+
export declare class LabelService extends DataService<Label> {
|
|
5
|
+
constructor(httpClient: HttpClient);
|
|
6
|
+
addMany(dtos: Label[], options?: TokenOption): Promise<Label[]>;
|
|
7
|
+
getOneByName(name: string, options?: TokenOption): Promise<Label>;
|
|
8
|
+
count(options?: TokenOption): Promise<number>;
|
|
9
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DataService } from './data.service';
|
|
2
|
+
export class LabelService extends DataService {
|
|
3
|
+
constructor(httpClient) {
|
|
4
|
+
super(httpClient, '/labels');
|
|
5
|
+
}
|
|
6
|
+
addMany(dtos, options = {}) {
|
|
7
|
+
return Promise.all(dtos.map((dto) => this.addOne(dto, options)));
|
|
8
|
+
}
|
|
9
|
+
getOneByName(name, options = {}) {
|
|
10
|
+
return this.httpClient.get(`${this.basePath}/name/${name}`, options);
|
|
11
|
+
}
|
|
12
|
+
count(options = {}) {
|
|
13
|
+
return this.httpClient.get(`${this.basePath}/count`, options);
|
|
14
|
+
}
|
|
15
|
+
}
|