@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,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
4
|
+
const DEFAULT_ITEMS_PER_PAGE = 15;
|
|
5
|
+
const DEFAULT_PAGE_TO_SKIP = 1;
|
|
6
|
+
class QueryStringParser {
|
|
7
|
+
static parseConditionTree(collection, context) {
|
|
8
|
+
try {
|
|
9
|
+
const filters = context.request.body?.data?.attributes?.all_records_subset_query?.filters ??
|
|
10
|
+
context.request.body?.filters ??
|
|
11
|
+
context.request.query?.filters;
|
|
12
|
+
if (!filters)
|
|
13
|
+
return null;
|
|
14
|
+
const json = JSON.parse(filters.toString());
|
|
15
|
+
const conditionTree = datasource_toolkit_1.ConditionTreeFactory.fromPlainObject(json);
|
|
16
|
+
datasource_toolkit_1.ConditionTreeValidator.validate(conditionTree, collection);
|
|
17
|
+
return conditionTree;
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid filters (${e.message})`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
static parseProjection(collection, context) {
|
|
24
|
+
try {
|
|
25
|
+
const fields = context.request.query[`fields[${collection.name}]`];
|
|
26
|
+
if (fields === '' || fields === undefined) {
|
|
27
|
+
return datasource_toolkit_1.ProjectionFactory.all(collection);
|
|
28
|
+
}
|
|
29
|
+
const rootFields = fields.toString().split(',');
|
|
30
|
+
const explicitRequest = rootFields.map(field => {
|
|
31
|
+
const schema = collection.schema.fields[field];
|
|
32
|
+
return schema.type === 'Column'
|
|
33
|
+
? field
|
|
34
|
+
: `${field}:${context.request.query[`fields[${field}]`]}`;
|
|
35
|
+
});
|
|
36
|
+
datasource_toolkit_1.ProjectionValidator.validate(collection, explicitRequest);
|
|
37
|
+
return new datasource_toolkit_1.Projection(...explicitRequest);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid projection`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
static parseProjectionWithPks(collection, context) {
|
|
44
|
+
const projection = QueryStringParser.parseProjection(collection, context);
|
|
45
|
+
// Primary keys are not explicitly listed in the projections that the frontend
|
|
46
|
+
// is sending, but are still required for the frontend to work.
|
|
47
|
+
return projection.withPks(collection);
|
|
48
|
+
}
|
|
49
|
+
static parseSearch(collection, context) {
|
|
50
|
+
const search = context.request.body?.data?.attributes?.all_records_subset_query?.search?.toString() ??
|
|
51
|
+
context.request.query.search?.toString();
|
|
52
|
+
if (search && !collection.schema.searchable) {
|
|
53
|
+
throw new datasource_toolkit_1.ValidationError(`Collection is not searchable`);
|
|
54
|
+
}
|
|
55
|
+
return search ?? null;
|
|
56
|
+
}
|
|
57
|
+
static parseSearchExtended(context) {
|
|
58
|
+
const { request } = context;
|
|
59
|
+
const extended = request.body?.data?.attributes?.all_records_subset_query?.searchExtended?.toString() ??
|
|
60
|
+
request.query.searchExtended?.toString();
|
|
61
|
+
return !!extended && extended !== '0' && extended !== 'false';
|
|
62
|
+
}
|
|
63
|
+
static parseSegment(collection, context) {
|
|
64
|
+
const segment = context.request.body?.data?.attributes?.all_records_subset_query?.segment?.toString() ??
|
|
65
|
+
context.request.query.segment?.toString();
|
|
66
|
+
if (!segment) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
if (!collection.schema.segments.includes(segment)) {
|
|
70
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid segment: "${segment}"`);
|
|
71
|
+
}
|
|
72
|
+
return segment;
|
|
73
|
+
}
|
|
74
|
+
static parseTimezone(context) {
|
|
75
|
+
const timezone = context.request.query.timezone?.toString();
|
|
76
|
+
if (!timezone) {
|
|
77
|
+
throw new datasource_toolkit_1.ValidationError('Missing timezone');
|
|
78
|
+
}
|
|
79
|
+
// This is a method to validate a timezone using node only
|
|
80
|
+
// @see https://stackoverflow.com/questions/44115681
|
|
81
|
+
if (!Intl || !Intl.DateTimeFormat().resolvedOptions().timeZone) {
|
|
82
|
+
throw new Error('Time zones are not available in this environment');
|
|
83
|
+
}
|
|
84
|
+
try {
|
|
85
|
+
Intl.DateTimeFormat('en-US', { timeZone: timezone });
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid timezone: "${timezone}"`);
|
|
89
|
+
}
|
|
90
|
+
return timezone;
|
|
91
|
+
}
|
|
92
|
+
static parsePagination(context) {
|
|
93
|
+
const queryItemsPerPage = (context.request.body?.data?.attributes?.all_records_subset_query?.['page[size]'] ??
|
|
94
|
+
context.request.query['page[size]'] ??
|
|
95
|
+
DEFAULT_ITEMS_PER_PAGE).toString();
|
|
96
|
+
const queryPageToSkip = (context.request.body?.data?.attributes?.all_records_subset_query?.['page[number]'] ??
|
|
97
|
+
context.request.query['page[number]'] ??
|
|
98
|
+
DEFAULT_PAGE_TO_SKIP).toString();
|
|
99
|
+
const itemsPerPage = Number.parseInt(queryItemsPerPage, 10);
|
|
100
|
+
let pageToSkip = Number.parseInt(queryPageToSkip, 10);
|
|
101
|
+
if (Number.isNaN(itemsPerPage) ||
|
|
102
|
+
Number.isNaN(pageToSkip) ||
|
|
103
|
+
itemsPerPage <= 0 ||
|
|
104
|
+
pageToSkip <= 0) {
|
|
105
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid pagination [limit: ${itemsPerPage}, skip: ${pageToSkip}]`);
|
|
106
|
+
}
|
|
107
|
+
pageToSkip = Math.max(pageToSkip - 1, 0);
|
|
108
|
+
pageToSkip *= itemsPerPage;
|
|
109
|
+
return new datasource_toolkit_1.Page(pageToSkip, itemsPerPage);
|
|
110
|
+
}
|
|
111
|
+
static parseSort(collection, context) {
|
|
112
|
+
const sortString = context.request.body?.data?.attributes?.all_records_subset_query?.sort?.toString() ??
|
|
113
|
+
context.request.query.sort?.toString();
|
|
114
|
+
try {
|
|
115
|
+
if (!sortString)
|
|
116
|
+
return datasource_toolkit_1.SortFactory.byPrimaryKeys(collection);
|
|
117
|
+
const sort = new datasource_toolkit_1.Sort({
|
|
118
|
+
field: sortString.replace(/^-/, '').replace('.', ':'),
|
|
119
|
+
ascending: !sortString.startsWith('-'),
|
|
120
|
+
});
|
|
121
|
+
datasource_toolkit_1.SortValidator.validate(collection, sort);
|
|
122
|
+
return sort;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
throw new datasource_toolkit_1.ValidationError(`Invalid sort: ${sortString}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.default = QueryStringParser;
|
|
130
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktc3RyaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2FnZW50L3V0aWxzL3F1ZXJ5LXN0cmluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHdFQWF5QztBQUd6QyxNQUFNLHNCQUFzQixHQUFHLEVBQUUsQ0FBQztBQUNsQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQztBQUUvQixNQUFxQixpQkFBaUI7SUFDcEMsTUFBTSxDQUFDLGtCQUFrQixDQUFDLFVBQXNCLEVBQUUsT0FBZ0I7UUFDaEUsSUFBSTtZQUNGLE1BQU0sT0FBTyxHQUNYLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsd0JBQXdCLEVBQUUsT0FBTztnQkFDekUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsT0FBTztnQkFDN0IsT0FBTyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDO1lBRWpDLElBQUksQ0FBQyxPQUFPO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBRTFCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDNUMsTUFBTSxhQUFhLEdBQUcseUNBQW9CLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2pFLDJDQUFzQixDQUFDLFFBQVEsQ0FBQyxhQUFhLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFFM0QsT0FBTyxhQUFhLENBQUM7U0FDdEI7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLE1BQU0sSUFBSSxvQ0FBZSxDQUFDLG9CQUFvQixDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztTQUM3RDtJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsZUFBZSxDQUFDLFVBQXNCLEVBQUUsT0FBZ0I7UUFDN0QsSUFBSTtZQUNGLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFP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
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ActionCollectionDecorator, BaseDataSource, Collection, ComputedCollectionDecorator, DataSource, DataSourceDecorator, OperatorsEmulateCollectionDecorator, OperatorsReplaceCollectionDecorator, PublicationCollectionDecorator, RelationCollectionDecorator, RenameCollectionDecorator, SearchCollectionDecorator, SegmentCollectionDecorator, SortEmulateCollectionDecorator, WriteCollectionDecorator } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { AgentOptions } from '../types';
|
|
3
|
+
import CollectionBuilder from './collection';
|
|
4
|
+
import ForestAdminHttpDriver, { HttpCallback } from '../agent/forestadmin-http-driver';
|
|
5
|
+
/**
|
|
6
|
+
* Allow to create a new Forest Admin agent from scratch.
|
|
7
|
+
* Builds the application by composing and configuring all the collection decorators.
|
|
8
|
+
*
|
|
9
|
+
* Minimal code to add a datasource
|
|
10
|
+
* @example
|
|
11
|
+
* new AgentBuilder(options)
|
|
12
|
+
* .addDatasource(new SomeDatasource())
|
|
13
|
+
* .start();
|
|
14
|
+
*/
|
|
15
|
+
export default class AgentBuilder {
|
|
16
|
+
forestAdminHttpDriver: ForestAdminHttpDriver;
|
|
17
|
+
compositeDatasource: BaseDataSource<Collection>;
|
|
18
|
+
action: DataSourceDecorator<ActionCollectionDecorator>;
|
|
19
|
+
earlyComputed: DataSourceDecorator<ComputedCollectionDecorator>;
|
|
20
|
+
earlyOpEmulate: DataSourceDecorator<OperatorsEmulateCollectionDecorator>;
|
|
21
|
+
earlyOpReplace: DataSourceDecorator<OperatorsReplaceCollectionDecorator>;
|
|
22
|
+
relation: DataSourceDecorator<RelationCollectionDecorator>;
|
|
23
|
+
lateComputed: DataSourceDecorator<ComputedCollectionDecorator>;
|
|
24
|
+
lateOpEmulate: DataSourceDecorator<OperatorsEmulateCollectionDecorator>;
|
|
25
|
+
lateOpReplace: DataSourceDecorator<OperatorsReplaceCollectionDecorator>;
|
|
26
|
+
publication: DataSourceDecorator<PublicationCollectionDecorator>;
|
|
27
|
+
rename: DataSourceDecorator<RenameCollectionDecorator>;
|
|
28
|
+
search: DataSourceDecorator<SearchCollectionDecorator>;
|
|
29
|
+
segment: DataSourceDecorator<SegmentCollectionDecorator>;
|
|
30
|
+
sortEmulate: DataSourceDecorator<SortEmulateCollectionDecorator>;
|
|
31
|
+
write: DataSourceDecorator<WriteCollectionDecorator>;
|
|
32
|
+
/**
|
|
33
|
+
* Native nodejs HttpCallback object
|
|
34
|
+
* @example
|
|
35
|
+
* import http from 'http';
|
|
36
|
+
* ...
|
|
37
|
+
* const server = http.createServer(agent.httpCallback);
|
|
38
|
+
*/
|
|
39
|
+
get httpCallback(): HttpCallback;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new Agent Builder.
|
|
42
|
+
* If any options are missing, the default will be applied:
|
|
43
|
+
* ```
|
|
44
|
+
* clientId: null,
|
|
45
|
+
* forestServerUrl: 'https://api.forestadmin.com',
|
|
46
|
+
* logger: (level, data) => console.error(OptionsUtils.loggerPrefix[level], data),
|
|
47
|
+
* prefix: '/forest',
|
|
48
|
+
* schemaPath: '.forestadmin-schema.json',
|
|
49
|
+
* permissionsCacheDurationInSeconds: 15 * 60,
|
|
50
|
+
* ```
|
|
51
|
+
* @param {AgentOptions} options options
|
|
52
|
+
* @example
|
|
53
|
+
* new AgentBuilder(options)
|
|
54
|
+
* .addDatasource(new Datasource())
|
|
55
|
+
* .start();
|
|
56
|
+
*/
|
|
57
|
+
constructor(options: AgentOptions);
|
|
58
|
+
/**
|
|
59
|
+
* Add a datasource
|
|
60
|
+
* @param {DataSource} datasource the datasource to add
|
|
61
|
+
*/
|
|
62
|
+
addDatasource(datasource: DataSource): this;
|
|
63
|
+
/**
|
|
64
|
+
* Allow to interact with a decorated collection
|
|
65
|
+
* @param {string} name the name of the collection to manipulate
|
|
66
|
+
* @param {(collection: CollectionBuilder) => unknown} handle a function that provide a
|
|
67
|
+
* collection builder on the given collection name
|
|
68
|
+
* @example
|
|
69
|
+
* .customizeCollection('books', books => books.renameField('xx', 'yy'))
|
|
70
|
+
*/
|
|
71
|
+
customizeCollection(name: string, handle: (collection: CollectionBuilder) => unknown): this;
|
|
72
|
+
/**
|
|
73
|
+
* Start the agent.
|
|
74
|
+
*/
|
|
75
|
+
start(): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Stop the agent gracefully.
|
|
78
|
+
*/
|
|
79
|
+
stop(): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1,113 @@
|
|
|
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 collection_1 = __importDefault(require("./collection"));
|
|
8
|
+
const forestadmin_http_driver_1 = __importDefault(require("../agent/forestadmin-http-driver"));
|
|
9
|
+
/**
|
|
10
|
+
* Allow to create a new Forest Admin agent from scratch.
|
|
11
|
+
* Builds the application by composing and configuring all the collection decorators.
|
|
12
|
+
*
|
|
13
|
+
* Minimal code to add a datasource
|
|
14
|
+
* @example
|
|
15
|
+
* new AgentBuilder(options)
|
|
16
|
+
* .addDatasource(new SomeDatasource())
|
|
17
|
+
* .start();
|
|
18
|
+
*/
|
|
19
|
+
class AgentBuilder {
|
|
20
|
+
/**
|
|
21
|
+
* Create a new Agent Builder.
|
|
22
|
+
* If any options are missing, the default will be applied:
|
|
23
|
+
* ```
|
|
24
|
+
* clientId: null,
|
|
25
|
+
* forestServerUrl: 'https://api.forestadmin.com',
|
|
26
|
+
* logger: (level, data) => console.error(OptionsUtils.loggerPrefix[level], data),
|
|
27
|
+
* prefix: '/forest',
|
|
28
|
+
* schemaPath: '.forestadmin-schema.json',
|
|
29
|
+
* permissionsCacheDurationInSeconds: 15 * 60,
|
|
30
|
+
* ```
|
|
31
|
+
* @param {AgentOptions} options options
|
|
32
|
+
* @example
|
|
33
|
+
* new AgentBuilder(options)
|
|
34
|
+
* .addDatasource(new Datasource())
|
|
35
|
+
* .start();
|
|
36
|
+
*/
|
|
37
|
+
constructor(options) {
|
|
38
|
+
let last;
|
|
39
|
+
/* eslint-disable no-multi-assign */
|
|
40
|
+
last = this.compositeDatasource = new datasource_toolkit_1.BaseDataSource();
|
|
41
|
+
// Step 1: Computed-Relation-Computed sandwich (needed because some emulated relations depend
|
|
42
|
+
// on computed fields, and some computed fields depend on relation...)
|
|
43
|
+
// Note that replacement goes before emulation, as replacements may use emulated operators.
|
|
44
|
+
last = this.earlyComputed = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.ComputedCollectionDecorator);
|
|
45
|
+
last = this.earlyOpEmulate = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.OperatorsEmulateCollectionDecorator);
|
|
46
|
+
last = this.earlyOpReplace = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.OperatorsReplaceCollectionDecorator);
|
|
47
|
+
last = this.relation = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.RelationCollectionDecorator);
|
|
48
|
+
last = this.lateComputed = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.ComputedCollectionDecorator);
|
|
49
|
+
last = this.lateOpEmulate = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.OperatorsEmulateCollectionDecorator);
|
|
50
|
+
last = this.lateOpReplace = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.OperatorsReplaceCollectionDecorator);
|
|
51
|
+
// Step 2: Those five need access to all fields. They can be loaded in any order.
|
|
52
|
+
last = this.publication = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.PublicationCollectionDecorator);
|
|
53
|
+
last = this.search = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.SearchCollectionDecorator);
|
|
54
|
+
last = this.segment = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.SegmentCollectionDecorator);
|
|
55
|
+
last = this.sortEmulate = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.SortEmulateCollectionDecorator);
|
|
56
|
+
last = this.write = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.WriteCollectionDecorator);
|
|
57
|
+
// Step 3: Access to all fields AND emulated capabilities
|
|
58
|
+
last = this.action = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.ActionCollectionDecorator);
|
|
59
|
+
// Step 4: Renaming must be either the very first or very last so that naming in customer code
|
|
60
|
+
// is consistent.
|
|
61
|
+
last = this.rename = new datasource_toolkit_1.DataSourceDecorator(last, datasource_toolkit_1.RenameCollectionDecorator);
|
|
62
|
+
/* eslint-enable no-multi-assign */
|
|
63
|
+
this.forestAdminHttpDriver = new forestadmin_http_driver_1.default(last, options);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Native nodejs HttpCallback object
|
|
67
|
+
* @example
|
|
68
|
+
* import http from 'http';
|
|
69
|
+
* ...
|
|
70
|
+
* const server = http.createServer(agent.httpCallback);
|
|
71
|
+
*/
|
|
72
|
+
get httpCallback() {
|
|
73
|
+
return this.forestAdminHttpDriver.handler;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add a datasource
|
|
77
|
+
* @param {DataSource} datasource the datasource to add
|
|
78
|
+
*/
|
|
79
|
+
addDatasource(datasource) {
|
|
80
|
+
datasource.collections.forEach(collection => {
|
|
81
|
+
this.compositeDatasource.addCollection(collection);
|
|
82
|
+
});
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Allow to interact with a decorated collection
|
|
87
|
+
* @param {string} name the name of the collection to manipulate
|
|
88
|
+
* @param {(collection: CollectionBuilder) => unknown} handle a function that provide a
|
|
89
|
+
* collection builder on the given collection name
|
|
90
|
+
* @example
|
|
91
|
+
* .customizeCollection('books', books => books.renameField('xx', 'yy'))
|
|
92
|
+
*/
|
|
93
|
+
customizeCollection(name, handle) {
|
|
94
|
+
if (this.publication.getCollection(name)) {
|
|
95
|
+
handle(new collection_1.default(this, name));
|
|
96
|
+
}
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Start the agent.
|
|
101
|
+
*/
|
|
102
|
+
async start() {
|
|
103
|
+
return this.forestAdminHttpDriver.start();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stop the agent gracefully.
|
|
107
|
+
*/
|
|
108
|
+
async stop() {
|
|
109
|
+
return this.forestAdminHttpDriver.stop();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.default = AgentBuilder;
|
|
113
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYnVpbGRlci9hZ2VudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHdFQWdCeUM7QUFHekMsOERBQTZDO0FBQzdDLCtGQUF1RjtBQUV2Rjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFxQixZQUFZO0lBa0MvQjs7Ozs7Ozs7Ozs7Ozs7OztPQWdCRztJQUNILFlBQVksT0FBcUI7UUFDL0IsSUFBSSxJQUFnQixDQUFDO1FBRXJCLG9DQUFvQztRQUNwQyxJQUFJLEdBQUcsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksbUNBQWMsRUFBYyxDQUFDO1FBRW5FLDZGQUE2RjtRQUM3RixzRUFBc0U7UUFDdEUsMkZBQTJGO1FBQzNGLElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLGdEQUEyQixDQUFDLENBQUM7UUFDdkYsSUFBSSxHQUFHLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSx3Q0FBbUIsQ0FBQyxJQUFJLEVBQUUsd0RBQW1DLENBQUMsQ0FBQztRQUNoRyxJQUFJLEdBQUcsSUFBSSxDQUFDLGNBQWMsR0FBRyxJQUFJLHdDQUFtQixDQUFDLElBQUksRUFBRSx3REFBbUMsQ0FBQyxDQUFDO1FBQ2hHLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLGdEQUEyQixDQUFDLENBQUM7UUFDbEYsSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSx3Q0FBbUIsQ0FBQyxJQUFJLEVBQUUsZ0RBQTJCLENBQUMsQ0FBQztRQUN0RixJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLHdDQUFtQixDQUFDLElBQUksRUFBRSx3REFBbUMsQ0FBQyxDQUFDO1FBQy9GLElBQUksR0FBRyxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLHdEQUFtQyxDQUFDLENBQUM7UUFFL0YsaUZBQWlGO1FBQ2pGLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLG1EQUE4QixDQUFDLENBQUM7UUFDeEYsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSx3Q0FBbUIsQ0FBQyxJQUFJLEVBQUUsOENBQXlCLENBQUMsQ0FBQztRQUM5RSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHdDQUFtQixDQUFDLElBQUksRUFBRSwrQ0FBMEIsQ0FBQyxDQUFDO1FBQ2hGLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLG1EQUE4QixDQUFDLENBQUM7UUFDeEYsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSx3Q0FBbUIsQ0FBQyxJQUFJLEVBQUUsNkNBQXdCLENBQUMsQ0FBQztRQUU1RSx5REFBeUQ7UUFDekQsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSx3Q0FBbUIsQ0FBQyxJQUFJLEVBQUUsOENBQXlCLENBQUMsQ0FBQztRQUU5RSw4RkFBOEY7UUFDOUYsaUJBQWlCO1FBQ2pCLElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksd0NBQW1CLENBQUMsSUFBSSxFQUFFLDhDQUF5QixDQUFDLENBQUM7UUFFOUUsbUNBQW1DO1FBRW5DLElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLGlDQUFxQixDQUFDLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN4RSxDQUFDO0lBOUREOzs7Ozs7T0FNRztJQUNILElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQztJQUM1QyxDQUFDO0lBdUREOzs7T0FHRztJQUNILGFBQWEsQ0FBQyxVQUFzQjtRQUNsQyxVQUFVLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUMxQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILG1CQUFtQixDQUFDLElBQVksRUFBRSxNQUFrRDtRQUNsRixJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3hDLE1BQU0sQ0FBQyxJQUFJLG9CQUFpQixDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1NBQzNDO1FBRUQsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsS0FBSztRQUNULE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLEtBQUssRUFBRSxDQUFDO0lBQzVDLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxJQUFJO1FBQ1IsT0FBTyxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDM0MsQ0FBQztDQUNGO0FBaElELCtCQWdJQyJ9
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { ActionDefinition, Operator, OperatorReplacer, PartialRelationSchema, PlainSortClause, SegmentDefinition, WriteDefinition } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { FieldDefinition } from './types';
|
|
3
|
+
import AgentBuilder from './agent';
|
|
4
|
+
export default class CollectionBuilder {
|
|
5
|
+
private agentBuilder;
|
|
6
|
+
private readonly name;
|
|
7
|
+
constructor(agentBuilder: AgentBuilder, name: string);
|
|
8
|
+
/**
|
|
9
|
+
* Import a field from a many to one or one to one relation.
|
|
10
|
+
*
|
|
11
|
+
* @param name the name of the field that will be created on the collection
|
|
12
|
+
* @param options options to import the field
|
|
13
|
+
* @example
|
|
14
|
+
* .importField('authorName', { path: 'author:fullName' })
|
|
15
|
+
*/
|
|
16
|
+
importField(name: string, options: {
|
|
17
|
+
path: string;
|
|
18
|
+
beforeRelations?: boolean;
|
|
19
|
+
}): this;
|
|
20
|
+
/**
|
|
21
|
+
* Allow to rename a field of a given collection.
|
|
22
|
+
* @param {string} oldName the current name of the field in a given collection
|
|
23
|
+
* @param {string} newName the new name of the field
|
|
24
|
+
* @example
|
|
25
|
+
* .renameField('theCurrentNameOfTheField', 'theNewNameOfTheField');
|
|
26
|
+
*/
|
|
27
|
+
renameField(oldName: string, newName: string): this;
|
|
28
|
+
/**
|
|
29
|
+
* Remove field by setting its visibility to false.
|
|
30
|
+
* @param {...string[]} names the fields to remove
|
|
31
|
+
* @example
|
|
32
|
+
* .removeField('aFieldToRemove', 'anOtherFieldToRemove');
|
|
33
|
+
*/
|
|
34
|
+
removeField(...names: string[]): this;
|
|
35
|
+
/**
|
|
36
|
+
* Add a new action on the collection.
|
|
37
|
+
* @param {string} name the name of the action
|
|
38
|
+
* @param {ActionDefinition} definition the definition of the action
|
|
39
|
+
* @example
|
|
40
|
+
* .addAction('is live', {
|
|
41
|
+
* scope: 'Single',
|
|
42
|
+
* execute: async (context, responseBuilder) => {
|
|
43
|
+
* return responseBuilder.success(`Is live!`);
|
|
44
|
+
* },
|
|
45
|
+
* })
|
|
46
|
+
*/
|
|
47
|
+
addAction(name: string, definition: ActionDefinition): this;
|
|
48
|
+
/**
|
|
49
|
+
* Add a new field on the collection.
|
|
50
|
+
* @param {string} name the name of the field
|
|
51
|
+
* @param {FieldDefinition} definition The definition of the field
|
|
52
|
+
* @example
|
|
53
|
+
* .addField('fullName', {
|
|
54
|
+
* columnType: 'String',
|
|
55
|
+
* dependencies: ['firstName', 'lastName'],
|
|
56
|
+
* getValues: (records) => records.map(record => `${record.lastName} ${record.firstName}`),
|
|
57
|
+
* });
|
|
58
|
+
*/
|
|
59
|
+
addField(name: string, definition: FieldDefinition): this;
|
|
60
|
+
/**
|
|
61
|
+
* Add a relation between two collections.
|
|
62
|
+
* @param name name of the new relation
|
|
63
|
+
* @param definition definition of the new relation
|
|
64
|
+
* @example
|
|
65
|
+
* .addRelation('author', {
|
|
66
|
+
* type: 'ManyToOne',
|
|
67
|
+
* foreignCollection: 'persons',
|
|
68
|
+
* foreignKey: 'authorId'
|
|
69
|
+
* });
|
|
70
|
+
*/
|
|
71
|
+
addRelation(name: string, definition: PartialRelationSchema): this;
|
|
72
|
+
/**
|
|
73
|
+
* Add a new segment on the collection.
|
|
74
|
+
* @param {string} name the name of the segment
|
|
75
|
+
* @param {SegmentDefinition} definition a function used to generate a condition tree
|
|
76
|
+
* or a condition tree
|
|
77
|
+
* @example
|
|
78
|
+
* .addSegment(
|
|
79
|
+
* 'Wrote more than 2 books',
|
|
80
|
+
* new ConditionTreeLeaf('booksCount', 'GreaterThan', 2),
|
|
81
|
+
* );
|
|
82
|
+
*/
|
|
83
|
+
addSegment(name: string, definition: SegmentDefinition): this;
|
|
84
|
+
/**
|
|
85
|
+
* Enable sorting on a specific field using emulation.
|
|
86
|
+
* As for all the emulation method, the field sorting will be done in-memory.
|
|
87
|
+
* @param {string} name the name of the field to enable emulation on
|
|
88
|
+
* @example
|
|
89
|
+
* .emulateFieldSorting('fullName');
|
|
90
|
+
*/
|
|
91
|
+
emulateFieldSorting(name: string): this;
|
|
92
|
+
/**
|
|
93
|
+
* Replace an implementation for the sorting.
|
|
94
|
+
* The field sorting will be done by the datasource.
|
|
95
|
+
* @param {string} name the name of the field to enable sort
|
|
96
|
+
* @param {SortClause[]} equivalentSort the sort equivalent
|
|
97
|
+
* @example
|
|
98
|
+
* .replaceFieldSorting(
|
|
99
|
+
* 'fullName',
|
|
100
|
+
* [
|
|
101
|
+
* { field: 'firstName', ascending: true },
|
|
102
|
+
* { field: 'lastName', ascending: true },
|
|
103
|
+
* ]
|
|
104
|
+
* )
|
|
105
|
+
*/
|
|
106
|
+
replaceFieldSorting(name: string, equivalentSort: PlainSortClause[]): this;
|
|
107
|
+
/**
|
|
108
|
+
* Enable filtering on a specific field using emulation.
|
|
109
|
+
* As for all the emulation method, the field filtering will be done in-memory.
|
|
110
|
+
* @param name the name of the field to enable emulation on
|
|
111
|
+
* @example
|
|
112
|
+
* .emulateFieldFiltering('aField');
|
|
113
|
+
*/
|
|
114
|
+
emulateFieldFiltering(name: string): this;
|
|
115
|
+
/**
|
|
116
|
+
* Enable filtering on a specific field with a specific operator using emulation.
|
|
117
|
+
* As for all the emulation method, the field filtering will be done in-memory.
|
|
118
|
+
* @param {string} name the name of the field to enable emulation on
|
|
119
|
+
* @param {Operator} operator the operator to emulate
|
|
120
|
+
* @example
|
|
121
|
+
* .emulateFieldOperator('aField', 'In');
|
|
122
|
+
*/
|
|
123
|
+
emulateFieldOperator(name: string, operator: Operator): this;
|
|
124
|
+
/**
|
|
125
|
+
* Replace an implementation for a specific operator on a specific field.
|
|
126
|
+
* The operator replacement will be done by the datasource.
|
|
127
|
+
* @param {string} name the name of the field to filter on
|
|
128
|
+
* @param {Operator} operator the operator to replace
|
|
129
|
+
* @param {OperatorReplacer} replacer the proposed implementation
|
|
130
|
+
* @example
|
|
131
|
+
* .replaceFieldOperator('booksCount', 'Equal', ({ value }) => new ConditionTreeNot(
|
|
132
|
+
* new ConditionTreeLeaf('booksCount', 'Equal', value),
|
|
133
|
+
* ));
|
|
134
|
+
*/
|
|
135
|
+
replaceFieldOperator(name: string, operator: Operator, replacer: OperatorReplacer): this;
|
|
136
|
+
/**
|
|
137
|
+
* Replace the write behavior of a field.
|
|
138
|
+
* @param {string} name the name of the field
|
|
139
|
+
* @param {WriteDefinition} definition the function or a value to represent the write behavior
|
|
140
|
+
* @example
|
|
141
|
+
* .replaceFieldWriting('fullName', ({ patch: fullName }) => {
|
|
142
|
+
* const [firstName, lastName] = fullName.split(' ');
|
|
143
|
+
* return { firstName, lastName };
|
|
144
|
+
* });
|
|
145
|
+
*/
|
|
146
|
+
replaceFieldWriting(name: string, definition: WriteDefinition): this;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=collection.d.ts.map
|