@forestadmin/datasource-customizer 1.0.0-alpha.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/collection-customizer.d.ts +263 -0
- package/dist/collection-customizer.js +397 -0
- package/dist/context/agent-context.d.ts +11 -0
- package/dist/context/agent-context.js +20 -0
- package/dist/context/collection-context.d.ts +10 -0
- package/dist/context/collection-context.js +18 -0
- package/dist/context/relaxed-wrappers/collection.d.ts +112 -0
- package/dist/context/relaxed-wrappers/collection.js +161 -0
- package/dist/context/relaxed-wrappers/datasource.d.ts +15 -0
- package/dist/context/relaxed-wrappers/datasource.js +22 -0
- package/dist/datasource-customizer.d.ts +53 -0
- package/dist/datasource-customizer.js +89 -0
- package/dist/decorators/actions/collection.d.ts +18 -0
- package/dist/decorators/actions/collection.js +104 -0
- package/dist/decorators/actions/context/base.d.ts +28 -0
- package/dist/decorators/actions/context/base.js +105 -0
- package/dist/decorators/actions/context/single.d.ts +9 -0
- package/dist/decorators/actions/context/single.js +22 -0
- package/dist/decorators/actions/result-builder.d.ts +53 -0
- package/dist/decorators/actions/result-builder.js +81 -0
- package/dist/decorators/actions/types/actions.d.ts +18 -0
- package/dist/decorators/actions/types/actions.js +3 -0
- package/dist/decorators/actions/types/fields.d.ts +32 -0
- package/dist/decorators/actions/types/fields.js +3 -0
- package/dist/decorators/chart/datasource.d.ts +11 -0
- package/dist/decorators/chart/datasource.js +38 -0
- package/dist/decorators/chart/result-builder.d.ts +12 -0
- package/dist/decorators/chart/result-builder.js +48 -0
- package/dist/decorators/chart/types.d.ts +6 -0
- package/dist/decorators/chart/types.js +3 -0
- package/dist/decorators/collection-decorator.d.ts +21 -0
- package/dist/decorators/collection-decorator.js +57 -0
- package/dist/decorators/composite-datasource.d.ts +11 -0
- package/dist/decorators/composite-datasource.js +38 -0
- package/dist/decorators/computed/collection.d.ts +14 -0
- package/dist/decorators/computed/collection.js +69 -0
- package/dist/decorators/computed/helpers/compute-fields.d.ts +5 -0
- package/dist/decorators/computed/helpers/compute-fields.js +36 -0
- package/dist/decorators/computed/helpers/rewrite-projection.d.ts +4 -0
- package/dist/decorators/computed/helpers/rewrite-projection.js +22 -0
- package/dist/decorators/computed/types.d.ts +11 -0
- package/dist/decorators/computed/types.js +3 -0
- package/dist/decorators/computed/utils/deduplication.d.ts +2 -0
- package/dist/decorators/computed/utils/deduplication.js +28 -0
- package/dist/decorators/computed/utils/flattener.d.ts +6 -0
- package/dist/decorators/computed/utils/flattener.js +35 -0
- package/dist/decorators/datasource-decorator.d.ts +15 -0
- package/dist/decorators/datasource-decorator.js +27 -0
- package/dist/decorators/decorators-stack.d.ts +42 -0
- package/dist/decorators/decorators-stack.js +59 -0
- package/dist/decorators/empty/collection.d.ts +18 -0
- package/dist/decorators/empty/collection.js +85 -0
- package/dist/decorators/hook/collection.d.ts +13 -0
- package/dist/decorators/hook/collection.js +67 -0
- package/dist/decorators/hook/context/aggregate.d.ts +22 -0
- package/dist/decorators/hook/context/aggregate.js +46 -0
- package/dist/decorators/hook/context/create.d.ts +17 -0
- package/dist/decorators/hook/context/create.js +35 -0
- package/dist/decorators/hook/context/delete.d.ts +14 -0
- package/dist/decorators/hook/context/delete.js +28 -0
- package/dist/decorators/hook/context/hook.d.ts +26 -0
- package/dist/decorators/hook/context/hook.js +38 -0
- package/dist/decorators/hook/context/list.d.ts +20 -0
- package/dist/decorators/hook/context/list.js +42 -0
- package/dist/decorators/hook/context/update.d.ts +16 -0
- package/dist/decorators/hook/context/update.js +31 -0
- package/dist/decorators/hook/hook.d.ts +10 -0
- package/dist/decorators/hook/hook.js +30 -0
- package/dist/decorators/hook/types.d.ts +27 -0
- package/dist/decorators/hook/types.js +3 -0
- package/dist/decorators/operators-emulate/collection.d.ts +15 -0
- package/dist/decorators/operators-emulate/collection.js +99 -0
- package/dist/decorators/operators-emulate/types.d.ts +4 -0
- package/dist/decorators/operators-emulate/types.js +3 -0
- package/dist/decorators/operators-replace/collection.d.ts +10 -0
- package/dist/decorators/operators-replace/collection.js +35 -0
- package/dist/decorators/publication/collection.d.ts +14 -0
- package/dist/decorators/publication/collection.js +63 -0
- package/dist/decorators/relation/collection.d.ts +23 -0
- package/dist/decorators/relation/collection.js +190 -0
- package/dist/decorators/relation/types.d.ts +5 -0
- package/dist/decorators/relation/types.js +3 -0
- package/dist/decorators/rename-collection/collection.d.ts +15 -0
- package/dist/decorators/rename-collection/collection.js +50 -0
- package/dist/decorators/rename-collection/datasource.d.ts +11 -0
- package/dist/decorators/rename-collection/datasource.js +33 -0
- package/dist/decorators/rename-field/collection.d.ts +33 -0
- package/dist/decorators/rename-field/collection.js +149 -0
- package/dist/decorators/schema/collection.d.ts +13 -0
- package/dist/decorators/schema/collection.js +26 -0
- package/dist/decorators/search/collection.d.ts +14 -0
- package/dist/decorators/search/collection.js +105 -0
- package/dist/decorators/search/types.d.ts +4 -0
- package/dist/decorators/search/types.js +3 -0
- package/dist/decorators/segment/collection.d.ts +10 -0
- package/dist/decorators/segment/collection.js +43 -0
- package/dist/decorators/segment/types.d.ts +4 -0
- package/dist/decorators/segment/types.js +3 -0
- package/dist/decorators/sort-emulate/collection.d.ts +15 -0
- package/dist/decorators/sort-emulate/collection.js +97 -0
- package/dist/decorators/validation/collection.d.ts +20 -0
- package/dist/decorators/validation/collection.js +109 -0
- package/dist/decorators/write/collection.d.ts +26 -0
- package/dist/decorators/write/collection.js +214 -0
- package/dist/decorators/write/context.d.ts +9 -0
- package/dist/decorators/write/context.js +15 -0
- package/dist/decorators/write/types.d.ts +4 -0
- package/dist/decorators/write/types.js +3 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +27 -0
- package/dist/templates.d.ts +65 -0
- package/dist/templates.js +3 -0
- package/dist/types.d.ts +18 -0
- package/dist/types.js +3 -0
- package/dist/typing-generator.d.ts +19 -0
- package/dist/typing-generator.js +123 -0
- package/package.json +37 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
4
|
+
class CompositeDatasource extends datasource_toolkit_1.BaseDataSource {
|
|
5
|
+
constructor() {
|
|
6
|
+
super();
|
|
7
|
+
this.datasourceChartMapping = {};
|
|
8
|
+
}
|
|
9
|
+
addDataSource(dataSource) {
|
|
10
|
+
this.addCollections(dataSource);
|
|
11
|
+
this.addCharts(dataSource);
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
get schema() {
|
|
15
|
+
return { charts: Object.keys(this.datasourceChartMapping) };
|
|
16
|
+
}
|
|
17
|
+
renderChart(caller, name) {
|
|
18
|
+
if (!this.datasourceChartMapping[name]) {
|
|
19
|
+
throw new Error(`Chart '${name}' is not defined in the dataSource.`);
|
|
20
|
+
}
|
|
21
|
+
return this.datasourceChartMapping[name].renderChart(caller, name);
|
|
22
|
+
}
|
|
23
|
+
addCollections(dataSource) {
|
|
24
|
+
for (const collection of dataSource.collections) {
|
|
25
|
+
this.addCollection(collection);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
addCharts(dataSource) {
|
|
29
|
+
for (const chartName of dataSource.schema.charts) {
|
|
30
|
+
if (this.datasourceChartMapping[chartName]) {
|
|
31
|
+
throw new Error(`Chart '${chartName}' is already defined in datasource.`);
|
|
32
|
+
}
|
|
33
|
+
this.datasourceChartMapping[chartName] = dataSource;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.default = CompositeDatasource;
|
|
38
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9zaXRlLWRhdGFzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGVjb3JhdG9ycy9jb21wb3NpdGUtZGF0YXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHdFQU95QztBQUV6QyxNQUFxQixtQkFFbkIsU0FBUSxtQ0FBaUI7SUFHekI7UUFDRSxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxFQUFFLENBQUM7SUFDbkMsQ0FBQztJQUVELGFBQWEsQ0FBQyxVQUFzQjtRQUNsQyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFM0IsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsSUFBYSxNQUFNO1FBQ2pCLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsRUFBRSxDQUFDO0lBQzlELENBQUM7SUFFUSxXQUFXLENBQUMsTUFBYyxFQUFFLElBQVk7UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUN0QyxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsSUFBSSxxQ0FBcUMsQ0FBQyxDQUFDO1NBQ3RFO1FBRUQsT0FBTyxJQUFJLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRU8sY0FBYyxDQUFDLFVBQXNCO1FBQzNDLEtBQUssTUFBTSxVQUFVLElBQUksVUFBVSxDQUFDLFdBQVcsRUFBRTtZQUMvQyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQWUsQ0FBQyxDQUFDO1NBQ3JDO0lBQ0gsQ0FBQztJQUVPLFNBQVMsQ0FBQyxVQUFzQjtRQUN0QyxLQUFLLE1BQU0sU0FBUyxJQUFJLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO1lBQ2hELElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUMxQyxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsU0FBUyxxQ0FBcUMsQ0FBQyxDQUFDO2FBQzNFO1lBRUQsSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxHQUFHLFVBQVUsQ0FBQztTQUNyRDtJQUNILENBQUM7Q0FDRjtBQTVDRCxzQ0E0Q0MifQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AggregateResult, Aggregation, Caller, CollectionSchema, Filter, PaginatedFilter, Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { ComputedDefinition } from './types';
|
|
3
|
+
import CollectionDecorator from '../collection-decorator';
|
|
4
|
+
import DataSourceDecorator from '../datasource-decorator';
|
|
5
|
+
/** Decorator injects computed fields */
|
|
6
|
+
export default class ComputedCollection extends CollectionDecorator {
|
|
7
|
+
readonly dataSource: DataSourceDecorator<ComputedCollection>;
|
|
8
|
+
protected computeds: Record<string, ComputedDefinition>;
|
|
9
|
+
registerComputed(name: string, computed: ComputedDefinition): void;
|
|
10
|
+
list(caller: Caller, filter: PaginatedFilter, projection: Projection): Promise<RecordData[]>;
|
|
11
|
+
aggregate(caller: Caller, filter: Filter, aggregation: Aggregation, limit?: number): Promise<AggregateResult[]>;
|
|
12
|
+
protected refineSchema(childSchema: CollectionSchema): CollectionSchema;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
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_context_1 = __importDefault(require("../../context/collection-context"));
|
|
8
|
+
const collection_decorator_1 = __importDefault(require("../collection-decorator"));
|
|
9
|
+
const compute_fields_1 = __importDefault(require("./helpers/compute-fields"));
|
|
10
|
+
const rewrite_projection_1 = __importDefault(require("./helpers/rewrite-projection"));
|
|
11
|
+
/** Decorator injects computed fields */
|
|
12
|
+
class ComputedCollection extends collection_decorator_1.default {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.computeds = {};
|
|
16
|
+
}
|
|
17
|
+
/** @internal */
|
|
18
|
+
getComputed(path) {
|
|
19
|
+
const index = path.indexOf(':');
|
|
20
|
+
if (index === -1)
|
|
21
|
+
return this.computeds[path];
|
|
22
|
+
const { foreignCollection } = this.schema.fields[path.substring(0, index)];
|
|
23
|
+
const association = this.dataSource.getCollection(foreignCollection);
|
|
24
|
+
return association.getComputed(path.substring(index + 1));
|
|
25
|
+
}
|
|
26
|
+
registerComputed(name, computed) {
|
|
27
|
+
// Check that all dependencies exist and are columns
|
|
28
|
+
for (const field of computed.dependencies) {
|
|
29
|
+
datasource_toolkit_1.FieldValidator.validate(this, field);
|
|
30
|
+
}
|
|
31
|
+
if (computed.dependencies.length <= 0) {
|
|
32
|
+
throw new Error(`Computed field '${this.name}.${name}' must have at least one dependency.`);
|
|
33
|
+
}
|
|
34
|
+
this.computeds[name] = computed;
|
|
35
|
+
this.markSchemaAsDirty();
|
|
36
|
+
}
|
|
37
|
+
async list(caller, filter, projection) {
|
|
38
|
+
const childProjection = projection.replace(path => (0, rewrite_projection_1.default)(this, path));
|
|
39
|
+
const records = await this.childCollection.list(caller, filter, childProjection);
|
|
40
|
+
const context = new collection_context_1.default(this, caller);
|
|
41
|
+
return (0, compute_fields_1.default)(context, this, childProjection, projection, records);
|
|
42
|
+
}
|
|
43
|
+
async aggregate(caller, filter, aggregation, limit) {
|
|
44
|
+
// No computed are used in the aggregation => just delegate to the underlying collection.
|
|
45
|
+
if (!aggregation.projection.some(field => this.getComputed(field))) {
|
|
46
|
+
return this.childCollection.aggregate(caller, filter, aggregation, limit);
|
|
47
|
+
}
|
|
48
|
+
// Fallback to full emulation.
|
|
49
|
+
return aggregation.apply(await this.list(caller, filter, aggregation.projection), caller.timezone, limit);
|
|
50
|
+
}
|
|
51
|
+
refineSchema(childSchema) {
|
|
52
|
+
const schema = { ...childSchema, fields: { ...childSchema.fields } };
|
|
53
|
+
for (const [name, computed] of Object.entries(this.computeds)) {
|
|
54
|
+
schema.fields[name] = {
|
|
55
|
+
columnType: computed.columnType,
|
|
56
|
+
defaultValue: computed.defaultValue,
|
|
57
|
+
enumValues: computed.enumValues,
|
|
58
|
+
filterOperators: new Set(),
|
|
59
|
+
isPrimaryKey: false,
|
|
60
|
+
isReadOnly: true,
|
|
61
|
+
isSortable: false,
|
|
62
|
+
type: 'Column',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return schema;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.default = ComputedCollection;
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL2NvbXB1dGVkL2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx3RUFXeUM7QUFHekMsMEZBQThFO0FBQzlFLG1GQUEwRDtBQUUxRCw4RUFBMEQ7QUFDMUQsc0ZBQXdEO0FBRXhELHdDQUF3QztBQUN4QyxNQUFxQixrQkFBbUIsU0FBUSw4QkFBbUI7SUFBbkU7O1FBRVksY0FBUyxHQUF1QyxFQUFFLENBQUM7SUE0RS9ELENBQUM7SUExRUMsZ0JBQWdCO0lBQ2hCLFdBQVcsQ0FBQyxJQUFZO1FBQ3RCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTlDLE1BQU0sRUFBRSxpQkFBaUIsRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFtQixDQUFDO1FBQzdGLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUM7UUFFckUsT0FBTyxXQUFXLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUQsQ0FBQztJQUVELGdCQUFnQixDQUFDLElBQVksRUFBRSxRQUE0QjtRQUN6RCxvREFBb0Q7UUFDcEQsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLENBQUMsWUFBWSxFQUFFO1lBQ3pDLG1DQUFjLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQztTQUN0QztRQUVELElBQUksUUFBUSxD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
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import CollectionCustomizationContext from '../../../context/collection-context';
|
|
3
|
+
import ComputedCollection from '../collection';
|
|
4
|
+
export default function computeFromRecords(ctx: CollectionCustomizationContext, collection: ComputedCollection, recordsProjection: Projection, desiredProjection: Projection, records: RecordData[]): Promise<RecordData[]>;
|
|
5
|
+
//# sourceMappingURL=compute-fields.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
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 flattener_1 = require("../utils/flattener");
|
|
8
|
+
const deduplication_1 = __importDefault(require("../utils/deduplication"));
|
|
9
|
+
async function computeField(ctx, computed, paths, promises) {
|
|
10
|
+
return (0, deduplication_1.default)((0, flattener_1.unflatten)(await Promise.all(promises), new datasource_toolkit_1.Projection(...paths)), async (uniquePartials) => computed.getValues(uniquePartials, ctx));
|
|
11
|
+
}
|
|
12
|
+
function queueField(ctx, collection, newPath, paths, promises) {
|
|
13
|
+
// Skip double computations (we're not checking before adding to queue).
|
|
14
|
+
if (!paths.includes(newPath)) {
|
|
15
|
+
const computed = collection.getComputed(newPath);
|
|
16
|
+
const nestedDependencies = new datasource_toolkit_1.Projection(...computed.dependencies).nest(newPath.includes(':') ? newPath.substring(0, newPath.lastIndexOf(':')) : null);
|
|
17
|
+
// Queue dependencies (so that computed can await them).
|
|
18
|
+
nestedDependencies.forEach(path => queueField(ctx, collection, path, paths, promises));
|
|
19
|
+
// Queue computed
|
|
20
|
+
const dependencyValues = nestedDependencies.map(path => promises[paths.indexOf(path)]);
|
|
21
|
+
paths.push(newPath);
|
|
22
|
+
promises.push(computeField(ctx, computed, computed.dependencies, dependencyValues));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function computeFromRecords(ctx, collection, recordsProjection, desiredProjection, records) {
|
|
26
|
+
// Format data for easy computation (one cell per path, with all values).
|
|
27
|
+
const paths = recordsProjection.slice();
|
|
28
|
+
const promises = (0, flattener_1.flatten)(records, paths).map(values => Promise.resolve(values));
|
|
29
|
+
// Queue all computations, and perform them all at once
|
|
30
|
+
desiredProjection.forEach(path => queueField(ctx, collection, path, paths, promises));
|
|
31
|
+
const values = await Promise.all(promises);
|
|
32
|
+
// Quick reproject and unflatten.
|
|
33
|
+
return (0, flattener_1.unflatten)(desiredProjection.map(path => values[paths.indexOf(path)]), desiredProjection);
|
|
34
|
+
}
|
|
35
|
+
exports.default = computeFromRecords;
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcHV0ZS1maWVsZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGVjb3JhdG9ycy9jb21wdXRlZC9oZWxwZXJzL2NvbXB1dGUtZmllbGRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBQXlFO0FBR3pFLGtEQUF3RDtBQUd4RCwyRUFBMkQ7QUFFM0QsS0FBSyxVQUFVLFlBQVksQ0FDekIsR0FBbUMsRUFDbkMsUUFBNEIsRUFDNUIsS0FBZSxFQUNmLFFBQThCO0lBRTlCLE9BQU8sSUFBQSx1QkFBcUIsRUFDMUIsSUFBQSxxQkFBUyxFQUFDLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLCtCQUFVLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxFQUNoRSxLQUFLLEVBQUMsY0FBYyxFQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGNBQWMsRUFBRSxHQUFHLENBQUMsQ0FDaEUsQ0FBQztBQUNKLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FDakIsR0FBbUMsRUFDbkMsVUFBOEIsRUFDOUIsT0FBZSxFQUNmLEtBQWUsRUFDZixRQUE4QjtJQUU5Qix3RUFBd0U7SUFDeEUsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUU7UUFDNUIsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNqRCxNQUFNLGtCQUFrQixHQUFHLElBQUksK0JBQVUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxJQUFJLENBQ3RFLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUM5RSxDQUFDO1FBRUYsd0RBQXdEO1FBQ3hELGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUV2RixpQkFBaUI7UUFDakIsTUFBTSxnQkFBZ0IsR0FBRyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFdkYsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNwQixRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0tBQ3JGO0FBQ0gsQ0FBQztBQUVjLEtBQUssVUFBVSxrQkFBa0IsQ0FDOUMsR0FBbUMsRUFDbkMsVUFBOEIsRUFDOUIsaUJBQTZCLEVBQzdCLGlCQUE2QixFQUM3QixPQUFxQjtJQUVyQix5RUFBeUU7SUFDekUsTUFBTSxLQUFLLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxFQUFnQixDQUFDO0lBQ3RELE1BQU0sUUFBUSxHQUFHLElBQUEsbUJBQU8sRUFBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBRWhGLHVEQUF1RDtJQUN2RCxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFDdEYsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTNDLGlDQUFpQztJQUNqQyxPQUFPLElBQUEscUJBQVMsRUFDZCxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQzFELGlCQUFpQixDQUNsQixDQUFDO0FBQ0osQ0FBQztBQXBCRCxxQ0FvQkMifQ==
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
4
|
+
function rewriteField(collection, path) {
|
|
5
|
+
// Projection is targeting a field on another collection => recurse.
|
|
6
|
+
if (path.includes(':')) {
|
|
7
|
+
const [prefix] = path.split(':');
|
|
8
|
+
const schema = collection.schema.fields[prefix];
|
|
9
|
+
const association = collection.dataSource.getCollection(schema.foreignCollection);
|
|
10
|
+
return new datasource_toolkit_1.Projection(path)
|
|
11
|
+
.unnest()
|
|
12
|
+
.replace(subPath => rewriteField(association, subPath))
|
|
13
|
+
.nest(prefix);
|
|
14
|
+
}
|
|
15
|
+
// Computed field that we own: recursively replace by dependencies
|
|
16
|
+
const computed = collection.getComputed(path);
|
|
17
|
+
return computed
|
|
18
|
+
? new datasource_toolkit_1.Projection(...computed.dependencies).replace(depPath => rewriteField(collection, depPath))
|
|
19
|
+
: new datasource_toolkit_1.Projection(path);
|
|
20
|
+
}
|
|
21
|
+
exports.default = rewriteField;
|
|
22
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV3cml0ZS1wcm9qZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2RlY29yYXRvcnMvY29tcHV0ZWQvaGVscGVycy9yZXdyaXRlLXByb2plY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSx3RUFBNkU7QUFJN0UsU0FBd0IsWUFBWSxDQUFDLFVBQThCLEVBQUUsSUFBWTtJQUMvRSxvRUFBb0U7SUFDcEUsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ3RCLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2pDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBbUIsQ0FBQztRQUNsRSxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUMsVUFBVSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQUVsRixPQUFPLElBQUksK0JBQVUsQ0FBQyxJQUFJLENBQUM7YUFDeEIsTUFBTSxFQUFFO2FBQ1IsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxPQUFPLENBQUMsQ0FBQzthQUN0RCxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDakI7SUFFRCxrRUFBa0U7SUFDbEUsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUU5QyxPQUFPLFFBQVE7UUFDYixDQUFDLENBQUMsSUFBSSwrQkFBVSxDQUFDLEdBQUcsUUFBUSxDQUFDLFlBQVksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDaEcsQ0FBQyxDQUFDLElBQUksK0JBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUMzQixDQUFDO0FBbkJELCtCQW1CQyJ9
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ColumnType } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { TCollectionName, TFieldName, TRow, TSchema } from '../../templates';
|
|
3
|
+
import CollectionCustomizationContext from '../../context/collection-context';
|
|
4
|
+
export interface ComputedDefinition<S extends TSchema = TSchema, N extends TCollectionName<S> = TCollectionName<S>> {
|
|
5
|
+
readonly columnType: ColumnType;
|
|
6
|
+
readonly dependencies: TFieldName<S, N>[];
|
|
7
|
+
readonly defaultValue?: unknown;
|
|
8
|
+
readonly enumValues?: string[];
|
|
9
|
+
getValues(records: TRow<S, N>[], context: CollectionCustomizationContext<S, N>): Promise<unknown[]> | unknown[];
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGVjb3JhdG9ycy9jb21wdXRlZC90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
|
|
@@ -0,0 +1,28 @@
|
|
|
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 object_hash_1 = __importDefault(require("object-hash"));
|
|
7
|
+
async function transformUniqueValues(inputs, callback) {
|
|
8
|
+
const indexes = {};
|
|
9
|
+
const mapping = [];
|
|
10
|
+
const uniqueInputs = [];
|
|
11
|
+
for (const input of inputs) {
|
|
12
|
+
if (input !== null) {
|
|
13
|
+
const hash = (0, object_hash_1.default)(input);
|
|
14
|
+
if (indexes[hash] === undefined) {
|
|
15
|
+
indexes[hash] = uniqueInputs.length;
|
|
16
|
+
uniqueInputs.push(input);
|
|
17
|
+
}
|
|
18
|
+
mapping.push(indexes[hash]);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
mapping.push(-1);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const uniqueOutputs = await callback(uniqueInputs);
|
|
25
|
+
return mapping.map(index => (index !== -1 ? uniqueOutputs[index] : null));
|
|
26
|
+
}
|
|
27
|
+
exports.default = transformUniqueValues;
|
|
28
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVkdXBsaWNhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL2NvbXB1dGVkL3V0aWxzL2RlZHVwbGljYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4REFBcUM7QUFFdEIsS0FBSyxVQUFVLHFCQUFxQixDQUNqRCxNQUFlLEVBQ2YsUUFBZ0Q7SUFFaEQsTUFBTSxPQUFPLEdBQTJCLEVBQUUsQ0FBQztJQUMzQyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFDN0IsTUFBTSxZQUFZLEdBQVksRUFBRSxDQUFDO0lBRWpDLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFO1FBQzFCLElBQUksS0FBSyxLQUFLLElBQUksRUFBRTtZQUNsQixNQUFNLElBQUksR0FBRyxJQUFBLHFCQUFVLEVBQUMsS0FBSyxDQUFDLENBQUM7WUFFL0IsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssU0FBUyxFQUFFO2dCQUMvQixPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQztnQkFDcEMsWUFBWSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUMxQjtZQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7U0FDN0I7YUFBTTtZQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUNsQjtLQUNGO0lBRUQsTUFBTSxhQUFhLEdBQUcsTUFBTSxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFbkQsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUM1RSxDQUFDO0FBMUJELHdDQTBCQyJ9
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
declare type FlatRecordList = Array<unknown[]>;
|
|
3
|
+
export declare function unflatten(flatList: FlatRecordList, projection: Projection): RecordData[];
|
|
4
|
+
export declare function flatten(records: RecordData[], projection: string[]): FlatRecordList;
|
|
5
|
+
export {};
|
|
6
|
+
//# sourceMappingURL=flattener.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.flatten = exports.unflatten = void 0;
|
|
4
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
5
|
+
function unflatten(flatList, projection) {
|
|
6
|
+
const numRecords = flatList[0]?.length ?? 0;
|
|
7
|
+
const records = [];
|
|
8
|
+
for (let i = 0; i < numRecords; i += 1)
|
|
9
|
+
records[i] = {};
|
|
10
|
+
// Set fields
|
|
11
|
+
for (const column of projection.columns) {
|
|
12
|
+
const pathIndex = projection.indexOf(column);
|
|
13
|
+
for (const [index, value] of flatList[pathIndex].entries())
|
|
14
|
+
records[index][column] = value ?? null;
|
|
15
|
+
}
|
|
16
|
+
// Set relations
|
|
17
|
+
for (const [relation, paths] of Object.entries(projection.relations)) {
|
|
18
|
+
const subFlatList = [];
|
|
19
|
+
for (const path of paths)
|
|
20
|
+
subFlatList.push(flatList[projection.indexOf(`${relation}:${path}`)]);
|
|
21
|
+
const subRecords = unflatten(subFlatList, paths);
|
|
22
|
+
for (const index of records.keys())
|
|
23
|
+
records[index][relation] = subRecords[index];
|
|
24
|
+
}
|
|
25
|
+
// Keep only objects where at least a non-null value is set
|
|
26
|
+
return records.map(r => {
|
|
27
|
+
return Object.values(r).some(v => v !== null) ? r : null;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
exports.unflatten = unflatten;
|
|
31
|
+
function flatten(records, projection) {
|
|
32
|
+
return projection.map(field => records.map(r => datasource_toolkit_1.RecordUtils.getFieldValue(r, field)));
|
|
33
|
+
}
|
|
34
|
+
exports.flatten = flatten;
|
|
35
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmxhdHRlbmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2RlY29yYXRvcnMvY29tcHV0ZWQvdXRpbHMvZmxhdHRlbmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHdFQUFzRjtBQUl0RixTQUFnQixTQUFTLENBQUMsUUFBd0IsRUFBRSxVQUFzQjtJQUN4RSxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxJQUFJLENBQUMsQ0FBQztJQUM1QyxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7SUFDbkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQztRQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7SUFFeEQsYUFBYTtJQUNiLEtBQUssTUFBTSxNQUFNLElBQUksVUFBVSxDQUFDLE9BQU8sRUFBRTtRQUN2QyxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTdDLEtBQUssTUFBTSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFO1lBQ3hELE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxLQUFLLElBQUksSUFBSSxDQUFDO0tBQzFDO0lBRUQsZ0JBQWdCO0lBQ2hCLEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRTtRQUNwRSxNQUFNLFdBQVcsR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLO1lBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLFFBQVEsSUFBSSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUVoRyxNQUFNLFVBQVUsR0FBRyxTQUFTLENBQUMsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQ2pELEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxDQUFDLElBQUksRUFBRTtZQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLENBQUMsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDbEY7SUFFRCwyREFBMkQ7SUFDM0QsT0FBTyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ3JCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzNELENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQTFCRCw4QkEwQkM7QUFFRCxTQUFnQixPQUFPLENBQUMsT0FBcUIsRUFBRSxVQUFvQjtJQUNqRSxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsZ0NBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUN4RixDQUFDO0FBRkQsMEJBRUMifQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { BaseDataSource, Caller, Chart, Collection, DataSource, DataSourceSchema } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
declare type CollectionDecoratorConstructor<CollectionDecorator extends Collection> = {
|
|
3
|
+
new (c: Collection, d: DataSource): CollectionDecorator;
|
|
4
|
+
};
|
|
5
|
+
export default class DataSourceDecorator<CollectionDecorator extends Collection = Collection> extends BaseDataSource<CollectionDecorator> {
|
|
6
|
+
protected readonly childDataSource: DataSource;
|
|
7
|
+
private readonly CollectionDecoratorCtor;
|
|
8
|
+
private readonly addCollectionToChildDataSource;
|
|
9
|
+
get schema(): DataSourceSchema;
|
|
10
|
+
constructor(childDataSource: DataSource, CollectionDecoratorCtor: CollectionDecoratorConstructor<CollectionDecorator>);
|
|
11
|
+
renderChart(caller: Caller, name: string): Promise<Chart>;
|
|
12
|
+
private addCollectionObserver;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=datasource-decorator.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const datasource_toolkit_1 = require("@forestadmin/datasource-toolkit");
|
|
4
|
+
class DataSourceDecorator extends datasource_toolkit_1.BaseDataSource {
|
|
5
|
+
constructor(childDataSource, CollectionDecoratorCtor) {
|
|
6
|
+
super();
|
|
7
|
+
this.addCollectionToChildDataSource = childDataSource.addCollection.bind(childDataSource);
|
|
8
|
+
Reflect.defineProperty(childDataSource, 'addCollection', {
|
|
9
|
+
value: this.addCollectionObserver.bind(this),
|
|
10
|
+
});
|
|
11
|
+
this.childDataSource = childDataSource;
|
|
12
|
+
this.CollectionDecoratorCtor = CollectionDecoratorCtor;
|
|
13
|
+
this.childDataSource.collections.forEach(collection => this.addCollection(new this.CollectionDecoratorCtor(collection, this)));
|
|
14
|
+
}
|
|
15
|
+
get schema() {
|
|
16
|
+
return this.childDataSource.schema;
|
|
17
|
+
}
|
|
18
|
+
renderChart(caller, name) {
|
|
19
|
+
return this.childDataSource.renderChart(caller, name);
|
|
20
|
+
}
|
|
21
|
+
addCollectionObserver(collection) {
|
|
22
|
+
this.addCollectionToChildDataSource(collection);
|
|
23
|
+
this.addCollection(new this.CollectionDecoratorCtor(collection, this));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.default = DataSourceDecorator;
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXNvdXJjZS1kZWNvcmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZGVjb3JhdG9ycy9kYXRhc291cmNlLWRlY29yYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLHdFQU95QztBQU16QyxNQUFxQixtQkFFbkIsU0FBUSxtQ0FBbUM7SUFTM0MsWUFDRSxlQUEyQixFQUMzQix1QkFBNEU7UUFFNUUsS0FBSyxFQUFFLENBQUM7UUFFUixJQUFJLENBQUMsOEJBQThCLEdBQUcsZUFBZSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDMUYsT0FBTyxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUUsZUFBZSxFQUFFO1lBQ3ZELEtBQUssRUFBRSxJQUFJLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztTQUM3QyxDQUFDLENBQUM7UUFFSCxJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQztRQUN2QyxJQUFJLENBQUMsdUJBQXVCLEdBQUcsdUJBQXVCLENBQUM7UUFFdkQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQ3BELElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxJQUFJLENBQUMsdUJBQXVCLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQ3ZFLENBQUM7SUFDSixDQUFDO0lBckJELElBQWEsTUFBTTtRQUNqQixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDO0lBQ3JDLENBQUM7SUFxQlEsV0FBVyxDQUFDLE1BQWMsRUFBRSxJQUFZO1FBQy9DLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFTyxxQkFBcUIsQ0FBQyxVQUFzQjtRQUNsRCxJQUFJLENBQUMsOEJBQThCLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDaEQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUN6RSxDQUFDO0NBQ0Y7QUF0Q0Qsc0NBc0NDIn0=
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DataSource } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import ActionCollectionDecorator from './actions/collection';
|
|
3
|
+
import ChartDataSourceDecorator from './chart/datasource';
|
|
4
|
+
import ComputedCollectionDecorator from './computed/collection';
|
|
5
|
+
import DataSourceDecorator from './datasource-decorator';
|
|
6
|
+
import EmptyCollectionDecorator from './empty/collection';
|
|
7
|
+
import HookCollectionDecorator from './hook/collection';
|
|
8
|
+
import OperatorsEmulateCollectionDecorator from './operators-emulate/collection';
|
|
9
|
+
import OperatorsReplaceCollectionDecorator from './operators-replace/collection';
|
|
10
|
+
import PublicationCollectionDecorator from './publication/collection';
|
|
11
|
+
import RelationCollectionDecorator from './relation/collection';
|
|
12
|
+
import RenameFieldCollectionDecorator from './rename-field/collection';
|
|
13
|
+
import SchemaCollectionDecorator from './schema/collection';
|
|
14
|
+
import SearchCollectionDecorator from './search/collection';
|
|
15
|
+
import SegmentCollectionDecorator from './segment/collection';
|
|
16
|
+
import SortEmulateCollectionDecorator from './sort-emulate/collection';
|
|
17
|
+
import ValidationCollectionDecorator from './validation/collection';
|
|
18
|
+
import WriteCollectionDecorator from './write/collection';
|
|
19
|
+
export default class DecoratorsStack {
|
|
20
|
+
action: DataSourceDecorator<ActionCollectionDecorator>;
|
|
21
|
+
chart: ChartDataSourceDecorator;
|
|
22
|
+
earlyComputed: DataSourceDecorator<ComputedCollectionDecorator>;
|
|
23
|
+
earlyOpEmulate: DataSourceDecorator<OperatorsEmulateCollectionDecorator>;
|
|
24
|
+
earlyOpReplace: DataSourceDecorator<OperatorsReplaceCollectionDecorator>;
|
|
25
|
+
empty: DataSourceDecorator<EmptyCollectionDecorator>;
|
|
26
|
+
relation: DataSourceDecorator<RelationCollectionDecorator>;
|
|
27
|
+
lateComputed: DataSourceDecorator<ComputedCollectionDecorator>;
|
|
28
|
+
lateOpEmulate: DataSourceDecorator<OperatorsEmulateCollectionDecorator>;
|
|
29
|
+
lateOpReplace: DataSourceDecorator<OperatorsReplaceCollectionDecorator>;
|
|
30
|
+
publication: DataSourceDecorator<PublicationCollectionDecorator>;
|
|
31
|
+
renameField: DataSourceDecorator<RenameFieldCollectionDecorator>;
|
|
32
|
+
schema: DataSourceDecorator<SchemaCollectionDecorator>;
|
|
33
|
+
search: DataSourceDecorator<SearchCollectionDecorator>;
|
|
34
|
+
segment: DataSourceDecorator<SegmentCollectionDecorator>;
|
|
35
|
+
sortEmulate: DataSourceDecorator<SortEmulateCollectionDecorator>;
|
|
36
|
+
validation: DataSourceDecorator<ValidationCollectionDecorator>;
|
|
37
|
+
write: DataSourceDecorator<WriteCollectionDecorator>;
|
|
38
|
+
hook: DataSourceDecorator<HookCollectionDecorator>;
|
|
39
|
+
dataSource: DataSource;
|
|
40
|
+
constructor(dataSource: DataSource);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=decorators-stack.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
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 collection_1 = __importDefault(require("./actions/collection"));
|
|
7
|
+
const datasource_1 = __importDefault(require("./chart/datasource"));
|
|
8
|
+
const collection_2 = __importDefault(require("./computed/collection"));
|
|
9
|
+
const datasource_decorator_1 = __importDefault(require("./datasource-decorator"));
|
|
10
|
+
const collection_3 = __importDefault(require("./empty/collection"));
|
|
11
|
+
const collection_4 = __importDefault(require("./hook/collection"));
|
|
12
|
+
const collection_5 = __importDefault(require("./operators-emulate/collection"));
|
|
13
|
+
const collection_6 = __importDefault(require("./operators-replace/collection"));
|
|
14
|
+
const collection_7 = __importDefault(require("./publication/collection"));
|
|
15
|
+
const collection_8 = __importDefault(require("./relation/collection"));
|
|
16
|
+
const collection_9 = __importDefault(require("./rename-field/collection"));
|
|
17
|
+
const collection_10 = __importDefault(require("./schema/collection"));
|
|
18
|
+
const collection_11 = __importDefault(require("./search/collection"));
|
|
19
|
+
const collection_12 = __importDefault(require("./segment/collection"));
|
|
20
|
+
const collection_13 = __importDefault(require("./sort-emulate/collection"));
|
|
21
|
+
const collection_14 = __importDefault(require("./validation/collection"));
|
|
22
|
+
const collection_15 = __importDefault(require("./write/collection"));
|
|
23
|
+
class DecoratorsStack {
|
|
24
|
+
constructor(dataSource) {
|
|
25
|
+
let last = dataSource;
|
|
26
|
+
/* eslint-disable no-multi-assign */
|
|
27
|
+
// Step 0: Do not query datasource when we know the result with yield an empty set.
|
|
28
|
+
last = this.empty = new datasource_decorator_1.default(last, collection_3.default);
|
|
29
|
+
// Step 1: Computed-Relation-Computed sandwich (needed because some emulated relations depend
|
|
30
|
+
// on computed fields, and some computed fields depend on relation...)
|
|
31
|
+
// Note that replacement goes before emulation, as replacements may use emulated operators.
|
|
32
|
+
last = this.earlyComputed = new datasource_decorator_1.default(last, collection_2.default);
|
|
33
|
+
last = this.earlyOpEmulate = new datasource_decorator_1.default(last, collection_5.default);
|
|
34
|
+
last = this.earlyOpReplace = new datasource_decorator_1.default(last, collection_6.default);
|
|
35
|
+
last = this.relation = new datasource_decorator_1.default(last, collection_8.default);
|
|
36
|
+
last = this.lateComputed = new datasource_decorator_1.default(last, collection_2.default);
|
|
37
|
+
last = this.lateOpEmulate = new datasource_decorator_1.default(last, collection_5.default);
|
|
38
|
+
last = this.lateOpReplace = new datasource_decorator_1.default(last, collection_6.default);
|
|
39
|
+
// Step 2: Those need access to all fields. They can be loaded in any order.
|
|
40
|
+
last = this.search = new datasource_decorator_1.default(last, collection_11.default);
|
|
41
|
+
last = this.segment = new datasource_decorator_1.default(last, collection_12.default);
|
|
42
|
+
last = this.sortEmulate = new datasource_decorator_1.default(last, collection_13.default);
|
|
43
|
+
last = this.write = new datasource_decorator_1.default(last, collection_15.default);
|
|
44
|
+
// Step 3: Access to all fields AND emulated capabilities
|
|
45
|
+
last = this.validation = new datasource_decorator_1.default(last, collection_14.default);
|
|
46
|
+
last = this.chart = new datasource_1.default(last);
|
|
47
|
+
last = this.action = new datasource_decorator_1.default(last, collection_1.default);
|
|
48
|
+
last = this.schema = new datasource_decorator_1.default(last, collection_10.default);
|
|
49
|
+
last = this.hook = new datasource_decorator_1.default(last, collection_4.default);
|
|
50
|
+
// Step 4: Renaming must be either the very first or very last so that naming in customer code
|
|
51
|
+
// is consistent.
|
|
52
|
+
last = this.publication = new datasource_decorator_1.default(last, collection_7.default);
|
|
53
|
+
last = this.renameField = new datasource_decorator_1.default(last, collection_9.default);
|
|
54
|
+
/* eslint-enable no-multi-assign */
|
|
55
|
+
this.dataSource = last;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.default = DecoratorsStack;
|
|
59
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjb3JhdG9ycy1zdGFjay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9kZWNvcmF0b3JzL2RlY29yYXRvcnMtc3RhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSxzRUFBNkQ7QUFDN0Qsb0VBQTBEO0FBQzFELHVFQUFnRTtBQUNoRSxrRkFBeUQ7QUFDekQsb0VBQTBEO0FBQzFELG1FQUF3RDtBQUN4RCxnRkFBaUY7QUFDakYsZ0ZBQWlGO0FBQ2pGLDBFQUFzRTtBQUN0RSx1RUFBZ0U7QUFDaEUsMkVBQXVFO0FBQ3ZFLHNFQUE0RDtBQUM1RCxzRUFBNEQ7QUFDNUQsdUVBQThEO0FBQzlELDRFQUF1RTtBQUN2RSwwRUFBb0U7QUFDcEUscUVBQTBEO0FBRTFELE1BQXFCLGVBQWU7SUFzQmxDLFlBQVksVUFBc0I7UUFDaEMsSUFBSSxJQUFJLEdBQWUsVUFBVSxDQUFDO1FBRWxDLG9DQUFvQztRQUNwQyxtRkFBbUY7UUFDbkYsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxJQUFJLEVBQUUsb0JBQXdCLENBQUMsQ0FBQztRQUU1RSw2RkFBNkY7UUFDN0Ysc0VBQXNFO1FBQ3RFLDJGQUEyRjtRQUMzRixJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxvQkFBMkIsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksR0FBRyxJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksOEJBQW1CLENBQUMsSUFBSSxFQUFFLG9CQUFtQyxDQUFDLENBQUM7UUFDaEcsSUFBSSxHQUFHLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxJQUFJLEVBQUUsb0JBQW1DLENBQUMsQ0FBQztRQUNoRyxJQUFJLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxvQkFBMkIsQ0FBQyxDQUFDO1FBQ2xGLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksOEJBQW1CLENBQUMsSUFBSSxFQUFFLG9CQUEyQixDQUFDLENBQUM7UUFDdEYsSUFBSSxHQUFHLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxJQUFJLEVBQUUsb0JBQW1DLENBQUMsQ0FBQztRQUMvRixJQUFJLEdBQUcsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxvQkFBbUMsQ0FBQyxDQUFDO1FBRS9GLDRFQUE0RTtRQUM1RSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxxQkFBeUIsQ0FBQyxDQUFDO1FBQzlFLElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksOEJBQW1CLENBQUMsSUFBSSxFQUFFLHFCQUEwQixDQUFDLENBQUM7UUFDaEYsSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxJQUFJLEVBQUUscUJBQThCLENBQUMsQ0FBQztRQUN4RixJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxxQkFBd0IsQ0FBQyxDQUFDO1FBRTVFLHlEQUF5RDtRQUN6RCxJQUFJLEdBQUcsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxxQkFBNkIsQ0FBQyxDQUFDO1FBQ3RGLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksb0JBQXdCLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdkQsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSw4QkFBbUIsQ0FBQyxJQUFJLEVBQUUsb0JBQXlCLENBQUMsQ0FBQztRQUM5RSxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxxQkFBeUIsQ0FBQyxDQUFDO1FBQzlFLElBQUksR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksOEJBQW1CLENBQUMsSUFBSSxFQUFFLG9CQUF1QixDQUFDLENBQUM7UUFFMUUsOEZBQThGO1FBQzlGLGlCQUFpQjtRQUNqQixJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLDhCQUFtQixDQUFDLElBQUksRUFBRSxvQkFBOEIsQ0FBQyxDQUFDO1FBQ3hGLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksOEJBQW1CLENBQUMsSUFBSSxFQUFFLG9CQUE4QixDQUFDLENBQUM7UUFDeEYsbUNBQW1DO1FBRW5DLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDO0lBQ3pCLENBQUM7Q0FDRjtBQTdERCxrQ0E2REMifQ==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AggregateResult, Aggregation, Caller, Filter, PaginatedFilter, Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import CollectionDecorator from '../collection-decorator';
|
|
3
|
+
/**
|
|
4
|
+
* Avoid performing useless database requests:
|
|
5
|
+
* Using segments + scopes + filters + jointure emulation often yields requests which have
|
|
6
|
+
* mutually exclusive conditions or empty "In" leafs.
|
|
7
|
+
*/
|
|
8
|
+
export default class EmptyCollectionDecorator extends CollectionDecorator {
|
|
9
|
+
list(caller: Caller, filter: PaginatedFilter, projection: Projection): Promise<RecordData[]>;
|
|
10
|
+
update(caller: Caller, filter: Filter, patch: RecordData): Promise<void>;
|
|
11
|
+
delete(caller: Caller, filter: Filter): Promise<void>;
|
|
12
|
+
aggregate(caller: Caller, filter: Filter, aggregation: Aggregation, limit?: number): Promise<AggregateResult[]>;
|
|
13
|
+
private returnsEmptySet;
|
|
14
|
+
private leafReturnsEmptySet;
|
|
15
|
+
private orReturnsEmptySet;
|
|
16
|
+
private andReturnsEmptySet;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,85 @@
|
|
|
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_decorator_1 = __importDefault(require("../collection-decorator"));
|
|
8
|
+
/**
|
|
9
|
+
* Avoid performing useless database requests:
|
|
10
|
+
* Using segments + scopes + filters + jointure emulation often yields requests which have
|
|
11
|
+
* mutually exclusive conditions or empty "In" leafs.
|
|
12
|
+
*/
|
|
13
|
+
class EmptyCollectionDecorator extends collection_decorator_1.default {
|
|
14
|
+
async list(caller, filter, projection) {
|
|
15
|
+
if (!this.returnsEmptySet(filter.conditionTree)) {
|
|
16
|
+
return super.list(caller, filter, projection);
|
|
17
|
+
}
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
async update(caller, filter, patch) {
|
|
21
|
+
if (!this.returnsEmptySet(filter.conditionTree)) {
|
|
22
|
+
return super.update(caller, filter, patch);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async delete(caller, filter) {
|
|
26
|
+
if (!this.returnsEmptySet(filter.conditionTree)) {
|
|
27
|
+
return super.delete(caller, filter);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async aggregate(caller, filter, aggregation, limit) {
|
|
31
|
+
if (!this.returnsEmptySet(filter.conditionTree)) {
|
|
32
|
+
return super.aggregate(caller, filter, aggregation, limit);
|
|
33
|
+
}
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
returnsEmptySet(tree) {
|
|
37
|
+
if (tree instanceof datasource_toolkit_1.ConditionTreeLeaf) {
|
|
38
|
+
return this.leafReturnsEmptySet(tree);
|
|
39
|
+
}
|
|
40
|
+
if (tree instanceof datasource_toolkit_1.ConditionTreeBranch && tree.aggregator === 'Or') {
|
|
41
|
+
return this.orReturnsEmptySet(tree.conditions);
|
|
42
|
+
}
|
|
43
|
+
if (tree instanceof datasource_toolkit_1.ConditionTreeBranch && tree.aggregator === 'And') {
|
|
44
|
+
return this.andReturnsEmptySet(tree.conditions);
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
leafReturnsEmptySet(leaf) {
|
|
49
|
+
// Empty 'in` always return zero records.
|
|
50
|
+
return leaf.operator === 'In' && leaf.value.length === 0;
|
|
51
|
+
}
|
|
52
|
+
orReturnsEmptySet(conditions) {
|
|
53
|
+
// Or return no records when
|
|
54
|
+
// - they have no conditions
|
|
55
|
+
// - they have only conditions which return zero records.
|
|
56
|
+
return conditions.length === 0 || conditions.every(c => this.returnsEmptySet(c));
|
|
57
|
+
}
|
|
58
|
+
andReturnsEmptySet(conditions) {
|
|
59
|
+
// There is a leaf which returns zero records
|
|
60
|
+
if (conditions.some(c => this.returnsEmptySet(c))) {
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
63
|
+
// Scans for mutually exclusive conditions
|
|
64
|
+
// (this a naive implementation, it will miss many occurences)
|
|
65
|
+
const valuesByField = {};
|
|
66
|
+
const leafs = conditions.filter(condition => condition instanceof datasource_toolkit_1.ConditionTreeLeaf);
|
|
67
|
+
for (const { field, operator, value } of leafs) {
|
|
68
|
+
if (!valuesByField[field] && operator === 'Equal') {
|
|
69
|
+
valuesByField[field] = [value];
|
|
70
|
+
}
|
|
71
|
+
else if (!valuesByField[field] && operator === 'In') {
|
|
72
|
+
valuesByField[field] = value;
|
|
73
|
+
}
|
|
74
|
+
else if (valuesByField[field] && operator === 'Equal') {
|
|
75
|
+
valuesByField[field] = valuesByField[field].includes(value) ? [value] : [];
|
|
76
|
+
}
|
|
77
|
+
else if (valuesByField[field] && operator === 'In') {
|
|
78
|
+
valuesByField[field] = valuesByField[field].filter(v => value.includes(v));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return Object.values(valuesByField).some(v => v.length === 0);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.default = EmptyCollectionDecorator;
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL2VtcHR5L2NvbGxlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx3RUFXeUM7QUFFekMsbUZBQTBEO0FBRTFEOzs7O0dBSUc7QUFDSCxNQUFxQix3QkFBeUIsU0FBUSw4QkFBbUI7SUFDOUQsS0FBSyxDQUFDLElBQUksQ0FDakIsTUFBYyxFQUNkLE1BQXVCLEVBQ3ZCLFVBQXNCO1FBRXRCLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFBRTtZQUMvQyxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLENBQUMsQ0FBQztTQUMvQztRQUVELE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVRLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBYyxFQUFFLE1BQWMsRUFBRSxLQUFpQjtRQUNyRSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDL0MsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7U0FDNUM7SUFDSCxDQUFDO0lBRVEsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFjLEVBQUUsTUFBYztRQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDL0MsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztTQUNyQztJQUNILENBQUM7SUFFUSxLQUFLLENBQUMsU0FBUyxDQUN0QixNQUFjLEVBQ2QsTUFBYyxFQUNkLFdBQXdCLEVBQ3hCLEtBQWM7UUFFZCxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQUU7WUFDL0MsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQzVEO1FBRUQsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRU8sZUFBZSxDQUFDLElBQW1CO1FBQ3pDLElBQUksSUFBSSxZQUFZLHNDQUFpQixFQUFFO1lBQ3JDLE9BQU8sSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3ZDO1FBRUQsSUFBSSxJQUFJLFlBQVksd0NBQW1CLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxJQUFJLEVBQUU7WUFDbkUsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQ2hEO1FBRUQsSUFBSSxJQUFJLFlBQVksd0NBQW1CLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxLQUFLLEVBQUU7WUFDcEUsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1NBQ2pEO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sbUJBQW1CLENBQUMsSUFBdUI7UUFDakQseUNBQXlDO1FBQ3pDLE9BQU8sSUFBSSxDQUFDLFFBQVEsS0FBSyxJQUFJLElBQUssSUFBSSxDQUFDLEtBQW1CLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBRU8saUJBQWlCLENBQUMsVUFBMkI7UUFDbkQsNEJBQTRCO1FBQzVCLDRCQUE0QjtRQUM1Qix5REFBeUQ7UUFDekQsT0FBTyxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25GLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxVQUEyQjtRQUNwRCw2Q0FBNkM7UUFDN0MsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQ2pELE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFFRCwwQ0FBMEM7UUFDMUMsOERBQThEO1FBQzlELE1BQU0sYUFBYSxHQUE4QixFQUFFLENBQUM7UUFDcEQsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FDN0IsU0FBUyxDQUFDLEVBQUUsQ0FBQyxTQUFTLFlBQVksc0NBQWlCLENBQzdCLENBQUM7UUFFekIsS0FBSyxNQUFNLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxLQUFLLEVBQUU7WUFDOUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsSUFBSSxRQUFRLEtBQUssT0FBTyxFQUFFO2dCQUNqRCxhQUFhLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQzthQUNoQztpQkFBTSxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUU7Z0JBQ3JELGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFrQixDQUFDO2FBQzNDO2lCQUFNLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLFFBQVEsS0FBSyxPQUFPLEVBQUU7Z0JBQ3ZELGFBQWEsQ0FBQyxLQUFLLENBQUMsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDNUU7aUJBQU0sSUFBSSxhQUFhLENBQUMsS0FBSyxDQUFDLElBQUksUUFBUSxLQUFLLElBQUksRUFBRTtnQkFDcEQsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBRSxLQUFtQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQzNGO1NBQ0Y7UUFFRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDO0NBQ0Y7QUE3RkQsMkNBNkZDIn0=
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AggregateResult, Aggregation, Caller, Filter, PaginatedFilter, Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { HookHandler, HookPosition, HookType, HooksContext } from './types';
|
|
3
|
+
import CollectionDecorator from '../collection-decorator';
|
|
4
|
+
export default class CollectionHookDecorator extends CollectionDecorator {
|
|
5
|
+
private hooks;
|
|
6
|
+
addHook<P extends HookPosition = HookPosition, T extends HookType = HookType>(position: P, type: T, handler: HookHandler<HooksContext[P][T]>): void;
|
|
7
|
+
create(caller: Caller, data: RecordData[]): Promise<RecordData[]>;
|
|
8
|
+
list(caller: Caller, filter: PaginatedFilter, projection: Projection): Promise<RecordData[]>;
|
|
9
|
+
update(caller: Caller, filter: Filter, patch: RecordData): Promise<void>;
|
|
10
|
+
delete(caller: Caller, filter: Filter): Promise<void>;
|
|
11
|
+
aggregate(caller: Caller, filter: Filter, aggregation: Aggregation, limit?: number): Promise<AggregateResult[]>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=collection.d.ts.map
|