@fibery/expression-utils 1.0.21 → 1.1.3
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/lib/contextVariables.js +20 -0
- package/lib/expression-utils.js +794 -0
- package/lib/paramsPlaceholders.js +156 -0
- package/lib/utils.js +234 -0
- package/lib/visitors.js +488 -0
- package/package.json +14 -5
- package/lib/index.js +0 -1
package/lib/visitors.js
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
var _ = require('lodash');
|
|
2
|
+
require('util');
|
|
3
|
+
|
|
4
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
5
|
+
|
|
6
|
+
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
|
+
|
|
8
|
+
function _extends() {
|
|
9
|
+
_extends = Object.assign || function (target) {
|
|
10
|
+
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
+
var source = arguments[i];
|
|
12
|
+
|
|
13
|
+
for (var key in source) {
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
15
|
+
target[key] = source[key];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return target;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return _extends.apply(this, arguments);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
[console.error.bind(console)];
|
|
27
|
+
|
|
28
|
+
const stringify = x => {
|
|
29
|
+
if (x === undefined) {
|
|
30
|
+
return "undefined";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return JSON.stringify(x);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
class NotImplementedError extends Error {
|
|
37
|
+
constructor(value, itemType = undefined) {
|
|
38
|
+
super([`"${stringify(value)}"`, itemType, "is not implemented"].filter(x => x !== undefined).join(" "));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]); // [op, left, right]
|
|
44
|
+
// [=, $true, $false]
|
|
45
|
+
// [=, $my-id, ["fibery/id"]]
|
|
46
|
+
|
|
47
|
+
const binaryOperations = new Set(["=", "!=", "<", ">", "<=", ">=", "in", //asc: obsolete,use q/in
|
|
48
|
+
"q/contains", "q/not-contains", "+", "-", "*", "/", "and", "or", //asc: obsolete. use q/and, q/or
|
|
49
|
+
"q/and", "q/or", "q/in", "q/not-in"]); // TODO: get rid of this. Use visitors everywhere
|
|
50
|
+
const logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
|
|
51
|
+
const isFunctionCallExpression = expression => expression.length > 1 && ___default["default"].isString(expression[0]) && (expression[0].startsWith("q/") || ["=", "!=", "<", ">", "<=", ">=", "+", "-", "*", "/", "in", "and", "or", "not-in"].includes(expression[0]));
|
|
52
|
+
const isCollectionFunctionExpression = expression => //expression has length 3 in case of q/join
|
|
53
|
+
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]) && isFieldExpression(expression[1]);
|
|
54
|
+
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
55
|
+
const isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
|
|
56
|
+
const isQueryExpression = expression => {
|
|
57
|
+
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
58
|
+
const fromExpression = expression["q/from"]; //asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
59
|
+
|
|
60
|
+
return fromExpression === null || isFieldExpression(fromExpression);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return false;
|
|
64
|
+
}; // [q/count, [..., collection]]
|
|
65
|
+
const createExpressionVisitor = visitor => {
|
|
66
|
+
let visitorWithDefault = null;
|
|
67
|
+
const visitorDefault = {
|
|
68
|
+
visitVariableExpression: expression => expression,
|
|
69
|
+
visitFunctionCallExpression: ([fnName, ...args]) => [fnName, ...args.map(x => visitorWithDefault.visitExpression(x))],
|
|
70
|
+
visitFieldExpression: expression => expression,
|
|
71
|
+
visitOrderByExpression: orderByExpression => orderByExpression.map(x => {
|
|
72
|
+
const [fieldExpression, orderDir] = x;
|
|
73
|
+
const fieldExpressionNew = visitorWithDefault.visitExpression(fieldExpression);
|
|
74
|
+
return [fieldExpressionNew, orderDir];
|
|
75
|
+
}),
|
|
76
|
+
visitQueryExpression: subQueryExpression => {
|
|
77
|
+
const {
|
|
78
|
+
"q/from": fromExpression,
|
|
79
|
+
"q/select": selectExpression,
|
|
80
|
+
"q/where": whereExpression,
|
|
81
|
+
"q/order-by": orderByExpression
|
|
82
|
+
} = subQueryExpression;
|
|
83
|
+
return _extends({}, subQueryExpression, fromExpression ? {
|
|
84
|
+
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
85
|
+
} : null, selectExpression ? {
|
|
86
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
87
|
+
} : null, whereExpression ? {
|
|
88
|
+
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
89
|
+
} : null, orderByExpression ? {
|
|
90
|
+
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
91
|
+
} : null);
|
|
92
|
+
},
|
|
93
|
+
visitExpression: expression => {
|
|
94
|
+
if (expression === null) {
|
|
95
|
+
throw new NotImplementedError(expression, "expression");
|
|
96
|
+
} else if (isVariableExpression(expression)) {
|
|
97
|
+
return visitorWithDefault.visitVariableExpression(expression, visitorDefault);
|
|
98
|
+
} else if (isFunctionCallExpression(expression)) {
|
|
99
|
+
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
100
|
+
} else if (isFieldExpression(expression)) {
|
|
101
|
+
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
102
|
+
} else if (isQueryExpression(expression)) {
|
|
103
|
+
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
104
|
+
} else {
|
|
105
|
+
throw new NotImplementedError(expression, "expression");
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
visitorWithDefault = _extends({}, visitorDefault, visitor);
|
|
110
|
+
return visitorWithDefault;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const defaultIdsWithNamesOnFieldNotFound = ({
|
|
114
|
+
fieldExpressionInNamesTerms,
|
|
115
|
+
fieldId
|
|
116
|
+
}) => {
|
|
117
|
+
return {
|
|
118
|
+
currentTypeObject: null,
|
|
119
|
+
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldId]
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
124
|
+
expression,
|
|
125
|
+
typeObject,
|
|
126
|
+
onFieldNotFound
|
|
127
|
+
}) => expression.reduce(({
|
|
128
|
+
currentTypeObject,
|
|
129
|
+
fieldExpressionInNamesTerms
|
|
130
|
+
}, fieldId) => {
|
|
131
|
+
if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
132
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
133
|
+
return {
|
|
134
|
+
currentTypeObject: fieldObject.typeObject,
|
|
135
|
+
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldObject.name]
|
|
136
|
+
};
|
|
137
|
+
} else {
|
|
138
|
+
return onFieldNotFound({
|
|
139
|
+
currentTypeObject,
|
|
140
|
+
fieldExpressionInNamesTerms,
|
|
141
|
+
fieldId,
|
|
142
|
+
expression
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}, {
|
|
146
|
+
currentTypeObject: typeObject,
|
|
147
|
+
fieldExpressionInNamesTerms: []
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWithNamesOnFieldNotFound) => {
|
|
151
|
+
const visitor = createExpressionVisitor({
|
|
152
|
+
visitFieldExpression: expression => visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
153
|
+
expression,
|
|
154
|
+
typeObject,
|
|
155
|
+
onFieldNotFound
|
|
156
|
+
}).fieldExpressionInNamesTerms,
|
|
157
|
+
visitQueryExpression: subQueryExpression => {
|
|
158
|
+
const {
|
|
159
|
+
"q/from": fromExpression,
|
|
160
|
+
"q/select": selectExpression,
|
|
161
|
+
"q/where": whereExpression,
|
|
162
|
+
"q/order-by": orderByExpression
|
|
163
|
+
} = subQueryExpression;
|
|
164
|
+
const subQueryTypeObject = visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
165
|
+
expression: fromExpression,
|
|
166
|
+
onFieldNotFound,
|
|
167
|
+
typeObject
|
|
168
|
+
}).currentTypeObject;
|
|
169
|
+
|
|
170
|
+
if (subQueryTypeObject) {
|
|
171
|
+
const subQueryVisitor = replaceIdsWithNamesVisitor(subQueryTypeObject, onFieldNotFound);
|
|
172
|
+
return _extends({}, subQueryExpression, {
|
|
173
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
174
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
175
|
+
}, whereExpression ? {
|
|
176
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
177
|
+
} : null, orderByExpression ? {
|
|
178
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
179
|
+
} : null);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return subQueryExpression;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
return visitor;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const defaultNamesWithIdsOnFieldNotFound = ({
|
|
189
|
+
fieldExpressionInIdsTerms,
|
|
190
|
+
field
|
|
191
|
+
}) => {
|
|
192
|
+
return {
|
|
193
|
+
currentTypeObject: null,
|
|
194
|
+
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, field]
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
199
|
+
expression,
|
|
200
|
+
onFieldNotFound,
|
|
201
|
+
typeObject
|
|
202
|
+
}) => expression.reduce(({
|
|
203
|
+
currentTypeObject,
|
|
204
|
+
fieldExpressionInIdsTerms
|
|
205
|
+
}, field) => {
|
|
206
|
+
if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
207
|
+
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
208
|
+
return {
|
|
209
|
+
currentTypeObject: fieldObject.typeObject,
|
|
210
|
+
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, fieldObject.id]
|
|
211
|
+
};
|
|
212
|
+
} else {
|
|
213
|
+
return onFieldNotFound({
|
|
214
|
+
currentTypeObject,
|
|
215
|
+
fieldExpressionInIdsTerms,
|
|
216
|
+
field,
|
|
217
|
+
expression
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}, {
|
|
221
|
+
currentTypeObject: typeObject,
|
|
222
|
+
fieldExpressionInIdsTerms: []
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWithIdsOnFieldNotFound) => {
|
|
226
|
+
const visitor = createExpressionVisitor({
|
|
227
|
+
visitFieldExpression: expression => visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
228
|
+
expression,
|
|
229
|
+
onFieldNotFound,
|
|
230
|
+
typeObject
|
|
231
|
+
}).fieldExpressionInIdsTerms,
|
|
232
|
+
visitQueryExpression: subQueryExpression => {
|
|
233
|
+
const {
|
|
234
|
+
"q/from": fromExpression,
|
|
235
|
+
"q/select": selectExpression,
|
|
236
|
+
"q/where": whereExpression,
|
|
237
|
+
"q/order-by": orderByExpression
|
|
238
|
+
} = subQueryExpression;
|
|
239
|
+
const subQueryTypeObject = visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
240
|
+
expression: fromExpression,
|
|
241
|
+
onFieldNotFound,
|
|
242
|
+
typeObject
|
|
243
|
+
}).currentTypeObject;
|
|
244
|
+
|
|
245
|
+
if (subQueryTypeObject) {
|
|
246
|
+
const subQueryVisitor = replaceNamesWithIdsVisitor(subQueryTypeObject);
|
|
247
|
+
return _extends({}, subQueryExpression, {
|
|
248
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
249
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
250
|
+
}, whereExpression ? {
|
|
251
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
252
|
+
} : null, orderByExpression ? {
|
|
253
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
254
|
+
} : null);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return subQueryExpression;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
return visitor;
|
|
261
|
+
};
|
|
262
|
+
const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
263
|
+
const visitor = createExpressionVisitor({
|
|
264
|
+
visitFunctionCallExpression: ([fnName, ...args]) => {
|
|
265
|
+
const argsNew = args.map(x => visitor.visitExpression(x)).filter(Boolean);
|
|
266
|
+
|
|
267
|
+
if (logicalOperators.has(fnName)) {
|
|
268
|
+
if (argsNew.length > 0) {
|
|
269
|
+
return argsNew.length === 1 ? argsNew[0] : [fnName, ...argsNew];
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return null;
|
|
273
|
+
} else {
|
|
274
|
+
return argsNew.length === args.length ? [fnName, ...argsNew] : null;
|
|
275
|
+
}
|
|
276
|
+
},
|
|
277
|
+
visitFieldExpression: expression => {
|
|
278
|
+
const fieldTypeObject = expression.reduce((holderTypeObject, field) => holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field) ? holderTypeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
279
|
+
return fieldTypeObject && expression;
|
|
280
|
+
},
|
|
281
|
+
visitOrderByExpression: orderByExpression => {
|
|
282
|
+
const orderByExpressionNew = orderByExpression.map(x => {
|
|
283
|
+
const [fieldExpression, orderDir] = x;
|
|
284
|
+
const fieldExpressionNew = visitor.visitExpression(fieldExpression);
|
|
285
|
+
return fieldExpressionNew && [fieldExpressionNew, orderDir];
|
|
286
|
+
}).filter(Boolean);
|
|
287
|
+
return orderByExpressionNew.length > 0 && orderByExpressionNew;
|
|
288
|
+
},
|
|
289
|
+
visitQueryExpression: subQueryExpression => {
|
|
290
|
+
const {
|
|
291
|
+
"q/from": fromExpression,
|
|
292
|
+
"q/select": selectExpression,
|
|
293
|
+
"q/where": whereExpression,
|
|
294
|
+
"q/order-by": orderByExpression
|
|
295
|
+
} = subQueryExpression;
|
|
296
|
+
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
297
|
+
|
|
298
|
+
if (subQueryTypeObject) {
|
|
299
|
+
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
300
|
+
|
|
301
|
+
const subQueryExpressionNew = ___default["default"].pickBy(_extends({}, subQueryExpression, {
|
|
302
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
303
|
+
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
304
|
+
}, whereExpression ? {
|
|
305
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
306
|
+
} : null, orderByExpression ? {
|
|
307
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
308
|
+
} : null));
|
|
309
|
+
|
|
310
|
+
const {
|
|
311
|
+
"q/select": selectExpressionNew
|
|
312
|
+
} = subQueryExpressionNew;
|
|
313
|
+
return selectExpressionNew ? subQueryExpressionNew : null;
|
|
314
|
+
} else {
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
return visitor;
|
|
320
|
+
};
|
|
321
|
+
const expressionContainsAggregation = expression => {
|
|
322
|
+
let result = false;
|
|
323
|
+
const visitor = createExpressionVisitor({
|
|
324
|
+
visitQueryExpression: queryExpression => {
|
|
325
|
+
const {
|
|
326
|
+
"q/select": selectExpression
|
|
327
|
+
} = queryExpression;
|
|
328
|
+
|
|
329
|
+
if (isCollectionFunctionExpression(selectExpression)) {
|
|
330
|
+
result = true;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
visitor.visitExpression(expression);
|
|
335
|
+
return result;
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
const defaultGetExpressionTypeOnFieldNotFound = () => {
|
|
339
|
+
return {
|
|
340
|
+
currentTypeObject: null
|
|
341
|
+
};
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
const getFieldAccessExpressionTypeObject = ({
|
|
345
|
+
expression,
|
|
346
|
+
typeObject,
|
|
347
|
+
onFieldNotFound,
|
|
348
|
+
returnRefTypeInsteadOfId
|
|
349
|
+
}) => {
|
|
350
|
+
const reduced = expression.reduce(({
|
|
351
|
+
currentTypeObject
|
|
352
|
+
}, fieldId, index) => {
|
|
353
|
+
const fieldObject = currentTypeObject && currentTypeObject.fieldObjects.find(f => f.id === fieldId);
|
|
354
|
+
|
|
355
|
+
if (fieldObject) {
|
|
356
|
+
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
357
|
+
return {
|
|
358
|
+
currentTypeObject
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return {
|
|
363
|
+
currentTypeObject: fieldObject.typeObject
|
|
364
|
+
};
|
|
365
|
+
} else {
|
|
366
|
+
return onFieldNotFound({
|
|
367
|
+
currentTypeObject,
|
|
368
|
+
fieldId
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}, {
|
|
372
|
+
currentTypeObject: typeObject
|
|
373
|
+
});
|
|
374
|
+
return reduced.currentTypeObject;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
const UNKNOWN_EXPRESSION_TYPE = "unknown";
|
|
378
|
+
|
|
379
|
+
const getExpressionTypeInternal = ({
|
|
380
|
+
expression,
|
|
381
|
+
typeObject,
|
|
382
|
+
functionsMeta,
|
|
383
|
+
onFieldNotFound,
|
|
384
|
+
returnRefTypeInsteadOfId
|
|
385
|
+
}) => {
|
|
386
|
+
let result = null;
|
|
387
|
+
const visitor = createExpressionVisitor({
|
|
388
|
+
visitVariableExpression: function () {
|
|
389
|
+
result = UNKNOWN_EXPRESSION_TYPE;
|
|
390
|
+
},
|
|
391
|
+
visitFunctionCallExpression: function ([fnName, ...args]) {
|
|
392
|
+
const fnMeta = functionsMeta[fnName];
|
|
393
|
+
|
|
394
|
+
if (!fnMeta) {
|
|
395
|
+
throw new Error(`Function meta for "${fnName}" was not provided`);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
const argTypes = args.map(arg => getExpressionTypeInternal({
|
|
399
|
+
expression: arg,
|
|
400
|
+
typeObject,
|
|
401
|
+
functionsMeta,
|
|
402
|
+
onFieldNotFound,
|
|
403
|
+
returnRefTypeInsteadOfId: false
|
|
404
|
+
}));
|
|
405
|
+
const overload = fnMeta.overloads.find(o => o["arg-types"].every((argType, index) => argTypes[index] === UNKNOWN_EXPRESSION_TYPE || argTypes[index] === argType));
|
|
406
|
+
|
|
407
|
+
if (!overload) {
|
|
408
|
+
throw new Error(`No overload with args ${argTypes.join(",")} found for "${fnName}" in meta`);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
result = overload["result-type"];
|
|
412
|
+
},
|
|
413
|
+
visitQueryExpression: expression => {
|
|
414
|
+
const {
|
|
415
|
+
"q/from": fromExpression,
|
|
416
|
+
"q/select": selectExpression
|
|
417
|
+
} = expression;
|
|
418
|
+
const fromTypeObject = getFieldAccessExpressionTypeObject({
|
|
419
|
+
expression: fromExpression,
|
|
420
|
+
typeObject,
|
|
421
|
+
onFieldNotFound,
|
|
422
|
+
returnRefTypeInsteadOfId
|
|
423
|
+
});
|
|
424
|
+
|
|
425
|
+
if (!fromTypeObject) {
|
|
426
|
+
result = null;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
if (___default["default"].isPlainObject(selectExpression)) {
|
|
430
|
+
if (Object.values(selectExpression).length !== 1) {
|
|
431
|
+
throw new Error(`Cannot determine type of query expression ${JSON.stringify(expression)}`);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
result = getExpressionTypeInternal({
|
|
435
|
+
expression: Object.values(selectExpression)[0],
|
|
436
|
+
typeObject: fromTypeObject,
|
|
437
|
+
functionsMeta,
|
|
438
|
+
onFieldNotFound,
|
|
439
|
+
returnRefTypeInsteadOfId
|
|
440
|
+
});
|
|
441
|
+
} else {
|
|
442
|
+
result = getExpressionTypeInternal({
|
|
443
|
+
expression: selectExpression,
|
|
444
|
+
typeObject: fromTypeObject,
|
|
445
|
+
functionsMeta,
|
|
446
|
+
onFieldNotFound,
|
|
447
|
+
returnRefTypeInsteadOfId
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
|
|
452
|
+
visitFieldExpression(expression) {
|
|
453
|
+
const fieldAccessExpressionTypeObject = getFieldAccessExpressionTypeObject({
|
|
454
|
+
expression,
|
|
455
|
+
typeObject,
|
|
456
|
+
onFieldNotFound,
|
|
457
|
+
returnRefTypeInsteadOfId
|
|
458
|
+
});
|
|
459
|
+
result = fieldAccessExpressionTypeObject && fieldAccessExpressionTypeObject.name;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
});
|
|
463
|
+
visitor.visitExpression(expression);
|
|
464
|
+
return result;
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
const getExpressionType = ({
|
|
468
|
+
expression,
|
|
469
|
+
typeObject,
|
|
470
|
+
functionsMeta,
|
|
471
|
+
onFieldNotFound = defaultGetExpressionTypeOnFieldNotFound,
|
|
472
|
+
returnRefTypeInsteadOfId = true
|
|
473
|
+
}) => {
|
|
474
|
+
return getExpressionTypeInternal({
|
|
475
|
+
expression,
|
|
476
|
+
typeObject,
|
|
477
|
+
functionsMeta,
|
|
478
|
+
onFieldNotFound,
|
|
479
|
+
returnRefTypeInsteadOfId
|
|
480
|
+
});
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
exports.UNKNOWN_EXPRESSION_TYPE = UNKNOWN_EXPRESSION_TYPE;
|
|
484
|
+
exports.deleteExpressionsWithNotFoundFieldsVisitor = deleteExpressionsWithNotFoundFieldsVisitor;
|
|
485
|
+
exports.expressionContainsAggregation = expressionContainsAggregation;
|
|
486
|
+
exports.getExpressionType = getExpressionType;
|
|
487
|
+
exports.replaceIdsWithNamesVisitor = replaceIdsWithNamesVisitor;
|
|
488
|
+
exports.replaceNamesWithIdsVisitor = replaceNamesWithIdsVisitor;
|
package/package.json
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/expression-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "utils for working with fibery api expressions",
|
|
5
|
-
"
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./lib/expression-utils.js",
|
|
7
|
+
"./contextVariables": "./lib/contextVariables.js",
|
|
8
|
+
"./utils": "./lib/utils.js",
|
|
9
|
+
"./visitors": "./lib/visitors.js",
|
|
10
|
+
"./paramsPlaceholders": "./lib/paramsPlaceholders.js"
|
|
11
|
+
},
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"main": "./lib/expression-utils.js"
|
|
14
|
+
},
|
|
15
|
+
"main": "./index.js",
|
|
6
16
|
"browser": "./index.js",
|
|
7
17
|
"files": [
|
|
8
18
|
"/lib"
|
|
@@ -19,14 +29,13 @@
|
|
|
19
29
|
"babel-preset-fibery": "7.2.0",
|
|
20
30
|
"eslint-config-fibery": "7.0.0",
|
|
21
31
|
"jest": "27.0.6",
|
|
22
|
-
"
|
|
23
|
-
"webpack-cli": "4.7.2"
|
|
32
|
+
"microbundle": "0.14.1"
|
|
24
33
|
},
|
|
25
34
|
"peerDependencies": {
|
|
26
35
|
"fibery-schema": "7.x"
|
|
27
36
|
},
|
|
28
37
|
"scripts": {
|
|
29
|
-
"build": "
|
|
38
|
+
"build": "rm -rf lib && microbundle paramsPlaceholders.js utils.js visitors.js contextVariables.js index.js -o lib -f cjs --no-compress --target node --sourcemap false",
|
|
30
39
|
"test": "node scripts/test.js",
|
|
31
40
|
"lint": "eslint ."
|
|
32
41
|
},
|
package/lib/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(()=>{"use strict";var e={n:t=>{var r=t&&t.__esModule?()=>t.default:()=>t;return e.d(r,{a:r}),r},d:(t,r)=>{for(var s in r)e.o(r,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:r[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t),r:e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})}},t={};e.r(t),e.d(t,{contextVariables:()=>o,paramsPlaceholders:()=>r,utils:()=>s,visitors:()=>n});var r={};e.r(r),e.d(r,{dateToDateTimeIntervalLookup:()=>W,formulaNowDateTimeParamPlaceholder:()=>m,formulaTodayDateParamPlaceholder:()=>u,monthAgoDateParamPlaceholder:()=>E,monthAgoEndDateTimeParamPlaceholder:()=>A,monthAgoStartDateTimeParamPlaceholder:()=>S,monthFromNowDateParamPlaceholder:()=>b,monthFromNowEndDateTimeParamPlaceholder:()=>k,monthFromNowStartDateTimeParamPlaceholder:()=>B,paramsPlaceholdersLookup:()=>C,replacePlaceholdersInParams:()=>_,todayDateParamPlaceholder:()=>y,todayEndDateTimeParamPlaceholder:()=>P,todayStartDateTimeParamPlaceholder:()=>q,tomorrowDateParamPlaceholder:()=>f,tomorrowEndDateTimeParamPlaceholder:()=>j,tomorrowStartDateTimeParamPlaceholder:()=>T,weekAgoDateParamPlaceholder:()=>x,weekAgoEndDateTimeParamPlaceholder:()=>N,weekAgoStartDateTimeParamPlaceholder:()=>I,weekFromNowDateParamPlaceholder:()=>O,weekFromNowEndDateTimeParamPlaceholder:()=>D,weekFromNowStartDateTimeParamPlaceholder:()=>$,yearAgoDateParamPlaceholder:()=>w,yearAgoEndDateTimeParamPlaceholder:()=>R,yearAgoStartDateTimeParamPlaceholder:()=>V,yearFromNowDateParamPlaceholder:()=>v,yearFromNowEndDateTimeParamPlaceholder:()=>Q,yearFromNowStartDateTimeParamPlaceholder:()=>M,yesterdayDateParamPlaceholder:()=>h,yesterdayEndDateTimeParamPlaceholder:()=>F,yesterdayStartDateTimeParamPlaceholder:()=>g});var s={};e.r(s),e.d(s,{assertIsValidExpression:()=>X,createExpressionVisitor:()=>Oe,dateRangeFunctions:()=>z,extractFieldExpressions:()=>xe,firstLastFunctions:()=>G,isAccessFunctionExpression:()=>de,isAxisFieldExpression:()=>me,isBinaryExpression:()=>le,isCollectionFunctionExpression:()=>ae,isDateRangeFunctionExpression:()=>ie,isFieldExpression:()=>ue,isFunctionCallExpression:()=>oe,isFunctionExpression:()=>fe,isNaryExpression:()=>ce,isQueryExpression:()=>ye,isVariableExpression:()=>pe,logicalOperators:()=>re,mathOperators:()=>ne,relationalOperators:()=>se});var n={};e.r(n),e.d(n,{UNKNOWN_EXPRESSION_TYPE:()=>Ie,deleteExpressionsWithNotFoundFieldsVisitor:()=>Te,expressionContainsAggregation:()=>je,getExpressionType:()=>$e,replaceIdsWithNamesVisitor:()=>we,replaceNamesWithIdsVisitor:()=>Pe});var o={};e.r(o),e.d(o,{getEntityQueryVariables:()=>De});const i=require("lodash");var a=e.n(i);const d=require("moment");var l=e.n(d);const c=e=>e.format("YYYY-MM-DD"),p=e=>e.toISOString(),u="$formula-today-date-placeholder",m="$formula-now-date-time-placeholder",y="$today-date",f="$tomorrow-date",h="$yesterday-date",x="$week-ago-date",O="$week-from-now-date",E="$month-ago-date",b="$month-from-now-date",w="$year-ago-date",v="$year-from-now-date",q="$today-date-time-start",P="$today-date-time-end",T="$tomorrow-date-time-start",j="$tomorrow-date-time-end",g="$yesterday-date-time-start",F="$yesterday-date-time-end",I="$week-ago-date-time-start",N="$week-ago-date-time-end",$="$week-from-now-date-time-start",D="$week-from-now-date-time-end",S="$month-ago-date-time-start",A="$month-ago-date-time-end",B="$month-from-now-date-time-start",k="$month-from-now-date-time-end",V="$year-ago-date-time-start",R="$year-ago-date-time-end",M="$year-from-now-date-time-start",Q="$year-from-now-date-time-end",C={[y]:()=>c(l()()),[u]:()=>c(l()()),[m]:()=>p(l()()),[f]:()=>c(l()().add(1,"days")),[h]:()=>c(l()().subtract(1,"days")),[x]:()=>c(l()().subtract(7,"days")),[O]:()=>c(l()().add(7,"days")),[E]:()=>c(l()().subtract(1,"months")),[b]:()=>c(l()().add(1,"months")),[w]:()=>c(l()().subtract(1,"year")),[v]:()=>c(l()().add(1,"year")),[q]:()=>p(l()().startOf("day")),[P]:()=>p(l()().endOf("day")),[T]:()=>p(l()().add(1,"days").startOf("day")),[j]:()=>p(l()().add(1,"days").endOf("day")),[g]:()=>p(l()().subtract(1,"days").startOf("day")),[F]:()=>p(l()().subtract(1,"days").endOf("day")),[I]:()=>p(l()().subtract(7,"days").startOf("day")),[N]:()=>p(l()().subtract(7,"days").endOf("day")),[$]:()=>p(l()().add(7,"days").startOf("day")),[D]:()=>p(l()().add(7,"days").endOf("day")),[S]:()=>p(l()().subtract(1,"months").startOf("day")),[A]:()=>p(l()().subtract(1,"months").endOf("day")),[B]:()=>p(l()().add(1,"months").startOf("day")),[k]:()=>p(l()().add(1,"months").endOf("day")),[V]:()=>p(l()().subtract(1,"year").startOf("day")),[R]:()=>p(l()().subtract(1,"year").endOf("day")),[M]:()=>p(l()().add(1,"year").startOf("day")),[Q]:()=>p(l()().add(1,"year").endOf("day"))},_=e=>e&&a().mapValues(e,((e,t)=>{const r=C[t];return r?r():e})),W={[y]:{start:q,end:P},[f]:{start:T,end:j},[h]:{start:g,end:F},[x]:{start:I,end:N},[O]:{start:$,end:D},[E]:{start:S,end:A},[b]:{start:B,end:k},[w]:{start:V,end:R},[v]:{start:M,end:Q}},Y=require("util");var L=e.n(Y);function J(e,t){if(e.length!==t.length)return!1;for(var r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function H(e,...t){if(!e){const e=t.length>0?function(e){const t=e.map((e=>"object"==typeof e?{[L().inspect.custom||"inspect"]:(t,r)=>L().inspect(e,{...r,showHidden:!1,depth:null,maxArrayLength:null})}:"string"==typeof e?{[L().inspect.custom||"inspect"]:(t,r)=>e}:e));return L().format(...t)}(t):"Assertion failed with no details";throw new Error(e)}}let K=[console.error.bind(console)];!function(e,t){var r;void 0===t&&(t=J);var s,n=[],o=!1}((function(...e){K.forEach(((t,r)=>{t(...e)}))}));class U extends Error{constructor(e,t){var r;super([`"${r=e,void 0===r?"undefined":JSON.stringify(r)}"`,t,"is not implemented"].filter((e=>void 0!==e)).join(" "))}}const X=e=>{H(Array.isArray(e),"expression must be array",{expression:e}),H(e.length>0,"empty expression does not make any sense")},z=new Set(["q/start","q/end"]),G=new Set(["q/first","q/last"]),Z=new Set(["q/count","q/count-distinct","q/sum","q/min","q/max","q/avg","q/join","q/first","q/last"]),ee=new Set(["=","!=","<",">","<=",">=","in","q/contains","q/not-contains","+","-","*","/","and","or","q/and","q/or","q/in","q/not-in"]),te=new Set(["and","or","q/and","q/or"]),re=new Set(["and","or","q/and","q/or"]),se=new Set(["=","!=","<",">","<=",">="]),ne=new Set(["+","-","*","/","q/+","q/-","q/concat"]),oe=e=>e.length>1&&a().isString(e[0])&&(e[0].startsWith("q/")||["=","!=","<",">","<=",">=","+","-","*","/","in","and","or","not-in"].includes(e[0])),ie=e=>2===e.length&&z.has(e[0])&&ue(e[1]),ae=e=>(2===e.length||3===e.length)&&Z.has(e[0])&&ue(e[1]),de=e=>2===e.length&&"q/access?"===e[0]&&ue(e[1]),le=e=>3===e.length&&ee.has(e[0]),ce=e=>e.length>1&&te.has(e[0]),pe=e=>a().isString(e)&&e.startsWith("$"),ue=e=>Array.isArray(e)&&e.every((e=>!pe(e)&&!ee.has(e)&&a().isString(e))),me=e=>ue(e)&&1===e.length,ye=e=>{if(a().isObject(e)&&"q/from"in e){const t=e["q/from"];return null===t||ue(t)}return!1},fe=e=>{if(!Array.isArray(e))return!1;if(ue(e))return!1;if(ie(e)||ae(e)||de(e))return!0;throw new Error("invalid expression:"+JSON.stringify(e))},he=(e,t)=>{if(pe(t));else if(le(t)||ce(t))for(const r of t.slice(1))pe(r)||null===r||(a().isString(r)?e.push([r]):he(e,r));else if(ue(t))e.push(t);else if(ie(t)||ae(t))he(e,t[1]);else{if(!t["q/from"]||!ue(t["q/from"]))throw new U(t,"expression");{const r=[];t["q/select"]&&he(r,t["q/select"]),t["q/where"]&&he(r,t["q/where"]);for(const s of r)e.push([...t["q/from"],...s])}}},xe=e=>{const t=[];return he(t,e),a().uniqBy(t,(e=>e.join(",")))},Oe=e=>{let t=null;const r={visitVariableExpression:e=>e,visitFunctionCallExpression:([e,...r])=>[e,...r.map((e=>t.visitExpression(e)))],visitFieldExpression:e=>e,visitOrderByExpression:e=>e.map((e=>{const[r,s]=e;return[t.visitExpression(r),s]})),visitQueryExpression:e=>{const{"q/from":r,"q/select":s,"q/where":n,"q/order-by":o}=e;return{...e,...r?{"q/from":t.visitFieldExpression(r)}:null,...s?{"q/select":a().isPlainObject(s)?a().mapValues(s,(e=>t.visitExpression(e))):t.visitExpression(s)}:null,...n?{"q/where":t.visitExpression(n)}:null,...o?{"q/order-by":t.visitOrderByExpression(o)}:null}},visitExpression:e=>{if(null===e)throw new U(e,"expression");if(pe(e))return t.visitVariableExpression(e,r);if(oe(e))return t.visitFunctionCallExpression(e,r);if(ue(e))return t.visitFieldExpression(e,r);if(ye(e))return t.visitQueryExpression(e,r);throw new U(e,"expression")}};return t={...r,...e},t},Ee=({fieldExpressionInNamesTerms:e,fieldId:t})=>({currentTypeObject:null,fieldExpressionInNamesTerms:[...e,t]}),be=({expression:e,typeObject:t,onFieldNotFound:r})=>e.reduce((({currentTypeObject:t,fieldExpressionInNamesTerms:s},n)=>{if(t&&t.fieldObjectsById.hasOwnProperty(n)){const e=t.fieldObjectsById[n];return{currentTypeObject:e.typeObject,fieldExpressionInNamesTerms:[...s,e.name]}}return r({currentTypeObject:t,fieldExpressionInNamesTerms:s,fieldId:n,expression:e})}),{currentTypeObject:t,fieldExpressionInNamesTerms:[]}),we=(e,t=Ee)=>{const r=Oe({visitFieldExpression:r=>be({expression:r,typeObject:e,onFieldNotFound:t}).fieldExpressionInNamesTerms,visitQueryExpression:s=>{const{"q/from":n,"q/select":o,"q/where":i,"q/order-by":d}=s,l=be({expression:n,onFieldNotFound:t,typeObject:e}).currentTypeObject;if(l){const e=we(l,t);return{...s,"q/from":r.visitFieldExpression(n),"q/select":a().isPlainObject(o)?a().mapValues(o,(t=>e.visitExpression(t))):e.visitExpression(o),...i?{"q/where":e.visitExpression(i)}:null,...d?{"q/order-by":e.visitOrderByExpression(d)}:null}}return s}});return r},ve=({fieldExpressionInIdsTerms:e,field:t})=>({currentTypeObject:null,fieldExpressionInIdsTerms:[...e,t]}),qe=({expression:e,onFieldNotFound:t,typeObject:r})=>e.reduce((({currentTypeObject:r,fieldExpressionInIdsTerms:s},n)=>{if(r&&r.fieldObjectsByName.hasOwnProperty(n)){const e=r.fieldObjectsByName[n];return{currentTypeObject:e.typeObject,fieldExpressionInIdsTerms:[...s,e.id]}}return t({currentTypeObject:r,fieldExpressionInIdsTerms:s,field:n,expression:e})}),{currentTypeObject:r,fieldExpressionInIdsTerms:[]}),Pe=(e,t=ve)=>{const r=Oe({visitFieldExpression:r=>qe({expression:r,onFieldNotFound:t,typeObject:e}).fieldExpressionInIdsTerms,visitQueryExpression:s=>{const{"q/from":n,"q/select":o,"q/where":i,"q/order-by":d}=s,l=qe({expression:n,onFieldNotFound:t,typeObject:e}).currentTypeObject;if(l){const e=Pe(l);return{...s,"q/from":r.visitFieldExpression(n),"q/select":a().isPlainObject(o)?a().mapValues(o,(t=>e.visitExpression(t))):e.visitExpression(o),...i?{"q/where":e.visitExpression(i)}:null,...d?{"q/order-by":e.visitOrderByExpression(d)}:null}}return s}});return r},Te=e=>{const t=Oe({visitFunctionCallExpression:([e,...r])=>{const s=r.map((e=>t.visitExpression(e))).filter(Boolean);return re.has(e)?s.length>0?1===s.length?s[0]:[e,...s]:null:s.length===r.length?[e,...s]:null},visitFieldExpression:t=>t.reduce(((e,t)=>e&&e.fieldObjectsByName.hasOwnProperty(t)?e.fieldObjectsByName[t].typeObject:null),e)&&t,visitOrderByExpression:e=>{const r=e.map((e=>{const[r,s]=e,n=t.visitExpression(r);return n&&[n,s]})).filter(Boolean);return r.length>0&&r},visitQueryExpression:r=>{const{"q/from":s,"q/select":n,"q/where":o,"q/order-by":i}=r,d=s.reduce(((e,t)=>e&&e.fieldObjectsByName.hasOwnProperty(t)?e.fieldObjectsByName[t].typeObject:null),e);if(d){const e=Te(d),l=a().pickBy({...r,"q/from":t.visitFieldExpression(s),"q/select":e.visitExpression(n),...o?{"q/where":e.visitExpression(o)}:null,...i?{"q/order-by":e.visitOrderByExpression(i)}:null}),{"q/select":c}=l;return c?l:null}return null}});return t},je=e=>{let t=!1;return Oe({visitQueryExpression:e=>{const{"q/select":r}=e;ae(r)&&(t=!0)}}).visitExpression(e),t},ge=()=>({currentTypeObject:null}),Fe=({expression:e,typeObject:t,onFieldNotFound:r,returnRefTypeInsteadOfId:s})=>e.reduce((({currentTypeObject:t},n,o)=>{const i=t&&t.fieldObjects.find((e=>e.id===n));return i?s&&o===e.length-1&&i.isId?{currentTypeObject:t}:{currentTypeObject:i.typeObject}:r({currentTypeObject:t,fieldId:n})}),{currentTypeObject:t}).currentTypeObject,Ie="unknown",Ne=({expression:e,typeObject:t,functionsMeta:r,onFieldNotFound:s,returnRefTypeInsteadOfId:n})=>{let o=null;return Oe({visitVariableExpression:function(){o=Ie},visitFunctionCallExpression:function([e,...n]){const i=r[e];if(!i)throw new Error(`Function meta for "${e}" was not provided`);const a=n.map((e=>Ne({expression:e,typeObject:t,functionsMeta:r,onFieldNotFound:s,returnRefTypeInsteadOfId:!1}))),d=i.overloads.find((e=>e["arg-types"].every(((e,t)=>a[t]===Ie||a[t]===e))));if(!d)throw new Error(`No overload with args ${a.join(",")} found for "${e}" in meta`);o=d["result-type"]},visitQueryExpression:e=>{const{"q/from":i,"q/select":d}=e,l=Fe({expression:i,typeObject:t,onFieldNotFound:s,returnRefTypeInsteadOfId:n});if(l||(o=null),a().isPlainObject(d)){if(1!==Object.values(d).length)throw new Error(`Cannot determine type of query expression ${JSON.stringify(e)}`);o=Ne({expression:Object.values(d)[0],typeObject:l,functionsMeta:r,onFieldNotFound:s,returnRefTypeInsteadOfId:n})}else o=Ne({expression:d,typeObject:l,functionsMeta:r,onFieldNotFound:s,returnRefTypeInsteadOfId:n})},visitFieldExpression(e){const r=Fe({expression:e,typeObject:t,onFieldNotFound:s,returnRefTypeInsteadOfId:n});o=r&&r.name}}).visitExpression(e),o},$e=({expression:e,typeObject:t,functionsMeta:r,onFieldNotFound:s=ge,returnRefTypeInsteadOfId:n=!0})=>Ne({expression:e,typeObject:t,functionsMeta:r,onFieldNotFound:s,returnRefTypeInsteadOfId:n}),De=e=>{const t=a().groupBy(e.typeObjects.filter((e=>e.isDomain)),(e=>e.pluralTitle));return a().flatten(Object.values(t).map((e=>e.map((t=>({typeObject:t,id:`entityQuery_${t.id}`,title:e.length>1?`${t.pluralTitle} (${t.nameParts.namespace})`:t.pluralTitle,isCollection:!0}))))))};module.exports=t})();
|