@qelos/sdk 3.8.1 → 3.8.3
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/dist/administrator/index.d.ts +2 -0
- package/dist/administrator/index.js +3 -0
- package/dist/administrator/index.js.map +1 -1
- package/dist/administrator/manage-plugins.d.ts +25 -0
- package/dist/administrator/manage-plugins.js +33 -0
- package/dist/administrator/manage-plugins.js.map +1 -0
- package/dist/administrator/tests/roles.test.d.ts +1 -0
- package/dist/administrator/tests/roles.test.js +32 -0
- package/dist/administrator/tests/roles.test.js.map +1 -0
- package/dist/base-sdk.d.ts +3 -0
- package/dist/base-sdk.js +68 -25
- package/dist/base-sdk.js.map +1 -1
- package/dist/workspaces.js +1 -1
- package/dist/workspaces.js.map +1 -1
- package/package.json +4 -4
- package/src/administrator/index.ts +3 -0
- package/src/administrator/manage-plugins.ts +58 -0
- package/src/base-sdk.ts +80 -24
- package/src/workspaces.ts +1 -1
- package/test/base-sdk-exceptions.test.ts +197 -0
- package/test/base-sdk.test.ts +80 -0
- package/test/index.test.ts +85 -0
- package/test/qelos-sdk-edge-cases.test.ts +301 -0
- package/test/qelos-sdk-refresh.test.ts +412 -0
- package/tsconfig.json +3 -2
|
@@ -9,6 +9,7 @@ import QlAdminWorkspaces from './workspaces';
|
|
|
9
9
|
import QlManageBlueprints from './manage-blueprints';
|
|
10
10
|
import { QlRoles } from './roles';
|
|
11
11
|
import QlIntegrationSources from './integration-sources';
|
|
12
|
+
import QlManagePlugins from './manage-plugins';
|
|
12
13
|
export default class QelosAdministratorSDK<T = any> extends QelosSDK {
|
|
13
14
|
users: QlUsers<T>;
|
|
14
15
|
manageLayouts: QlManageLayouts;
|
|
@@ -19,6 +20,7 @@ export default class QelosAdministratorSDK<T = any> extends QelosSDK {
|
|
|
19
20
|
adminWorkspaces: QlAdminWorkspaces;
|
|
20
21
|
roles: QlRoles;
|
|
21
22
|
integrationSources: QlIntegrationSources;
|
|
23
|
+
managePlugins: QlManagePlugins;
|
|
22
24
|
constructor(options: QelosSDKOptions);
|
|
23
25
|
impersonateUser(userId: string, workspaceId?: string): void;
|
|
24
26
|
clearImpersonation(): void;
|
|
@@ -8,6 +8,7 @@ import QlAdminWorkspaces from './workspaces';
|
|
|
8
8
|
import QlManageBlueprints from './manage-blueprints';
|
|
9
9
|
import { QlRoles } from './roles';
|
|
10
10
|
import QlIntegrationSources from './integration-sources';
|
|
11
|
+
import QlManagePlugins from './manage-plugins';
|
|
11
12
|
export default class QelosAdministratorSDK extends QelosSDK {
|
|
12
13
|
users;
|
|
13
14
|
manageLayouts;
|
|
@@ -18,6 +19,7 @@ export default class QelosAdministratorSDK extends QelosSDK {
|
|
|
18
19
|
adminWorkspaces;
|
|
19
20
|
roles;
|
|
20
21
|
integrationSources;
|
|
22
|
+
managePlugins;
|
|
21
23
|
constructor(options) {
|
|
22
24
|
super(options);
|
|
23
25
|
this.users = new QlUsers(options);
|
|
@@ -29,6 +31,7 @@ export default class QelosAdministratorSDK extends QelosSDK {
|
|
|
29
31
|
this.adminWorkspaces = new QlAdminWorkspaces(options);
|
|
30
32
|
this.roles = new QlRoles(options);
|
|
31
33
|
this.integrationSources = new QlIntegrationSources(options);
|
|
34
|
+
this.managePlugins = new QlManagePlugins(options);
|
|
32
35
|
if (!options.extraQueryParams) {
|
|
33
36
|
options.extraQueryParams = () => ({
|
|
34
37
|
bypassAdmin: 'true'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/administrator/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,sBAAsB,MAAM,yBAAyB,CAAC;AAC7D,OAAO,iBAAiB,MAAM,cAAc,CAAC;AAC7C,OAAO,kBAAkB,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,oBAAoB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/administrator/index.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAEhC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAC/C,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,sBAAsB,MAAM,yBAAyB,CAAC;AAC7D,OAAO,iBAAiB,MAAM,cAAc,CAAC;AAC7C,OAAO,kBAAkB,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,oBAAoB,MAAM,uBAAuB,CAAC;AACzD,OAAO,eAAe,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,qBAA+B,SAAQ,QAAQ;IAClE,KAAK,CAAa;IAClB,aAAa,CAAkB;IAC/B,oBAAoB,CAAyB;IAC7C,gBAAgB,CAAqB;IACrC,MAAM,CAAW;IACjB,MAAM,CAAW;IACjB,eAAe,CAAoB;IACnC,KAAK,CAAU;IACf,kBAAkB,CAAuB;IACzC,aAAa,CAAkB;IAE/B,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,KAAK,GAAG,IAAI,OAAO,CAAI,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,aAAa,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;QAClD,IAAI,CAAC,oBAAoB,GAAG,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChE,IAAI,CAAC,gBAAgB,GAAG,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,IAAI,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,kBAAkB,GAAG,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC5D,IAAI,CAAC,aAAa,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;QAElD,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE;YAC7B,OAAO,CAAC,gBAAgB,GAAG,GAAG,EAAE,CAAC,CAAC;gBAChC,WAAW,EAAE,MAAM;aACpB,CAAC,CAAA;SACH;IACH,CAAC;IAED,eAAe,CAAC,MAAc,EAAE,WAAoB;QAClD,IAAI,CAAC,eAAe,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;QACnD,IAAI,WAAW,EAAE;YACf,IAAI,CAAC,eAAe,CAAC,yBAAyB,EAAE,WAAW,CAAC,CAAC;SAC9D;IACH,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAC;QAC9C,IAAI,CAAC,kBAAkB,CAAC,yBAAyB,CAAC,CAAC;IACrD,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import BaseSDK from '../base-sdk';
|
|
2
|
+
import { QelosSDKOptions } from '../types';
|
|
3
|
+
import { IPlugin, IEventSubscriber, IMicroFrontend, IPluginCrud, IInjectable, INavbarGroup } from '@qelos/global-types';
|
|
4
|
+
type ServerManagedPluginFields = 'tenant' | 'user' | 'token' | 'auth' | '_id' | 'id' | 'createdAt' | 'updatedAt';
|
|
5
|
+
export type IPluginCreateParams = Omit<IPlugin, ServerManagedPluginFields | 'subscribedEvents' | 'microFrontends' | 'cruds' | 'injectables' | 'navBarGroups'> & {
|
|
6
|
+
subscribedEvents?: Partial<IEventSubscriber>[];
|
|
7
|
+
microFrontends?: Partial<IMicroFrontend>[];
|
|
8
|
+
cruds?: Partial<IPluginCrud>[];
|
|
9
|
+
injectables?: Partial<IInjectable>[];
|
|
10
|
+
navBarGroups?: Partial<INavbarGroup>[];
|
|
11
|
+
version?: string;
|
|
12
|
+
url?: string;
|
|
13
|
+
proxyUrl?: string;
|
|
14
|
+
};
|
|
15
|
+
export type IPluginUpdateParams = Partial<Omit<IPlugin, ServerManagedPluginFields>>;
|
|
16
|
+
export default class QlManagePlugins extends BaseSDK {
|
|
17
|
+
private relativePath;
|
|
18
|
+
constructor(options: QelosSDKOptions);
|
|
19
|
+
create(pluginData: IPluginCreateParams): Promise<IPlugin>;
|
|
20
|
+
update(pluginId: string, pluginData: IPluginUpdateParams): Promise<IPlugin>;
|
|
21
|
+
remove(pluginId: string): Promise<void>;
|
|
22
|
+
getList(): Promise<IPlugin[]>;
|
|
23
|
+
getById(pluginId: string): Promise<IPlugin>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import BaseSDK from '../base-sdk';
|
|
2
|
+
export default class QlManagePlugins extends BaseSDK {
|
|
3
|
+
relativePath = '/api/plugins'; // Please confirm/adjust this path
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super(options);
|
|
6
|
+
}
|
|
7
|
+
async create(pluginData) {
|
|
8
|
+
return this.callJsonApi(this.relativePath, {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
headers: { 'content-type': 'application/json' },
|
|
11
|
+
body: JSON.stringify(pluginData),
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
async update(pluginId, pluginData) {
|
|
15
|
+
return this.callJsonApi(`${this.relativePath}/${pluginId}`, {
|
|
16
|
+
method: 'PUT',
|
|
17
|
+
headers: { 'content-type': 'application/json' },
|
|
18
|
+
body: JSON.stringify(pluginData),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async remove(pluginId) {
|
|
22
|
+
// callApi usually doesn't expect a JSON response, so no <void> generic needed for it.
|
|
23
|
+
// It will throw on non-2xx responses.
|
|
24
|
+
await this.callApi(`${this.relativePath}/${pluginId}`, { method: 'DELETE' });
|
|
25
|
+
}
|
|
26
|
+
async getList() {
|
|
27
|
+
return this.callJsonApi(this.relativePath);
|
|
28
|
+
}
|
|
29
|
+
async getById(pluginId) {
|
|
30
|
+
return this.callJsonApi(`${this.relativePath}/${pluginId}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=manage-plugins.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage-plugins.js","sourceRoot":"","sources":["../../src/administrator/manage-plugins.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,aAAa,CAAC;AAqBlC,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,OAAO;IAC1C,YAAY,GAAG,cAAc,CAAC,CAAC,kCAAkC;IAEzE,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,UAA+B;QAC1C,OAAO,IAAI,CAAC,WAAW,CAAU,IAAI,CAAC,YAAY,EAAE;YAClD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,UAA+B;QAC5D,OAAO,IAAI,CAAC,WAAW,CAAU,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,EAAE;YACnE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;SACjC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,sFAAsF;QACtF,sCAAsC;QACtC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,CAAC,WAAW,CAAY,IAAI,CAAC,YAAY,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,QAAgB;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAU,GAAG,IAAI,CAAC,YAAY,IAAI,QAAQ,EAAE,CAAC,CAAC;IACvE,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as assert from 'node:assert/strict';
|
|
2
|
+
import { QlRoles } from '../roles';
|
|
3
|
+
const { describe, beforeEach, test } = require('node:test');
|
|
4
|
+
describe('QlRoles', () => {
|
|
5
|
+
let options;
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
// Initialize SDK with the mocked fetch function and mock authentication
|
|
8
|
+
options = {
|
|
9
|
+
appUrl: 'http://localhost:3000',
|
|
10
|
+
fetch: () => null,
|
|
11
|
+
extraHeaders: async () => ({}),
|
|
12
|
+
refreshToken: 'mock-refresh-token' // Ensure a mock refresh token is set
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
test('should instantiate the roles property', () => {
|
|
16
|
+
const rolesSdk = new QlRoles(options);
|
|
17
|
+
assert.ok(rolesSdk);
|
|
18
|
+
});
|
|
19
|
+
test('should fetch roles successfully', async () => {
|
|
20
|
+
// Mock fetch to return a valid JSON response
|
|
21
|
+
options.fetch = async () => {
|
|
22
|
+
const res = new Response(JSON.stringify(['admin', 'user', 'plugin']));
|
|
23
|
+
res.headers.set('Content-Type', 'application/json');
|
|
24
|
+
return res;
|
|
25
|
+
};
|
|
26
|
+
const rolesSdk = new QlRoles(options);
|
|
27
|
+
// Call the function and verify results
|
|
28
|
+
const roles = await rolesSdk.getExistingRoles();
|
|
29
|
+
assert.deepEqual(roles, ['admin', 'user', 'plugin']);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
//# sourceMappingURL=roles.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.test.js","sourceRoot":"","sources":["../../../src/administrator/tests/roles.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC,CAAA;AAE3D,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,IAAI,OAAwB,CAAA;IAE5B,UAAU,CAAC,GAAG,EAAE;QACd,wEAAwE;QACxE,OAAO,GAAG;YACR,MAAM,EAAE,uBAAuB;YAC/B,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI;YACjB,YAAY,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9B,YAAY,EAAE,oBAAoB,CAAC,qCAAqC;SACzE,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;QACjD,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QACjD,6CAA6C;QAC7C,OAAO,CAAC,KAAK,GAAG,KAAK,IAAI,EAAE;YACzB,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;YACrE,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;YACpD,OAAO,GAAG,CAAC;QACb,CAAC,CAAA;QAED,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;QAEtC,uCAAuC;QACvC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAChD,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/base-sdk.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export default class BaseSDK {
|
|
|
4
4
|
private qlOptions;
|
|
5
5
|
constructor(qlOptions: QelosSDKOptions);
|
|
6
6
|
callApi(relativeUrl: string, data?: RequestInit): Promise<Response>;
|
|
7
|
+
private handleFailedRefreshToken;
|
|
8
|
+
private getContentType;
|
|
9
|
+
private parseResponse;
|
|
7
10
|
callJsonApi<T>(relativeUrl: string, data?: RequestInit): Promise<T>;
|
|
8
11
|
getQueryParams(moreQuery?: Record<string, any>): string;
|
|
9
12
|
}
|
package/dist/base-sdk.js
CHANGED
|
@@ -1,48 +1,91 @@
|
|
|
1
|
+
const ERRORS = {
|
|
2
|
+
EXTRA_HEADERS: 'could not get extra headers',
|
|
3
|
+
FAILED_REFRESH_TOKEN: 'could not handle failed refresh token',
|
|
4
|
+
UNABLE_TO_REFRESH_TOKEN: 'could not able to refresh token'
|
|
5
|
+
};
|
|
1
6
|
export default class BaseSDK {
|
|
2
7
|
qlOptions;
|
|
3
8
|
#appUrl;
|
|
4
9
|
#fetch;
|
|
5
10
|
constructor(qlOptions) {
|
|
6
11
|
this.qlOptions = qlOptions;
|
|
7
|
-
this.#appUrl = qlOptions.appUrl
|
|
12
|
+
this.#appUrl = qlOptions.appUrl?.endsWith('/') ? qlOptions.appUrl.slice(0, -1) : qlOptions.appUrl;
|
|
8
13
|
this.#fetch = qlOptions.fetch || globalThis.fetch;
|
|
9
14
|
}
|
|
10
15
|
async callApi(relativeUrl, data) {
|
|
11
16
|
data = data || {};
|
|
12
17
|
data.headers = data.headers || {};
|
|
13
|
-
|
|
18
|
+
if (this.qlOptions.extraHeaders) {
|
|
19
|
+
try {
|
|
20
|
+
const extraHeaders = await this.qlOptions.extraHeaders(relativeUrl);
|
|
21
|
+
Object.assign(data.headers, extraHeaders);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
throw new Error(ERRORS.EXTRA_HEADERS);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
14
27
|
return this.#fetch(this.#appUrl + relativeUrl, data);
|
|
15
28
|
}
|
|
16
|
-
|
|
17
|
-
|
|
29
|
+
async handleFailedRefreshToken() {
|
|
30
|
+
if (this.qlOptions.onFailedRefreshToken) {
|
|
31
|
+
try {
|
|
32
|
+
await this.qlOptions.onFailedRefreshToken();
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
throw new Error(ERRORS.FAILED_REFRESH_TOKEN);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
throw new Error(ERRORS.UNABLE_TO_REFRESH_TOKEN);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
getContentType(res) {
|
|
43
|
+
return res.headers.get('Content-Type') ||
|
|
44
|
+
res.headers.get('content-type') ||
|
|
45
|
+
res.headers.get('ContentType') ||
|
|
46
|
+
res.headers.get('contenttype') ||
|
|
47
|
+
res.headers.get('contentType') || 'text';
|
|
48
|
+
}
|
|
49
|
+
async parseResponse(res) {
|
|
50
|
+
const contentType = this.getContentType(res);
|
|
51
|
+
const isJson = contentType.includes('json');
|
|
52
|
+
const body = await (isJson ? res.json() : res.text());
|
|
53
|
+
if (!res.ok) {
|
|
54
|
+
throw (typeof body === 'string' ? new Error(body) : body);
|
|
55
|
+
}
|
|
56
|
+
return body;
|
|
57
|
+
}
|
|
58
|
+
async callJsonApi(relativeUrl, data) {
|
|
59
|
+
try {
|
|
60
|
+
let res = await this.callApi(relativeUrl, data);
|
|
61
|
+
// Handle token refresh if needed
|
|
18
62
|
if (this.qlOptions.forceRefresh && res.status >= 400 && res.status < 500) {
|
|
19
|
-
|
|
20
|
-
if (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
await this.qlOptions.onFailedRefreshToken();
|
|
24
|
-
}
|
|
25
|
-
catch (e) {
|
|
26
|
-
throw new Error('could not handle failed refresh token');
|
|
27
|
-
}
|
|
63
|
+
let headers = {};
|
|
64
|
+
if (this.qlOptions.extraHeaders) {
|
|
65
|
+
try {
|
|
66
|
+
headers = await this.qlOptions.extraHeaders(relativeUrl, true);
|
|
28
67
|
}
|
|
29
|
-
|
|
30
|
-
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore error during refresh attempt
|
|
31
70
|
}
|
|
32
71
|
}
|
|
72
|
+
if (!headers?.authorization) {
|
|
73
|
+
await this.handleFailedRefreshToken();
|
|
74
|
+
}
|
|
33
75
|
res = await this.callApi(relativeUrl, data);
|
|
34
76
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
77
|
+
return this.parseResponse(res);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
// Type guard for Error objects
|
|
81
|
+
if (err instanceof Error && err.message === ERRORS.EXTRA_HEADERS) {
|
|
82
|
+
// Handle token refresh for EXTRA_HEADERS_ERROR
|
|
83
|
+
await this.handleFailedRefreshToken();
|
|
84
|
+
const res = await this.callApi(relativeUrl, data);
|
|
85
|
+
return this.parseResponse(res);
|
|
43
86
|
}
|
|
44
|
-
|
|
45
|
-
}
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
46
89
|
}
|
|
47
90
|
getQueryParams(moreQuery) {
|
|
48
91
|
const qs = this.qlOptions.extraQueryParams ? { ...this.qlOptions.extraQueryParams(), ...(moreQuery || {}) } : moreQuery;
|
package/dist/base-sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-sdk.js","sourceRoot":"","sources":["../src/base-sdk.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,OAAO;IAIN;IAHpB,OAAO,CAAS;IAChB,MAAM,CAAY;IAElB,YAAoB,SAA0B;QAA1B,cAAS,GAAT,SAAS,CAAiB;QAC5C,IAAI,CAAC,OAAO,GAAG,SAAS,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"base-sdk.js","sourceRoot":"","sources":["../src/base-sdk.ts"],"names":[],"mappings":"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"}
|
package/dist/workspaces.js
CHANGED
|
@@ -31,7 +31,7 @@ export default class QlWorkspaces extends BaseSDK {
|
|
|
31
31
|
});
|
|
32
32
|
}
|
|
33
33
|
activate(workspaceId) {
|
|
34
|
-
return this.callJsonApi(`${this.relativePath}/${workspaceId}`, {
|
|
34
|
+
return this.callJsonApi(`${this.relativePath}/${workspaceId}/activate`, {
|
|
35
35
|
method: 'post',
|
|
36
36
|
headers: { 'content-type': 'application/json' },
|
|
37
37
|
});
|
package/dist/workspaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AA0BjC,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IACvC,YAAY,GAAG,iBAAiB,CAAC;IAEzC,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChB,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,OAAO,IAAI,CAAC,WAAW,CAAa,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,UAAU,CAAC,WAAmB;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAqB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,UAAU,CAAC,CAAA;IAC5F,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,WAAW,CAAe,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,WAAmB;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,OAA4B;QACtD,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,EACrC;YACE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;YAC7C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CACF,CAAA;IACH,CAAC;IAED,MAAM,CAAC,SAAiD;QACtD,OAAO,IAAI,CAAC,WAAW,CAAa,IAAI,CAAC,YAAY,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;YAC7C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;SAChC,CAAC,CAAA;IACJ,CAAC;IAED,QAAQ,CAAC,WAAmB;QAC1B,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,
|
|
1
|
+
{"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AA0BjC,MAAM,CAAC,OAAO,OAAO,YAAa,SAAQ,OAAO;IACvC,YAAY,GAAG,iBAAiB,CAAC;IAEzC,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAA;IAChB,CAAC;IAED,YAAY,CAAC,WAAmB;QAC9B,OAAO,IAAI,CAAC,WAAW,CAAa,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,UAAU,CAAC,WAAmB;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAqB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,UAAU,CAAC,CAAA;IAC5F,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,WAAW,CAAe,IAAI,CAAC,YAAY,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,CAAC,WAAmB;QACxB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,EAAE,EAAC,MAAM,EAAE,QAAQ,EAAC,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,CAAC,WAAmB,EAAE,OAA4B;QACtD,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,EAAE,EACrC;YACE,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;YAC7C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CACF,CAAA;IACH,CAAC;IAED,MAAM,CAAC,SAAiD;QACtD,OAAO,IAAI,CAAC,WAAW,CAAa,IAAI,CAAC,YAAY,EAAE;YACrD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;YAC7C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;SAChC,CAAC,CAAA;IACJ,CAAC;IAED,QAAQ,CAAC,WAAmB;QAC1B,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,IAAI,WAAW,WAAW,EAC9C;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAC,cAAc,EAAE,kBAAkB,EAAC;SAC9C,CACF,CAAA;IACH,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qelos/sdk",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.3",
|
|
4
4
|
"description": "SDK for Qelos API",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@qelos/global-types": "^3.8.
|
|
16
|
+
"@qelos/global-types": "^3.8.3"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"tsx": "^
|
|
19
|
+
"tsx": "^4.19.4",
|
|
20
20
|
"typescript": "^4.9.5"
|
|
21
21
|
},
|
|
22
|
-
"gitHead": "
|
|
22
|
+
"gitHead": "4f4acba1f01d2659431e3149cc6efa927926c5f1"
|
|
23
23
|
}
|
|
@@ -9,6 +9,7 @@ import QlAdminWorkspaces from './workspaces';
|
|
|
9
9
|
import QlManageBlueprints from './manage-blueprints';
|
|
10
10
|
import { QlRoles } from './roles';
|
|
11
11
|
import QlIntegrationSources from './integration-sources';
|
|
12
|
+
import QlManagePlugins from './manage-plugins';
|
|
12
13
|
|
|
13
14
|
export default class QelosAdministratorSDK<T = any> extends QelosSDK {
|
|
14
15
|
users: QlUsers<T>;
|
|
@@ -20,6 +21,7 @@ export default class QelosAdministratorSDK<T = any> extends QelosSDK {
|
|
|
20
21
|
adminWorkspaces: QlAdminWorkspaces;
|
|
21
22
|
roles: QlRoles;
|
|
22
23
|
integrationSources: QlIntegrationSources;
|
|
24
|
+
managePlugins: QlManagePlugins;
|
|
23
25
|
|
|
24
26
|
constructor(options: QelosSDKOptions) {
|
|
25
27
|
super(options);
|
|
@@ -32,6 +34,7 @@ export default class QelosAdministratorSDK<T = any> extends QelosSDK {
|
|
|
32
34
|
this.adminWorkspaces = new QlAdminWorkspaces(options);
|
|
33
35
|
this.roles = new QlRoles(options);
|
|
34
36
|
this.integrationSources = new QlIntegrationSources(options);
|
|
37
|
+
this.managePlugins = new QlManagePlugins(options);
|
|
35
38
|
|
|
36
39
|
if (!options.extraQueryParams) {
|
|
37
40
|
options.extraQueryParams = () => ({
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import BaseSDK from '../base-sdk';
|
|
2
|
+
import { QelosSDKOptions } from '../types';
|
|
3
|
+
import { IPlugin, IEventSubscriber, IMicroFrontend, IPluginCrud, IInjectable, INavbarGroup } from '@qelos/global-types';
|
|
4
|
+
|
|
5
|
+
// Fields that are typically set by the server or not directly updatable by admin
|
|
6
|
+
type ServerManagedPluginFields = 'tenant' | 'user' | 'token' | 'auth' | '_id' | 'id' | 'createdAt' | 'updatedAt';
|
|
7
|
+
|
|
8
|
+
export type IPluginCreateParams = Omit<IPlugin, ServerManagedPluginFields | 'subscribedEvents' | 'microFrontends' | 'cruds' | 'injectables' | 'navBarGroups'> & {
|
|
9
|
+
// Make optional arrays explicitly optional for creation if they can be omitted
|
|
10
|
+
subscribedEvents?: Partial<IEventSubscriber>[];
|
|
11
|
+
microFrontends?: Partial<IMicroFrontend>[];
|
|
12
|
+
cruds?: Partial<IPluginCrud>[];
|
|
13
|
+
injectables?: Partial<IInjectable>[];
|
|
14
|
+
navBarGroups?: Partial<INavbarGroup>[];
|
|
15
|
+
version?: string; // Add version if it's part of creation payload
|
|
16
|
+
url?: string; // Add url if it's part of creation payload (often same as appUrl)
|
|
17
|
+
proxyUrl?: string; // Allow setting proxyUrl during creation
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export type IPluginUpdateParams = Partial<Omit<IPlugin, ServerManagedPluginFields>>;
|
|
21
|
+
|
|
22
|
+
export default class QlManagePlugins extends BaseSDK {
|
|
23
|
+
private relativePath = '/api/plugins'; // Please confirm/adjust this path
|
|
24
|
+
|
|
25
|
+
constructor(options: QelosSDKOptions) {
|
|
26
|
+
super(options);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async create(pluginData: IPluginCreateParams): Promise<IPlugin> {
|
|
30
|
+
return this.callJsonApi<IPlugin>(this.relativePath, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: { 'content-type': 'application/json' },
|
|
33
|
+
body: JSON.stringify(pluginData),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async update(pluginId: string, pluginData: IPluginUpdateParams): Promise<IPlugin> {
|
|
38
|
+
return this.callJsonApi<IPlugin>(`${this.relativePath}/${pluginId}`, {
|
|
39
|
+
method: 'PUT',
|
|
40
|
+
headers: { 'content-type': 'application/json' },
|
|
41
|
+
body: JSON.stringify(pluginData),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async remove(pluginId: string): Promise<void> {
|
|
46
|
+
// callApi usually doesn't expect a JSON response, so no <void> generic needed for it.
|
|
47
|
+
// It will throw on non-2xx responses.
|
|
48
|
+
await this.callApi(`${this.relativePath}/${pluginId}`, { method: 'DELETE' });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async getList(): Promise<IPlugin[]> {
|
|
52
|
+
return this.callJsonApi<IPlugin[]>(this.relativePath);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async getById(pluginId: string): Promise<IPlugin> {
|
|
56
|
+
return this.callJsonApi<IPlugin>(`${this.relativePath}/${pluginId}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
package/src/base-sdk.ts
CHANGED
|
@@ -1,49 +1,105 @@
|
|
|
1
1
|
import { FetchLike, QelosSDKOptions } from './types';
|
|
2
2
|
|
|
3
|
+
const ERRORS = {
|
|
4
|
+
EXTRA_HEADERS: 'could not get extra headers',
|
|
5
|
+
FAILED_REFRESH_TOKEN: 'could not handle failed refresh token',
|
|
6
|
+
UNABLE_TO_REFRESH_TOKEN: 'could not able to refresh token'
|
|
7
|
+
}
|
|
8
|
+
|
|
3
9
|
export default class BaseSDK {
|
|
4
10
|
#appUrl: string;
|
|
5
11
|
#fetch: FetchLike;
|
|
6
12
|
|
|
7
13
|
constructor(private qlOptions: QelosSDKOptions) {
|
|
8
|
-
this.#appUrl = qlOptions.appUrl
|
|
14
|
+
this.#appUrl = qlOptions.appUrl?.endsWith('/') ? qlOptions.appUrl.slice(0, -1) : qlOptions.appUrl;
|
|
9
15
|
this.#fetch = qlOptions.fetch || globalThis.fetch;
|
|
10
16
|
}
|
|
11
17
|
|
|
12
18
|
async callApi(relativeUrl: string, data?: RequestInit) {
|
|
13
19
|
data = data || {};
|
|
14
20
|
data.headers = data.headers || {};
|
|
15
|
-
|
|
21
|
+
|
|
22
|
+
if (this.qlOptions.extraHeaders) {
|
|
23
|
+
try {
|
|
24
|
+
const extraHeaders = await this.qlOptions.extraHeaders(relativeUrl);
|
|
25
|
+
Object.assign(data.headers, extraHeaders);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
throw new Error(ERRORS.EXTRA_HEADERS);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
16
31
|
return this.#fetch(this.#appUrl + relativeUrl, data);
|
|
17
32
|
}
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
private async handleFailedRefreshToken(): Promise<void> {
|
|
35
|
+
if (this.qlOptions.onFailedRefreshToken) {
|
|
36
|
+
try {
|
|
37
|
+
await this.qlOptions.onFailedRefreshToken();
|
|
38
|
+
} catch (e) {
|
|
39
|
+
throw new Error(ERRORS.FAILED_REFRESH_TOKEN);
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
throw new Error(ERRORS.UNABLE_TO_REFRESH_TOKEN);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private getContentType(res: Response): string {
|
|
47
|
+
return res.headers.get('Content-Type') ||
|
|
48
|
+
res.headers.get('content-type') ||
|
|
49
|
+
res.headers.get('ContentType') ||
|
|
50
|
+
res.headers.get('contenttype') ||
|
|
51
|
+
res.headers.get('contentType') || 'text';
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private async parseResponse<T>(res: Response): Promise<T> {
|
|
55
|
+
const contentType = this.getContentType(res);
|
|
56
|
+
const isJson = contentType.includes('json');
|
|
57
|
+
|
|
58
|
+
const body = await (isJson ? res.json() : res.text());
|
|
59
|
+
|
|
60
|
+
if (!res.ok) {
|
|
61
|
+
throw (typeof body === 'string' ? new Error(body) : body);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return body;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async callJsonApi<T>(relativeUrl: string, data?: RequestInit): Promise<T> {
|
|
68
|
+
try {
|
|
69
|
+
let res = await this.callApi(relativeUrl, data);
|
|
70
|
+
|
|
71
|
+
// Handle token refresh if needed
|
|
21
72
|
if (this.qlOptions.forceRefresh && res.status >= 400 && res.status < 500) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
} else {
|
|
31
|
-
throw new Error('could not able to refresh token');
|
|
73
|
+
let headers: Record<string, string> = {};
|
|
74
|
+
|
|
75
|
+
if (this.qlOptions.extraHeaders) {
|
|
76
|
+
try {
|
|
77
|
+
headers = await this.qlOptions.extraHeaders(relativeUrl, true);
|
|
78
|
+
} catch {
|
|
79
|
+
// Ignore error during refresh attempt
|
|
32
80
|
}
|
|
33
81
|
}
|
|
82
|
+
|
|
83
|
+
if (!headers?.authorization) {
|
|
84
|
+
await this.handleFailedRefreshToken();
|
|
85
|
+
}
|
|
86
|
+
|
|
34
87
|
res = await this.callApi(relativeUrl, data);
|
|
35
88
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
89
|
+
|
|
90
|
+
return this.parseResponse<T>(res);
|
|
91
|
+
} catch (err: unknown) {
|
|
92
|
+
// Type guard for Error objects
|
|
93
|
+
if (err instanceof Error && err.message === ERRORS.EXTRA_HEADERS) {
|
|
94
|
+
// Handle token refresh for EXTRA_HEADERS_ERROR
|
|
95
|
+
await this.handleFailedRefreshToken();
|
|
96
|
+
|
|
97
|
+
const res = await this.callApi(relativeUrl, data);
|
|
98
|
+
return this.parseResponse<T>(res);
|
|
44
99
|
}
|
|
45
|
-
|
|
46
|
-
|
|
100
|
+
|
|
101
|
+
throw err;
|
|
102
|
+
}
|
|
47
103
|
}
|
|
48
104
|
|
|
49
105
|
getQueryParams(moreQuery?: Record<string, any>) {
|
package/src/workspaces.ts
CHANGED
|
@@ -69,7 +69,7 @@ export default class QlWorkspaces extends BaseSDK {
|
|
|
69
69
|
|
|
70
70
|
activate(workspaceId: string): Promise<IWorkspace> {
|
|
71
71
|
return this.callJsonApi<IWorkspace>(
|
|
72
|
-
`${this.relativePath}/${workspaceId}`,
|
|
72
|
+
`${this.relativePath}/${workspaceId}/activate`,
|
|
73
73
|
{
|
|
74
74
|
method: 'post',
|
|
75
75
|
headers: {'content-type': 'application/json'},
|