@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/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;