@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,149 @@
|
|
|
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_decorator_1 = __importDefault(require("../collection-decorator"));
|
|
7
|
+
/**
|
|
8
|
+
* This decorator renames fields.
|
|
9
|
+
*
|
|
10
|
+
* It works on one side, by rewriting all references to fields in aggregations, filters, projections
|
|
11
|
+
* and on the other, by rewriting records and aggregation results which are returned by the
|
|
12
|
+
* subCollection.
|
|
13
|
+
*/
|
|
14
|
+
class RenameFieldCollectionDecorator extends collection_decorator_1.default {
|
|
15
|
+
constructor() {
|
|
16
|
+
super(...arguments);
|
|
17
|
+
this.fromChildCollection = {};
|
|
18
|
+
this.toChildCollection = {};
|
|
19
|
+
}
|
|
20
|
+
/** Rename a field from the collection */
|
|
21
|
+
renameField(currentName, newName) {
|
|
22
|
+
if (!this.schema.fields[currentName]) {
|
|
23
|
+
throw new Error(`No such field '${currentName}'`);
|
|
24
|
+
}
|
|
25
|
+
let initialName = currentName;
|
|
26
|
+
// Revert previous renaming (avoids conflicts and need to recurse on this.toSubCollection).
|
|
27
|
+
if (this.toChildCollection[currentName]) {
|
|
28
|
+
const childName = this.toChildCollection[currentName];
|
|
29
|
+
delete this.toChildCollection[currentName];
|
|
30
|
+
delete this.fromChildCollection[childName];
|
|
31
|
+
initialName = childName;
|
|
32
|
+
this.markAllSchemaAsDirty();
|
|
33
|
+
}
|
|
34
|
+
// Do not update arrays if renaming is a no-op (ie: customer is cancelling a previous rename).
|
|
35
|
+
if (initialName !== newName) {
|
|
36
|
+
this.fromChildCollection[initialName] = newName;
|
|
37
|
+
this.toChildCollection[newName] = initialName;
|
|
38
|
+
this.markAllSchemaAsDirty();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
refineSchema(childSchema) {
|
|
42
|
+
const fields = {};
|
|
43
|
+
for (const [oldName, oldSchema] of Object.entries(childSchema.fields)) {
|
|
44
|
+
const schema = { ...oldSchema };
|
|
45
|
+
if (schema.type === 'ManyToOne') {
|
|
46
|
+
schema.foreignKey = this.fromChildCollection[schema.foreignKey] ?? schema.foreignKey;
|
|
47
|
+
}
|
|
48
|
+
else if (schema.type === 'OneToMany' || schema.type === 'OneToOne') {
|
|
49
|
+
const relation = this.dataSource.getCollection(schema.foreignCollection);
|
|
50
|
+
schema.originKey = relation.fromChildCollection[schema.originKey] ?? schema.originKey;
|
|
51
|
+
}
|
|
52
|
+
else if (schema.type === 'ManyToMany') {
|
|
53
|
+
const through = this.dataSource.getCollection(schema.throughCollection);
|
|
54
|
+
schema.foreignKey = through.fromChildCollection[schema.foreignKey] ?? schema.foreignKey;
|
|
55
|
+
schema.originKey = through.fromChildCollection[schema.originKey] ?? schema.originKey;
|
|
56
|
+
}
|
|
57
|
+
fields[this.fromChildCollection[oldName] ?? oldName] = schema;
|
|
58
|
+
}
|
|
59
|
+
return { ...childSchema, fields };
|
|
60
|
+
}
|
|
61
|
+
async refineFilter(caller, filter) {
|
|
62
|
+
return filter?.override({
|
|
63
|
+
conditionTree: filter.conditionTree?.replaceFields(field => this.pathToChildCollection(field)),
|
|
64
|
+
sort: filter.sort?.replaceClauses(clause => ({
|
|
65
|
+
field: this.pathToChildCollection(clause.field),
|
|
66
|
+
ascending: clause.ascending,
|
|
67
|
+
})),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async create(caller, records) {
|
|
71
|
+
const newRecords = await super.create(caller, records.map(record => this.recordToChildCollection(record)));
|
|
72
|
+
return newRecords.map(record => this.recordFromChildCollection(record));
|
|
73
|
+
}
|
|
74
|
+
async list(caller, filter, projection) {
|
|
75
|
+
const childProjection = projection.replace(field => this.pathToChildCollection(field));
|
|
76
|
+
const records = await super.list(caller, filter, childProjection);
|
|
77
|
+
return records.map(record => this.recordFromChildCollection(record));
|
|
78
|
+
}
|
|
79
|
+
async update(caller, filter, patch) {
|
|
80
|
+
return super.update(caller, filter, this.recordToChildCollection(patch));
|
|
81
|
+
}
|
|
82
|
+
async aggregate(caller, filter, aggregation, limit) {
|
|
83
|
+
const rows = await super.aggregate(caller, filter, aggregation.replaceFields(f => this.pathToChildCollection(f)), limit);
|
|
84
|
+
return rows.map(row => ({
|
|
85
|
+
value: row.value,
|
|
86
|
+
group: Object.entries(row.group).reduce((memo, [path, value]) => ({ ...memo, [this.pathFromChildCollection(path)]: value }), {}),
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
markAllSchemaAsDirty() {
|
|
90
|
+
for (const collection of this.dataSource.collections) {
|
|
91
|
+
collection.markSchemaAsDirty();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** Convert field path from child collection to this collection */
|
|
95
|
+
pathFromChildCollection(childPath) {
|
|
96
|
+
if (childPath.includes(':')) {
|
|
97
|
+
const dotIndex = childPath.indexOf(':');
|
|
98
|
+
const childField = childPath.substring(0, dotIndex);
|
|
99
|
+
const thisField = this.fromChildCollection[childField] ?? childField;
|
|
100
|
+
const schema = this.schema.fields[thisField];
|
|
101
|
+
const relation = this.dataSource.getCollection(schema.foreignCollection);
|
|
102
|
+
return `${thisField}:${relation.pathFromChildCollection(childPath.substring(dotIndex + 1))}`;
|
|
103
|
+
}
|
|
104
|
+
return this.fromChildCollection[childPath] ?? childPath;
|
|
105
|
+
}
|
|
106
|
+
/** Convert field path from this collection to child collection */
|
|
107
|
+
pathToChildCollection(thisPath) {
|
|
108
|
+
if (thisPath.includes(':')) {
|
|
109
|
+
const dotIndex = thisPath.indexOf(':');
|
|
110
|
+
const thisField = thisPath.substring(0, dotIndex);
|
|
111
|
+
const schema = this.schema.fields[thisField];
|
|
112
|
+
const relation = this.dataSource.getCollection(schema.foreignCollection);
|
|
113
|
+
const childField = this.toChildCollection[thisField] ?? thisField;
|
|
114
|
+
return `${childField}:${relation.pathToChildCollection(thisPath.substring(dotIndex + 1))}`;
|
|
115
|
+
}
|
|
116
|
+
return this.toChildCollection[thisPath] ?? thisPath;
|
|
117
|
+
}
|
|
118
|
+
/** Convert record from this collection to the child collection */
|
|
119
|
+
recordToChildCollection(thisRecord) {
|
|
120
|
+
const childRecord = {};
|
|
121
|
+
for (const [thisField, value] of Object.entries(thisRecord)) {
|
|
122
|
+
childRecord[this.toChildCollection[thisField] ?? thisField] = value;
|
|
123
|
+
}
|
|
124
|
+
return childRecord;
|
|
125
|
+
}
|
|
126
|
+
/** Convert record from the child collection to this collection */
|
|
127
|
+
recordFromChildCollection(childRecord) {
|
|
128
|
+
const { schema } = this;
|
|
129
|
+
const thisRecord = {};
|
|
130
|
+
for (const [childField, value] of Object.entries(childRecord)) {
|
|
131
|
+
const thisField = this.fromChildCollection[childField] ?? childField;
|
|
132
|
+
const fieldSchema = schema.fields[thisField];
|
|
133
|
+
// Perform the mapping, recurse for relations.
|
|
134
|
+
if (fieldSchema.type === 'Column') {
|
|
135
|
+
thisRecord[thisField] = value;
|
|
136
|
+
}
|
|
137
|
+
else if (value === null) {
|
|
138
|
+
thisRecord[thisField] = value;
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
const relation = this.dataSource.getCollection(fieldSchema.foreignCollection);
|
|
142
|
+
thisRecord[thisField] = relation.recordFromChildCollection(value);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return thisRecord;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.default = RenameFieldCollectionDecorator;
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL3JlbmFtZS1maWVsZC9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBWUEsbUZBQTBEO0FBRzFEOzs7Ozs7R0FNRztBQUNILE1BQXFCLDhCQUErQixTQUFRLDhCQUFtQjtJQUEvRTs7UUFHbUIsd0JBQW1CLEdBQWtDLEVBQUUsQ0FBQztRQUN4RCxzQkFBaUIsR0FBbUMsRUFBRSxDQUFDO0lBb0wxRSxDQUFDO0lBbExDLHlDQUF5QztJQUN6QyxXQUFXLENBQUMsV0FBbUIsRUFBRSxPQUFlO1FBQzlDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRTtZQUNwQyxNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixXQUFXLEdBQUcsQ0FBQyxDQUFDO1NBQ25EO1FBRUQsSUFBSSxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBRTlCLDJGQUEyRjtRQUMzRixJQUFJLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsRUFBRTtZQUN2QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDdEQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDM0MsT0FBTyxJQUFJLENBQUMsbUJBQW1CLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDM0MsV0FBVyxHQUFHLFNBQVMsQ0FBQztZQUN4QixJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztTQUM3QjtRQUVELDhGQUE4RjtRQUM5RixJQUFJLFdBQVcsS0FBSyxPQUFPLEVBQUU7WUFDM0IsSUFBSSxDQUFDLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxHQUFHLE9BQU8sQ0FBQztZQUNoRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLEdBQUcsV0FBVyxD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
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { CollectionSchema } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import CollectionDecorator from '../collection-decorator';
|
|
3
|
+
/**
|
|
4
|
+
* This decorator allows to override parts of the collections schema.
|
|
5
|
+
* It can be used to toggle off collection level capabilities for performance
|
|
6
|
+
* (for now, list-view counts and the search bar)
|
|
7
|
+
*/
|
|
8
|
+
export default class SchemaCollectionDecorator extends CollectionDecorator {
|
|
9
|
+
private schemaOverride;
|
|
10
|
+
overrideSchema(value: Partial<CollectionSchema>): void;
|
|
11
|
+
protected refineSchema(subSchema: CollectionSchema): CollectionSchema;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
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_decorator_1 = __importDefault(require("../collection-decorator"));
|
|
7
|
+
/**
|
|
8
|
+
* This decorator allows to override parts of the collections schema.
|
|
9
|
+
* It can be used to toggle off collection level capabilities for performance
|
|
10
|
+
* (for now, list-view counts and the search bar)
|
|
11
|
+
*/
|
|
12
|
+
class SchemaCollectionDecorator extends collection_decorator_1.default {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.schemaOverride = {};
|
|
16
|
+
}
|
|
17
|
+
overrideSchema(value) {
|
|
18
|
+
Object.assign(this.schemaOverride, value);
|
|
19
|
+
this.markSchemaAsDirty();
|
|
20
|
+
}
|
|
21
|
+
refineSchema(subSchema) {
|
|
22
|
+
return { ...subSchema, ...this.schemaOverride };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.default = SchemaCollectionDecorator;
|
|
26
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL3NjaGVtYS9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQ0EsbUZBQTBEO0FBRTFEOzs7O0dBSUc7QUFDSCxNQUFxQix5QkFBMEIsU0FBUSw4QkFBbUI7SUFBMUU7O1FBQ1UsbUJBQWMsR0FBOEIsRUFBRSxDQUFDO0lBVXpELENBQUM7SUFSQyxjQUFjLENBQUMsS0FBZ0M7UUFDN0MsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFa0IsWUFBWSxDQUFDLFNBQTJCO1FBQ3pELE9BQU8sRUFBRSxHQUFHLFNBQVMsRUFBRSxHQUFHLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUNsRCxDQUFDO0NBQ0Y7QUFYRCw0Q0FXQyJ9
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Caller, CollectionSchema, PaginatedFilter } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { SearchDefinition } from './types';
|
|
3
|
+
import CollectionDecorator from '../collection-decorator';
|
|
4
|
+
export default class SearchCollectionDecorator extends CollectionDecorator {
|
|
5
|
+
replacer: SearchDefinition;
|
|
6
|
+
replaceSearch(replacer: SearchDefinition): void;
|
|
7
|
+
refineSchema(subSchema: CollectionSchema): CollectionSchema;
|
|
8
|
+
refineFilter(caller: Caller, filter?: PaginatedFilter): Promise<PaginatedFilter>;
|
|
9
|
+
private defaultReplacer;
|
|
10
|
+
private static buildCondition;
|
|
11
|
+
private static getFields;
|
|
12
|
+
private static lenientFind;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
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 uuid_1 = require("uuid");
|
|
8
|
+
const collection_context_1 = __importDefault(require("../../context/collection-context"));
|
|
9
|
+
const collection_decorator_1 = __importDefault(require("../collection-decorator"));
|
|
10
|
+
class SearchCollectionDecorator extends collection_decorator_1.default {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.replacer = null;
|
|
14
|
+
}
|
|
15
|
+
replaceSearch(replacer) {
|
|
16
|
+
this.replacer = replacer;
|
|
17
|
+
}
|
|
18
|
+
refineSchema(subSchema) {
|
|
19
|
+
return { ...subSchema, searchable: true };
|
|
20
|
+
}
|
|
21
|
+
async refineFilter(caller, filter) {
|
|
22
|
+
// Search string is not significant
|
|
23
|
+
if (!filter?.search?.trim().length) {
|
|
24
|
+
return filter.override({ search: null });
|
|
25
|
+
}
|
|
26
|
+
// Implement search ourselves
|
|
27
|
+
if (this.replacer || !this.childCollection.schema.searchable) {
|
|
28
|
+
const ctx = new collection_context_1.default(this, caller);
|
|
29
|
+
let tree = this.defaultReplacer(filter.search, filter.searchExtended);
|
|
30
|
+
if (this.replacer) {
|
|
31
|
+
const plainTree = await this.replacer(filter.search, filter.searchExtended, ctx);
|
|
32
|
+
tree = datasource_toolkit_1.ConditionTreeFactory.fromPlainObject(plainTree);
|
|
33
|
+
}
|
|
34
|
+
// Note that if no fields are searchable with the provided searchString, the conditions
|
|
35
|
+
// array might be empty, which will create a condition returning zero records
|
|
36
|
+
// (this is the desired behavior).
|
|
37
|
+
return filter.override({
|
|
38
|
+
conditionTree: datasource_toolkit_1.ConditionTreeFactory.intersect(filter.conditionTree, tree),
|
|
39
|
+
search: null,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// Let subcollection deal with the search
|
|
43
|
+
return filter;
|
|
44
|
+
}
|
|
45
|
+
defaultReplacer(search, extended) {
|
|
46
|
+
const searchableFields = SearchCollectionDecorator.getFields(this.childCollection, extended);
|
|
47
|
+
const conditions = searchableFields
|
|
48
|
+
.map(([field, schema]) => SearchCollectionDecorator.buildCondition(field, schema, search))
|
|
49
|
+
.filter(Boolean);
|
|
50
|
+
return datasource_toolkit_1.ConditionTreeFactory.union(...conditions);
|
|
51
|
+
}
|
|
52
|
+
static buildCondition(field, schema, searchString) {
|
|
53
|
+
const { columnType, enumValues, filterOperators } = schema;
|
|
54
|
+
const isNumber = Number(searchString).toString() === searchString;
|
|
55
|
+
const isUuid = (0, uuid_1.validate)(searchString);
|
|
56
|
+
if (columnType === 'Number' && isNumber && filterOperators?.has('Equal')) {
|
|
57
|
+
return new datasource_toolkit_1.ConditionTreeLeaf(field, 'Equal', Number(searchString));
|
|
58
|
+
}
|
|
59
|
+
if (columnType === 'Enum' && filterOperators?.has('Equal')) {
|
|
60
|
+
const searchValue = SearchCollectionDecorator.lenientFind(enumValues, searchString);
|
|
61
|
+
if (searchValue)
|
|
62
|
+
return new datasource_toolkit_1.ConditionTreeLeaf(field, 'Equal', searchValue);
|
|
63
|
+
}
|
|
64
|
+
if (columnType === 'String') {
|
|
65
|
+
const isCaseSensitive = searchString.toLocaleLowerCase() !== searchString.toLocaleUpperCase();
|
|
66
|
+
const supportsIContains = filterOperators?.has('IContains');
|
|
67
|
+
const supportsContains = filterOperators?.has('Contains');
|
|
68
|
+
const supportsEqual = filterOperators?.has('Equal');
|
|
69
|
+
// Perf: don't use case-insensitive operator when the search string is indifferent to case
|
|
70
|
+
let operator;
|
|
71
|
+
if (supportsIContains && (isCaseSensitive || !supportsContains))
|
|
72
|
+
operator = 'IContains';
|
|
73
|
+
else if (supportsContains)
|
|
74
|
+
operator = 'Contains';
|
|
75
|
+
else if (supportsEqual)
|
|
76
|
+
operator = 'Equal';
|
|
77
|
+
if (operator)
|
|
78
|
+
return new datasource_toolkit_1.ConditionTreeLeaf(field, operator, searchString);
|
|
79
|
+
}
|
|
80
|
+
if (columnType === 'Uuid' && isUuid && filterOperators?.has('Equal')) {
|
|
81
|
+
return new datasource_toolkit_1.ConditionTreeLeaf(field, 'Equal', searchString);
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
static getFields(collection, extended) {
|
|
86
|
+
const fields = [];
|
|
87
|
+
for (const [name, field] of Object.entries(collection.schema.fields)) {
|
|
88
|
+
if (field.type === 'Column')
|
|
89
|
+
fields.push([name, field]);
|
|
90
|
+
if (extended && (field.type === 'ManyToOne' || field.type === 'OneToOne')) {
|
|
91
|
+
const related = collection.dataSource.getCollection(field.foreignCollection);
|
|
92
|
+
for (const [subName, subField] of Object.entries(related.schema.fields))
|
|
93
|
+
if (subField.type === 'Column')
|
|
94
|
+
fields.push([`${name}:${subName}`, subField]);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return fields;
|
|
98
|
+
}
|
|
99
|
+
static lenientFind(haystack, needle) {
|
|
100
|
+
return (haystack?.find(v => v === needle.trim()) ??
|
|
101
|
+
haystack?.find(v => v.toLocaleLowerCase() === needle.toLocaleLowerCase().trim()));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.default = SearchCollectionDecorator;
|
|
105
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL3NlYXJjaC9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBVXlDO0FBQ3pDLCtCQUFnRDtBQUdoRCwwRkFBOEU7QUFDOUUsbUZBQTBEO0FBRTFELE1BQXFCLHlCQUEwQixTQUFRLDhCQUFtQjtJQUExRTs7UUFDRSxhQUFRLEdBQXFCLElBQUksQ0FBQztJQW1IcEMsQ0FBQztJQWpIQyxhQUFhLENBQUMsUUFBMEI7UUFDdEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUM7SUFDM0IsQ0FBQztJQUVlLFlBQVksQ0FBQyxTQUEyQjtRQUN0RCxPQUFPLEVBQUUsR0FBRyxTQUFTLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQzVDLENBQUM7SUFFZSxLQUFLLENBQUMsWUFBWSxDQUNoQyxNQUFjLEVBQ2QsTUFBd0I7UUFFeEIsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRTtZQUNsQyxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztTQUMxQztRQUVELDZCQUE2QjtRQUM3QixJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUU7WUFDNUQsTUFBTSxHQUFHLEdBQUcsSUFBSSw0QkFBOEIsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDN0QsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUV0RSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2pCLE1BQU0sU0FBUyxHQUFH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
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TCollectionName, TConditionTree, TSchema } from '../../templates';
|
|
2
|
+
import CollectionCustomizationContext from '../../context/collection-context';
|
|
3
|
+
export declare type SearchDefinition<S extends TSchema = TSchema, N extends TCollectionName<S> = TCollectionName<S>> = (value: string, extended: boolean, context: CollectionCustomizationContext<S, N>) => Promise<TConditionTree<S, N>> | TConditionTree<S, N>;
|
|
4
|
+
//# 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGVjb3JhdG9ycy9zZWFyY2gvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Caller, CollectionSchema, PaginatedFilter } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { SegmentDefinition } from './types';
|
|
3
|
+
import CollectionDecorator from '../collection-decorator';
|
|
4
|
+
export default class SegmentCollectionDecorator extends CollectionDecorator {
|
|
5
|
+
private segments;
|
|
6
|
+
addSegment(segmentName: string, definition: SegmentDefinition): void;
|
|
7
|
+
protected refineSchema(subSchema: CollectionSchema): CollectionSchema;
|
|
8
|
+
refineFilter(caller: Caller, filter?: PaginatedFilter): Promise<PaginatedFilter>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
class SegmentCollectionDecorator extends collection_decorator_1.default {
|
|
10
|
+
constructor() {
|
|
11
|
+
super(...arguments);
|
|
12
|
+
this.segments = {};
|
|
13
|
+
}
|
|
14
|
+
addSegment(segmentName, definition) {
|
|
15
|
+
this.segments[segmentName] = definition;
|
|
16
|
+
this.markSchemaAsDirty();
|
|
17
|
+
}
|
|
18
|
+
refineSchema(subSchema) {
|
|
19
|
+
return {
|
|
20
|
+
...subSchema,
|
|
21
|
+
segments: [...subSchema.segments, ...Object.keys(this.segments)],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
async refineFilter(caller, filter) {
|
|
25
|
+
if (!filter) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
let { conditionTree, segment } = filter;
|
|
29
|
+
if (segment && this.segments[segment]) {
|
|
30
|
+
const definition = this.segments[segment];
|
|
31
|
+
const result = typeof definition === 'function'
|
|
32
|
+
? await definition(new collection_context_1.default(this, caller))
|
|
33
|
+
: await definition;
|
|
34
|
+
const conditionTreeSegment = result instanceof datasource_toolkit_1.ConditionTree ? result : datasource_toolkit_1.ConditionTreeFactory.fromPlainObject(result);
|
|
35
|
+
datasource_toolkit_1.ConditionTreeValidator.validate(conditionTreeSegment, this);
|
|
36
|
+
conditionTree = datasource_toolkit_1.ConditionTreeFactory.intersect(conditionTree, conditionTreeSegment);
|
|
37
|
+
segment = null;
|
|
38
|
+
}
|
|
39
|
+
return filter.override({ conditionTree, segment });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.default = SegmentCollectionDecorator;
|
|
43
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL3NlZ21lbnQvY29sbGVjdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHdFQU95QztBQUV6QywwRkFBOEU7QUFDOUUsbUZBQTBEO0FBRTFELE1BQXFCLDBCQUEyQixTQUFRLDhCQUFtQjtJQUEzRTs7UUFDVSxhQUFRLEdBQTBDLEVBQUUsQ0FBQztJQTBDL0QsQ0FBQztJQXhDQyxVQUFVLENBQUMsV0FBbUIsRUFBRSxVQUE2QjtRQUMzRCxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxHQUFHLFVBQVUsQ0FBQztRQUN4QyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRWtCLFlBQVksQ0FBQyxTQUEyQjtRQUN6RCxPQUFPO1lBQ0wsR0FBRyxTQUFTO1lBQ1osUUFBUSxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsUUFBUSxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7U0FDakUsQ0FBQztJQUNKLENBQUM7SUFFZSxLQUFLLENBQUMsWUFBWSxDQUNoQyxNQUFjLEVBQ2QsTUFBd0I7UUFFeEIsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNYLE9BQU8sSUFBSSxDQUFDO1NBQ2I7UUFFRCxJQUFJLEVBQUUsYUFBYSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sQ0FBQztRQUV4QyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ3JDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDMUMsTUFBTSxNQUFNLEdBQ1YsT0FBTyxVQUFVLEtBQUssVUFBVTtnQkFDOUIsQ0FBQyxDQUFDLE1BQU0sVUFBVSxDQUFDLElBQUksNEJBQThCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUNwRSxDQUFDLENBQUMsTUFBTSxVQUFVLENBQUM7WUFFdkIsTUFBTSxvQkFBb0IsR0FDeEIsTUFBTSxZQUFZLGtDQUFhLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMseUNBQW9CLENBQUMsZUFBZSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBRTFGLDJDQUFzQixDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUU1RCxhQUFhLEdBQUcseUNBQW9CLENBQUMsU0FBUyxDQUFDLGFBQWEsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO1lBQ3BGLE9BQU8sR0FBRyxJQUFJLENBQUM7U0FDaEI7UUFFRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRCxDQUFDO0NBQ0Y7QUEzQ0QsNkNBMkNDIn0=
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TCollectionName, TConditionTree, TSchema } from '../../templates';
|
|
2
|
+
import CollectionCustomizationContext from '../../context/collection-context';
|
|
3
|
+
export declare type SegmentDefinition<S extends TSchema = TSchema, N extends TCollectionName<S> = TCollectionName<S>> = ((context: CollectionCustomizationContext<S, N>) => Promise<TConditionTree<S, N>> | TConditionTree<S, N>) | TConditionTree<S, N>;
|
|
4
|
+
//# 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGVjb3JhdG9ycy9zZWdtZW50L3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Caller, CollectionSchema, PaginatedFilter, PlainSortClause, Projection, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import CollectionDecorator from '../collection-decorator';
|
|
3
|
+
import DataSourceDecorator from '../datasource-decorator';
|
|
4
|
+
export default class SortEmulate extends CollectionDecorator {
|
|
5
|
+
readonly dataSource: DataSourceDecorator<SortEmulate>;
|
|
6
|
+
private readonly sorts;
|
|
7
|
+
emulateFieldSorting(name: string): void;
|
|
8
|
+
replaceFieldSorting(name: string, equivalentSort: PlainSortClause[]): void;
|
|
9
|
+
list(caller: Caller, filter: PaginatedFilter, projection: Projection): Promise<RecordData[]>;
|
|
10
|
+
protected refineSchema(childSchema: CollectionSchema): CollectionSchema;
|
|
11
|
+
private sortRecords;
|
|
12
|
+
private rewritePlainSortClause;
|
|
13
|
+
private isEmulated;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
class SortEmulate extends collection_decorator_1.default {
|
|
9
|
+
constructor() {
|
|
10
|
+
super(...arguments);
|
|
11
|
+
this.sorts = new Map();
|
|
12
|
+
}
|
|
13
|
+
emulateFieldSorting(name) {
|
|
14
|
+
this.replaceFieldSorting(name, null);
|
|
15
|
+
}
|
|
16
|
+
replaceFieldSorting(name, equivalentSort) {
|
|
17
|
+
datasource_toolkit_1.FieldValidator.validate(this, name);
|
|
18
|
+
const field = this.childCollection.schema.fields[name];
|
|
19
|
+
if (!field)
|
|
20
|
+
throw new Error('Cannot replace sort on relation');
|
|
21
|
+
this.sorts.set(name, equivalentSort ? new datasource_toolkit_1.Sort(...equivalentSort) : null);
|
|
22
|
+
this.markSchemaAsDirty();
|
|
23
|
+
}
|
|
24
|
+
async list(caller, filter, projection) {
|
|
25
|
+
const childFilter = filter.override({
|
|
26
|
+
sort: filter.sort?.replaceClauses(clause => this.rewritePlainSortClause(clause)),
|
|
27
|
+
});
|
|
28
|
+
if (!childFilter.sort?.some(({ field }) => this.isEmulated(field))) {
|
|
29
|
+
return this.childCollection.list(caller, childFilter, projection);
|
|
30
|
+
}
|
|
31
|
+
// Fetch the whole collection, but only with the fields we need to sort
|
|
32
|
+
let referenceRecords;
|
|
33
|
+
referenceRecords = await this.childCollection.list(caller, childFilter.override({ sort: null, page: null }), childFilter.sort.projection.withPks(this));
|
|
34
|
+
referenceRecords = childFilter.sort.apply(referenceRecords);
|
|
35
|
+
if (childFilter.page)
|
|
36
|
+
referenceRecords = childFilter.page.apply(referenceRecords);
|
|
37
|
+
// We now have the information we need to sort by the field
|
|
38
|
+
const newFilter = new datasource_toolkit_1.Filter({
|
|
39
|
+
conditionTree: datasource_toolkit_1.ConditionTreeFactory.matchRecords(this.schema, referenceRecords),
|
|
40
|
+
});
|
|
41
|
+
let records;
|
|
42
|
+
records = await this.childCollection.list(caller, newFilter, projection.withPks(this));
|
|
43
|
+
records = this.sortRecords(referenceRecords, records);
|
|
44
|
+
records = projection.apply(records);
|
|
45
|
+
return records;
|
|
46
|
+
}
|
|
47
|
+
refineSchema(childSchema) {
|
|
48
|
+
const fields = {};
|
|
49
|
+
for (const [name, schema] of Object.entries(childSchema.fields)) {
|
|
50
|
+
fields[name] =
|
|
51
|
+
this.sorts.has(name) && schema.type === 'Column' ? { ...schema, isSortable: true } : schema;
|
|
52
|
+
}
|
|
53
|
+
return { ...childSchema, fields };
|
|
54
|
+
}
|
|
55
|
+
sortRecords(referenceRecords, records) {
|
|
56
|
+
const positionById = {};
|
|
57
|
+
const sorted = new Array(records.length);
|
|
58
|
+
for (const [index, record] of referenceRecords.entries()) {
|
|
59
|
+
positionById[datasource_toolkit_1.RecordUtils.getPrimaryKey(this.schema, record).join('|')] = index;
|
|
60
|
+
}
|
|
61
|
+
for (const record of records) {
|
|
62
|
+
const id = datasource_toolkit_1.RecordUtils.getPrimaryKey(this.schema, record).join('|');
|
|
63
|
+
sorted[positionById[id]] = record;
|
|
64
|
+
}
|
|
65
|
+
return sorted;
|
|
66
|
+
}
|
|
67
|
+
rewritePlainSortClause(clause) {
|
|
68
|
+
// Order by is targeting a field on another collection => recurse.
|
|
69
|
+
if (clause.field.includes(':')) {
|
|
70
|
+
const [prefix] = clause.field.split(':');
|
|
71
|
+
const schema = this.schema.fields[prefix];
|
|
72
|
+
const association = this.dataSource.getCollection(schema.foreignCollection);
|
|
73
|
+
return new datasource_toolkit_1.Sort(clause)
|
|
74
|
+
.unnest()
|
|
75
|
+
.replaceClauses(subClause => association.rewritePlainSortClause(subClause))
|
|
76
|
+
.nest(prefix);
|
|
77
|
+
}
|
|
78
|
+
// Field that we own: recursively replace using equivalent sort
|
|
79
|
+
let equivalentSort = this.sorts.get(clause.field);
|
|
80
|
+
if (equivalentSort) {
|
|
81
|
+
if (!clause.ascending)
|
|
82
|
+
equivalentSort = equivalentSort.inverse();
|
|
83
|
+
return equivalentSort.replaceClauses(subClause => this.rewritePlainSortClause(subClause));
|
|
84
|
+
}
|
|
85
|
+
return new datasource_toolkit_1.Sort(clause);
|
|
86
|
+
}
|
|
87
|
+
isEmulated(path) {
|
|
88
|
+
const index = path.indexOf(':');
|
|
89
|
+
if (index === -1)
|
|
90
|
+
return this.sorts.has(path);
|
|
91
|
+
const { foreignCollection } = this.schema.fields[path.substring(0, index)];
|
|
92
|
+
const association = this.dataSource.getCollection(foreignCollection);
|
|
93
|
+
return association.isEmulated(path.substring(index + 1));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
exports.default = SortEmulate;
|
|
97
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29sbGVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9kZWNvcmF0b3JzL3NvcnQtZW11bGF0ZS9jb2xsZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsd0VBZXlDO0FBRXpDLG1GQUEwRDtBQUcxRCxNQUFxQixXQUFZLFNBQVEsOEJBQW1CO0lBQTVEOztRQUVtQixVQUFLLEdBQXNCLElBQUksR0FBRyxFQUFFLENBQUM7SUFpSHhELENBQUM7SUEvR0MsbUJBQW1CLENBQUMsSUFBWTtRQUM5QixJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxtQkFBbUIsQ0FBQyxJQUFZLEVBQUUsY0FBaUM7UUFDakUsbUNBQWMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRXBDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQWlCLENBQUM7UUFDdkUsSUFBSSxDQUFDLEtBQUs7WUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7UUFFL0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUMsSUFBSSx5QkFBSSxDQUFDLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBQzNCLENBQUM7SUFFUSxLQUFLLENBQUMsSUFBSSxDQUNqQixNQUFjLEVBQ2QsTUFBdUIsRUFDdkIsVUFBc0I7UUFFdEIsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztZQUNsQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxjQUFjLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJ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
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Caller, CollectionSchema, ColumnSchema, Filter, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import CollectionDecorator from '../collection-decorator';
|
|
3
|
+
declare type ValidationRule = ColumnSchema['validation'][number];
|
|
4
|
+
export default class ValidationDecorator extends CollectionDecorator {
|
|
5
|
+
private validation;
|
|
6
|
+
addValidation(name: string, validation: ValidationRule): void;
|
|
7
|
+
create(caller: Caller, data: RecordData[]): Promise<RecordData[]>;
|
|
8
|
+
update(caller: Caller, filter: Filter, patch: RecordData): Promise<void>;
|
|
9
|
+
protected refineSchema(subSchema: CollectionSchema): CollectionSchema;
|
|
10
|
+
private validate;
|
|
11
|
+
/**
|
|
12
|
+
* Deduplicate rules which the frontend understand
|
|
13
|
+
* We ignore other rules as duplications are not an issue within the agent
|
|
14
|
+
*/
|
|
15
|
+
private static deduplicate;
|
|
16
|
+
private static min;
|
|
17
|
+
private static max;
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=collection.d.ts.map
|