@forestadmin/datasource-mongoose 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/dist/collection.d.ts +15 -0
- package/dist/collection.js +141 -0
- package/dist/datasource.d.ts +12 -0
- package/dist/datasource.js +42 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +16 -0
- package/dist/mongoose/schema.d.ts +21 -0
- package/dist/mongoose/schema.js +89 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.js +3 -0
- package/dist/utils/helpers.d.ts +51 -0
- package/dist/utils/helpers.js +109 -0
- package/dist/utils/pipeline/filter.d.ts +18 -0
- package/dist/utils/pipeline/filter.js +160 -0
- package/dist/utils/pipeline/group.d.ts +15 -0
- package/dist/utils/pipeline/group.js +70 -0
- package/dist/utils/pipeline/lookup.d.ts +12 -0
- package/dist/utils/pipeline/lookup.js +49 -0
- package/dist/utils/pipeline/projection.d.ts +7 -0
- package/dist/utils/pipeline/projection.js +18 -0
- package/dist/utils/pipeline/reparent.d.ts +13 -0
- package/dist/utils/pipeline/reparent.js +71 -0
- package/dist/utils/pipeline/virtual-fields.d.ts +21 -0
- package/dist/utils/pipeline/virtual-fields.js +65 -0
- package/dist/utils/schema/fields.d.ts +18 -0
- package/dist/utils/schema/fields.js +110 -0
- package/dist/utils/schema/filter-operators.d.ts +9 -0
- package/dist/utils/schema/filter-operators.js +52 -0
- package/dist/utils/schema/relations.d.ts +19 -0
- package/dist/utils/schema/relations.js +75 -0
- package/package.json +31 -0
|
@@ -0,0 +1,160 @@
|
|
|
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 luxon_1 = require("luxon");
|
|
8
|
+
const mongoose_1 = require("mongoose");
|
|
9
|
+
const schema_1 = __importDefault(require("../../mongoose/schema"));
|
|
10
|
+
const STRING_OPERATORS = ['Like', 'ILike', 'NotContains', 'LongerThan', 'ShorterThan'];
|
|
11
|
+
/** Transform a forest admin filter into mongo pipeline */
|
|
12
|
+
class FilterGenerator {
|
|
13
|
+
static filter(model, prefix, filter) {
|
|
14
|
+
const schema = schema_1.default.fromModel(model).getSubSchema(prefix, true);
|
|
15
|
+
const fields = new Set();
|
|
16
|
+
const tree = filter?.conditionTree;
|
|
17
|
+
const match = this.computeMatch(schema, tree, fields);
|
|
18
|
+
const sort = this.computeSort(filter?.sort);
|
|
19
|
+
const pipeline = [];
|
|
20
|
+
if (fields.size)
|
|
21
|
+
pipeline.push(this.computeFields(fields));
|
|
22
|
+
if (match)
|
|
23
|
+
pipeline.push({ $match: match });
|
|
24
|
+
if (sort)
|
|
25
|
+
pipeline.push({ $sort: sort });
|
|
26
|
+
if (filter?.page?.skip !== undefined)
|
|
27
|
+
pipeline.push({ $skip: filter.page.skip });
|
|
28
|
+
if (filter?.page?.limit !== undefined)
|
|
29
|
+
pipeline.push({ $limit: filter.page.limit });
|
|
30
|
+
return pipeline;
|
|
31
|
+
}
|
|
32
|
+
static computeMatch(schema, tree, fields) {
|
|
33
|
+
if (tree instanceof datasource_toolkit_1.ConditionTreeBranch) {
|
|
34
|
+
return {
|
|
35
|
+
[`$${tree.aggregator.toLowerCase()}`]: tree.conditions.map(condition => this.computeMatch(schema, condition, fields)),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
if (tree instanceof datasource_toolkit_1.ConditionTreeLeaf) {
|
|
39
|
+
const value = this.formatAndCastLeafValue(schema, tree, fields);
|
|
40
|
+
const condition = this.buildMatchCondition(tree.operator, value);
|
|
41
|
+
return { [this.formatNestedFieldPath(tree.field)]: condition };
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
static formatAndCastLeafValue(schema, leaf, fields) {
|
|
46
|
+
// @fixme not a big fan of modifying the condition tree here.
|
|
47
|
+
// those objects should be frozen, as the modification will show if the condition tree
|
|
48
|
+
// is used after the request (for instance for "after hooks").
|
|
49
|
+
let { value } = leaf;
|
|
50
|
+
leaf.field = this.formatNestedFieldPath(leaf.field);
|
|
51
|
+
const { isArray, schemaType: { instance }, } = schema.getSubSchema(leaf.field, true);
|
|
52
|
+
// @fixme I'm really not sure that this can work in all cases.
|
|
53
|
+
// It assumes that the type of the value is the same than the type of the column
|
|
54
|
+
// which is not the case for many operators.
|
|
55
|
+
if (isArray) {
|
|
56
|
+
if (instance === 'Date' &&
|
|
57
|
+
Array.isArray(value) &&
|
|
58
|
+
value.every(v => luxon_1.DateTime.fromISO(v).isValid)) {
|
|
59
|
+
value = value.map(v => new Date(v));
|
|
60
|
+
}
|
|
61
|
+
else if (instance === 'ObjectID' &&
|
|
62
|
+
Array.isArray(value) &&
|
|
63
|
+
value.every(v => (0, mongoose_1.isValidObjectId)(v))) {
|
|
64
|
+
value = value.map(id => new mongoose_1.Types.ObjectId(id));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (instance === 'ObjectID') {
|
|
68
|
+
if (STRING_OPERATORS.includes(leaf.operator)) {
|
|
69
|
+
fields.add(leaf.field);
|
|
70
|
+
leaf.field = this.formatStringFieldName(leaf.field);
|
|
71
|
+
}
|
|
72
|
+
else if (Array.isArray(value) && value.every(v => (0, mongoose_1.isValidObjectId)(v))) {
|
|
73
|
+
value = value.map(id => new mongoose_1.Types.ObjectId(id));
|
|
74
|
+
}
|
|
75
|
+
else if ((0, mongoose_1.isValidObjectId)(value)) {
|
|
76
|
+
value = new mongoose_1.Types.ObjectId(value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else if (instance === 'Date') {
|
|
80
|
+
value = new Date(value);
|
|
81
|
+
}
|
|
82
|
+
return value;
|
|
83
|
+
}
|
|
84
|
+
static buildMatchCondition(operator, formattedLeafValue) {
|
|
85
|
+
switch (operator) {
|
|
86
|
+
case 'GreaterThan':
|
|
87
|
+
return { $gt: formattedLeafValue };
|
|
88
|
+
case 'LessThan':
|
|
89
|
+
return { $lt: formattedLeafValue };
|
|
90
|
+
case 'Equal':
|
|
91
|
+
return { $eq: formattedLeafValue };
|
|
92
|
+
case 'NotEqual':
|
|
93
|
+
return { $ne: formattedLeafValue };
|
|
94
|
+
case 'In':
|
|
95
|
+
return { $in: formattedLeafValue };
|
|
96
|
+
case 'IncludesAll':
|
|
97
|
+
return { $all: formattedLeafValue };
|
|
98
|
+
case 'NotContains':
|
|
99
|
+
return { $not: new RegExp(`.*${formattedLeafValue}.*`) };
|
|
100
|
+
case 'Like':
|
|
101
|
+
return this.like(formattedLeafValue, true);
|
|
102
|
+
case 'ILike':
|
|
103
|
+
return this.like(formattedLeafValue, false);
|
|
104
|
+
case 'Present':
|
|
105
|
+
return { $exists: true, $ne: null };
|
|
106
|
+
default:
|
|
107
|
+
throw new Error(`Unsupported '${operator}' operator`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/** @see https://stackoverflow.com/a/18418386/1897495 */
|
|
111
|
+
static like(pattern, caseSensitive) {
|
|
112
|
+
let regexp = pattern;
|
|
113
|
+
// eslint-disable-next-line no-useless-escape
|
|
114
|
+
regexp = regexp.replace(/([\.\\\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:\-])/g, '\\$1');
|
|
115
|
+
regexp = regexp.replace(/%/g, '.*').replace(/_/g, '.');
|
|
116
|
+
return RegExp(`^${regexp}$`, caseSensitive ? 'g' : 'gi');
|
|
117
|
+
}
|
|
118
|
+
static computeSort(sorts) {
|
|
119
|
+
if (!sorts || sorts.length === 0)
|
|
120
|
+
return null;
|
|
121
|
+
const result = {};
|
|
122
|
+
for (const { field, ascending } of sorts) {
|
|
123
|
+
const formattedField = this.formatNestedFieldPath(field);
|
|
124
|
+
result[formattedField] = ascending ? 1 : -1;
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
static computeFields(fields) {
|
|
129
|
+
return Array.from(fields).reduce((computed, field) => {
|
|
130
|
+
const stringField = this.formatStringFieldName(field);
|
|
131
|
+
computed.$addFields[stringField] = { $toString: `$${field}` };
|
|
132
|
+
return computed;
|
|
133
|
+
}, { $addFields: {} });
|
|
134
|
+
}
|
|
135
|
+
static formatNestedFieldPath(field) {
|
|
136
|
+
return field.replace(/:/g, '.');
|
|
137
|
+
}
|
|
138
|
+
static formatStringFieldName(field) {
|
|
139
|
+
const parentPath = this.getParentPath(field);
|
|
140
|
+
const fieldName = this.getFieldName(field);
|
|
141
|
+
if (parentPath === field) {
|
|
142
|
+
return `string_${fieldName}`;
|
|
143
|
+
}
|
|
144
|
+
return `${parentPath}.string_${fieldName}`;
|
|
145
|
+
}
|
|
146
|
+
static getParentPath(path) {
|
|
147
|
+
if (!path.includes('.')) {
|
|
148
|
+
return path;
|
|
149
|
+
}
|
|
150
|
+
return path.split('.').slice(0, -1).join('.');
|
|
151
|
+
}
|
|
152
|
+
static getFieldName(path) {
|
|
153
|
+
if (!path.includes('.')) {
|
|
154
|
+
return path;
|
|
155
|
+
}
|
|
156
|
+
return path.split('.').slice(-1).join('.');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.default = FilterGenerator;
|
|
160
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL3BpcGVsaW5lL2ZpbHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLHdFQU15QztBQUN6QyxpQ0FBaUM7QUFDakMsdUNBQXdFO0FBQ3hFLG1FQUFtRDtBQUVuRCxNQUFNLGdCQUFnQixHQUFHLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLGFBQWEsQ0FBQyxDQUFDO0FBRXZGLDBEQUEwRDtBQUMxRCxNQUFxQixlQUFlO0lBQ2xDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBcUIsRUFBRSxNQUFjLEVBQUUsTUFBdUI7UUFDMUUsTUFBTSxNQUFNLEdBQUcsZ0JBQWMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQztRQUUxRSxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ2pDLE1BQU0sSUFBSSxHQUFHLE1BQU0sRUFBRSxhQUFhLENBQUM7UUFDbkMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ3RELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDO1FBRTVDLE1BQU0sUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNwQixJQUFJLE1BQU0sQ0FBQyxJQUFJO1lBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDM0QsSUFBSSxLQUFLO1lBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQzVDLElBQUksSUFBSTtZQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMs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
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Aggregation } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { PipelineStage } from 'mongoose';
|
|
3
|
+
/** Transform a forest admin aggregation into mongo pipeline */
|
|
4
|
+
export default class GroupGenerator {
|
|
5
|
+
private static AGGREGATION_OPERATION;
|
|
6
|
+
private static GROUP_OPERATION;
|
|
7
|
+
static group(aggregation: Aggregation): PipelineStage[];
|
|
8
|
+
/** Compute aggregation value */
|
|
9
|
+
private static computeValue;
|
|
10
|
+
/** Compute _id field for the $group pipeline stage */
|
|
11
|
+
private static computeGroups;
|
|
12
|
+
/** Move fields in _id to the root of the document */
|
|
13
|
+
private static computeGroupsProjection;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=group.d.ts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** Transform a forest admin aggregation into mongo pipeline */
|
|
4
|
+
class GroupGenerator {
|
|
5
|
+
static group(aggregation) {
|
|
6
|
+
return [
|
|
7
|
+
{
|
|
8
|
+
$group: {
|
|
9
|
+
_id: this.computeGroups(aggregation.groups),
|
|
10
|
+
value: this.computeValue(aggregation),
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
$project: {
|
|
15
|
+
_id: 0,
|
|
16
|
+
value: '$value',
|
|
17
|
+
group: this.computeGroupsProjection(aggregation.groups),
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
/** Compute aggregation value */
|
|
23
|
+
static computeValue(aggregation) {
|
|
24
|
+
// Handle count(*) case
|
|
25
|
+
if (!aggregation.field)
|
|
26
|
+
return { $sum: 1 };
|
|
27
|
+
// General case
|
|
28
|
+
const field = `$${aggregation.field.replace(/:/g, '.')}`;
|
|
29
|
+
return aggregation.operation === 'Count'
|
|
30
|
+
? { $sum: { $cond: [{ $ne: [field, null] }, 1, 0] } }
|
|
31
|
+
: { [this.AGGREGATION_OPERATION[aggregation.operation]]: field };
|
|
32
|
+
}
|
|
33
|
+
/** Compute _id field for the $group pipeline stage */
|
|
34
|
+
static computeGroups(groups) {
|
|
35
|
+
return (groups ?? []).reduce((memo, group) => {
|
|
36
|
+
let field = `$${group.field.replace(/:/g, '.')}`;
|
|
37
|
+
if (group.operation) {
|
|
38
|
+
if (group.operation === 'Week') {
|
|
39
|
+
const date = { $dateTrunc: { date: field, startOfWeek: 'Monday', unit: 'week' } };
|
|
40
|
+
field = { $dateToString: { format: this.GROUP_OPERATION[group.operation], date } };
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
field = { $dateToString: { format: this.GROUP_OPERATION[group.operation], date: field } };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return { ...(memo ?? {}), [group.field]: field };
|
|
47
|
+
}, null);
|
|
48
|
+
}
|
|
49
|
+
/** Move fields in _id to the root of the document */
|
|
50
|
+
static computeGroupsProjection(groups) {
|
|
51
|
+
return groups?.length
|
|
52
|
+
? groups.reduce((memo, group) => ({ ...memo, [group.field]: `$_id.${group.field}` }), {})
|
|
53
|
+
: { $literal: {} };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
exports.default = GroupGenerator;
|
|
57
|
+
GroupGenerator.AGGREGATION_OPERATION = {
|
|
58
|
+
Sum: '$sum',
|
|
59
|
+
Avg: '$avg',
|
|
60
|
+
Count: '$sum',
|
|
61
|
+
Max: '$max',
|
|
62
|
+
Min: '$min',
|
|
63
|
+
};
|
|
64
|
+
GroupGenerator.GROUP_OPERATION = {
|
|
65
|
+
Year: '%Y-01-01',
|
|
66
|
+
Month: '%Y-%m-01',
|
|
67
|
+
Day: '%Y-%m-%d',
|
|
68
|
+
Week: '%Y-%m-%d',
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JvdXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvcGlwZWxpbmUvZ3JvdXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSwrREFBK0Q7QUFDL0QsTUFBcUIsY0FBYztJQWdCakMsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUF3QjtRQUNuQyxPQUFPO1lBQ0w7Z0JBQ0UsTUFBTSxFQUFFO29CQUNOLEdBQUcsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7b0JBQzNDLEtBQUssRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLFdBQVcsQ0FBQztpQkFDdEM7YUFDRjtZQUNEO2dCQUNFLFFBQVEsRUFBRTtvQkFDUixHQUFHLEVBQUUsQ0FBQztvQkFDTixLQUFLLEVBQUUsUUFBUTtvQkFDZixLQUFLLEVBQUUsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUM7aUJBQ3hEO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVELGdDQUFnQztJQUN4QixNQUFNLENBQUMsWUFBWSxDQUFDLFdBQXdCO1FBQ2xELHVCQUF1QjtRQUN2QixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUs7WUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1FBRTNDLGVBQWU7UUFDZixNQUFNLEtBQUssR0FBRyxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1FBRXpELE9BQU8sV0FBVyxDQUFDLFNBQVMsS0FBSyxPQUFPO1lBQ3RDLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7WUFDckQsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDckUsQ0FBQztJQUVELHNEQUFzRDtJQUM5QyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQTZCO1FBQ3hELE9BQU8sQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFO1lBQzNDLElBQUksS0FBSyxHQUFZLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFFMUQsSUFBSSxLQUFLLENBQUMsU0FBUyxFQUFFO2dCQUNuQixJQUFJLEtBQUssQ0FBQyxTQUFTLEtBQUssTUFBTSxFQUFFO29CQUM5QixNQUFNLElBQUksR0FBRyxFQUFFLFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsQ0FBQztvQkFDbEYsS0FBSyxHQUFHLEVBQUUsYUFBYSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7aUJBQ3BGO3FCQUFNO29CQUNMLEtBQUssR0FBRyxFQUFFLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQztpQkFDM0Y7YUFDRjtZQUVELE9BQU8sRUFBRSxHQUFHLENBQUMsSUFBSSxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ25ELENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNYLENBQUM7SUFFRCxxREFBcUQ7SUFDN0MsTUFBTSxDQUFDLHVCQUF1QixDQUFDLE1BQTZCO1FBQ2xFLE9BQU8sTUFBTSxFQUFFLE1BQU07WUFDbkIsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxJQUFJLEVBQUUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUUsUUFBUSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN6RixDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDdkIsQ0FBQzs7QUF0RUgsaUNBdUVDO0FBdEVnQixvQ0FBcUIsR0FBeUM7SUFDM0UsR0FBRyxFQUFFLE1BQU07SUFDWCxHQUFHLEVBQUUsTUFBTTtJQUNYLEtBQUssRUFBRSxNQUFNO0lBQ2IsR0FBRyxFQUFFLE1BQU07SUFDWCxHQUFHLEVBQUUsTUFBTTtDQUNaLENBQUM7QUFFYSw4QkFBZSxHQUFrQztJQUM5RCxJQUFJLEVBQUUsVUFBVTtJQUNoQixLQUFLLEVBQUUsVUFBVTtJQUNqQixHQUFHLEVBQUUsVUFBVTtJQUNmLElBQUksRUFBRSxVQUFVO0NBQ2pCLENBQUMifQ==
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Model, PipelineStage } from 'mongoose';
|
|
2
|
+
import { Projection } from '@forestadmin/datasource-toolkit';
|
|
3
|
+
/**
|
|
4
|
+
* Transform a forest admin projection into a mongo pipeline that performs the lookups
|
|
5
|
+
* and transformations to target them
|
|
6
|
+
*/
|
|
7
|
+
export default class LookupGenerator {
|
|
8
|
+
static lookup(model: Model<unknown>, prefix: string, projection: Projection): PipelineStage[];
|
|
9
|
+
private static lookupProjection;
|
|
10
|
+
private static lookupRelation;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=lookup.d.ts.map
|
|
@@ -0,0 +1,49 @@
|
|
|
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 schema_1 = __importDefault(require("../../mongoose/schema"));
|
|
7
|
+
/**
|
|
8
|
+
* Transform a forest admin projection into a mongo pipeline that performs the lookups
|
|
9
|
+
* and transformations to target them
|
|
10
|
+
*/
|
|
11
|
+
class LookupGenerator {
|
|
12
|
+
static lookup(model, prefix, projection) {
|
|
13
|
+
const childSchema = schema_1.default.fromModel(model).getSubSchema(prefix, true).fields;
|
|
14
|
+
return this.lookupProjection(model.db.models, null, childSchema, projection);
|
|
15
|
+
}
|
|
16
|
+
static lookupProjection(models, currentPath, schema, projection) {
|
|
17
|
+
const pipeline = [];
|
|
18
|
+
for (const [name, subProjection] of Object.entries(projection.relations))
|
|
19
|
+
pipeline.push(...this.lookupRelation(models, currentPath, schema, name, subProjection));
|
|
20
|
+
return pipeline;
|
|
21
|
+
}
|
|
22
|
+
static lookupRelation(models, currentPath, schema, name, subProjection) {
|
|
23
|
+
const as = currentPath ? `${currentPath}.${name}` : name;
|
|
24
|
+
// Native many to one relation
|
|
25
|
+
if (name.endsWith('__manyToOne')) {
|
|
26
|
+
const foreignKeyName = name.substring(0, name.length - '__manyToOne'.length);
|
|
27
|
+
const model = models[schema[foreignKeyName].options.ref];
|
|
28
|
+
const from = model.collection.collectionName;
|
|
29
|
+
const localField = currentPath ? `${currentPath}.${foreignKeyName}` : foreignKeyName;
|
|
30
|
+
const foreignField = '_id';
|
|
31
|
+
const subSchema = schema_1.default.fromModel(model).fields;
|
|
32
|
+
return [
|
|
33
|
+
// Push lookup to pipeline
|
|
34
|
+
{ $lookup: { from, localField, foreignField, as } },
|
|
35
|
+
{ $unwind: { path: `$${as}`, preserveNullAndEmptyArrays: true } },
|
|
36
|
+
// Recurse to get relations of relations
|
|
37
|
+
...this.lookupProjection(models, as, subSchema, subProjection),
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
// Fake relation or inverse of fake relation
|
|
41
|
+
if (name === 'parent' || schema[name]) {
|
|
42
|
+
return this.lookupProjection(models, as, schema[name], subProjection);
|
|
43
|
+
}
|
|
44
|
+
// We should have handled all possible cases.
|
|
45
|
+
throw new Error(`Unexpected relation: '${name}'`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.default = LookupGenerator;
|
|
49
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9va3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL3BpcGVsaW5lL2xvb2t1cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUVBLG1FQUFtRTtBQUVuRTs7O0dBR0c7QUFDSCxNQUFxQixlQUFlO0lBQ2xDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBcUIsRUFBRSxNQUFjLEVBQUUsVUFBc0I7UUFDekUsTUFBTSxXQUFXLEdBQUcsZ0JBQWMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsWUFBWSxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFFdEYsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsQ0FBQztJQUMvRSxDQUFDO0lBRU8sTUFBTSxDQUFDLGdCQUFnQixDQUM3QixNQUFzQyxFQUN0QyxXQUFtQixFQUNuQixNQUFrQixFQUNsQixVQUFzQjtRQUV0QixNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFFcEIsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQztZQUN0RSxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUUxRixPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRU8sTUFBTSxDQUFDLGNBQWMsQ0FDM0IsTUFBc0MsRUFDdEMsV0FBbUIsRUFDbkIsTUFBa0IsRUFDbEIsSUFBWSxFQUNaLGFBQXlCO1FBRXpCLE1BQU0sRUFBRSxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxXQUFXLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUV6RCw4QkFBOEI7UUFDOUIsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxFQUFFO1lBQ2hDLE1BQU0sY0FBYyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzdFLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBRXpELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO1lBQzdDLE1BQU0sVUFBVSxHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxXQUFXLElBQUksY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQztZQUNyRixNQUFNLFlBQVksR0FBRyxLQUFLLENBQUM7WUFFM0IsTUFBTSxTQUFTLEdBQUcsZ0JBQWMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBRXpELE9BQU87Z0JBQ0wsMEJBQTBCO2dCQUMxQixFQUFFLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxFQUFFO2dCQUNuRCxFQUFFLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLElBQUksRUFBRSxFQUFFO2dCQUVqRSx3Q0FBd0M7Z0JBQ3hDLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxFQUFFLEVBQUUsU0FBUyxFQUFFLGFBQWEsQ0FBQzthQUMvRCxDQUFDO1NBQ0g7UUFFRCw0Q0FBNEM7UUFDNUMsSUFBSSxJQUFJLEtBQUssUUFBUSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNyQyxPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxhQUFhLENBQUMsQ0FBQztTQUN2RTtRQUVELDZDQUE2QztRQUM3QyxNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQTNERCxrQ0EyREMifQ==
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { PipelineStage } from 'mongoose';
|
|
2
|
+
import { Projection } from '@forestadmin/datasource-toolkit';
|
|
3
|
+
/** Generate a mongo pipeline which applies a forest admin projection */
|
|
4
|
+
export default class ProjectionGenerator {
|
|
5
|
+
static project(projection: Projection): PipelineStage[];
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=projection.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
/** Generate a mongo pipeline which applies a forest admin projection */
|
|
4
|
+
class ProjectionGenerator {
|
|
5
|
+
static project(projection) {
|
|
6
|
+
if (projection.length === 0) {
|
|
7
|
+
return [{ $replaceRoot: { newRoot: { $literal: {} } } }];
|
|
8
|
+
}
|
|
9
|
+
const project = { _id: false };
|
|
10
|
+
for (const field of projection) {
|
|
11
|
+
const formattedField = field.replace(/:/g, '.');
|
|
12
|
+
project[formattedField] = true;
|
|
13
|
+
}
|
|
14
|
+
return [{ $project: project }];
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.default = ProjectionGenerator;
|
|
18
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy91dGlscy9waXBlbGluZS9wcm9qZWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBR0Esd0VBQXdFO0FBQ3hFLE1BQXFCLG1CQUFtQjtJQUN0QyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQXNCO1FBQ25DLElBQUksVUFBVSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDM0IsT0FBTyxDQUFDLEVBQUUsWUFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQzFEO1FBRUQsTUFBTSxPQUFPLEdBQXNDLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBRWxFLEtBQUssTUFBTSxLQUFLLElBQUksVUFBVSxFQUFFO1lBQzlCLE1BQU0sY0FBYyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQ2hELE9BQU8sQ0FBQyxjQUFjLENBQUMsR0FBRyxJQUFJLENBQUM7U0FDaEM7UUFFRCxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNqQyxDQUFDO0NBQ0Y7QUFmRCxzQ0FlQyJ9
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Model, PipelineStage } from 'mongoose';
|
|
2
|
+
/**
|
|
3
|
+
* Generate pipeline to query submodels.
|
|
4
|
+
*
|
|
5
|
+
* The operations make rotations in the documents so that the root is changed to the submodel
|
|
6
|
+
* without loosing the parent (which may be needed later on).
|
|
7
|
+
*/
|
|
8
|
+
export default class ReparentGenerator {
|
|
9
|
+
static reparent(model: Model<unknown>, prefix: string): PipelineStage[];
|
|
10
|
+
private static reparentArray;
|
|
11
|
+
private static reparentObject;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=reparent.d.ts.map
|
|
@@ -0,0 +1,71 @@
|
|
|
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 mongoose_1 = require("mongoose");
|
|
7
|
+
const schema_1 = __importDefault(require("../../mongoose/schema"));
|
|
8
|
+
/**
|
|
9
|
+
* Generate pipeline to query submodels.
|
|
10
|
+
*
|
|
11
|
+
* The operations make rotations in the documents so that the root is changed to the submodel
|
|
12
|
+
* without loosing the parent (which may be needed later on).
|
|
13
|
+
*/
|
|
14
|
+
class ReparentGenerator {
|
|
15
|
+
static reparent(model, prefix) {
|
|
16
|
+
if (!prefix?.length)
|
|
17
|
+
return [];
|
|
18
|
+
// Take only the part of the records we are interested in
|
|
19
|
+
const pipeline = [];
|
|
20
|
+
let schema = schema_1.default.fromModel(model).fields;
|
|
21
|
+
for (const part of prefix.split('.')) {
|
|
22
|
+
pipeline.push(...(schema[part]['[]']
|
|
23
|
+
? this.reparentArray(part, schema[part]['[]'] instanceof mongoose_1.SchemaType)
|
|
24
|
+
: this.reparentObject(part, schema[part] instanceof mongoose_1.SchemaType)));
|
|
25
|
+
schema = schema[part];
|
|
26
|
+
if (schema['[]'])
|
|
27
|
+
schema = schema['[]'];
|
|
28
|
+
}
|
|
29
|
+
// If we end up on a field, create a virtual record
|
|
30
|
+
return pipeline;
|
|
31
|
+
}
|
|
32
|
+
static reparentArray(prefix, inDoc) {
|
|
33
|
+
return [
|
|
34
|
+
{ $unwind: { path: `$${prefix}`, includeArrayIndex: 'index' } },
|
|
35
|
+
{
|
|
36
|
+
$replaceRoot: {
|
|
37
|
+
newRoot: {
|
|
38
|
+
$mergeObjects: [
|
|
39
|
+
inDoc ? { content: `$${prefix}` } : `$${prefix}`,
|
|
40
|
+
{
|
|
41
|
+
_id: { $concat: [{ $toString: '$_id' }, `.${prefix}.`, { $toString: '$index' }] },
|
|
42
|
+
_pid: '$_id',
|
|
43
|
+
parent: '$$ROOT',
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
static reparentObject(prefix, inDoc) {
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
$replaceRoot: {
|
|
55
|
+
newRoot: {
|
|
56
|
+
$mergeObjects: [
|
|
57
|
+
inDoc ? { content: `$${prefix}` } : `$${prefix}`,
|
|
58
|
+
{
|
|
59
|
+
_id: { $concat: [{ $toString: '$_id' }, `.${prefix}`] },
|
|
60
|
+
_pid: '$_id',
|
|
61
|
+
parent: '$$ROOT',
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.default = ReparentGenerator;
|
|
71
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwYXJlbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvcGlwZWxpbmUvcmVwYXJlbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx1Q0FBNEQ7QUFDNUQsbUVBQW1FO0FBRW5FOzs7OztHQUtHO0FBQ0gsTUFBcUIsaUJBQWlCO0lBQ3BDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBcUIsRUFBRSxNQUFjO1FBQ25ELElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTTtZQUFFLE9BQU8sRUFBRSxDQUFDO1FBRS9CLHlEQUF5RDtRQUN6RCxNQUFNLFFBQVEsR0FBRyxFQUFFLENBQUM7UUFDcEIsSUFBSSxNQUFNLEdBQWUsZ0JBQWMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBRWhFLEtBQUssTUFBTSxJQUFJLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRTtZQUNwQyxRQUFRLENBQUMsSUFBSSxDQUNYLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNwQixDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxZQUFZLHFCQUFVLENBQUM7Z0JBQ3BFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFlBQVkscUJBQVUsQ0FBQyxDQUFDLENBQ25FLENBQUM7WUFFRixNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3RCLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQztnQkFBRSxNQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ3pDO1FBRUQsbURBQW1EO1FBQ25ELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFTyxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQWMsRUFBRSxLQUFjO1FBQ3pELE9BQU87WUFDTCxFQUFFLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLE1BQU0sRUFBRSxFQUFFLGlCQUFpQixFQUFFLE9BQU8sRUFBRSxFQUFFO1lBQy9EO2dCQUNFLFlBQVksRUFBRTtvQkFDWixPQUFPLEVBQUU7d0JBQ1AsYUFBYSxFQUFFOzRCQUNiLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLEVBQUUsSUFBSSxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLE1BQU0sRUFBRTs0QkFDaEQ7Z0NBQ0UsR0FBRyxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEVBQUUsSUFBSSxNQUFNLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFFO2dDQUNqRixJQUFJLEVBQUUsTUFBTTtnQ0FDWixNQUFNLEVBQUUsUUFBUTs2QkFDakI7eUJBQ0Y7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFjLEVBQUUsS0FBYztRQUMxRCxPQUFPO1lBQ0w7Z0JBQ0UsWUFBWSxFQUFFO29CQUNaLE9BQU8sRUFBRTt3QkFDUCxhQUFhLEVBQUU7NEJBQ2IsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxJQUFJLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxFQUFFOzRCQUNoRDtnQ0FDRSxHQUFHLEVBQUUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsRUFBRSxJQUFJLE1BQU0sRUFBRSxDQUFDLEVBQUU7Z0NBQ3ZELElBQUksRUFBRSxNQUFNO2dDQUNaLE1BQU0sRUFBRSxRQUFROzZCQUNqQjt5QkFDRjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQTdERCxvQ0E2REMifQ==
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Model, PipelineStage } from 'mongoose';
|
|
2
|
+
import { Projection } from '@forestadmin/datasource-toolkit';
|
|
3
|
+
import MongooseSchema from '../../mongoose/schema';
|
|
4
|
+
/**
|
|
5
|
+
* When using the `asModel` options, users can request/filter on the virtual _id and _pid fields
|
|
6
|
+
* of children (using the generated OneToOne relation).
|
|
7
|
+
*
|
|
8
|
+
* As those fields are not written to mongo, they are injected here so that they can be used like
|
|
9
|
+
* any other field.
|
|
10
|
+
*
|
|
11
|
+
* This could be also be done by preprocessing the filter, and postprocessing the records, but this
|
|
12
|
+
* solution seemed simpler, at the cost of additional pipeline stages when making queries.
|
|
13
|
+
*
|
|
14
|
+
* Note that a projection is taken as a parameter so that only fields which are actually used are
|
|
15
|
+
* injected to save resources.
|
|
16
|
+
*/
|
|
17
|
+
export default class VirtualFieldsGenerator {
|
|
18
|
+
static addVirtual(model: Model<unknown>, prefix: string, ignoredFields: string[], projection: Projection): PipelineStage[];
|
|
19
|
+
static getVirtuals(path: string, schema: MongooseSchema, projection: Projection): Record<string, unknown>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=virtual-fields.d.ts.map
|
|
@@ -0,0 +1,65 @@
|
|
|
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 schema_1 = __importDefault(require("../../mongoose/schema"));
|
|
7
|
+
/**
|
|
8
|
+
* When using the `asModel` options, users can request/filter on the virtual _id and _pid fields
|
|
9
|
+
* of children (using the generated OneToOne relation).
|
|
10
|
+
*
|
|
11
|
+
* As those fields are not written to mongo, they are injected here so that they can be used like
|
|
12
|
+
* any other field.
|
|
13
|
+
*
|
|
14
|
+
* This could be also be done by preprocessing the filter, and postprocessing the records, but this
|
|
15
|
+
* solution seemed simpler, at the cost of additional pipeline stages when making queries.
|
|
16
|
+
*
|
|
17
|
+
* Note that a projection is taken as a parameter so that only fields which are actually used are
|
|
18
|
+
* injected to save resources.
|
|
19
|
+
*/
|
|
20
|
+
class VirtualFieldsGenerator {
|
|
21
|
+
static addVirtual(model, prefix, ignoredFields, projection) {
|
|
22
|
+
const schema = schema_1.default.fromModel(model).getSubSchema(prefix, true);
|
|
23
|
+
const set = {};
|
|
24
|
+
for (const [relation, subProjection] of Object.entries(projection.relations)) {
|
|
25
|
+
// if it is a virtual one to one (<=> inverse of "parent")
|
|
26
|
+
if (ignoredFields.includes(relation)) {
|
|
27
|
+
const virtuals = this.getVirtuals(relation, schema.getSubSchema(relation, true), subProjection);
|
|
28
|
+
for (const [key, value] of Object.entries(virtuals)) {
|
|
29
|
+
set[key] = value;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return Object.keys(set).length ? [{ $addFields: set }] : [];
|
|
34
|
+
}
|
|
35
|
+
static getVirtuals(path, schema, projection) {
|
|
36
|
+
const result = {};
|
|
37
|
+
if (projection.columns.includes('_id')) {
|
|
38
|
+
result[`${path}._id`] = { $concat: [{ $toString: '$_id' }, `.${path}`] };
|
|
39
|
+
}
|
|
40
|
+
if (projection.columns.includes('_pid')) {
|
|
41
|
+
const dotIndex = path.lastIndexOf('.');
|
|
42
|
+
const parentPath = dotIndex !== -1 ? path.substring(0, dotIndex) : null;
|
|
43
|
+
result[`${path}._pid`] = parentPath
|
|
44
|
+
? { $concat: [{ $toString: '$_id' }, `.${parentPath}`] }
|
|
45
|
+
: '$_id';
|
|
46
|
+
}
|
|
47
|
+
if (projection.columns.includes('content') && schema.isLeaf) {
|
|
48
|
+
result[`${path}.content`] = `$${path}`;
|
|
49
|
+
}
|
|
50
|
+
for (const [relation, subProjection] of Object.entries(projection.relations)) {
|
|
51
|
+
// If we're asking for data that is inside of this mongo document (and not a __manyToOne)
|
|
52
|
+
// This condition should be equivalent to `!relation.endWith('__manyToOne')` but we want
|
|
53
|
+
// to get rid of the fact that the code depends on the naming.
|
|
54
|
+
if (schema.fields[relation]) {
|
|
55
|
+
const subVirtuals = this.getVirtuals(`${path}.${relation}`, schema.getSubSchema(relation, true), subProjection);
|
|
56
|
+
for (const [key, value] of Object.entries(subVirtuals)) {
|
|
57
|
+
result[key] = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.default = VirtualFieldsGenerator;
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1maWVsZHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvdXRpbHMvcGlwZWxpbmUvdmlydHVhbC1maWVsZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFHQSxtRUFBbUQ7QUFFbkQ7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBcUIsc0JBQXNCO0lBQ3pDLE1BQU0sQ0FBQyxVQUFVLENBQ2YsS0FBcUIsRUFDckIsTUFBYyxFQUNkLGFBQXVCLEVBQ3ZCLFVBQXNCO1FBRXRCLE1BQU0sTUFBTSxHQUFHLGdCQUFjLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLFlBQVksQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDMUUsTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUFDO1FBRWYsS0FBSyxNQUFNLENBQUMsUUFBUSxFQUFFLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxFQUFFO1lBQzVFLDBEQUEwRDtZQUMxRCxJQUFJLGFBQWEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQ3BDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQy9CLFFBQVEsRUFDUixNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFDbkMsYUFBYSxDQUNkLENBQUM7Z0JBRUYsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUU7b0JBQ25ELEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7aUJBQ2xCO2FBQ0Y7U0FDRjtRQUVELE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzlELENBQUM7SUFFRCxNQUFNLENBQUMsV0FBVyxDQUNoQixJQUFZLEVBQ1osTUFBc0IsRUFDdEIsVUFBc0I7UUFFdEIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO1FBRWxCLElBQUksVUFBVSxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDdEMsTUFBTSxDQUFDLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1NBQzFFO1FBRUQsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUN2QyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3ZDLE1BQU0sVUFBVSxHQUFHLFFBQVEsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUN4RSxNQUFNLENBQUMsR0FBRyxJQUFJLE9BQU8sQ0FBQyxHQUFHLFVBQVU7Z0JBQ2pDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxFQUFFLElBQUksVUFBVSxFQUFFLENBQUMsRUFBRTtnQkFDeEQsQ0FBQyxDQUFDLE1BQU0sQ0FBQztTQUNaO1FBRUQsSUFBSSxVQUFVLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFO1lBQzNELE1BQU0sQ0FBQyxHQUFHLElBQUksVUFBVSxDQUFDLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztTQUN4QztRQUVELEtBQUssTUFBTSxDQUFDLFFBQVEsRUFBRSxhQUFhLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUM1RSx5RkFBeUY7WUFDekYsd0ZBQXdGO1lBQ3hGLDhEQUE4RDtZQUM5RCxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUU7Z0JBQzNCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQ2xDLEdBQUcsSUFBSSxJQUFJLFFBQVEsRUFBRSxFQUNyQixNQUFNLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsRUFDbkMsYUFBYSxDQUNkLENBQUM7Z0JBRUYsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQ3RELE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7aUJBQ3JCO2FBQ0Y7U0FDRjtRQUVELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7Q0FDRjtBQXRFRCx5Q0FzRUMifQ==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CollectionSchema, RecordData } from '@forestadmin/datasource-toolkit';
|
|
2
|
+
import { Model } from 'mongoose';
|
|
3
|
+
/** Generate forest admin schema from mongoose schema */
|
|
4
|
+
export default class FieldsGenerator {
|
|
5
|
+
static buildFieldsSchema(model: Model<RecordData>, prefix?: string, skips?: string[]): CollectionSchema['fields'];
|
|
6
|
+
/** Fake primary key that will be used when we're flattening collections */
|
|
7
|
+
private static buildVirtualPrimaryKey;
|
|
8
|
+
private static buildManyToOne;
|
|
9
|
+
/** Build ColumnSchema from CleanSchema */
|
|
10
|
+
private static buildColumnSchema;
|
|
11
|
+
/** Compute column type from CleanSchema */
|
|
12
|
+
private static getColumnType;
|
|
13
|
+
/** Build ColumnType from CleanSchema recursively */
|
|
14
|
+
private static getColumnTypeRec;
|
|
15
|
+
/** Get enum validator from field definition */
|
|
16
|
+
private static getEnumValues;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=fields.d.ts.map
|