@forestadmin/agent-testing 0.1.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/LICENSE +674 -0
- package/README.md +52 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +20 -0
- package/dist/integrations/benchmark.d.ts +13 -0
- package/dist/integrations/benchmark.js +36 -0
- package/dist/integrations/forest-admin-client-mock.d.ts +28 -0
- package/dist/integrations/forest-admin-client-mock.js +76 -0
- package/dist/integrations/forest-server-sandbox.d.ts +14 -0
- package/dist/integrations/forest-server-sandbox.js +153 -0
- package/dist/integrations/http-requester-mock.d.ts +8 -0
- package/dist/integrations/http-requester-mock.js +15 -0
- package/dist/integrations/index.d.ts +43 -0
- package/dist/integrations/index.js +119 -0
- package/dist/integrations/schema-converter.d.ts +6 -0
- package/dist/integrations/schema-converter.js +16 -0
- package/dist/integrations/schema-path-manager.d.ts +6 -0
- package/dist/integrations/schema-path-manager.js +25 -0
- package/dist/integrations/testable-agent-base.d.ts +7 -0
- package/dist/integrations/testable-agent-base.js +14 -0
- package/dist/integrations/testable-agent.d.ts +15 -0
- package/dist/integrations/testable-agent.js +33 -0
- package/dist/integrations/types.d.ts +5 -0
- package/dist/integrations/types.js +3 -0
- package/dist/remote-agent-client/action-fields/action-field-checkbox-group.d.ts +8 -0
- package/dist/remote-agent-client/action-fields/action-field-checkbox-group.js +23 -0
- package/dist/remote-agent-client/action-fields/action-field-checkbox.d.ts +6 -0
- package/dist/remote-agent-client/action-fields/action-field-checkbox.js +16 -0
- package/dist/remote-agent-client/action-fields/action-field-color-picker.d.ts +7 -0
- package/dist/remote-agent-client/action-fields/action-field-color-picker.js +19 -0
- package/dist/remote-agent-client/action-fields/action-field-date.d.ts +5 -0
- package/dist/remote-agent-client/action-fields/action-field-date.js +13 -0
- package/dist/remote-agent-client/action-fields/action-field-dropdown.d.ts +7 -0
- package/dist/remote-agent-client/action-fields/action-field-dropdown.js +16 -0
- package/dist/remote-agent-client/action-fields/action-field-enum.d.ts +6 -0
- package/dist/remote-agent-client/action-fields/action-field-enum.js +19 -0
- package/dist/remote-agent-client/action-fields/action-field-json.d.ts +5 -0
- package/dist/remote-agent-client/action-fields/action-field-json.js +13 -0
- package/dist/remote-agent-client/action-fields/action-field-multiple-choice.d.ts +7 -0
- package/dist/remote-agent-client/action-fields/action-field-multiple-choice.js +19 -0
- package/dist/remote-agent-client/action-fields/action-field-number-list.d.ts +6 -0
- package/dist/remote-agent-client/action-fields/action-field-number-list.js +20 -0
- package/dist/remote-agent-client/action-fields/action-field-number.d.ts +5 -0
- package/dist/remote-agent-client/action-fields/action-field-number.js +13 -0
- package/dist/remote-agent-client/action-fields/action-field-radio-group.d.ts +7 -0
- package/dist/remote-agent-client/action-fields/action-field-radio-group.js +16 -0
- package/dist/remote-agent-client/action-fields/action-field-string-list.d.ts +6 -0
- package/dist/remote-agent-client/action-fields/action-field-string-list.js +20 -0
- package/dist/remote-agent-client/action-fields/action-field-string.d.ts +5 -0
- package/dist/remote-agent-client/action-fields/action-field-string.js +13 -0
- package/dist/remote-agent-client/action-fields/action-field.d.ts +15 -0
- package/dist/remote-agent-client/action-fields/action-field.js +34 -0
- package/dist/remote-agent-client/action-fields/field-form-states.d.ts +25 -0
- package/dist/remote-agent-client/action-fields/field-form-states.js +94 -0
- package/dist/remote-agent-client/action-fields/field-getter.d.ts +10 -0
- package/dist/remote-agent-client/action-fields/field-getter.js +21 -0
- package/dist/remote-agent-client/action-fields/types.d.ts +28 -0
- package/dist/remote-agent-client/action-fields/types.js +3 -0
- package/dist/remote-agent-client/action-layout/action-layout-container.d.ts +9 -0
- package/dist/remote-agent-client/action-layout/action-layout-container.js +24 -0
- package/dist/remote-agent-client/action-layout/action-layout-element.d.ts +14 -0
- package/dist/remote-agent-client/action-layout/action-layout-element.js +47 -0
- package/dist/remote-agent-client/action-layout/action-layout-input.d.ts +7 -0
- package/dist/remote-agent-client/action-layout/action-layout-input.js +12 -0
- package/dist/remote-agent-client/action-layout/action-layout-page.d.ts +8 -0
- package/dist/remote-agent-client/action-layout/action-layout-page.js +18 -0
- package/dist/remote-agent-client/action-layout/action-layout-root.d.ts +6 -0
- package/dist/remote-agent-client/action-layout/action-layout-root.js +19 -0
- package/dist/remote-agent-client/action-layout/errors.d.ts +8 -0
- package/dist/remote-agent-client/action-layout/errors.js +16 -0
- package/dist/remote-agent-client/domains/action.d.ts +59 -0
- package/dist/remote-agent-client/domains/action.js +139 -0
- package/dist/remote-agent-client/domains/chart.d.ts +21 -0
- package/dist/remote-agent-client/domains/chart.js +39 -0
- package/dist/remote-agent-client/domains/collection-chart.d.ts +19 -0
- package/dist/remote-agent-client/domains/collection-chart.js +40 -0
- package/dist/remote-agent-client/domains/collection.d.ts +26 -0
- package/dist/remote-agent-client/domains/collection.js +109 -0
- package/dist/remote-agent-client/domains/relation.d.ts +11 -0
- package/dist/remote-agent-client/domains/relation.js +23 -0
- package/dist/remote-agent-client/domains/remote-agent-client.d.ts +41 -0
- package/dist/remote-agent-client/domains/remote-agent-client.js +43 -0
- package/dist/remote-agent-client/domains/segment.d.ts +14 -0
- package/dist/remote-agent-client/domains/segment.js +46 -0
- package/dist/remote-agent-client/http-requester.d.ts +30 -0
- package/dist/remote-agent-client/http-requester.js +67 -0
- package/dist/remote-agent-client/index.d.ts +10 -0
- package/dist/remote-agent-client/index.js +18 -0
- package/dist/remote-agent-client/query-serializer.d.ts +7 -0
- package/dist/remote-agent-client/query-serializer.js +34 -0
- package/dist/remote-agent-client/types.d.ts +25 -0
- package/dist/remote-agent-client/types.js +3 -0
- package/dist/units/add-action.d.ts +16 -0
- package/dist/units/add-action.js +70 -0
- package/dist/units/add-field.d.ts +3 -0
- package/dist/units/add-field.js +18 -0
- package/dist/units/add-hook.d.ts +3 -0
- package/dist/units/add-hook.js +18 -0
- package/dist/units/import-field.d.ts +3 -0
- package/dist/units/import-field.js +18 -0
- package/dist/units/index.d.ts +9 -0
- package/dist/units/index.js +25 -0
- package/dist/units/many-to-one-relation.d.ts +3 -0
- package/dist/units/many-to-one-relation.js +18 -0
- package/dist/units/replace-search.d.ts +3 -0
- package/dist/units/replace-search.js +18 -0
- package/dist/units/types.d.ts +34 -0
- package/dist/units/types.js +3 -0
- package/dist/units/use-plugin.d.ts +3 -0
- package/dist/units/use-plugin.js +18 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# @forestadmin/agent-testing
|
|
2
|
+
|
|
3
|
+
Testing utilities for Forest Admin agents. Test your customizations (actions, hooks, segments, charts) locally without connecting to Forest Admin servers.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install --save-dev @forestadmin/agent-testing
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import {
|
|
15
|
+
createAgentTestClient,
|
|
16
|
+
createForestServerSandbox,
|
|
17
|
+
} from '@forestadmin/agent-testing';
|
|
18
|
+
|
|
19
|
+
describe('My Agent', () => {
|
|
20
|
+
let sandbox, client;
|
|
21
|
+
|
|
22
|
+
beforeAll(async () => {
|
|
23
|
+
// 1. Start a local sandbox that replaces Forest Admin servers
|
|
24
|
+
sandbox = await createForestServerSandbox(3001);
|
|
25
|
+
|
|
26
|
+
// 2. Start your agent pointing to the sandbox
|
|
27
|
+
// FOREST_SERVER_URL=http://localhost:3001 node your-agent.js
|
|
28
|
+
|
|
29
|
+
// 3. Connect the test client
|
|
30
|
+
client = await createAgentTestClient({
|
|
31
|
+
serverUrl: 'http://localhost:3001',
|
|
32
|
+
agentUrl: 'http://localhost:3310',
|
|
33
|
+
agentSchemaPath: './.forestadmin-schema.json',
|
|
34
|
+
agentForestEnvSecret: process.env.FOREST_ENV_SECRET,
|
|
35
|
+
agentForestAuthSecret: process.env.FOREST_AUTH_SECRET,
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
afterAll(async () => {
|
|
40
|
+
await sandbox?.close();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should list users', async () => {
|
|
44
|
+
const users = await client.collection('users').list();
|
|
45
|
+
expect(users.length).toBeGreaterThan(0);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## License
|
|
51
|
+
|
|
52
|
+
GPL-3.0
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./integrations"), exports);
|
|
18
|
+
__exportStar(require("./units"), exports);
|
|
19
|
+
__exportStar(require("./remote-agent-client"), exports);
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGlEQUErQjtBQUMvQiwwQ0FBd0I7QUFDeEIsd0RBQXNDIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default class Benchmark {
|
|
2
|
+
private _times;
|
|
3
|
+
times(times: number): this;
|
|
4
|
+
run(func: () => Promise<void>): Promise<{
|
|
5
|
+
durations: number[];
|
|
6
|
+
times: number;
|
|
7
|
+
average: number;
|
|
8
|
+
min: number;
|
|
9
|
+
max: number;
|
|
10
|
+
total: number;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=benchmark.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const node_perf_hooks_1 = require("node:perf_hooks");
|
|
4
|
+
class Benchmark {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._times = 1;
|
|
7
|
+
}
|
|
8
|
+
times(times) {
|
|
9
|
+
if (times < 1)
|
|
10
|
+
throw new Error('Times must be greater than 0');
|
|
11
|
+
this._times = times;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
async run(func) {
|
|
15
|
+
const durations = [];
|
|
16
|
+
for (let i = 0; i < this._times; i += 1) {
|
|
17
|
+
// eslint-disable-next-line no-await-in-loop
|
|
18
|
+
const start = node_perf_hooks_1.performance.now();
|
|
19
|
+
// eslint-disable-next-line no-await-in-loop
|
|
20
|
+
await func();
|
|
21
|
+
const end = node_perf_hooks_1.performance.now();
|
|
22
|
+
const duration = end - start;
|
|
23
|
+
durations.push(duration);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
times: this._times,
|
|
27
|
+
durations,
|
|
28
|
+
average: durations.reduce((acc, curr) => acc + curr, 0) / this._times,
|
|
29
|
+
total: durations.reduce((acc, curr) => acc + curr, 0),
|
|
30
|
+
min: Math.min(...durations),
|
|
31
|
+
max: Math.max(...durations),
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.default = Benchmark;
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmVuY2htYXJrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludGVncmF0aW9ucy9iZW5jaG1hcmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxxREFBOEM7QUFFOUMsTUFBcUIsU0FBUztJQUE5QjtRQUNVLFdBQU0sR0FBRyxDQUFDLENBQUM7SUFzQ3JCLENBQUM7SUFwQ0MsS0FBSyxDQUFDLEtBQWE7UUFDakIsSUFBSSxLQUFLLEdBQUcsQ0FBQztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUVwQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLElBQXlCO1FBUWpDLE1BQU0sU0FBUyxHQUFhLEVBQUUsQ0FBQztRQUUvQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDeEMsNENBQTRDO1lBQzVDLE1BQU0sS0FBSyxHQUFHLDZCQUFXLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDaEMsNENBQTRDO1lBQzVDLE1BQU0sSUFBSSxFQUFFLENBQUM7WUFDYixNQUFNLEdBQUcsR0FBRyw2QkFBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO1lBQzlCLE1BQU0sUUFBUSxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7WUFDN0IsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMzQixDQUFDO1FBRUQsT0FBTztZQUNMLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTTtZQUNsQixTQUFTO1lBQ1QsT0FBTyxFQUFFLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNO1lBQ3JFLEtBQUssRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLElBQUksRUFBRSxDQUFDLENBQUM7WUFDckQsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUM7WUFDM0IsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxTQUFTLENBQUM7U0FDNUIsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQXZDRCw0QkF1Q0MifQ==
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ChartHandlerInterface, ContextVariablesInstantiatorInterface, ForestAdminClient, IpWhitelistConfiguration, ModelCustomizationService, UserInfo } from '@forestadmin/forestadmin-client';
|
|
2
|
+
export type UserInfoToSupportAnyAgents = UserInfo & {
|
|
3
|
+
roleId: number;
|
|
4
|
+
rendering_id: number;
|
|
5
|
+
first_name: string;
|
|
6
|
+
last_name: string;
|
|
7
|
+
permission_level: string;
|
|
8
|
+
role_id: number;
|
|
9
|
+
};
|
|
10
|
+
export declare const CURRENT_USER: UserInfoToSupportAnyAgents;
|
|
11
|
+
export default class ForestAdminClientMock implements ForestAdminClient {
|
|
12
|
+
readonly chartHandler: ChartHandlerInterface;
|
|
13
|
+
readonly contextVariablesInstantiator: ContextVariablesInstantiatorInterface;
|
|
14
|
+
readonly modelCustomizationService: ModelCustomizationService;
|
|
15
|
+
readonly mcpServerConfigService: ForestAdminClient['mcpServerConfigService'];
|
|
16
|
+
readonly permissionService: any;
|
|
17
|
+
readonly authService: any;
|
|
18
|
+
constructor();
|
|
19
|
+
close(): void;
|
|
20
|
+
getIpWhitelistConfiguration(): Promise<IpWhitelistConfiguration>;
|
|
21
|
+
getScope(): Promise<undefined>;
|
|
22
|
+
markScopesAsUpdated(): void;
|
|
23
|
+
onRefreshCustomizations(): void;
|
|
24
|
+
postSchema(): Promise<boolean>;
|
|
25
|
+
subscribeToServerEvents(): Promise<void>;
|
|
26
|
+
verifySignedActionParameters<TSignedParameters>(): TSignedParameters;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=forest-admin-client-mock.d.ts.map
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CURRENT_USER = void 0;
|
|
4
|
+
exports.CURRENT_USER = {
|
|
5
|
+
id: 1,
|
|
6
|
+
email: 'forest@forest.com',
|
|
7
|
+
team: 'admin',
|
|
8
|
+
rendering_id: 1,
|
|
9
|
+
renderingId: 1,
|
|
10
|
+
first_name: 'forest',
|
|
11
|
+
firstName: 'forest',
|
|
12
|
+
last_name: 'admin',
|
|
13
|
+
lastName: 'admin',
|
|
14
|
+
role: 'Admin',
|
|
15
|
+
permissionLevel: 'admin',
|
|
16
|
+
permission_level: 'admin',
|
|
17
|
+
tags: {},
|
|
18
|
+
roleId: 1,
|
|
19
|
+
role_id: 1,
|
|
20
|
+
};
|
|
21
|
+
class ForestAdminClientMock {
|
|
22
|
+
constructor() {
|
|
23
|
+
this.contextVariablesInstantiator = {
|
|
24
|
+
buildContextVariables: () => ({}), // TODO: return actual context variables
|
|
25
|
+
};
|
|
26
|
+
this.mcpServerConfigService = {
|
|
27
|
+
getConfiguration: () => Promise.resolve({ configs: {} }),
|
|
28
|
+
};
|
|
29
|
+
this.permissionService = {
|
|
30
|
+
canOnCollection: () => true,
|
|
31
|
+
canTriggerCustomAction: () => true,
|
|
32
|
+
doesTriggerCustomActionRequiresApproval: () => false,
|
|
33
|
+
canApproveCustomAction: () => true,
|
|
34
|
+
canRequestCustomActionParameters: () => true,
|
|
35
|
+
canExecuteChart: () => true,
|
|
36
|
+
canExecuteSegmentQuery: () => true,
|
|
37
|
+
getConditionalTriggerCondition: () => undefined,
|
|
38
|
+
getConditionalRequiresApprovalCondition: () => undefined,
|
|
39
|
+
getConditionalApproveCondition: () => undefined,
|
|
40
|
+
getConditionalApproveConditions: () => undefined,
|
|
41
|
+
getRoleIdsAllowedToApproveWithoutConditions: () => undefined,
|
|
42
|
+
};
|
|
43
|
+
this.authService = {
|
|
44
|
+
init: () => Promise.resolve(undefined),
|
|
45
|
+
getUserInfo: () => Promise.resolve(exports.CURRENT_USER),
|
|
46
|
+
generateAuthorizationUrl: () => Promise.resolve(undefined),
|
|
47
|
+
generateTokens: () => Promise.resolve({ accessToken: 'AUTH-TOKEN' }),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
close() {
|
|
51
|
+
// Do nothing
|
|
52
|
+
}
|
|
53
|
+
getIpWhitelistConfiguration() {
|
|
54
|
+
return Promise.resolve({ isFeatureEnabled: false, ipRules: [] });
|
|
55
|
+
}
|
|
56
|
+
getScope() {
|
|
57
|
+
return Promise.resolve(undefined);
|
|
58
|
+
}
|
|
59
|
+
markScopesAsUpdated() {
|
|
60
|
+
// Do nothing
|
|
61
|
+
}
|
|
62
|
+
onRefreshCustomizations() {
|
|
63
|
+
// Do nothing
|
|
64
|
+
}
|
|
65
|
+
postSchema() {
|
|
66
|
+
return Promise.resolve(true);
|
|
67
|
+
}
|
|
68
|
+
subscribeToServerEvents() {
|
|
69
|
+
return Promise.resolve();
|
|
70
|
+
}
|
|
71
|
+
verifySignedActionParameters() {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.default = ForestAdminClientMock;
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZXN0LWFkbWluLWNsaWVudC1tb2NrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludGVncmF0aW9ucy9mb3Jlc3QtYWRtaW4tY2xpZW50LW1vY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBa0JhLFFBQUEsWUFBWSxHQUErQjtJQUN0RCxFQUFFLEVBQUUsQ0FBQztJQUNMLEtBQUssRUFBRSxtQkFBbUI7SUFDMUIsSUFBSSxFQUFFLE9BQU87SUFFYixZQUFZLEVBQUUsQ0FBQztJQUNmLFdBQVcsRUFBRSxDQUFDO0lBRWQsVUFBVSxFQUFFLFFBQVE7SUFDcEIsU0FBUyxFQUFFLFFBQVE7SUFFbkIsU0FBUyxFQUFFLE9BQU87SUFDbEIsUUFBUSxFQUFFLE9BQU87SUFFakIsSUFBSSxFQUFFLE9BQU87SUFFYixlQUFlLEVBQUUsT0FBTztJQUN4QixnQkFBZ0IsRUFBRSxPQUFPO0lBRXpCLElBQUksRUFBRSxFQUFFO0lBRVIsTUFBTSxFQUFFLENBQUM7SUFDVCxPQUFPLEVBQUUsQ0FBQztDQUNYLENBQUM7QUFFRixNQUFxQixxQkFBcUI7SUFjeEM7UUFaUyxpQ0FBNEIsR0FBMEM7WUFDN0UscUJBQXFCLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFVLENBQUEsRUFBRSx3Q0FBd0M7U0FDbkYsQ0FBQztRQUdPLDJCQUFzQixHQUFnRDtZQUM3RSxnQkFBZ0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDO1NBQ3pELENBQUM7UUFNQSxJQUFJLENBQUMsaUJBQWlCLEdBQUc7WUFDdkIsZUFBZSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUk7WUFDM0Isc0JBQXNCLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSTtZQUNsQyx1Q0FBdUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLO1lBQ3BELHNCQUFzQixFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUk7WUFDbEMsZ0NBQWdDLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSTtZQUM1QyxlQUFlLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBSTtZQUMzQixzQkFBc0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxJQUFJO1lBQ2xDLDhCQUE4QixFQUFFLEdBQUcsRUFBRSxDQUFDLFNBQVM7WUFDL0MsdUNBQXVDLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUztZQUN4RCw4QkFBOEIsRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTO1lBQy9DLCtCQUErQixFQUFFLEdBQUcsRUFBRSxDQUFDLFNBQVM7WUFDaEQsMkNBQTJDLEVBQUUsR0FBRyxFQUFFLENBQUMsU0FBUztTQUM3RCxDQUFDO1FBQ0YsSUFBSSxDQUFDLFdBQVcsR0FBRztZQUNqQixJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDdEMsV0FBVyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQVcsb0JBQVksQ0FBQztZQUMxRCx3QkFBd0IsRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQztZQUMxRCxjQUFjLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsQ0FBQztTQUNyRSxDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUs7UUFDSCxhQUFhO0lBQ2YsQ0FBQztJQUVELDJCQUEyQjtRQUN6QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUVELFFBQVE7UUFDTixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQVksU0FBUyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELG1CQUFtQjtRQUNqQixhQUFhO0lBQ2YsQ0FBQztJQUVELHVCQUF1QjtRQUNyQixhQUFhO0lBQ2YsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVELHVCQUF1QjtRQUNyQixPQUFPLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsNEJBQTRCO1FBQzFCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7Q0FDRjtBQXBFRCx3Q0FvRUMifQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export default class ForestServerSandbox {
|
|
2
|
+
private fakeForestServer;
|
|
3
|
+
private readonly agentSchemaCache;
|
|
4
|
+
private readonly permissionsOverrideCache;
|
|
5
|
+
port: number;
|
|
6
|
+
constructor(port: number);
|
|
7
|
+
createServer(): Promise<this>;
|
|
8
|
+
stop(): Promise<void>;
|
|
9
|
+
private routes;
|
|
10
|
+
private transformForestSchemaToEnvironmentPermissionsV4Remote;
|
|
11
|
+
private getCollectionCrudPermissions;
|
|
12
|
+
private getCollectionActionPermissions;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=forest-server-sandbox.d.ts.map
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
7
|
+
const forest_admin_client_mock_1 = require("./forest-admin-client-mock");
|
|
8
|
+
class ForestServerSandbox {
|
|
9
|
+
constructor(port) {
|
|
10
|
+
// cache the agent schema for every client to avoid to start several servers when testing agent.
|
|
11
|
+
this.agentSchemaCache = new Map();
|
|
12
|
+
// allow to override some permissions directly from the agent
|
|
13
|
+
this.permissionsOverrideCache = new Map();
|
|
14
|
+
this.port = port;
|
|
15
|
+
}
|
|
16
|
+
async createServer() {
|
|
17
|
+
const server = node_http_1.default.createServer(this.routes.bind(this));
|
|
18
|
+
this.fakeForestServer = await new Promise((resolve, reject) => {
|
|
19
|
+
server.listen(this.port, () => resolve(server));
|
|
20
|
+
server.on('error', error => {
|
|
21
|
+
console.error('Server error:', error);
|
|
22
|
+
reject(error);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
this.port = this.fakeForestServer.address().port;
|
|
26
|
+
// eslint-disable-next-line no-console
|
|
27
|
+
console.log(`Server listening on port ${this.port}`);
|
|
28
|
+
return this;
|
|
29
|
+
}
|
|
30
|
+
async stop() {
|
|
31
|
+
await new Promise((resolve, reject) => {
|
|
32
|
+
this.fakeForestServer.close(error => {
|
|
33
|
+
if (error)
|
|
34
|
+
reject(error);
|
|
35
|
+
else
|
|
36
|
+
resolve(null);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
routes(req, res) {
|
|
41
|
+
const agentSchemaCacheIdentifier = req.headers['forest-secret-key'];
|
|
42
|
+
const sendResponse = (statusCode, data) => {
|
|
43
|
+
if (!res.headersSent) {
|
|
44
|
+
res.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
45
|
+
}
|
|
46
|
+
if (!res.writableEnded) {
|
|
47
|
+
res.end(data ? JSON.stringify(data) : undefined);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
try {
|
|
51
|
+
switch (req.url) {
|
|
52
|
+
case '/agent-schema': {
|
|
53
|
+
let data = '';
|
|
54
|
+
req.on('data', chunk => {
|
|
55
|
+
data += chunk;
|
|
56
|
+
});
|
|
57
|
+
req.on('end', () => {
|
|
58
|
+
this.agentSchemaCache.set(agentSchemaCacheIdentifier, JSON.parse(data));
|
|
59
|
+
sendResponse(200);
|
|
60
|
+
});
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case '/permission-override': {
|
|
64
|
+
let data = '';
|
|
65
|
+
req.on('data', chunk => {
|
|
66
|
+
data += chunk;
|
|
67
|
+
});
|
|
68
|
+
req.on('end', () => {
|
|
69
|
+
this.permissionsOverrideCache.set(agentSchemaCacheIdentifier, JSON.parse(data));
|
|
70
|
+
sendResponse(200);
|
|
71
|
+
});
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case '/liana/v4/subscribe-to-events':
|
|
75
|
+
sendResponse(200);
|
|
76
|
+
break;
|
|
77
|
+
case '/liana/v1/ip-whitelist-rules':
|
|
78
|
+
sendResponse(200, { data: { attributes: { use_ip_whitelist: false, rules: [] } } });
|
|
79
|
+
break;
|
|
80
|
+
case '/liana/v4/permissions/environment': {
|
|
81
|
+
try {
|
|
82
|
+
const permissionsV4 = this.transformForestSchemaToEnvironmentPermissionsV4Remote(this.agentSchemaCache.get(agentSchemaCacheIdentifier), this.permissionsOverrideCache.get(agentSchemaCacheIdentifier));
|
|
83
|
+
sendResponse(200, permissionsV4);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
sendResponse(400, { error: 'Provide a valid schema path' });
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
case '/liana/v4/permissions/users':
|
|
91
|
+
sendResponse(200, [forest_admin_client_mock_1.CURRENT_USER]);
|
|
92
|
+
break;
|
|
93
|
+
case '/forest/apimaps/hashcheck':
|
|
94
|
+
sendResponse(200, { sendSchema: false });
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
if (req.url?.startsWith('/liana/v4/permissions/renderings/')) {
|
|
98
|
+
sendResponse(200, { team: {}, collections: {}, stats: [] });
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
sendResponse(404, { error: 'Not Found' });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
console.error('Error handling request:', error);
|
|
107
|
+
sendResponse(500, { error: 'Internal Server Error' });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
transformForestSchemaToEnvironmentPermissionsV4Remote(schema, permissionsOverride) {
|
|
111
|
+
const collections = {};
|
|
112
|
+
schema.collections.forEach(collection => {
|
|
113
|
+
const actionPermissions = {};
|
|
114
|
+
collection.actions.forEach(action => {
|
|
115
|
+
actionPermissions[action.name] = this.getCollectionActionPermissions(permissionsOverride?.[collection.name]?.actions?.[action.name] || {});
|
|
116
|
+
});
|
|
117
|
+
collections[collection.name] = {
|
|
118
|
+
collection: this.getCollectionCrudPermissions(permissionsOverride?.[collection.name]?.collection || {}),
|
|
119
|
+
actions: actionPermissions,
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
return { collections };
|
|
123
|
+
}
|
|
124
|
+
getCollectionCrudPermissions(override) {
|
|
125
|
+
return {
|
|
126
|
+
browseEnabled: { roles: [override.browseEnabled === false ? 0 : 1] },
|
|
127
|
+
deleteEnabled: { roles: [override.deleteEnabled === false ? 0 : 1] },
|
|
128
|
+
editEnabled: { roles: [override.editEnabled === false ? 0 : 1] },
|
|
129
|
+
exportEnabled: { roles: [override.exportEnabled === false ? 0 : 1] },
|
|
130
|
+
addEnabled: { roles: [override.addEnabled === false ? 0 : 1] },
|
|
131
|
+
readEnabled: { roles: [override.readEnabled === false ? 0 : 1] },
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
getCollectionActionPermissions(override) {
|
|
135
|
+
return {
|
|
136
|
+
approvalRequired: { roles: [override.approvalRequired === true ? 1 : 0] },
|
|
137
|
+
userApprovalEnabled: { roles: [override.userApprovalEnabled === false ? 0 : 1] },
|
|
138
|
+
selfApprovalEnabled: { roles: [override.selfApprovalEnabled === false ? 0 : 1] },
|
|
139
|
+
triggerEnabled: { roles: [override.triggerEnabled === false ? 0 : 1] },
|
|
140
|
+
triggerConditions: override.triggerConditions
|
|
141
|
+
? [{ roleId: 1, filter: override.triggerConditions }]
|
|
142
|
+
: [],
|
|
143
|
+
userApprovalConditions: override.userApprovalConditions
|
|
144
|
+
? [{ roleId: 1, filter: override.userApprovalConditions }]
|
|
145
|
+
: [],
|
|
146
|
+
approvalRequiredConditions: override.approvalRequiredConditions
|
|
147
|
+
? [{ roleId: 1, filter: override.approvalRequiredConditions }]
|
|
148
|
+
: [],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.default = ForestServerSandbox;
|
|
153
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9yZXN0LXNlcnZlci1zYW5kYm94LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludGVncmF0aW9ucy9mb3Jlc3Qtc2VydmVyLXNhbmRib3gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFNQSwwREFBNkI7QUFFN0IseUVBQTBEO0FBTzFELE1BQXFCLG1CQUFtQjtJQVd0QyxZQUFZLElBQVk7UUFSeEIsZ0dBQWdHO1FBQy9FLHFCQUFnQixHQUE4QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBRXpFLDZEQUE2RDtRQUM1Qyw2QkFBd0IsR0FBcUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUt0RixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQztJQUNuQixDQUFDO0lBRUQsS0FBSyxDQUFDLFlBQVk7UUFDaEIsTUFBTSxNQUFNLEdBQUcsbUJBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUV6RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUM1RCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDaEQsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLEVBQUU7Z0JBQ3pCLE9BQU8sQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUN0QyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxJQUFJLEdBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sRUFBdUIsQ0FBQyxJQUFJLENBQUM7UUFFdkUsc0NBQXNDO1FBQ3RDLE9BQU8sQ0FBQyxHQUFHLENBQUMsNEJBQTRCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBRXJELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJO1FBQ1IsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNwQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUNsQyxJQUFJLEtBQUs7b0JBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDOztvQkFDcEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sTUFBTSxDQUFDLEdBQXlCLEVBQUUsR0FBd0I7UUFDaEUsTUFBTSwwQkFBMEIsR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFXLENBQUM7UUFFOUUsTUFBTSxZQUFZLEdBQUcsQ0FBQyxVQUFrQixFQUFFLElBQWEsRUFBRSxFQUFFO1lBQ3pELElBQUksQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ3JCLEdBQUcsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLEVBQUUsY0FBYyxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQztZQUNwRSxDQUFDO1lBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDdkIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQ25ELENBQUM7UUFDSCxDQUFDLENBQUM7UUFFRixJQUFJLENBQUM7WUFDSCxRQUFRLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztnQkFDaEIsS0FBSyxlQUFlLENBQUMsQ0FBQyxDQUFDO29CQUNyQixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ2QsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUU7d0JBQ3JCLElBQUksSUFBSSxLQUFLLENBQUM7b0JBQ2hCLENBQUMsQ0FBQyxDQUFDO29CQUNILEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTt3QkFDakIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEdBQUcsQ0FBQywwQkFBMEIsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ3hFLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDcEIsQ0FBQyxDQUFDLENBQUM7b0JBQ0gsTUFBTTtnQkFDUixDQUFDO2dCQUVELEtBQUssc0JBQXNCLENBQUMsQ0FBQyxDQUFDO29CQUM1QixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7b0JBQ2QsR0FBRyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUU7d0JBQ3JCLElBQUksSUFBSSxLQUFLLENBQUM7b0JBQ2hCLENBQUMsQ0FBQyxDQUFDO29CQUNILEdBQUcsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLEdBQUcsRUFBRTt3QkFDakIsSUFBSSxDQUFDLHdCQUF3QixDQUFDLEdBQUcsQ0FBQywwQkFBMEIsRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7d0JBQ2hGLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztvQkFDcEIsQ0FBQyxDQUFDLENBQUM7b0JBQ0gsTUFBTTtnQkFDUixDQUFDO2dCQUVELEtBQUssK0JBQStCO29CQUNsQyxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ2xCLE1BQU07Z0JBRVIsS0FBSyw4QkFBOEI7b0JBQ2pDLFlBQVksQ0FBQyxHQUFHLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxVQUFVLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUNwRixNQUFNO2dCQUVSLEtBQUssbUNBQW1DLENBQUMsQ0FBQyxDQUFDO29CQUN6QyxJQUFJLENBQUM7d0JBQ0gsTUFBTSxhQUFhLEdBQUcsSUFBSSxDQUFDLHFEQUFxRCxDQUM5RSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsR0FBRyxDQUFDLDBCQUEwQixDQUFDLEVBQ3JELElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsMEJBQTBCLENBQUMsQ0FDOUQsQ0FBQzt3QkFFRixZQUFZLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFDO29CQUNuQyxDQUFDO29CQUFDLE1BQU0sQ0FBQzt3QkFDUCxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsS0FBSyxFQUFFLDZCQUE2QixFQUFFLENBQUMsQ0FBQztvQkFDOUQsQ0FBQztvQkFFRCxNQUFNO2dCQUNSLENBQUM7Z0JBRUQsS0FBSyw2QkFBNkI7b0JBQ2hDLFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQyx1Q0FBWSxDQUFDLENBQUMsQ0FBQztvQkFDbEMsTUFBTTtnQkFFUixLQUFLLDJCQUEyQjtvQkFDOUIsWUFBWSxDQUFDLEdBQUcsRUFBRSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO29CQUN6QyxNQUFNO2dCQUVSO29CQUNFLElBQUksR0FBRyxDQUFDLEdBQUcsRUFBRSxVQUFVLENBQUMsbUNBQW1DLENBQUMsRUFBRSxDQUFDO3dCQUM3RCxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUM5RCxDQUFDO3lCQUFNLENBQUM7d0JBQ04sWUFBWSxDQUFDLEdBQUcsRUFBRSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO29CQUM1QyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsT0FBTyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNoRCxZQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsS0FBSyxFQUFFLHVCQUF1QixFQUFFLENBQUMsQ0FBQztRQUN4RCxDQUFDO0lBQ0gsQ0FBQztJQUVPLHFEQUFxRCxDQUMzRCxNQUFvQixFQUNwQixtQkFBeUM7UUFFekMsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFDO1FBRXZCLE1BQU0sQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFO1lBQ3RDLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxDQUFDO1lBRTdCLFVBQVUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFO2dCQUNsQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLDhCQUE4QixDQUNsRSxtQkFBbUIsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUNyRSxDQUFDO1lBQ0osQ0FBQyxDQUFDLENBQUM7WUFFSCxXQUFXLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHO2dCQUM3QixVQUFVLEVBQUUsSUFBSSxDQUFDLDRCQUE0QixDQUMzQyxtQkFBbUIsRUFBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLElBQUksRUFBRSxDQUN6RDtnQkFDRCxPQUFPLEVBQUUsaUJBQWlCO2FBQzNCLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRU8sNEJBQTRCLENBQ2xDLFFBQXVDO1FBRXZDLE9BQU87WUFDTCxhQUFhLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsYUFBYSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNwRSxhQUFhLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsYUFBYSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNwRSxXQUFXLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNoRSxhQUFhLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsYUFBYSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNwRSxVQUFVLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUM5RCxXQUFXLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsV0FBVyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtTQUNqRSxDQUFDO0lBQ0osQ0FBQztJQUVPLDhCQUE4QixDQUNwQyxRQUF3QztRQUV4QyxPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ3pFLG1CQUFtQixFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLG1CQUFtQixLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNoRixtQkFBbUIsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDaEYsY0FBYyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLGNBQWMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7WUFDdEUsaUJBQWlCLEVBQUUsUUFBUSxDQUFDLGlCQUFpQjtnQkFDM0MsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxRQUFRLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztnQkFDckQsQ0FBQyxDQUFDLEVBQUU7WUFDTixzQkFBc0IsRUFBRSxRQUFRLENBQUMsc0JBQXNCO2dCQUNyRCxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2dCQUMxRCxDQUFDLENBQUMsRUFBRTtZQUNOLDBCQUEwQixFQUFFLFFBQVEsQ0FBQywwQkFBMEI7Z0JBQzdELENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxDQUFDLDBCQUEwQixFQUFFLENBQUM7Z0JBQzlELENBQUMsQ0FBQyxFQUFFO1NBQ1AsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQXhMRCxzQ0F3TEMifQ==
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TestableAgentOptions } from './types';
|
|
2
|
+
import HttpRequester from '../remote-agent-client/http-requester';
|
|
3
|
+
export declare function createHttpRequester(options: {
|
|
4
|
+
url: string;
|
|
5
|
+
authSecret: string;
|
|
6
|
+
prefix?: string;
|
|
7
|
+
}, agentOptions: TestableAgentOptions): HttpRequester;
|
|
8
|
+
//# sourceMappingURL=http-requester-mock.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createHttpRequester = createHttpRequester;
|
|
7
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
8
|
+
const forest_admin_client_mock_1 = require("./forest-admin-client-mock");
|
|
9
|
+
const http_requester_1 = __importDefault(require("../remote-agent-client/http-requester"));
|
|
10
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
11
|
+
function createHttpRequester(options, agentOptions) {
|
|
12
|
+
const token = jsonwebtoken_1.default.sign(forest_admin_client_mock_1.CURRENT_USER, options.authSecret, { expiresIn: '1 hours' });
|
|
13
|
+
return new http_requester_1.default(token, options, agentOptions);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1yZXF1ZXN0ZXItbW9jay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnRlZ3JhdGlvbnMvaHR0cC1yZXF1ZXN0ZXItbW9jay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQU9BLGtEQVdDO0FBbEJELGdFQUF3QztBQUV4Qyx5RUFBMEQ7QUFFMUQsMkZBQWtFO0FBRWxFLHdEQUF3RDtBQUN4RCxTQUFnQixtQkFBbUIsQ0FDakMsT0FJQyxFQUNELFlBQWtDO0lBRWxDLE1BQU0sS0FBSyxHQUFHLHNCQUFZLENBQUMsSUFBSSxDQUFDLHVDQUFZLEVBQUUsT0FBTyxDQUFDLFVBQVUsRUFBRSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBRTVGLE9BQU8sSUFBSSx3QkFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUM7QUFDekQsQ0FBQyJ9
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Agent } from '@forestadmin/agent';
|
|
2
|
+
import { TSchema } from '@forestadmin/datasource-customizer';
|
|
3
|
+
import ForestServerSandbox from './forest-server-sandbox';
|
|
4
|
+
import SchemaPathManager from './schema-path-manager';
|
|
5
|
+
import TestableAgent from './testable-agent';
|
|
6
|
+
import TestableAgentBase from './testable-agent-base';
|
|
7
|
+
import { TestableAgentOptions } from './types';
|
|
8
|
+
export { AgentOptions, Agent } from '@forestadmin/agent';
|
|
9
|
+
export * from './types';
|
|
10
|
+
export { SchemaPathManager, ForestServerSandbox, TestableAgent };
|
|
11
|
+
export type ForestAgentClient = TestableAgentBase;
|
|
12
|
+
/**
|
|
13
|
+
* Create a forest server sandbox
|
|
14
|
+
* It is useful to test the agent if you use the createForestAgentClient way to test your agent
|
|
15
|
+
* @param port
|
|
16
|
+
*/
|
|
17
|
+
export declare function createForestServerSandbox(port: number): Promise<ForestServerSandbox>;
|
|
18
|
+
/**
|
|
19
|
+
* Create a forest client to test your agent customizations
|
|
20
|
+
* by sending requests to the agent like the frontend does.
|
|
21
|
+
* With this client, you should start your agent by yourself.
|
|
22
|
+
* You can test any agent with this client (python, ruby, nodeJs, etc.)
|
|
23
|
+
* @param options
|
|
24
|
+
*/
|
|
25
|
+
export declare function createForestAgentClient(options: {
|
|
26
|
+
agentForestEnvSecret: string;
|
|
27
|
+
agentForestAuthSecret: string;
|
|
28
|
+
agentUrl: string;
|
|
29
|
+
serverUrl: string;
|
|
30
|
+
agentSchemaPath: string;
|
|
31
|
+
}): Promise<ForestAgentClient>;
|
|
32
|
+
/**
|
|
33
|
+
* Create a testable agent
|
|
34
|
+
* You can test your agentNodejs customizations by injecting your customizations.
|
|
35
|
+
* It will start the agent for you. You don't need to start the agent by yourself and a server.
|
|
36
|
+
* It's not compatible with the createForestAgentClient & createForestServerSandbox way.
|
|
37
|
+
* It is recommended to user createForestAgentClient & createForestServerSandbox to test your agent.
|
|
38
|
+
*
|
|
39
|
+
* @param customizer
|
|
40
|
+
* @param options
|
|
41
|
+
*/
|
|
42
|
+
export declare function createTestableAgent<TypingsSchema extends TSchema = TSchema>(customizer: (agent: Agent<TypingsSchema>) => void, options?: TestableAgentOptions): Promise<TestableAgent<TypingsSchema>>;
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
17
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.TestableAgent = exports.ForestServerSandbox = exports.SchemaPathManager = exports.Agent = void 0;
|
|
21
|
+
exports.createForestServerSandbox = createForestServerSandbox;
|
|
22
|
+
exports.createForestAgentClient = createForestAgentClient;
|
|
23
|
+
exports.createTestableAgent = createTestableAgent;
|
|
24
|
+
const agent_1 = require("@forestadmin/agent");
|
|
25
|
+
const fs_1 = __importDefault(require("fs"));
|
|
26
|
+
const superagent_1 = __importDefault(require("superagent"));
|
|
27
|
+
const forest_admin_client_mock_1 = __importDefault(require("./forest-admin-client-mock"));
|
|
28
|
+
const forest_server_sandbox_1 = __importDefault(require("./forest-server-sandbox"));
|
|
29
|
+
exports.ForestServerSandbox = forest_server_sandbox_1.default;
|
|
30
|
+
const http_requester_mock_1 = require("./http-requester-mock");
|
|
31
|
+
const schema_converter_1 = __importDefault(require("./schema-converter"));
|
|
32
|
+
const schema_path_manager_1 = __importDefault(require("./schema-path-manager"));
|
|
33
|
+
exports.SchemaPathManager = schema_path_manager_1.default;
|
|
34
|
+
const testable_agent_1 = __importDefault(require("./testable-agent"));
|
|
35
|
+
exports.TestableAgent = testable_agent_1.default;
|
|
36
|
+
const testable_agent_base_1 = __importDefault(require("./testable-agent-base"));
|
|
37
|
+
var agent_2 = require("@forestadmin/agent");
|
|
38
|
+
Object.defineProperty(exports, "Agent", { enumerable: true, get: function () { return agent_2.Agent; } });
|
|
39
|
+
__exportStar(require("./types"), exports);
|
|
40
|
+
/**
|
|
41
|
+
* Create a forest server sandbox
|
|
42
|
+
* It is useful to test the agent if you use the createForestAgentClient way to test your agent
|
|
43
|
+
* @param port
|
|
44
|
+
*/
|
|
45
|
+
async function createForestServerSandbox(port) {
|
|
46
|
+
return new forest_server_sandbox_1.default(port).createServer();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a forest client to test your agent customizations
|
|
50
|
+
* by sending requests to the agent like the frontend does.
|
|
51
|
+
* With this client, you should start your agent by yourself.
|
|
52
|
+
* You can test any agent with this client (python, ruby, nodeJs, etc.)
|
|
53
|
+
* @param options
|
|
54
|
+
*/
|
|
55
|
+
async function createForestAgentClient(options) {
|
|
56
|
+
const { serverUrl, agentUrl, agentSchemaPath } = options;
|
|
57
|
+
let schema;
|
|
58
|
+
try {
|
|
59
|
+
schema = JSON.parse(fs_1.default.readFileSync(agentSchemaPath, { encoding: 'utf-8' }));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
throw new Error('Provide a right schema path');
|
|
63
|
+
}
|
|
64
|
+
// send the schema to the server to allow the server to build fake answers
|
|
65
|
+
await superagent_1.default
|
|
66
|
+
.post(`${serverUrl}/agent-schema`)
|
|
67
|
+
.set('forest-secret-key', options.agentForestEnvSecret)
|
|
68
|
+
.send(schema);
|
|
69
|
+
const httpRequester = (0, http_requester_mock_1.createHttpRequester)({
|
|
70
|
+
authSecret: options.agentForestAuthSecret,
|
|
71
|
+
url: agentUrl,
|
|
72
|
+
}, {
|
|
73
|
+
envSecret: options.agentForestEnvSecret,
|
|
74
|
+
authSecret: options.agentForestAuthSecret,
|
|
75
|
+
isProduction: false,
|
|
76
|
+
});
|
|
77
|
+
const overridePermissions = async (permissions) => {
|
|
78
|
+
await superagent_1.default
|
|
79
|
+
.post(`${serverUrl}/permission-override`)
|
|
80
|
+
.set('forest-secret-key', options.agentForestEnvSecret)
|
|
81
|
+
.send(permissions);
|
|
82
|
+
};
|
|
83
|
+
return new testable_agent_base_1.default({
|
|
84
|
+
actionEndpoints: schema_converter_1.default.extractActionEndpoints(schema),
|
|
85
|
+
httpRequester,
|
|
86
|
+
overridePermissions,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Create a testable agent
|
|
91
|
+
* You can test your agentNodejs customizations by injecting your customizations.
|
|
92
|
+
* It will start the agent for you. You don't need to start the agent by yourself and a server.
|
|
93
|
+
* It's not compatible with the createForestAgentClient & createForestServerSandbox way.
|
|
94
|
+
* It is recommended to user createForestAgentClient & createForestServerSandbox to test your agent.
|
|
95
|
+
*
|
|
96
|
+
* @param customizer
|
|
97
|
+
* @param options
|
|
98
|
+
*/
|
|
99
|
+
async function createTestableAgent(customizer, options) {
|
|
100
|
+
const agentOptions = {
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
102
|
+
logger: () => { },
|
|
103
|
+
schemaPath: schema_path_manager_1.default.generateTemporarySchemaPath(),
|
|
104
|
+
isProduction: false,
|
|
105
|
+
...(options || {}),
|
|
106
|
+
// 0 is a random port
|
|
107
|
+
port: options?.port || 0,
|
|
108
|
+
// Cast to any to avoid type mismatch when workspace has different forestadmin-client version
|
|
109
|
+
forestAdminClient: new forest_admin_client_mock_1.default(),
|
|
110
|
+
authSecret: options?.authSecret || 'b0bdf0a639c16bae8851dd24ee3d79ef0a352e957c5b86cb',
|
|
111
|
+
envSecret: options?.envSecret || 'ceba742f5bc73946b34da192816a4d7177b3233fee7769955c29c0e90fd584f2',
|
|
112
|
+
};
|
|
113
|
+
const agent = (0, agent_1.createAgent)(agentOptions);
|
|
114
|
+
if (!agent)
|
|
115
|
+
throw new Error('Agent is not defined');
|
|
116
|
+
customizer(agent);
|
|
117
|
+
return new testable_agent_1.default({ agent, agentOptions });
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW50ZWdyYXRpb25zL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkJBLDhEQUVDO0FBU0QsMERBOENDO0FBWUQsa0RBeUJDO0FBekhELDhDQUF3RDtBQUd4RCw0Q0FBb0I7QUFDcEIsNERBQW9DO0FBRXBDLDBGQUErRDtBQUMvRCxvRkFBMEQ7QUFZOUIsOEJBWnJCLCtCQUFtQixDQVlxQjtBQVgvQywrREFBNEQ7QUFDNUQsMEVBQWlEO0FBQ2pELGdGQUFzRDtBQVM3Qyw0QkFURiw2QkFBaUIsQ0FTRTtBQVIxQixzRUFBNkM7QUFRSSx3QkFSMUMsd0JBQWEsQ0FRMEM7QUFQOUQsZ0ZBQXNEO0FBSXRELDRDQUF5RDtBQUFsQyw4RkFBQSxLQUFLLE9BQUE7QUFDNUIsMENBQXdCO0FBS3hCOzs7O0dBSUc7QUFDSSxLQUFLLFVBQVUseUJBQXlCLENBQUMsSUFBWTtJQUMxRCxPQUFPLElBQUksK0JBQW1CLENBQUMsSUFBSSxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7QUFDdEQsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNJLEtBQUssVUFBVSx1QkFBdUIsQ0FBQyxPQU03QztJQUNDLE1BQU0sRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLGVBQWUsRUFBRSxHQUFHLE9BQU8sQ0FBQztJQUN6RCxJQUFJLE1BQW9CLENBQUM7SUFFekIsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBRSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQy9FLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1gsTUFBTSxJQUFJLEtBQUssQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFRCwwRUFBMEU7SUFDMUUsTUFBTSxvQkFBVTtTQUNiLElBQUksQ0FBQyxHQUFHLFNBQVMsZUFBZSxDQUFDO1NBQ2pDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsb0JBQW9CLENBQUM7U0FDdEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBRWhCLE1BQU0sYUFBYSxHQUFHLElBQUEseUNBQW1CLEVBQ3ZDO1FBQ0UsVUFBVSxFQUFFLE9BQU8sQ0FBQyxxQkFBcUI7UUFDekMsR0FBRyxFQUFFLFFBQVE7S0FDZCxFQUNEO1FBQ0UsU0FBUyxFQUFFLE9BQU8sQ0FBQyxvQkFBb0I7UUFDdkMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxxQkFBcUI7UUFDekMsWUFBWSxFQUFFLEtBQUs7S0FDcEIsQ0FDRixDQUFDO0lBRUYsTUFBTSxtQkFBbUIsR0FBRyxLQUFLLEVBQUUsV0FBZ0MsRUFBRSxFQUFFO1FBQ3JFLE1BQU0sb0JBQVU7YUFDYixJQUFJLENBQUMsR0FBRyxTQUFTLHNCQUFzQixDQUFDO2FBQ3hDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxPQUFPLENBQUMsb0JBQW9CLENBQUM7YUFDdEQsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3ZCLENBQUMsQ0FBQztJQUVGLE9BQU8sSUFBSSw2QkFBaUIsQ0FBQztRQUMzQixlQUFlLEVBQUUsMEJBQWUsQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUM7UUFDL0QsYUFBYTtRQUNiLG1CQUFtQjtLQUNwQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0ksS0FBSyxVQUFVLG1CQUFtQixDQUN2QyxVQUFpRCxFQUNqRCxPQUE4QjtJQUU5QixNQUFNLFlBQVksR0FBeUI7UUFDekMsZ0VBQWdFO1FBQ2hFLE1BQU0sRUFBRSxHQUFHLEVBQUUsR0FBRSxDQUFDO1FBQ2hCLFVBQVUsRUFBRSw2QkFBaUIsQ0FBQywyQkFBMkIsRUFBRTtRQUMzRCxZQUFZLEVBQUUsS0FBSztRQUNuQixHQUFHLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUNsQixxQkFBcUI7UUFDckIsSUFBSSxFQUFFLE9BQU8sRUFBRSxJQUFJLElBQUksQ0FBQztRQUN4Qiw2RkFBNkY7UUFDN0YsaUJBQWlCLEVBQUUsSUFBSSxrQ0FBcUIsRUFBUztRQUNyRCxVQUFVLEVBQUUsT0FBTyxFQUFFLFVBQVUsSUFBSSxrREFBa0Q7UUFDckYsU0FBUyxFQUNQLE9BQU8sRUFBRSxTQUFTLElBQUksa0VBQWtFO0tBQzNGLENBQUM7SUFFRixNQUFNLEtBQUssR0FBRyxJQUFBLG1CQUFXLEVBQWdCLFlBQVksQ0FBQyxDQUFDO0lBQ3ZELElBQUksQ0FBQyxLQUFLO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO0lBRXBELFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVsQixPQUFPLElBQUksd0JBQWEsQ0FBZ0IsRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztBQUNuRSxDQUFDIn0=
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ForestSchema } from '@forestadmin/forestadmin-client';
|
|
2
|
+
import { ActionEndpointsByCollection } from '../remote-agent-client/domains/action';
|
|
3
|
+
export default class SchemaConverter {
|
|
4
|
+
static extractActionEndpoints(schema: ForestSchema): ActionEndpointsByCollection;
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=schema-converter.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class SchemaConverter {
|
|
4
|
+
static extractActionEndpoints(schema) {
|
|
5
|
+
const actionEndpoints = {};
|
|
6
|
+
Object.values(schema.collections).forEach(c => {
|
|
7
|
+
actionEndpoints[c.name] = c.actions.reduce((acc, action) => ({
|
|
8
|
+
...acc,
|
|
9
|
+
[action.name]: { name: action.name, endpoint: action.endpoint },
|
|
10
|
+
}), {});
|
|
11
|
+
});
|
|
12
|
+
return actionEndpoints;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.default = SchemaConverter;
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLWNvbnZlcnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9pbnRlZ3JhdGlvbnMvc2NoZW1hLWNvbnZlcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUlBLE1BQXFCLGVBQWU7SUFDbEMsTUFBTSxDQUFDLHNCQUFzQixDQUFDLE1BQW9CO1FBQ2hELE1BQU0sZUFBZSxHQUFnQyxFQUFFLENBQUM7UUFDeEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzVDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQ3hDLENBQUMsR0FBRyxFQUFFLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztnQkFDaEIsR0FBRyxHQUFHO2dCQUNOLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUU7YUFDaEUsQ0FBQyxFQUNGLEVBQUUsQ0FDSCxDQUFDO1FBQ0osQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLGVBQWUsQ0FBQztJQUN6QixDQUFDO0NBQ0Y7QUFmRCxrQ0FlQyJ9
|