@fibery/expression-utils 9.3.0 → 9.4.0
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/index.d.ts +6 -0
- package/lib/index.js +44 -0
- package/lib/src/context-variables.d.ts +22 -0
- package/lib/src/context-variables.js +122 -0
- package/lib/src/errors.d.ts +4 -0
- package/lib/src/errors.js +15 -0
- package/lib/src/fieldExpressionVisitorTypeAware.d.ts +5 -0
- package/lib/src/fieldExpressionVisitorTypeAware.js +133 -0
- package/lib/src/params-placeholders.d.ts +55 -0
- package/lib/src/params-placeholders.js +204 -0
- package/lib/src/tsfixme.d.ts +1 -0
- package/lib/src/tsfixme.js +2 -0
- package/lib/src/types.d.ts +35 -0
- package/lib/src/types.js +2 -0
- package/lib/src/utils.d.ts +42 -0
- package/lib/src/utils.js +260 -0
- package/lib/src/visitors.d.ts +44 -0
- package/lib/src/visitors.js +382 -0
- package/lib/testData/schemaMock.d.ts +502 -0
- package/lib/testData/schemaMock.js +138 -0
- package/package.json +22 -22
- package/lib/contextVariables.js +0 -106
- package/lib/expression-utils.js +0 -1121
- package/lib/paramsPlaceholders.js +0 -232
- package/lib/utils.js +0 -223
- package/lib/visitors.js +0 -660
- package/types.d.ts +0 -139
package/lib/visitors.js
DELETED
|
@@ -1,660 +0,0 @@
|
|
|
1
|
-
var _ = require('lodash');
|
|
2
|
-
require('@fibery/helpers/utils/trace');
|
|
3
|
-
|
|
4
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
5
|
-
|
|
6
|
-
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
|
-
|
|
8
|
-
const stringify = x => {
|
|
9
|
-
if (x === undefined) {
|
|
10
|
-
return "undefined";
|
|
11
|
-
}
|
|
12
|
-
return JSON.stringify(x);
|
|
13
|
-
};
|
|
14
|
-
class NotImplementedError extends Error {
|
|
15
|
-
constructor(value, itemType = undefined) {
|
|
16
|
-
super([`"${stringify(value)}"`, itemType, "is not implemented"].filter(x => x !== undefined).join(" "));
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const firstLastFunctions = new Set(["q/first", "q/last"]);
|
|
21
|
-
const collectionOps = new Set(["q/count", "q/count-distinct", "q/sum", "q/min", "q/max", "q/avg", "q/join", "q/first", "q/last"]);
|
|
22
|
-
// [op, left, right]
|
|
23
|
-
// [=, $true, $false]
|
|
24
|
-
// [=, $my-id, ["fibery/id"]]
|
|
25
|
-
const binaryOperations = new Set(["=", "!=", "<", ">", "<=", ">=", "in",
|
|
26
|
-
//asc: obsolete,use q/in
|
|
27
|
-
"q/contains", "q/not-contains", "+", "-", "q/+", "q/-", "*", "/", "and", "or",
|
|
28
|
-
//asc: obsolete. use q/and, q/or
|
|
29
|
-
"q/and", "q/or", "q/in", "q/not-in"]);
|
|
30
|
-
const logicalOperators = new Set(["and", "or", "q/and", "q/or"]);
|
|
31
|
-
const isFunctionCallExpression = expression => expression.length > 1 && ___default["default"].isString(expression[0]) && (expression[0].startsWith("q/") || ["=", "!=", "<", ">", "<=", ">=", "+", "-", "*", "/", "in", "and", "or", "not-in"].includes(expression[0]));
|
|
32
|
-
const fromRootKeyword = "q/from-root";
|
|
33
|
-
const isFromRootFieldExpression = expression => ___default["default"].isArray(expression) && expression[0] === fromRootKeyword;
|
|
34
|
-
const isCollectionFunctionExpression = expression =>
|
|
35
|
-
//expression has length 3 in case of q/join
|
|
36
|
-
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]);
|
|
37
|
-
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
38
|
-
const isMultiFieldAccess = expression => ___default["default"].isArray(expression) && expression.length === 2 && !isFunctionCallExpression(expression) && expression.every(x => ___default["default"].isString(x));
|
|
39
|
-
const isMultiFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.some(x => isMultiFieldAccess(x)) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && (___default["default"].isString(x) || isMultiFieldAccess(x)));
|
|
40
|
-
const isFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.every(x => !isVariableExpression(x) && ___default["default"].isString(x));
|
|
41
|
-
const isQueryExpression = expression => {
|
|
42
|
-
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
43
|
-
const fromExpression = expression["q/from"];
|
|
44
|
-
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
45
|
-
return fromExpression === null || isFieldExpression(fromExpression) || isFromRootFieldExpression(fromExpression) || isMultiFieldExpression(fromExpression);
|
|
46
|
-
}
|
|
47
|
-
return false;
|
|
48
|
-
};
|
|
49
|
-
const createExpressionVisitor = visitor => {
|
|
50
|
-
let visitorWithDefault = null;
|
|
51
|
-
const visitorDefault = {
|
|
52
|
-
visitVariableExpression: expression => expression,
|
|
53
|
-
visitFunctionCallExpression: ([fnName, ...args]) => [fnName, ...args.map(x => visitorWithDefault.visitExpression(x))],
|
|
54
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => visitorWithDefault.visitExpression(x))],
|
|
55
|
-
visitFieldExpression: expression => expression,
|
|
56
|
-
visitOrderByExpression: orderByExpression => orderByExpression.map(x => {
|
|
57
|
-
const [fieldExpression, orderDir] = x;
|
|
58
|
-
const fieldExpressionNew = visitorWithDefault.visitExpression(fieldExpression);
|
|
59
|
-
return [fieldExpressionNew, orderDir];
|
|
60
|
-
}),
|
|
61
|
-
visitQueryExpression: subQueryExpression => {
|
|
62
|
-
const {
|
|
63
|
-
"q/from": fromExpression,
|
|
64
|
-
"q/select": selectExpression,
|
|
65
|
-
"q/where": whereExpression,
|
|
66
|
-
"q/order-by": orderByExpression
|
|
67
|
-
} = subQueryExpression;
|
|
68
|
-
return {
|
|
69
|
-
...subQueryExpression,
|
|
70
|
-
...(fromExpression ? {
|
|
71
|
-
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
72
|
-
} : null),
|
|
73
|
-
...(selectExpression ? {
|
|
74
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
75
|
-
} : null),
|
|
76
|
-
...(whereExpression ? {
|
|
77
|
-
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
78
|
-
} : null),
|
|
79
|
-
...(orderByExpression ? {
|
|
80
|
-
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
81
|
-
} : null)
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
visitExpression: expression => {
|
|
85
|
-
if (expression === null) {
|
|
86
|
-
throw new NotImplementedError(expression, "expression");
|
|
87
|
-
} else if (isVariableExpression(expression)) {
|
|
88
|
-
return visitorWithDefault.visitVariableExpression(expression, visitorDefault);
|
|
89
|
-
} else if (isFromRootFieldExpression(expression)) {
|
|
90
|
-
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
91
|
-
} else if (isFunctionCallExpression(expression)) {
|
|
92
|
-
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
93
|
-
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
94
|
-
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
95
|
-
} else if (isQueryExpression(expression)) {
|
|
96
|
-
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
97
|
-
} else {
|
|
98
|
-
throw new NotImplementedError(expression, "expression");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
visitorWithDefault = {
|
|
103
|
-
...visitorDefault,
|
|
104
|
-
...visitor
|
|
105
|
-
};
|
|
106
|
-
return visitorWithDefault;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
const visitFieldExpression = ({
|
|
110
|
-
expression: fieldExpression,
|
|
111
|
-
typeObject: initialTypeObject,
|
|
112
|
-
onField,
|
|
113
|
-
onFieldNotFound
|
|
114
|
-
}) => fieldExpression.reduce(({
|
|
115
|
-
typeObject,
|
|
116
|
-
expression
|
|
117
|
-
}, fieldAccess) => {
|
|
118
|
-
if (typeObject && isMultiFieldAccess(fieldAccess) && typeObject.fieldObjectsById.hasOwnProperty(fieldAccess[0])) {
|
|
119
|
-
var _fieldObject$multiRel;
|
|
120
|
-
const typeId = fieldAccess[1];
|
|
121
|
-
const fieldObject = typeObject.fieldObjectsById[fieldAccess[0]];
|
|
122
|
-
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
123
|
-
if (!nextTypeObject) {
|
|
124
|
-
const notFoundResult = onFieldNotFound({
|
|
125
|
-
currentTypeObject: typeObject,
|
|
126
|
-
expression: fieldExpression,
|
|
127
|
-
fieldAccess
|
|
128
|
-
});
|
|
129
|
-
return notFoundResult ? {
|
|
130
|
-
typeObject: notFoundResult.typeObject,
|
|
131
|
-
expression: [...expression, notFoundResult.fieldAccess]
|
|
132
|
-
} : {
|
|
133
|
-
typeObject,
|
|
134
|
-
expression
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
const onFieldResult = onField({
|
|
138
|
-
fieldAccess,
|
|
139
|
-
fieldObject,
|
|
140
|
-
typeObject: nextTypeObject
|
|
141
|
-
});
|
|
142
|
-
return onFieldResult ? {
|
|
143
|
-
typeObject: onFieldResult.typeObject,
|
|
144
|
-
expression: [...expression, onFieldResult.fieldAccess]
|
|
145
|
-
} : {
|
|
146
|
-
typeObject,
|
|
147
|
-
expression
|
|
148
|
-
};
|
|
149
|
-
} else if (typeObject && typeObject.fieldObjectsById.hasOwnProperty(fieldAccess)) {
|
|
150
|
-
const fieldObject = typeObject.fieldObjectsById[fieldAccess];
|
|
151
|
-
const onFieldResult = onField({
|
|
152
|
-
fieldAccess,
|
|
153
|
-
fieldObject,
|
|
154
|
-
typeObject: fieldObject.typeObject
|
|
155
|
-
});
|
|
156
|
-
return onFieldResult ? {
|
|
157
|
-
typeObject: onFieldResult.typeObject,
|
|
158
|
-
expression: [...expression, onFieldResult.fieldAccess]
|
|
159
|
-
} : {
|
|
160
|
-
typeObject,
|
|
161
|
-
expression
|
|
162
|
-
};
|
|
163
|
-
} else {
|
|
164
|
-
const notFoundResult = onFieldNotFound({
|
|
165
|
-
currentTypeObject: typeObject,
|
|
166
|
-
expression: fieldExpression,
|
|
167
|
-
fieldAccess
|
|
168
|
-
});
|
|
169
|
-
return notFoundResult ? {
|
|
170
|
-
typeObject: notFoundResult.typeObject,
|
|
171
|
-
expression: [...expression, notFoundResult.fieldAccess]
|
|
172
|
-
} : {
|
|
173
|
-
typeObject,
|
|
174
|
-
expression
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
}, {
|
|
178
|
-
typeObject: initialTypeObject,
|
|
179
|
-
expression: []
|
|
180
|
-
});
|
|
181
|
-
const defaultOnFieldNotFound = () => undefined;
|
|
182
|
-
const defaultOnField = () => undefined;
|
|
183
|
-
const fieldAccessVisitorTypeAwareInternal = ({
|
|
184
|
-
typeObject,
|
|
185
|
-
rootTypeObject,
|
|
186
|
-
onField = defaultOnField,
|
|
187
|
-
onFieldNotFound = defaultOnFieldNotFound
|
|
188
|
-
}) => {
|
|
189
|
-
return createExpressionVisitor({
|
|
190
|
-
visitFieldExpression: expression => visitFieldExpression({
|
|
191
|
-
typeObject,
|
|
192
|
-
expression,
|
|
193
|
-
onField,
|
|
194
|
-
onFieldNotFound
|
|
195
|
-
}).expression,
|
|
196
|
-
visitFromRootFieldExpression: ([fromRootKeyword, ...rest]) => [fromRootKeyword, ...rest.map(x => fieldAccessVisitorTypeAwareInternal({
|
|
197
|
-
typeObject: rootTypeObject,
|
|
198
|
-
rootTypeObject,
|
|
199
|
-
onField,
|
|
200
|
-
onFieldNotFound
|
|
201
|
-
}).visitExpression(x))],
|
|
202
|
-
visitQueryExpression: subQueryExpression => {
|
|
203
|
-
const {
|
|
204
|
-
"q/from": fromExpression,
|
|
205
|
-
"q/select": selectExpression,
|
|
206
|
-
"q/where": whereExpression,
|
|
207
|
-
"q/order-by": orderByExpression
|
|
208
|
-
} = subQueryExpression;
|
|
209
|
-
const fromVisitResult = visitFieldExpression({
|
|
210
|
-
typeObject,
|
|
211
|
-
expression: fromExpression,
|
|
212
|
-
onField,
|
|
213
|
-
onFieldNotFound
|
|
214
|
-
});
|
|
215
|
-
if (fromVisitResult != null && fromVisitResult.typeObject) {
|
|
216
|
-
const subQueryVisitor = fieldAccessVisitorTypeAwareInternal({
|
|
217
|
-
typeObject: fromVisitResult == null ? void 0 : fromVisitResult.typeObject,
|
|
218
|
-
rootTypeObject,
|
|
219
|
-
onField,
|
|
220
|
-
onFieldNotFound
|
|
221
|
-
});
|
|
222
|
-
return {
|
|
223
|
-
...subQueryExpression,
|
|
224
|
-
...{
|
|
225
|
-
"q/from": fromVisitResult.expression,
|
|
226
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
227
|
-
},
|
|
228
|
-
...(whereExpression ? {
|
|
229
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
230
|
-
} : null),
|
|
231
|
-
...(orderByExpression ? {
|
|
232
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
233
|
-
} : null)
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
return subQueryExpression;
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
};
|
|
240
|
-
const fieldAccessVisitorTypeAware = ({
|
|
241
|
-
typeObject,
|
|
242
|
-
onField = defaultOnField,
|
|
243
|
-
onFieldNotFound = defaultOnFieldNotFound
|
|
244
|
-
}) => {
|
|
245
|
-
return fieldAccessVisitorTypeAwareInternal({
|
|
246
|
-
typeObject,
|
|
247
|
-
rootTypeObject: typeObject,
|
|
248
|
-
onField,
|
|
249
|
-
onFieldNotFound
|
|
250
|
-
});
|
|
251
|
-
};
|
|
252
|
-
|
|
253
|
-
const defaultIdsWithNamesOnFieldNotFound = ({
|
|
254
|
-
fieldExpressionInNamesTerms,
|
|
255
|
-
fieldId
|
|
256
|
-
}) => {
|
|
257
|
-
return {
|
|
258
|
-
currentTypeObject: null,
|
|
259
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldId]
|
|
260
|
-
};
|
|
261
|
-
};
|
|
262
|
-
const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
263
|
-
expression,
|
|
264
|
-
typeObject,
|
|
265
|
-
onFieldNotFound
|
|
266
|
-
}) => expression.reduce(({
|
|
267
|
-
currentTypeObject,
|
|
268
|
-
fieldExpressionInNamesTerms
|
|
269
|
-
}, fieldId) => {
|
|
270
|
-
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
271
|
-
var _fieldObject$multiRel;
|
|
272
|
-
const typeId = fieldId[1];
|
|
273
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
274
|
-
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
275
|
-
if (!nextTypeObject) {
|
|
276
|
-
return onFieldNotFound({
|
|
277
|
-
currentTypeObject,
|
|
278
|
-
fieldExpressionInNamesTerms,
|
|
279
|
-
fieldId: fieldId,
|
|
280
|
-
expression
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
return {
|
|
284
|
-
currentTypeObject: nextTypeObject,
|
|
285
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, [fieldObject.name, nextTypeObject.name]]
|
|
286
|
-
};
|
|
287
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
288
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
289
|
-
return {
|
|
290
|
-
currentTypeObject: fieldObject.typeObject,
|
|
291
|
-
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, fieldObject.name]
|
|
292
|
-
};
|
|
293
|
-
} else {
|
|
294
|
-
return onFieldNotFound({
|
|
295
|
-
currentTypeObject,
|
|
296
|
-
fieldExpressionInNamesTerms,
|
|
297
|
-
fieldId,
|
|
298
|
-
expression
|
|
299
|
-
});
|
|
300
|
-
}
|
|
301
|
-
}, {
|
|
302
|
-
currentTypeObject: typeObject,
|
|
303
|
-
fieldExpressionInNamesTerms: []
|
|
304
|
-
});
|
|
305
|
-
const fieldExpressionVisitor = (typeObject, visitFieldExpression, replacedExpressionKey = "replacedExpression") => {
|
|
306
|
-
const visitor = createExpressionVisitor({
|
|
307
|
-
visitFieldExpression: expression => visitFieldExpression(typeObject, expression)[replacedExpressionKey],
|
|
308
|
-
visitQueryExpression: subQueryExpression => {
|
|
309
|
-
const {
|
|
310
|
-
"q/from": fromExpression,
|
|
311
|
-
"q/select": selectExpression,
|
|
312
|
-
"q/where": whereExpression,
|
|
313
|
-
"q/order-by": orderByExpression
|
|
314
|
-
} = subQueryExpression;
|
|
315
|
-
const subQueryTypeObject = visitFieldExpression(typeObject, fromExpression).currentTypeObject;
|
|
316
|
-
if (subQueryTypeObject) {
|
|
317
|
-
const subQueryVisitor = fieldExpressionVisitor(subQueryTypeObject, visitFieldExpression, replacedExpressionKey);
|
|
318
|
-
return {
|
|
319
|
-
...subQueryExpression,
|
|
320
|
-
...{
|
|
321
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
322
|
-
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
323
|
-
},
|
|
324
|
-
...(whereExpression ? {
|
|
325
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
326
|
-
} : null),
|
|
327
|
-
...(orderByExpression ? {
|
|
328
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
329
|
-
} : null)
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
return subQueryExpression;
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
return visitor;
|
|
336
|
-
};
|
|
337
|
-
const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWithNamesOnFieldNotFound) => {
|
|
338
|
-
return fieldExpressionVisitor(typeObject, (typeObject, expression) => visitFieldExpressionForReplaceIdsWithNamesVisitor({
|
|
339
|
-
expression,
|
|
340
|
-
typeObject,
|
|
341
|
-
onFieldNotFound
|
|
342
|
-
}), "fieldExpressionInNamesTerms");
|
|
343
|
-
};
|
|
344
|
-
const defaultNamesWithIdsOnFieldNotFound = ({
|
|
345
|
-
fieldExpressionInIdsTerms,
|
|
346
|
-
field
|
|
347
|
-
}) => {
|
|
348
|
-
return {
|
|
349
|
-
currentTypeObject: null,
|
|
350
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, field]
|
|
351
|
-
};
|
|
352
|
-
};
|
|
353
|
-
const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
354
|
-
expression,
|
|
355
|
-
typeObject,
|
|
356
|
-
onFieldNotFound
|
|
357
|
-
}) => expression.reduce(({
|
|
358
|
-
currentTypeObject,
|
|
359
|
-
fieldExpressionInIdsTerms
|
|
360
|
-
}, field) => {
|
|
361
|
-
if (currentTypeObject && isMultiFieldAccess(field) && currentTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
362
|
-
var _fieldObject$multiRel2;
|
|
363
|
-
const type = field[1];
|
|
364
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[field[0]];
|
|
365
|
-
const nextTypeObject = (_fieldObject$multiRel2 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel2.holderTypeObject;
|
|
366
|
-
if (!nextTypeObject) {
|
|
367
|
-
return onFieldNotFound({
|
|
368
|
-
currentTypeObject,
|
|
369
|
-
fieldExpressionInIdsTerms,
|
|
370
|
-
field,
|
|
371
|
-
expression
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
return {
|
|
375
|
-
currentTypeObject: nextTypeObject,
|
|
376
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, [fieldObject.id, nextTypeObject.id]]
|
|
377
|
-
};
|
|
378
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
379
|
-
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
380
|
-
return {
|
|
381
|
-
currentTypeObject: fieldObject.typeObject,
|
|
382
|
-
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, fieldObject.id]
|
|
383
|
-
};
|
|
384
|
-
} else {
|
|
385
|
-
return onFieldNotFound({
|
|
386
|
-
currentTypeObject,
|
|
387
|
-
fieldExpressionInIdsTerms,
|
|
388
|
-
field,
|
|
389
|
-
expression
|
|
390
|
-
});
|
|
391
|
-
}
|
|
392
|
-
}, {
|
|
393
|
-
currentTypeObject: typeObject,
|
|
394
|
-
fieldExpressionInIdsTerms: []
|
|
395
|
-
});
|
|
396
|
-
const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWithIdsOnFieldNotFound) => {
|
|
397
|
-
return fieldExpressionVisitor(typeObject, (typeObject, expression) => visitFieldExpressionForReplaceNamesWithIdsVisitor({
|
|
398
|
-
expression,
|
|
399
|
-
typeObject,
|
|
400
|
-
onFieldNotFound
|
|
401
|
-
}), "fieldExpressionInIdsTerms");
|
|
402
|
-
};
|
|
403
|
-
const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
404
|
-
const visitor = createExpressionVisitor({
|
|
405
|
-
visitFunctionCallExpression: ([fnName, ...args]) => {
|
|
406
|
-
const argsNew = args.map(x => visitor.visitExpression(x)).filter(Boolean);
|
|
407
|
-
if (logicalOperators.has(fnName)) {
|
|
408
|
-
if (argsNew.length > 0) {
|
|
409
|
-
return argsNew.length === 1 ? argsNew[0] : [fnName, ...argsNew];
|
|
410
|
-
}
|
|
411
|
-
return null;
|
|
412
|
-
} else {
|
|
413
|
-
return argsNew.length === args.length ? [fnName, ...argsNew] : null;
|
|
414
|
-
}
|
|
415
|
-
},
|
|
416
|
-
visitFieldExpression: expression => {
|
|
417
|
-
const fieldTypeObject = expression.reduce((holderTypeObject, field) => {
|
|
418
|
-
if (holderTypeObject && isMultiFieldAccess(field) && holderTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
419
|
-
var _fieldObject$multiRel3;
|
|
420
|
-
const type = field[1];
|
|
421
|
-
const fieldObject = holderTypeObject.fieldObjectsByName[field[0]];
|
|
422
|
-
const nextTypeObject = (_fieldObject$multiRel3 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel3.holderTypeObject;
|
|
423
|
-
if (!nextTypeObject) {
|
|
424
|
-
return null;
|
|
425
|
-
}
|
|
426
|
-
return nextTypeObject;
|
|
427
|
-
} else if (holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
428
|
-
return holderTypeObject.fieldObjectsByName[field].typeObject;
|
|
429
|
-
} else {
|
|
430
|
-
return null;
|
|
431
|
-
}
|
|
432
|
-
}, typeObject);
|
|
433
|
-
return fieldTypeObject && expression;
|
|
434
|
-
},
|
|
435
|
-
visitOrderByExpression: orderByExpression => {
|
|
436
|
-
return orderByExpression.map(x => {
|
|
437
|
-
const [fieldExpression, orderDir] = x;
|
|
438
|
-
const fieldExpressionNew = visitor.visitExpression(fieldExpression);
|
|
439
|
-
return fieldExpressionNew && [fieldExpressionNew, orderDir];
|
|
440
|
-
}).filter(Boolean);
|
|
441
|
-
},
|
|
442
|
-
visitQueryExpression: subQueryExpression => {
|
|
443
|
-
const {
|
|
444
|
-
"q/from": fromExpression,
|
|
445
|
-
"q/select": selectExpression,
|
|
446
|
-
"q/where": whereExpression,
|
|
447
|
-
"q/order-by": orderByExpression
|
|
448
|
-
} = subQueryExpression;
|
|
449
|
-
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
450
|
-
if (subQueryTypeObject) {
|
|
451
|
-
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
452
|
-
const subQueryExpressionNew = ___default["default"].pickBy({
|
|
453
|
-
...subQueryExpression,
|
|
454
|
-
...{
|
|
455
|
-
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
456
|
-
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
457
|
-
},
|
|
458
|
-
...(whereExpression ? {
|
|
459
|
-
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
460
|
-
} : null),
|
|
461
|
-
...(orderByExpression ? {
|
|
462
|
-
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
463
|
-
} : null)
|
|
464
|
-
});
|
|
465
|
-
const {
|
|
466
|
-
"q/select": selectExpressionNew
|
|
467
|
-
} = subQueryExpressionNew;
|
|
468
|
-
return selectExpressionNew ? subQueryExpressionNew : null;
|
|
469
|
-
} else {
|
|
470
|
-
return null;
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
});
|
|
474
|
-
return visitor;
|
|
475
|
-
};
|
|
476
|
-
const expressionContainsAggregation = expression => {
|
|
477
|
-
let result = false;
|
|
478
|
-
const visitor = createExpressionVisitor({
|
|
479
|
-
visitQueryExpression: queryExpression => {
|
|
480
|
-
const {
|
|
481
|
-
"q/select": selectExpression
|
|
482
|
-
} = queryExpression;
|
|
483
|
-
if (isCollectionFunctionExpression(selectExpression)) {
|
|
484
|
-
result = true;
|
|
485
|
-
}
|
|
486
|
-
},
|
|
487
|
-
visitFunctionCallExpression: (expression, visitorDefault) => {
|
|
488
|
-
if (firstLastFunctions.has(expression[0])) {
|
|
489
|
-
result = true;
|
|
490
|
-
} else {
|
|
491
|
-
visitorDefault.visitFunctionCallExpression(expression);
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
});
|
|
495
|
-
visitor.visitExpression(expression);
|
|
496
|
-
return result;
|
|
497
|
-
};
|
|
498
|
-
const defaultGetExpressionTypeOnFieldNotFound = () => {
|
|
499
|
-
return {
|
|
500
|
-
currentTypeObject: null
|
|
501
|
-
};
|
|
502
|
-
};
|
|
503
|
-
const getFieldAccessExpressionTypeObject = ({
|
|
504
|
-
expression,
|
|
505
|
-
typeObject,
|
|
506
|
-
onFieldNotFound,
|
|
507
|
-
returnRefTypeInsteadOfId
|
|
508
|
-
}) => {
|
|
509
|
-
const reduced = expression.reduce(({
|
|
510
|
-
currentTypeObject
|
|
511
|
-
}, fieldId, index) => {
|
|
512
|
-
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
513
|
-
var _fieldObject$multiRel4;
|
|
514
|
-
const typeId = fieldId[1];
|
|
515
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
516
|
-
const nextTypeObject = (_fieldObject$multiRel4 = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel4.holderTypeObject;
|
|
517
|
-
if (!nextTypeObject) {
|
|
518
|
-
return onFieldNotFound({
|
|
519
|
-
currentTypeObject,
|
|
520
|
-
fieldId
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
return {
|
|
524
|
-
currentTypeObject: nextTypeObject
|
|
525
|
-
};
|
|
526
|
-
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
527
|
-
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
528
|
-
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
529
|
-
return {
|
|
530
|
-
currentTypeObject
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
return {
|
|
534
|
-
currentTypeObject: fieldObject.typeObject
|
|
535
|
-
};
|
|
536
|
-
} else {
|
|
537
|
-
return onFieldNotFound({
|
|
538
|
-
currentTypeObject,
|
|
539
|
-
fieldId
|
|
540
|
-
});
|
|
541
|
-
}
|
|
542
|
-
}, {
|
|
543
|
-
currentTypeObject: typeObject
|
|
544
|
-
});
|
|
545
|
-
return reduced.currentTypeObject;
|
|
546
|
-
};
|
|
547
|
-
const UNKNOWN_EXPRESSION_TYPE = "unknown";
|
|
548
|
-
const getExpressionTypeInternal = ({
|
|
549
|
-
expression,
|
|
550
|
-
typeObject,
|
|
551
|
-
functionsMeta,
|
|
552
|
-
onFieldNotFound,
|
|
553
|
-
returnRefTypeInsteadOfId
|
|
554
|
-
}) => {
|
|
555
|
-
let result = null;
|
|
556
|
-
const visitor = createExpressionVisitor({
|
|
557
|
-
visitVariableExpression: function () {
|
|
558
|
-
result = UNKNOWN_EXPRESSION_TYPE;
|
|
559
|
-
},
|
|
560
|
-
visitFunctionCallExpression: function ([fnName, ...args]) {
|
|
561
|
-
const fnMeta = functionsMeta[fnName];
|
|
562
|
-
if (!fnMeta) {
|
|
563
|
-
throw new Error(`Function meta for "${fnName}" was not provided`);
|
|
564
|
-
}
|
|
565
|
-
const argTypes = args.map(arg => getExpressionTypeInternal({
|
|
566
|
-
expression: arg,
|
|
567
|
-
typeObject,
|
|
568
|
-
functionsMeta,
|
|
569
|
-
onFieldNotFound,
|
|
570
|
-
returnRefTypeInsteadOfId: firstLastFunctions.has(fnName) || fnName === "q/if" || fnName === "q/if-null" ? returnRefTypeInsteadOfId : false
|
|
571
|
-
}));
|
|
572
|
-
if (firstLastFunctions.has(fnName)) {
|
|
573
|
-
//assuming q/first has one argument and result type equals arg type.
|
|
574
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/first and q/last.
|
|
575
|
-
result = argTypes[0];
|
|
576
|
-
} else if (fnName === "q/if") {
|
|
577
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/if.
|
|
578
|
-
result = argTypes[1];
|
|
579
|
-
} else if (fnName === "q/if-null" && argTypes.some(x => !x.isPrimitive)) {
|
|
580
|
-
//we need this trick to support 'returnRefTypeInsteadOfId' behavior for q/if.
|
|
581
|
-
result = argTypes[0];
|
|
582
|
-
} else {
|
|
583
|
-
const overload = fnMeta.overloads.find(o => o["arg-types"].every((argType, index) => argTypes[index] === UNKNOWN_EXPRESSION_TYPE || argTypes[index] === argType || ["fibery/email", "fibery/url", "fibery/emoji", "fibery/color"].includes(argTypes[index]) && argType === "fibery/text"));
|
|
584
|
-
if (!overload) {
|
|
585
|
-
throw new Error(`No overload with args ${argTypes.join(",")} found for "${fnName}" in meta`);
|
|
586
|
-
}
|
|
587
|
-
result = overload["result-type"];
|
|
588
|
-
}
|
|
589
|
-
},
|
|
590
|
-
visitQueryExpression: expression => {
|
|
591
|
-
const {
|
|
592
|
-
"q/from": fromExpression,
|
|
593
|
-
"q/select": selectExpression
|
|
594
|
-
} = expression;
|
|
595
|
-
const fromTypeObject = getFieldAccessExpressionTypeObject({
|
|
596
|
-
expression: fromExpression,
|
|
597
|
-
typeObject,
|
|
598
|
-
onFieldNotFound,
|
|
599
|
-
returnRefTypeInsteadOfId
|
|
600
|
-
});
|
|
601
|
-
if (!fromTypeObject) {
|
|
602
|
-
result = null;
|
|
603
|
-
}
|
|
604
|
-
if (___default["default"].isPlainObject(selectExpression)) {
|
|
605
|
-
if (Object.values(selectExpression).length !== 1) {
|
|
606
|
-
throw new Error(`Can't determine type of query expression ${JSON.stringify(expression)}`);
|
|
607
|
-
}
|
|
608
|
-
result = getExpressionTypeInternal({
|
|
609
|
-
expression: Object.values(selectExpression)[0],
|
|
610
|
-
typeObject: fromTypeObject,
|
|
611
|
-
functionsMeta,
|
|
612
|
-
onFieldNotFound,
|
|
613
|
-
returnRefTypeInsteadOfId
|
|
614
|
-
});
|
|
615
|
-
} else {
|
|
616
|
-
result = getExpressionTypeInternal({
|
|
617
|
-
expression: selectExpression,
|
|
618
|
-
typeObject: fromTypeObject,
|
|
619
|
-
functionsMeta,
|
|
620
|
-
onFieldNotFound,
|
|
621
|
-
returnRefTypeInsteadOfId
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
},
|
|
625
|
-
visitFieldExpression(expression) {
|
|
626
|
-
const fieldAccessExpressionTypeObject = getFieldAccessExpressionTypeObject({
|
|
627
|
-
expression,
|
|
628
|
-
typeObject,
|
|
629
|
-
onFieldNotFound,
|
|
630
|
-
returnRefTypeInsteadOfId
|
|
631
|
-
});
|
|
632
|
-
result = fieldAccessExpressionTypeObject && fieldAccessExpressionTypeObject.name;
|
|
633
|
-
}
|
|
634
|
-
});
|
|
635
|
-
visitor.visitExpression(expression);
|
|
636
|
-
return result;
|
|
637
|
-
};
|
|
638
|
-
const getExpressionType = ({
|
|
639
|
-
expression,
|
|
640
|
-
typeObject,
|
|
641
|
-
functionsMeta,
|
|
642
|
-
onFieldNotFound = defaultGetExpressionTypeOnFieldNotFound,
|
|
643
|
-
returnRefTypeInsteadOfId = true
|
|
644
|
-
}) => {
|
|
645
|
-
return getExpressionTypeInternal({
|
|
646
|
-
expression,
|
|
647
|
-
typeObject,
|
|
648
|
-
functionsMeta,
|
|
649
|
-
onFieldNotFound,
|
|
650
|
-
returnRefTypeInsteadOfId
|
|
651
|
-
});
|
|
652
|
-
};
|
|
653
|
-
|
|
654
|
-
exports.UNKNOWN_EXPRESSION_TYPE = UNKNOWN_EXPRESSION_TYPE;
|
|
655
|
-
exports.deleteExpressionsWithNotFoundFieldsVisitor = deleteExpressionsWithNotFoundFieldsVisitor;
|
|
656
|
-
exports.expressionContainsAggregation = expressionContainsAggregation;
|
|
657
|
-
exports.fieldAccessVisitorTypeAware = fieldAccessVisitorTypeAware;
|
|
658
|
-
exports.getExpressionType = getExpressionType;
|
|
659
|
-
exports.replaceIdsWithNamesVisitor = replaceIdsWithNamesVisitor;
|
|
660
|
-
exports.replaceNamesWithIdsVisitor = replaceNamesWithIdsVisitor;
|