@forestadmin/agent 1.0.0-beta.1
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 +0 -0
- package/dist/agent/forestadmin-http-driver.d.ts +34 -0
- package/dist/agent/forestadmin-http-driver.js +73 -0
- package/dist/agent/routes/access/chart.d.ts +17 -0
- package/dist/agent/routes/access/chart.js +125 -0
- package/dist/agent/routes/access/count-related.d.ts +9 -0
- package/dist/agent/routes/access/count-related.js +24 -0
- package/dist/agent/routes/access/count.d.ts +9 -0
- package/dist/agent/routes/access/count.js +24 -0
- package/dist/agent/routes/access/csv-related.d.ts +9 -0
- package/dist/agent/routes/access/csv-related.js +33 -0
- package/dist/agent/routes/access/csv.d.ts +9 -0
- package/dist/agent/routes/access/csv.js +30 -0
- package/dist/agent/routes/access/get.d.ts +9 -0
- package/dist/agent/routes/access/get.js +28 -0
- package/dist/agent/routes/access/list-related.d.ts +9 -0
- package/dist/agent/routes/access/list-related.js +26 -0
- package/dist/agent/routes/access/list.d.ts +9 -0
- package/dist/agent/routes/access/list.js +23 -0
- package/dist/agent/routes/base-route.d.ts +14 -0
- package/dist/agent/routes/base-route.js +16 -0
- package/dist/agent/routes/collection-route.d.ts +12 -0
- package/dist/agent/routes/collection-route.js +20 -0
- package/dist/agent/routes/index.d.ts +30 -0
- package/dist/agent/routes/index.js +90 -0
- package/dist/agent/routes/modification/action.d.ts +17 -0
- package/dist/agent/routes/modification/action.js +103 -0
- package/dist/agent/routes/modification/associate-related.d.ts +12 -0
- package/dist/agent/routes/modification/associate-related.js +49 -0
- package/dist/agent/routes/modification/create.d.ts +14 -0
- package/dist/agent/routes/modification/create.js +81 -0
- package/dist/agent/routes/modification/delete.d.ts +11 -0
- package/dist/agent/routes/modification/delete.js +40 -0
- package/dist/agent/routes/modification/dissociate-delete-related.d.ts +20 -0
- package/dist/agent/routes/modification/dissociate-delete-related.js +88 -0
- package/dist/agent/routes/modification/update-relation.d.ts +11 -0
- package/dist/agent/routes/modification/update-relation.js +53 -0
- package/dist/agent/routes/modification/update.d.ts +9 -0
- package/dist/agent/routes/modification/update.js +29 -0
- package/dist/agent/routes/relation-route.d.ts +10 -0
- package/dist/agent/routes/relation-route.js +18 -0
- package/dist/agent/routes/security/authentication.d.ts +17 -0
- package/dist/agent/routes/security/authentication.js +86 -0
- package/dist/agent/routes/security/ip-whitelist.d.ts +14 -0
- package/dist/agent/routes/security/ip-whitelist.js +35 -0
- package/dist/agent/routes/security/scope-invalidation.d.ts +11 -0
- package/dist/agent/routes/security/scope-invalidation.js +28 -0
- package/dist/agent/routes/system/error-handling.d.ts +11 -0
- package/dist/agent/routes/system/error-handling.js +56 -0
- package/dist/agent/routes/system/healthcheck.d.ts +11 -0
- package/dist/agent/routes/system/healthcheck.js +22 -0
- package/dist/agent/routes/system/logger.d.ts +10 -0
- package/dist/agent/routes/system/logger.js +36 -0
- package/dist/agent/services/index.d.ts +10 -0
- package/dist/agent/services/index.js +12 -0
- package/dist/agent/services/permissions.d.ts +19 -0
- package/dist/agent/services/permissions.js +79 -0
- package/dist/agent/services/serializer.d.ts +17 -0
- package/dist/agent/services/serializer.js +120 -0
- package/dist/agent/types.d.ts +23 -0
- package/dist/agent/types.js +22 -0
- package/dist/agent/utils/body-parser.d.ts +7 -0
- package/dist/agent/utils/body-parser.js +18 -0
- package/dist/agent/utils/context-filter-factory.d.ts +7 -0
- package/dist/agent/utils/context-filter-factory.js +29 -0
- package/dist/agent/utils/csv-generator.d.ts +12 -0
- package/dist/agent/utils/csv-generator.js +39 -0
- package/dist/agent/utils/csv-route-context.d.ts +5 -0
- package/dist/agent/utils/csv-route-context.js +14 -0
- package/dist/agent/utils/forest-http-api.d.ts +63 -0
- package/dist/agent/utils/forest-http-api.js +173 -0
- package/dist/agent/utils/forest-schema/action-values.d.ts +34 -0
- package/dist/agent/utils/forest-schema/action-values.js +144 -0
- package/dist/agent/utils/forest-schema/emitter.d.ts +20 -0
- package/dist/agent/utils/forest-schema/emitter.js +70 -0
- package/dist/agent/utils/forest-schema/filterable.d.ts +16 -0
- package/dist/agent/utils/forest-schema/filterable.js +68 -0
- package/dist/agent/utils/forest-schema/generator-actions.d.ts +14 -0
- package/dist/agent/utils/forest-schema/generator-actions.js +99 -0
- package/dist/agent/utils/forest-schema/generator-collection.d.ts +7 -0
- package/dist/agent/utils/forest-schema/generator-collection.js +31 -0
- package/dist/agent/utils/forest-schema/generator-fields.d.ts +13 -0
- package/dist/agent/utils/forest-schema/generator-fields.js +131 -0
- package/dist/agent/utils/forest-schema/generator-segments.d.ts +6 -0
- package/dist/agent/utils/forest-schema/generator-segments.js +9 -0
- package/dist/agent/utils/forest-schema/types.d.ts +79 -0
- package/dist/agent/utils/forest-schema/types.js +16 -0
- package/dist/agent/utils/forest-schema/validation.d.ts +10 -0
- package/dist/agent/utils/forest-schema/validation.js +26 -0
- package/dist/agent/utils/http-driver-options.d.ts +13 -0
- package/dist/agent/utils/http-driver-options.js +86 -0
- package/dist/agent/utils/id.d.ts +8 -0
- package/dist/agent/utils/id.js +43 -0
- package/dist/agent/utils/query-string.d.ts +14 -0
- package/dist/agent/utils/query-string.js +130 -0
- package/dist/builder/agent.d.ts +81 -0
- package/dist/builder/agent.js +113 -0
- package/dist/builder/collection.d.ts +148 -0
- package/dist/builder/collection.js +226 -0
- package/dist/builder/types.d.ts +5 -0
- package/dist/builder/types.js +3 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +22 -0
- package/dist/types.d.ts +22 -0
- package/dist/types.js +11 -0
- package/dist/utils/csv-generator.d.ts +12 -0
- package/dist/utils/csv-generator.js +39 -0
- package/package.json +55 -0
|
@@ -0,0 +1,79 @@
|
|
|
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 lru_cache_1 = __importDefault(require("lru-cache"));
|
|
7
|
+
const object_hash_1 = __importDefault(require("object-hash"));
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
const forest_http_api_1 = __importDefault(require("../utils/forest-http-api"));
|
|
10
|
+
class PermissionService {
|
|
11
|
+
constructor(options) {
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.cache = new lru_cache_1.default({
|
|
14
|
+
max: 256,
|
|
15
|
+
ttl: this.options.permissionsCacheDurationInSeconds * 1000,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
invalidateCache(renderingId) {
|
|
19
|
+
this.cache.delete(renderingId);
|
|
20
|
+
}
|
|
21
|
+
/** Checks that a charting query is in the list of allowed queries */
|
|
22
|
+
async canChart(context) {
|
|
23
|
+
const chart = { ...context.request.body };
|
|
24
|
+
// When the server sends the data of the allowed charts, the target column is not specified
|
|
25
|
+
// for relations => allow them all.
|
|
26
|
+
if (chart?.group_by_field?.includes(':'))
|
|
27
|
+
chart.group_by_field = chart.group_by_field.substring(0, chart.group_by_field.indexOf(':'));
|
|
28
|
+
const chartHash = (0, object_hash_1.default)(chart, {
|
|
29
|
+
respectType: false,
|
|
30
|
+
excludeKeys: key => chart[key] === null,
|
|
31
|
+
});
|
|
32
|
+
await this.can(context, `chart:${chartHash}`);
|
|
33
|
+
}
|
|
34
|
+
/** Check if a user is allowed to perform a specific action */
|
|
35
|
+
async can(context, action, allowRefetch = true) {
|
|
36
|
+
const { id: userId, renderingId } = context.state.user;
|
|
37
|
+
const perms = await this.getRenderingPermissions(renderingId);
|
|
38
|
+
const isAllowed = perms.actions.has(action) || perms.actionsByUser[action]?.has(userId);
|
|
39
|
+
if (!isAllowed && allowRefetch) {
|
|
40
|
+
this.invalidateCache(renderingId);
|
|
41
|
+
return this.can(context, action, false);
|
|
42
|
+
}
|
|
43
|
+
if (!isAllowed) {
|
|
44
|
+
context.throw(types_1.HttpCode.Forbidden, 'Forbidden');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async getScope(collection, context) {
|
|
48
|
+
const { user } = context.state;
|
|
49
|
+
const perms = await this.getRenderingPermissions(user.renderingId);
|
|
50
|
+
const scopes = perms.scopes[collection.name];
|
|
51
|
+
if (!scopes)
|
|
52
|
+
return null;
|
|
53
|
+
return scopes.conditionTree.replaceLeafs(leaf => {
|
|
54
|
+
const dynamicValues = scopes.dynamicScopeValues?.[user.id];
|
|
55
|
+
if (typeof leaf.value === 'string' && leaf.value.startsWith('$currentUser')) {
|
|
56
|
+
// Search replacement hash from forestadmin server
|
|
57
|
+
if (dynamicValues) {
|
|
58
|
+
return leaf.override({ value: dynamicValues[leaf.value] });
|
|
59
|
+
}
|
|
60
|
+
// Search JWT token (new user)
|
|
61
|
+
return leaf.override({
|
|
62
|
+
value: leaf.value.startsWith('$currentUser.tags.')
|
|
63
|
+
? user.tags[leaf.value.substring(18)]
|
|
64
|
+
: user[leaf.value.substring(13)],
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return leaf;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Get cached version of "rendering permissions" */
|
|
71
|
+
getRenderingPermissions(renderingId) {
|
|
72
|
+
if (!this.cache.has(renderingId))
|
|
73
|
+
this.cache.set(renderingId, forest_http_api_1.default.getPermissions(this.options, renderingId));
|
|
74
|
+
// We already checked the entry is up-to-date with the .has() call => allowStale
|
|
75
|
+
return this.cache.get(renderingId, { allowStale: true });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.default = PermissionService;
|
|
79
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGVybWlzc2lvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWdlbnQvc2VydmljZXMvcGVybWlzc2lvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFFQSwwREFBaUM7QUFDakMsOERBQXFDO0FBRXJDLG9DQUE4RDtBQUM5RCwrRUFBK0U7QUFPL0UsTUFBcUIsaUJBQWlCO0lBSXBDLFlBQVksT0FBcUI7UUFDL0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLG1CQUFRLENBQUM7WUFDeEIsR0FBRyxFQUFFLEdBQUc7WUFDUixHQUFHLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxpQ0FBaUMsR0FBRyxJQUFJO1NBQzNELENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxlQUFlLENBQUMsV0FBbUI7UUFDakMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDakMsQ0FBQztJQUVELHFFQUFxRTtJQUNyRSxLQUFLLENBQUMsUUFBUSxDQUFDLE9BQWdCO1FBQzdCLE1BQU0sS0FBSyxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1FBRTFDLDJGQUEyRjtRQUMzRixtQ0FBbUM7UUFDbkMsSUFBSSxLQUFLLEVBQUUsY0FBYyxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUM7WUFDdEMsS0FBSyxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUU5RixNQUFNLFNBQVMsR0FBRyxJQUFBLHFCQUFVLEVBQUMsS0FBSyxFQUFFO1lBQ2xDLFdBQVcsRUFBRSxLQUFLO1lBQ2xCLFdBQVcsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FB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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Collection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { AgentOptionsWithDefaults } from '../types';
|
|
3
|
+
declare type SerializerOptions = Pick<AgentOptionsWithDefaults, 'prefix'>;
|
|
4
|
+
export default class Serializer {
|
|
5
|
+
private readonly serializers;
|
|
6
|
+
private readonly prefix;
|
|
7
|
+
constructor(options: SerializerOptions);
|
|
8
|
+
serialize(collection: Collection, data: RecordData | RecordData[]): unknown;
|
|
9
|
+
deserialize(collection: Collection, body: unknown): RecordData;
|
|
10
|
+
serializeWithSearchMetadata(collection: Collection, data: RecordData[], searchValue: string): unknown;
|
|
11
|
+
private getSerializer;
|
|
12
|
+
private registerCollection;
|
|
13
|
+
private buildRelationshipsConfiguration;
|
|
14
|
+
private stripUndefinedsInPlace;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=serializer.d.ts.map
|
|
@@ -0,0 +1,120 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const json_api_serializer_1 = __importDefault(require("json-api-serializer"));
|
|
8
|
+
const id_1 = __importDefault(require("../utils/id"));
|
|
9
|
+
class Serializer {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
// No need to keep references to serializers for outdated schemas => weakmap.
|
|
12
|
+
this.serializers = new WeakMap();
|
|
13
|
+
this.prefix = options.prefix;
|
|
14
|
+
}
|
|
15
|
+
serialize(collection, data) {
|
|
16
|
+
const result = this.getSerializer(collection).serialize(collection.name, data);
|
|
17
|
+
this.stripUndefinedsInPlace(result);
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
deserialize(collection, body) {
|
|
21
|
+
return this.getSerializer(collection).deserialize(collection.name, body);
|
|
22
|
+
}
|
|
23
|
+
serializeWithSearchMetadata(collection, data, searchValue) {
|
|
24
|
+
const results = this.serialize(collection, data);
|
|
25
|
+
if (searchValue && searchValue.trim().length > 0) {
|
|
26
|
+
const resultsData = results.data;
|
|
27
|
+
const decorators = resultsData.reduce((decorator, record) => {
|
|
28
|
+
const search = Object.keys(record.attributes).filter(attribute => {
|
|
29
|
+
const value = record.attributes[attribute];
|
|
30
|
+
return value && value.toString().toLowerCase().includes(searchValue.toLowerCase());
|
|
31
|
+
});
|
|
32
|
+
if (search.length === 0) {
|
|
33
|
+
return decorator;
|
|
34
|
+
}
|
|
35
|
+
return { ...decorator, [Object.keys(decorator).length]: { id: record.id, search } };
|
|
36
|
+
}, {});
|
|
37
|
+
if (Object.values(decorators).length === 0) {
|
|
38
|
+
return results;
|
|
39
|
+
}
|
|
40
|
+
results.meta = { decorators };
|
|
41
|
+
}
|
|
42
|
+
return results;
|
|
43
|
+
}
|
|
44
|
+
getSerializer(collection) {
|
|
45
|
+
if (this.serializers.has(collection.schema)) {
|
|
46
|
+
return this.serializers.get(collection.schema);
|
|
47
|
+
}
|
|
48
|
+
const serializer = new json_api_serializer_1.default();
|
|
49
|
+
for (const sibling of collection.dataSource.collections) {
|
|
50
|
+
this.registerCollection(sibling, serializer);
|
|
51
|
+
this.serializers.set(sibling.schema, serializer);
|
|
52
|
+
}
|
|
53
|
+
return serializer;
|
|
54
|
+
}
|
|
55
|
+
registerCollection(collection, serializer) {
|
|
56
|
+
serializer.register(collection.name, {
|
|
57
|
+
id: 'forestId',
|
|
58
|
+
relationships: this.buildRelationshipsConfiguration(collection),
|
|
59
|
+
beforeSerialize: (data) => {
|
|
60
|
+
const copy = { ...data };
|
|
61
|
+
copy.forestId = id_1.default.packId(collection.schema, data);
|
|
62
|
+
return copy;
|
|
63
|
+
},
|
|
64
|
+
afterDeserialize: (data) => {
|
|
65
|
+
const copy = { ...data };
|
|
66
|
+
if (data.forestId) {
|
|
67
|
+
const parts = id_1.default.unpackId(collection.schema, data.forestId);
|
|
68
|
+
const primaryKeys = datasource_toolkit_1.SchemaUtils.getPrimaryKeys(collection.schema);
|
|
69
|
+
primaryKeys.forEach((field, index) => {
|
|
70
|
+
copy[field] = parts[index];
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
delete copy.forestId;
|
|
74
|
+
return copy;
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
buildRelationshipsConfiguration(collection) {
|
|
79
|
+
const relationships = {};
|
|
80
|
+
const urlPrefix = `${this.prefix}/${collection.name}`;
|
|
81
|
+
for (const [name, field] of Object.entries(collection.schema.fields)) {
|
|
82
|
+
if (field.type === 'ManyToOne' || field.type === 'OneToOne') {
|
|
83
|
+
relationships[name] = {
|
|
84
|
+
type: field.foreignCollection,
|
|
85
|
+
deserialize: (data) => {
|
|
86
|
+
const foreignCollection = collection.dataSource.getCollection(field.foreignCollection);
|
|
87
|
+
return id_1.default.unpackId(foreignCollection.schema, data.id);
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
if (field.type === 'ManyToMany' || field.type === 'OneToMany') {
|
|
92
|
+
relationships[name] = {
|
|
93
|
+
type: field.foreignCollection,
|
|
94
|
+
links: (data) => ({
|
|
95
|
+
related: {
|
|
96
|
+
href: `${urlPrefix}/${data.forestId}/relationships/${name}`,
|
|
97
|
+
},
|
|
98
|
+
}),
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return relationships;
|
|
103
|
+
}
|
|
104
|
+
stripUndefinedsInPlace(record) {
|
|
105
|
+
if (record === null || typeof record !== 'object') {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const indexable = record;
|
|
109
|
+
for (const key of Object.keys(indexable)) {
|
|
110
|
+
if (indexable[key] === undefined) {
|
|
111
|
+
delete indexable[key];
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
this.stripUndefinedsInPlace(indexable[key]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.default = Serializer;
|
|
120
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXplci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hZ2VudC9zZXJ2aWNlcy9zZXJpYWxpemVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBS3lDO0FBQ3pDLDhFQUFvRDtBQUdwRCxxREFBa0M7QUFLbEMsTUFBcUIsVUFBVTtJQUs3QixZQUFZLE9BQTBCO1FBSnRDLDZFQUE2RTtRQUM1RCxnQkFBVyxHQUFpRCxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBSXpGLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUMvQixDQUFDO0lBRUQsU0FBUyxDQUFDLFVBQXNCLEVBQUUsSUFBK0I7UUFDL0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFcEMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELFdBQVcsQ0FBQyxVQUFzQixFQUFFLElBQWE7UUFDL0MsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzNFLENBQUM7SUFFRCwyQkFBMkIsQ0FDekIsVUFBc0IsRUFDdEIsSUFBa0IsRUFDbEIsV0FBbUI7UUFFbkIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFlLENBQUM7UUFFL0QsSUFBSSxXQUFXLElBQUksV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7WUFDaEQsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDLElBQW9CLENBQUM7WUFDakQsTUFBTSxVQUFVLEdBQUcsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDLFNBQVMsRUFBRSxNQUFrQixFQUFFLEVBQUU7Z0JBQ3RFLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDL0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQztvQkFFM0MsT0FBTyxLQUFLLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDckYsQ0FBQyxDQUFDLENBQUM7Z0JBRUgsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtvQkFDdkIsT0FBTyxTQUFTLENBQUM7aUJBQ2xCO2dCQUVELE9BQU8sRUFBRSxHQUFHLFNBQVMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3RGLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUVQLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUMxQyxPQUFPLE9BQU8sQ0FBQzthQUNoQjtZQUVELE9BQU8sQ0FBQyxJQUFJLEdBQUcsRUFBRSxVQUFVLEVBQUUsQ0FBQztTQUMvQjtRQUVELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTyxhQUFhLENBQUMsVUFBc0I7UUFDMUMsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDM0MsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7U0FDaEQ7UUFFRCxNQUFNLFVBQVUsR0FBRyxJQUFJLDZCQUFpQixFQUFFLENBQUM7UUFFM0MsS0FBSyxNQUFNLE9BQU8sSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRTtZQUN2RCxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQzdDLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUM7U0FDbEQ7UUFFRCxPQUFPLFVBQVUsQ0FBQztJQUNwQixDQUFDO0lBRU8sa0JBQWtCLENBQUMsVUFBc0IsRUFBRSxVQUE2QjtRQUM5RSxVQUFVLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUU7WUFDbkMsRUFBRSxFQUFFLFVBQVU7WUFDZCxhQUFhLEVBQUUsSUFBSSxDQUFDLCtCQUErQixDQUFDLFVBQVUsQ0FBQztZQUMvRCxlQUFlLEVBQUUsQ0FBQyxJQUE2QixFQUFFLEVBQUU7Z0JBQ2pELE1BQU0sSUFBSSxHQUFHLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQztnQkFDekIsSUFBSSxDQUFDLFFBQVEsR0FBRyxZQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBRXhELE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELGdCQUFnQixFQUFFLENBQUMsSUFBNkIsRUFBRSxFQUFFO2dCQUNsRCxNQUFNLElBQUksR0FBRyxFQUFFLEdBQUcsSUFBSSxFQUFFLENBQUM7Z0JBRXpCLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtvQkFDakIsTUFBTSxLQUFLLEdBQUcsWUFBTyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxRQUFrQixDQUFDLENBQUM7b0JBQzNFLE1BQU0sV0FBVyxHQUFHLGdDQUFXLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztvQkFDbEUsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRTt3QkFDbkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDN0IsQ0FBQyxDQUFDLENBQUM7aUJBQ0o7Z0JBRUQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDO2dCQUVyQixPQUFPLElBQUksQ0FBQztZQUNkLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sK0JBQStCLENBQ3JDLFVBQXNCO1FBRXRCLE1BQU0sYUFBYSxHQUEwRCxFQUFFLENBQUM7UUFDaEYsTUFBTSxTQUFTLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV0RCxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFO1lBQ3BFLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxXQUFXLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxVQUFVLEVBQUU7Z0JBQzNELGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRztvQkFDcEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxpQkFBaUI7b0JBQzdCLFdBQVcsRUFBRSxDQUFDLElBQTZCLEVBQUUsRUFBRTt3QkFDN0MsTUFBTSxpQkFBaUIsR0FBRyxVQUFVLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQzt3QkFFdkYsT0FBTyxZQUFPLENBQUMsUUFBUSxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsRUFBWSxDQUFDLENBQUM7b0JBQ3ZFLENBQUM7aUJBQ0YsQ0FBQzthQUNIO1lBRUQsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFlBQVksSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRTtnQkFDN0QsYUFBYSxDQUFDLElBQUksQ0FBQyxHQUFHO29CQUNwQixJQUFJLEVBQUUsS0FBSyxDQUFDLGlCQUFpQjtvQkFDN0IsS0FBSyxFQUFFLENBQUMsSUFBc0IsRUFBRSxFQUFFLENBQUMsQ0FBQzt3QkFDbEMsT0FBTyxFQUFFOzRCQUNQLElBQUksRUFBRSxHQUFHLFNBQVMsSUFBSSxJQUFJLENBQUMsUUFBUSxrQkFBa0IsSUFBSSxFQUFFO3lCQUM1RDtxQkFDRixDQUFDO2lCQUNILENBQUM7YUFDSDtTQUNGO1FBRUQsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQUVPLHNCQUFzQixDQUFDLE1BQWU7UUFDNUMsSUFBSSxNQUFNLEtBQUssSUFBSSxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsRUFBRTtZQUNqRCxPQUFPO1NBQ1I7UUFFRCxNQUFNLFNBQVMsR0FBRyxNQUFpQyxDQUFDO1FBRXBELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN4QyxJQUFJLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxTQUFTLEVBQUU7Z0JBQ2hDLE9BQU8sU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2FBQ3ZCO2lCQUFNO2dCQUNMLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzthQUM3QztTQUNGO0lBQ0gsQ0FBQztDQUNGO0FBaEpELDZCQWdKQyJ9
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { CompositeId } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { AgentOptions } from '../types';
|
|
3
|
+
export declare enum HttpCode {
|
|
4
|
+
BadRequest = 400,
|
|
5
|
+
Forbidden = 403,
|
|
6
|
+
InternalServerError = 500,
|
|
7
|
+
NoContent = 204,
|
|
8
|
+
NotFound = 404,
|
|
9
|
+
Ok = 200
|
|
10
|
+
}
|
|
11
|
+
export declare enum RouteType {
|
|
12
|
+
Logger = 0,
|
|
13
|
+
ErrorHandler = 1,
|
|
14
|
+
PublicRoute = 2,
|
|
15
|
+
Authentication = 3,
|
|
16
|
+
PrivateRoute = 4
|
|
17
|
+
}
|
|
18
|
+
export declare type SelectionIds = {
|
|
19
|
+
areExcluded: boolean;
|
|
20
|
+
ids: CompositeId[];
|
|
21
|
+
};
|
|
22
|
+
export declare type AgentOptionsWithDefaults = Readonly<Required<AgentOptions>>;
|
|
23
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RouteType = exports.HttpCode = void 0;
|
|
4
|
+
var HttpCode;
|
|
5
|
+
(function (HttpCode) {
|
|
6
|
+
HttpCode[HttpCode["BadRequest"] = 400] = "BadRequest";
|
|
7
|
+
HttpCode[HttpCode["Forbidden"] = 403] = "Forbidden";
|
|
8
|
+
HttpCode[HttpCode["InternalServerError"] = 500] = "InternalServerError";
|
|
9
|
+
HttpCode[HttpCode["NoContent"] = 204] = "NoContent";
|
|
10
|
+
HttpCode[HttpCode["NotFound"] = 404] = "NotFound";
|
|
11
|
+
HttpCode[HttpCode["Ok"] = 200] = "Ok";
|
|
12
|
+
})(HttpCode = exports.HttpCode || (exports.HttpCode = {}));
|
|
13
|
+
var RouteType;
|
|
14
|
+
(function (RouteType) {
|
|
15
|
+
// Changing the values of this enum changes the order in which routes are loaded into koa-router.
|
|
16
|
+
RouteType[RouteType["Logger"] = 0] = "Logger";
|
|
17
|
+
RouteType[RouteType["ErrorHandler"] = 1] = "ErrorHandler";
|
|
18
|
+
RouteType[RouteType["PublicRoute"] = 2] = "PublicRoute";
|
|
19
|
+
RouteType[RouteType["Authentication"] = 3] = "Authentication";
|
|
20
|
+
RouteType[RouteType["PrivateRoute"] = 4] = "PrivateRoute";
|
|
21
|
+
})(RouteType = exports.RouteType || (exports.RouteType = {}));
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYWdlbnQvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBSUEsSUFBWSxRQU9YO0FBUEQsV0FBWSxRQUFRO0lBQ2xCLHFEQUFnQixDQUFBO0lBQ2hCLG1EQUFlLENBQUE7SUFDZix1RUFBeUIsQ0FBQTtJQUN6QixtREFBZSxDQUFBO0lBQ2YsaURBQWMsQ0FBQTtJQUNkLHFDQUFRLENBQUE7QUFDVixDQUFDLEVBUFcsUUFBUSxHQUFSLGdCQUFRLEtBQVIsZ0JBQVEsUUFPbkI7QUFFRCxJQUFZLFNBT1g7QUFQRCxXQUFZLFNBQVM7SUFDbkIsaUdBQWlHO0lBQ2pHLDZDQUFVLENBQUE7SUFDVix5REFBZ0IsQ0FBQTtJQUNoQix1REFBZSxDQUFBO0lBQ2YsNkRBQWtCLENBQUE7SUFDbEIseURBQWdCLENBQUE7QUFDbEIsQ0FBQyxFQVBXLFNBQVMsR0FBVCxpQkFBUyxLQUFULGlCQUFTLFFBT3BCIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CollectionSchema } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
import { SelectionIds } from '../types';
|
|
4
|
+
export default class BodyParser {
|
|
5
|
+
static parseSelectionIds(schema: CollectionSchema, context: Context): SelectionIds;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=body-parser.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
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 id_1 = __importDefault(require("./id"));
|
|
7
|
+
class BodyParser {
|
|
8
|
+
static parseSelectionIds(schema, context) {
|
|
9
|
+
const data = context.request.body?.data;
|
|
10
|
+
const attributes = data?.attributes;
|
|
11
|
+
const areExcluded = Boolean(attributes?.all_records);
|
|
12
|
+
let ids = attributes?.ids || (Array.isArray(data) && data.map(r => r.id)) || undefined;
|
|
13
|
+
ids = id_1.default.unpackIds(schema, areExcluded ? attributes?.all_records_ids_excluded : ids);
|
|
14
|
+
return { areExcluded, ids };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.default = BodyParser;
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9keS1wYXJzZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWdlbnQvdXRpbHMvYm9keS1wYXJzZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSw4Q0FBMkI7QUFFM0IsTUFBcUIsVUFBVTtJQUM3QixNQUFNLENBQUMsaUJBQWlCLENBQUMsTUFBd0IsRUFBRSxPQUFnQjtRQUNqRSxNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7UUFDeEMsTUFBTSxVQUFVLEdBQUcsSUFBSSxFQUFFLFVBQVUsQ0FBQztRQUNwQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ3JELElBQUksR0FBRyxHQUFHLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxTQUFTLENBQUM7UUFDdkYsR0FBRyxHQUFHLFlBQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUMsVUFBVSxFQUFFLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUUxRixPQUFPLEVBQUUsV0FBVyxFQUFFLEdBQUcsRUFBRSxDQUFDO0lBQzlCLENBQUM7Q0FDRjtBQVZELDZCQVVDIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Collection, ConditionTree, Filter, PaginatedFilter } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { Context } from 'koa';
|
|
3
|
+
export default class ContextFilterFactory {
|
|
4
|
+
static buildPaginated(collection: Collection, context: Context, scope: ConditionTree, partialFilter?: Partial<PaginatedFilter>): PaginatedFilter;
|
|
5
|
+
static build(collection: Collection, context: Context, scope: ConditionTree, partialFilter?: Partial<Filter>): PaginatedFilter;
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=context-filter-factory.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
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 datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
7
|
+
const query_string_1 = __importDefault(require("./query-string"));
|
|
8
|
+
class ContextFilterFactory {
|
|
9
|
+
static buildPaginated(collection, context, scope, partialFilter) {
|
|
10
|
+
return new datasource_toolkit_1.PaginatedFilter({
|
|
11
|
+
sort: query_string_1.default.parseSort(collection, context),
|
|
12
|
+
page: query_string_1.default.parsePagination(context),
|
|
13
|
+
...ContextFilterFactory.build(collection, context, scope),
|
|
14
|
+
...partialFilter,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
static build(collection, context, scope, partialFilter) {
|
|
18
|
+
return new datasource_toolkit_1.Filter({
|
|
19
|
+
search: query_string_1.default.parseSearch(collection, context),
|
|
20
|
+
segment: query_string_1.default.parseSegment(collection, context),
|
|
21
|
+
timezone: query_string_1.default.parseTimezone(context),
|
|
22
|
+
searchExtended: query_string_1.default.parseSearchExtended(context),
|
|
23
|
+
conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(query_string_1.default.parseConditionTree(collection, context), scope),
|
|
24
|
+
...partialFilter,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = ContextFilterFactory;
|
|
29
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1maWx0ZXItZmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hZ2VudC91dGlscy9jb250ZXh0LWZpbHRlci1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBTXlDO0FBRXpDLGtFQUErQztBQUUvQyxNQUFxQixvQkFBb0I7SUFDdkMsTUFBTSxDQUFDLGNBQWMsQ0FDbkIsVUFBc0IsRUFDdEIsT0FBZ0IsRUFDaEIsS0FBb0IsRUFDcEIsYUFBd0M7UUFFeEMsT0FBTyxJQUFJLG9DQUFlLENBQUM7WUFDekIsSUFBSSxFQUFFLHNCQUFpQixDQUFDLFNBQVMsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDO1lBQ3RELElBQUksRUFBRSxzQkFBaUIsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDO1lBQ2hELEdBQUcsb0JBQW9CLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDO1lBQ3pELEdBQUcsYUFBYTtTQUNqQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsTUFBTSxDQUFDLEtBQUssQ0FDVixVQUFzQixFQUN0QixPQUFnQixFQUNoQixLQUFvQixFQUNwQixhQUErQjtRQUUvQixPQUFPLElBQUksMkJBQU0sQ0FBQztZQUNoQixNQUFNLEVBQUUsc0JBQWlCLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUM7WUFDMUQsT0FBTyxFQUFFLHNCQUFpQixDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDO1lBQzVELFFBQVEsRUFBRSxzQkFBaUIsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO1lBQ2xELGNBQWMsRUFBRSxzQkFBaUIsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUM7WUFDOUQsYUFBYSxFQUFFLHlDQUFvQixDQUFDLFNBQVMsQ0FDM0Msc0JBQWlCLENBQUMsa0JBQWtCLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxFQUN6RCxLQUFLLENBQ047WUFDRCxHQUFHLGFBQWE7U0FDakIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBakNELHVDQWlDQyJ9
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Collection, PaginatedFilter, Projection } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
export declare const CHUNK_SIZE = 1000;
|
|
3
|
+
export default class CsvGenerator {
|
|
4
|
+
/**
|
|
5
|
+
* Use an async generator to ensure that
|
|
6
|
+
* - backpressure is properly applied without needing to extend Readable (for slow clients)
|
|
7
|
+
* - we stop making queries to the database if the client closes the connection.
|
|
8
|
+
*/
|
|
9
|
+
static generate(projection: Projection, header: string, filter: PaginatedFilter, collection: Collection, list: Collection['list']): AsyncGenerator<string>;
|
|
10
|
+
private static convert;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=csv-generator.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CHUNK_SIZE = void 0;
|
|
4
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
5
|
+
const format_1 = require("@fast-csv/format");
|
|
6
|
+
exports.CHUNK_SIZE = 1000;
|
|
7
|
+
class CsvGenerator {
|
|
8
|
+
/**
|
|
9
|
+
* Use an async generator to ensure that
|
|
10
|
+
* - backpressure is properly applied without needing to extend Readable (for slow clients)
|
|
11
|
+
* - we stop making queries to the database if the client closes the connection.
|
|
12
|
+
*/
|
|
13
|
+
static async *generate(projection, header, filter, collection, list) {
|
|
14
|
+
yield (0, format_1.writeToString)([header.split(',')], { headers: true, includeEndRowDelimiter: true });
|
|
15
|
+
const limit = filter.page?.limit;
|
|
16
|
+
let skip = filter.page?.skip || 0;
|
|
17
|
+
let areAllRecordsFetched = false;
|
|
18
|
+
const copiedFilter = { ...filter };
|
|
19
|
+
while (!areAllRecordsFetched) {
|
|
20
|
+
let currentPageSize = exports.CHUNK_SIZE;
|
|
21
|
+
if (limit < skip)
|
|
22
|
+
currentPageSize = skip - limit;
|
|
23
|
+
copiedFilter.page = new datasource_toolkit_1.Page(skip, currentPageSize);
|
|
24
|
+
if (!copiedFilter.sort || copiedFilter.sort.length === 0) {
|
|
25
|
+
copiedFilter.sort = datasource_toolkit_1.SortFactory.byPrimaryKeys(collection);
|
|
26
|
+
}
|
|
27
|
+
// eslint-disable-next-line no-await-in-loop
|
|
28
|
+
const records = await list(new datasource_toolkit_1.PaginatedFilter(copiedFilter), projection);
|
|
29
|
+
yield CsvGenerator.convert(records, projection);
|
|
30
|
+
areAllRecordsFetched = records.length < exports.CHUNK_SIZE;
|
|
31
|
+
skip += currentPageSize;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
static convert(records, projection) {
|
|
35
|
+
return (0, format_1.writeToString)(records.map(record => projection.map(field => datasource_toolkit_1.RecordUtils.getFieldValue(record, field))));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.default = CsvGenerator;
|
|
39
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3N2LWdlbmVyYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hZ2VudC91dGlscy9jc3YtZ2VuZXJhdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHdFQVF5QztBQUN6Qyw2Q0FBaUQ7QUFFcEMsUUFBQSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBRS9CLE1BQXFCLFlBQVk7SUFDL0I7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQ3BCLFVBQXNCLEVBQ3RCLE1BQWMsRUFDZCxNQUF1QixFQUN2QixVQUFzQixFQUN0QixJQUF3QjtRQUV4QixNQUFNLElBQUEsc0JBQWEsRUFBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsc0JBQXNCLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUUxRixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQztRQUNqQyxJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksSUFBSSxDQUFDLENBQUM7UUFFbEMsSUFBSSxvQkFBb0IsR0FBRyxLQUFLLENBQUM7UUFDakMsTUFBTSxZQUFZLEdBQUcsRUFBRSxHQUFHLE1BQU0sRUFBRSxDQUFDO1FBRW5DLE9BQU8sQ0FBQyxvQkFBb0IsRUFBRTtZQUM1QixJQUFJLGVBQWUsR0FBRyxrQkFBVSxDQUFDO1lBQ2pDLElBQUksS0FBSyxHQUFHLElBQUk7Z0JBQUUsZUFBZSxHQUFHLElBQUksR0FBRyxLQUFLLENBQUM7WUFFakQsWUFBWSxDQUFDLElBQUksR0FBRyxJQUFJLHlCQUFJLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1lBRXBELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDeEQsWUFBWSxDQUFDLElBQUksR0FBRyxnQ0FBVyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQzthQUMzRDtZQUVELDRDQUE0QztZQUM1QyxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLG9DQUFlLENBQUMsWUFBWSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFFMUUsTUFBTSxZQUFZLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQztZQUVoRCxvQkFBb0IsR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLGtCQUFVLENBQUM7WUFDbkQsSUFBSSxJQUFJLGVBQWUsQ0FBQztTQUN6QjtJQUNILENBQUM7SUFFTyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQXFCLEVBQUUsVUFBc0I7UUFDbEUsT0FBTyxJQUFBLHNCQUFhLEVBQ2xCLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsZ0NBQVcsQ0FBQyxhQUFhLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FDekYsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQTlDRCwrQkE4Q0MifQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
class CsvRouteContext {
|
|
4
|
+
static buildResponse(context) {
|
|
5
|
+
const { filename } = context.request.query;
|
|
6
|
+
context.response.type = 'text/csv; charset=utf-8';
|
|
7
|
+
context.response.attachment(`attachment; filename=${filename}`);
|
|
8
|
+
context.response.lastModified = new Date();
|
|
9
|
+
context.response.set({ 'X-Accel-Buffering': 'no' });
|
|
10
|
+
context.response.set({ 'Cache-Control': 'no-cache' });
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = CsvRouteContext;
|
|
14
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3N2LXJvdXRlLWNvbnRleHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYWdlbnQvdXRpbHMvY3N2LXJvdXRlLWNvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFFQSxNQUFxQixlQUFlO0lBQ2xDLE1BQU0sQ0FBQyxhQUFhLENBQUMsT0FBZ0I7UUFDbkMsTUFBTSxFQUFFLFFBQVEsRUFBRSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO1FBRTNDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxHQUFHLHlCQUF5QixDQUFDO1FBQ2xELE9BQU8sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLHdCQUF3QixRQUFRLEVBQUUsQ0FBQyxDQUFDO1FBQ2hFLE9BQU8sQ0FBQyxRQUFRLENBQUMsWUFBWSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDM0MsT0FBTyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUUsZUFBZSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztDQUNGO0FBVkQsa0NBVUMifQ==
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ConditionTree } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { IssuerMetadata } from 'openid-client';
|
|
3
|
+
import { JSONAPIDocument } from 'json-api-serializer';
|
|
4
|
+
import { AgentOptions } from '../../types';
|
|
5
|
+
export declare type IpWhitelistConfiguration = {
|
|
6
|
+
isFeatureEnabled: boolean;
|
|
7
|
+
ipRules: Array<{
|
|
8
|
+
type: number;
|
|
9
|
+
ipMinimum?: string;
|
|
10
|
+
ipMaximum?: string;
|
|
11
|
+
ip?: string;
|
|
12
|
+
range?: string;
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
15
|
+
export declare type UserInfo = {
|
|
16
|
+
id: number;
|
|
17
|
+
email: string;
|
|
18
|
+
firstName: string;
|
|
19
|
+
lastName: string;
|
|
20
|
+
team: string;
|
|
21
|
+
renderingId: number;
|
|
22
|
+
role: string;
|
|
23
|
+
tags: {
|
|
24
|
+
[key: string]: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
export declare type RenderingPermissions = {
|
|
28
|
+
actions: Set<string>;
|
|
29
|
+
actionsByUser: {
|
|
30
|
+
[actionName: string]: Set<number>;
|
|
31
|
+
};
|
|
32
|
+
scopes: {
|
|
33
|
+
[collectionName: string]: {
|
|
34
|
+
conditionTree: ConditionTree;
|
|
35
|
+
dynamicScopeValues: {
|
|
36
|
+
[userId: number]: {
|
|
37
|
+
[replacementKey: string]: unknown;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
declare type HttpOptions = Pick<AgentOptions, 'envSecret' | 'forestServerUrl' | 'isProduction'>;
|
|
44
|
+
export default class ForestHttpApi {
|
|
45
|
+
static getIpWhitelistConfiguration(options: HttpOptions): Promise<IpWhitelistConfiguration>;
|
|
46
|
+
static getOpenIdIssuerMetadata(options: HttpOptions): Promise<IssuerMetadata>;
|
|
47
|
+
static getUserInformation(options: HttpOptions, renderingId: number, accessToken: string): Promise<UserInfo>;
|
|
48
|
+
static hasSchema(options: HttpOptions, hash: string): Promise<boolean>;
|
|
49
|
+
static uploadSchema(options: HttpOptions, apimap: JSONAPIDocument): Promise<void>;
|
|
50
|
+
static getPermissions(options: HttpOptions, renderingId: number): Promise<RenderingPermissions>;
|
|
51
|
+
/** Helper to format permissions into something easy to validate against */
|
|
52
|
+
private static decodeChartPermissions;
|
|
53
|
+
/**
|
|
54
|
+
* Helper to format permissions into something easy to validate against
|
|
55
|
+
* Note that the format the server is sending varies depending on if we're using a remote or
|
|
56
|
+
* local environment.
|
|
57
|
+
*/
|
|
58
|
+
private static decodeActionPermissions;
|
|
59
|
+
/** Helper to format permissions into something easy to validate against */
|
|
60
|
+
private static decodeScopePermissions;
|
|
61
|
+
}
|
|
62
|
+
export {};
|
|
63
|
+
//# sourceMappingURL=forest-http-api.d.ts.map
|