@fibery/expression-utils 6.0.0 → 7.0.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/expression-utils.js +134 -74
- package/lib/utils.js +27 -45
- package/lib/visitors.js +131 -57
- package/package.json +6 -6
- package/index.js +0 -6
package/lib/expression-utils.js
CHANGED
|
@@ -193,21 +193,6 @@ var paramsPlaceholders = {
|
|
|
193
193
|
dateToDateTimeIntervalLookup: dateToDateTimeIntervalLookup
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
-
function _extends() {
|
|
197
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
198
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
199
|
-
var source = arguments[i];
|
|
200
|
-
for (var key in source) {
|
|
201
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
202
|
-
target[key] = source[key];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return target;
|
|
207
|
-
};
|
|
208
|
-
return _extends.apply(this, arguments);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
196
|
const stringify = x => {
|
|
212
197
|
if (x === undefined) {
|
|
213
198
|
return "undefined";
|
|
@@ -254,30 +239,17 @@ const isAccessFunctionExpression = expresion => expresion.length === 2 && expres
|
|
|
254
239
|
const isBinaryExpression = expression => expression.length === 3 && binaryOperations.has(expression[0]);
|
|
255
240
|
const isNaryExpression = expression => expression.length > 1 && naryOperations.has(expression[0]);
|
|
256
241
|
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
257
|
-
const
|
|
242
|
+
const isMultiFieldAccess = expression => ___default["default"].isArray(expression) && expression.length === 2 && !isFunctionCallExpression(expression) && expression.every(x => ___default["default"].isString(x));
|
|
243
|
+
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)));
|
|
244
|
+
const isFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.every(x => !isVariableExpression(x) && ___default["default"].isString(x));
|
|
258
245
|
const isQueryExpression = expression => {
|
|
259
246
|
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
260
247
|
const fromExpression = expression["q/from"];
|
|
261
248
|
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
262
|
-
return fromExpression === null || isFieldExpression(fromExpression);
|
|
249
|
+
return fromExpression === null || isFieldExpression(fromExpression) || isFromRootFieldExpression(fromExpression) || isMultiFieldExpression(fromExpression);
|
|
263
250
|
}
|
|
264
251
|
return false;
|
|
265
252
|
};
|
|
266
|
-
// [q/count, [..., collection]]
|
|
267
|
-
// [q/start, [..., range]]
|
|
268
|
-
// [q/end, [..., range]]
|
|
269
|
-
// [q/access?, [..., field-expr]]
|
|
270
|
-
const isFunctionExpression = expression => {
|
|
271
|
-
if (!Array.isArray(expression)) {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
if (isFieldExpression(expression)) {
|
|
275
|
-
return false;
|
|
276
|
-
} else if (isDateRangeFunctionExpression(expression) || isCollectionFunctionExpression(expression) || isAccessFunctionExpression(expression)) {
|
|
277
|
-
return true;
|
|
278
|
-
}
|
|
279
|
-
throw new Error("invalid expression:" + JSON.stringify(expression));
|
|
280
|
-
};
|
|
281
253
|
const collectFieldExpressions = (memo, expression) => {
|
|
282
254
|
if (isVariableExpression(expression)) ; else if (isFunctionCallExpression(expression)) {
|
|
283
255
|
for (const part of expression.slice(1)) {
|
|
@@ -290,7 +262,7 @@ const collectFieldExpressions = (memo, expression) => {
|
|
|
290
262
|
}
|
|
291
263
|
}
|
|
292
264
|
}
|
|
293
|
-
} else if (isFieldExpression(expression)) {
|
|
265
|
+
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
294
266
|
memo.push(expression);
|
|
295
267
|
} else if (expression["q/from"] && isFieldExpression(expression["q/from"])) {
|
|
296
268
|
const innerMemo = [];
|
|
@@ -327,15 +299,21 @@ const createExpressionVisitor = visitor => {
|
|
|
327
299
|
"q/where": whereExpression,
|
|
328
300
|
"q/order-by": orderByExpression
|
|
329
301
|
} = subQueryExpression;
|
|
330
|
-
return
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
302
|
+
return {
|
|
303
|
+
...subQueryExpression,
|
|
304
|
+
...(fromExpression ? {
|
|
305
|
+
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
306
|
+
} : null),
|
|
307
|
+
...(selectExpression ? {
|
|
308
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
309
|
+
} : null),
|
|
310
|
+
...(whereExpression ? {
|
|
311
|
+
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
312
|
+
} : null),
|
|
313
|
+
...(orderByExpression ? {
|
|
314
|
+
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
315
|
+
} : null)
|
|
316
|
+
};
|
|
339
317
|
},
|
|
340
318
|
visitExpression: expression => {
|
|
341
319
|
if (expression === null) {
|
|
@@ -346,7 +324,7 @@ const createExpressionVisitor = visitor => {
|
|
|
346
324
|
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
347
325
|
} else if (isFunctionCallExpression(expression)) {
|
|
348
326
|
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
349
|
-
} else if (isFieldExpression(expression)) {
|
|
327
|
+
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
350
328
|
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
351
329
|
} else if (isQueryExpression(expression)) {
|
|
352
330
|
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
@@ -355,7 +333,10 @@ const createExpressionVisitor = visitor => {
|
|
|
355
333
|
}
|
|
356
334
|
}
|
|
357
335
|
};
|
|
358
|
-
visitorWithDefault =
|
|
336
|
+
visitorWithDefault = {
|
|
337
|
+
...visitorDefault,
|
|
338
|
+
...visitor
|
|
339
|
+
};
|
|
359
340
|
return visitorWithDefault;
|
|
360
341
|
};
|
|
361
342
|
|
|
@@ -376,9 +357,10 @@ var utils = {
|
|
|
376
357
|
isBinaryExpression: isBinaryExpression,
|
|
377
358
|
isNaryExpression: isNaryExpression,
|
|
378
359
|
isVariableExpression: isVariableExpression,
|
|
360
|
+
isMultiFieldAccess: isMultiFieldAccess,
|
|
361
|
+
isMultiFieldExpression: isMultiFieldExpression,
|
|
379
362
|
isFieldExpression: isFieldExpression,
|
|
380
363
|
isQueryExpression: isQueryExpression,
|
|
381
|
-
isFunctionExpression: isFunctionExpression,
|
|
382
364
|
extractFieldExpressions: extractFieldExpressions,
|
|
383
365
|
createExpressionVisitor: createExpressionVisitor
|
|
384
366
|
};
|
|
@@ -400,7 +382,24 @@ const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
|
400
382
|
currentTypeObject,
|
|
401
383
|
fieldExpressionInNamesTerms
|
|
402
384
|
}, fieldId) => {
|
|
403
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
385
|
+
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
386
|
+
var _fieldObject$multiRel;
|
|
387
|
+
const typeId = fieldId[1];
|
|
388
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
389
|
+
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
390
|
+
if (!nextTypeObject) {
|
|
391
|
+
return onFieldNotFound({
|
|
392
|
+
currentTypeObject,
|
|
393
|
+
fieldExpressionInNamesTerms,
|
|
394
|
+
fieldId: fieldId,
|
|
395
|
+
expression
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
return {
|
|
399
|
+
currentTypeObject: nextTypeObject,
|
|
400
|
+
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, [fieldObject.name, nextTypeObject.name]]
|
|
401
|
+
};
|
|
402
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
404
403
|
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
405
404
|
return {
|
|
406
405
|
currentTypeObject: fieldObject.typeObject,
|
|
@@ -439,14 +438,19 @@ const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWith
|
|
|
439
438
|
}).currentTypeObject;
|
|
440
439
|
if (subQueryTypeObject) {
|
|
441
440
|
const subQueryVisitor = replaceIdsWithNamesVisitor(subQueryTypeObject, onFieldNotFound);
|
|
442
|
-
return
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
441
|
+
return {
|
|
442
|
+
...subQueryExpression,
|
|
443
|
+
...{
|
|
444
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
445
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
446
|
+
},
|
|
447
|
+
...(whereExpression ? {
|
|
448
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
449
|
+
} : null),
|
|
450
|
+
...(orderByExpression ? {
|
|
451
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
452
|
+
} : null)
|
|
453
|
+
};
|
|
450
454
|
}
|
|
451
455
|
return subQueryExpression;
|
|
452
456
|
}
|
|
@@ -470,7 +474,24 @@ const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
|
470
474
|
currentTypeObject,
|
|
471
475
|
fieldExpressionInIdsTerms
|
|
472
476
|
}, field) => {
|
|
473
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
477
|
+
if (currentTypeObject && isMultiFieldAccess(field) && currentTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
478
|
+
var _fieldObject$multiRel2;
|
|
479
|
+
const type = field[1];
|
|
480
|
+
const fieldObject = currentTypeObject.fieldObjectsByName[field[0]];
|
|
481
|
+
const nextTypeObject = (_fieldObject$multiRel2 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel2.holderTypeObject;
|
|
482
|
+
if (!nextTypeObject) {
|
|
483
|
+
return onFieldNotFound({
|
|
484
|
+
currentTypeObject,
|
|
485
|
+
fieldExpressionInIdsTerms,
|
|
486
|
+
field,
|
|
487
|
+
expression
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
return {
|
|
491
|
+
currentTypeObject: nextTypeObject,
|
|
492
|
+
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, [fieldObject.id, nextTypeObject.id]]
|
|
493
|
+
};
|
|
494
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
474
495
|
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
475
496
|
return {
|
|
476
497
|
currentTypeObject: fieldObject.typeObject,
|
|
@@ -509,14 +530,19 @@ const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWi
|
|
|
509
530
|
}).currentTypeObject;
|
|
510
531
|
if (subQueryTypeObject) {
|
|
511
532
|
const subQueryVisitor = replaceNamesWithIdsVisitor(subQueryTypeObject, onFieldNotFound);
|
|
512
|
-
return
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
533
|
+
return {
|
|
534
|
+
...subQueryExpression,
|
|
535
|
+
...{
|
|
536
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
537
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
538
|
+
},
|
|
539
|
+
...(whereExpression ? {
|
|
540
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
541
|
+
} : null),
|
|
542
|
+
...(orderByExpression ? {
|
|
543
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
544
|
+
} : null)
|
|
545
|
+
};
|
|
520
546
|
}
|
|
521
547
|
return subQueryExpression;
|
|
522
548
|
}
|
|
@@ -537,7 +563,22 @@ const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
|
537
563
|
}
|
|
538
564
|
},
|
|
539
565
|
visitFieldExpression: expression => {
|
|
540
|
-
const fieldTypeObject = expression.reduce((holderTypeObject, field) =>
|
|
566
|
+
const fieldTypeObject = expression.reduce((holderTypeObject, field) => {
|
|
567
|
+
if (holderTypeObject && isMultiFieldAccess(field) && holderTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
568
|
+
var _fieldObject$multiRel3;
|
|
569
|
+
const type = field[1];
|
|
570
|
+
const fieldObject = holderTypeObject.fieldObjectsByName[field[0]];
|
|
571
|
+
const nextTypeObject = (_fieldObject$multiRel3 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel3.holderTypeObject;
|
|
572
|
+
if (!nextTypeObject) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
return nextTypeObject;
|
|
576
|
+
} else if (holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
577
|
+
return holderTypeObject.fieldObjectsByName[field].typeObject;
|
|
578
|
+
} else {
|
|
579
|
+
return null;
|
|
580
|
+
}
|
|
581
|
+
}, typeObject);
|
|
541
582
|
return fieldTypeObject && expression;
|
|
542
583
|
},
|
|
543
584
|
visitOrderByExpression: orderByExpression => {
|
|
@@ -557,14 +598,19 @@ const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
|
557
598
|
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
558
599
|
if (subQueryTypeObject) {
|
|
559
600
|
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
560
|
-
const subQueryExpressionNew = ___default["default"].pickBy(
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
601
|
+
const subQueryExpressionNew = ___default["default"].pickBy({
|
|
602
|
+
...subQueryExpression,
|
|
603
|
+
...{
|
|
604
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
605
|
+
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
606
|
+
},
|
|
607
|
+
...(whereExpression ? {
|
|
608
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
609
|
+
} : null),
|
|
610
|
+
...(orderByExpression ? {
|
|
611
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
612
|
+
} : null)
|
|
613
|
+
});
|
|
568
614
|
const {
|
|
569
615
|
"q/select": selectExpressionNew
|
|
570
616
|
} = subQueryExpressionNew;
|
|
@@ -612,8 +658,22 @@ const getFieldAccessExpressionTypeObject = ({
|
|
|
612
658
|
const reduced = expression.reduce(({
|
|
613
659
|
currentTypeObject
|
|
614
660
|
}, fieldId, index) => {
|
|
615
|
-
|
|
616
|
-
|
|
661
|
+
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
662
|
+
var _fieldObject$multiRel4;
|
|
663
|
+
const typeId = fieldId[1];
|
|
664
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
665
|
+
const nextTypeObject = (_fieldObject$multiRel4 = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel4.holderTypeObject;
|
|
666
|
+
if (!nextTypeObject) {
|
|
667
|
+
return onFieldNotFound({
|
|
668
|
+
currentTypeObject,
|
|
669
|
+
fieldId
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
return {
|
|
673
|
+
currentTypeObject: nextTypeObject
|
|
674
|
+
};
|
|
675
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
676
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
617
677
|
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
618
678
|
return {
|
|
619
679
|
currentTypeObject
|
package/lib/utils.js
CHANGED
|
@@ -5,21 +5,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
5
5
|
|
|
6
6
|
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
7
|
|
|
8
|
-
function _extends() {
|
|
9
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
for (var key in source) {
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
14
|
-
target[key] = source[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
return _extends.apply(this, arguments);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
8
|
const stringify = x => {
|
|
24
9
|
if (x === undefined) {
|
|
25
10
|
return "undefined";
|
|
@@ -66,30 +51,17 @@ const isAccessFunctionExpression = expresion => expresion.length === 2 && expres
|
|
|
66
51
|
const isBinaryExpression = expression => expression.length === 3 && binaryOperations.has(expression[0]);
|
|
67
52
|
const isNaryExpression = expression => expression.length > 1 && naryOperations.has(expression[0]);
|
|
68
53
|
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
69
|
-
const
|
|
54
|
+
const isMultiFieldAccess = expression => ___default["default"].isArray(expression) && expression.length === 2 && !isFunctionCallExpression(expression) && expression.every(x => ___default["default"].isString(x));
|
|
55
|
+
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)));
|
|
56
|
+
const isFieldExpression = expression => Array.isArray(expression) && !isFunctionCallExpression(expression) && expression.every(x => !isVariableExpression(x) && ___default["default"].isString(x));
|
|
70
57
|
const isQueryExpression = expression => {
|
|
71
58
|
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
72
59
|
const fromExpression = expression["q/from"];
|
|
73
60
|
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
74
|
-
return fromExpression === null || isFieldExpression(fromExpression);
|
|
61
|
+
return fromExpression === null || isFieldExpression(fromExpression) || isFromRootFieldExpression(fromExpression) || isMultiFieldExpression(fromExpression);
|
|
75
62
|
}
|
|
76
63
|
return false;
|
|
77
64
|
};
|
|
78
|
-
// [q/count, [..., collection]]
|
|
79
|
-
// [q/start, [..., range]]
|
|
80
|
-
// [q/end, [..., range]]
|
|
81
|
-
// [q/access?, [..., field-expr]]
|
|
82
|
-
const isFunctionExpression = expression => {
|
|
83
|
-
if (!Array.isArray(expression)) {
|
|
84
|
-
return false;
|
|
85
|
-
}
|
|
86
|
-
if (isFieldExpression(expression)) {
|
|
87
|
-
return false;
|
|
88
|
-
} else if (isDateRangeFunctionExpression(expression) || isCollectionFunctionExpression(expression) || isAccessFunctionExpression(expression)) {
|
|
89
|
-
return true;
|
|
90
|
-
}
|
|
91
|
-
throw new Error("invalid expression:" + JSON.stringify(expression));
|
|
92
|
-
};
|
|
93
65
|
const collectFieldExpressions = (memo, expression) => {
|
|
94
66
|
if (isVariableExpression(expression)) ; else if (isFunctionCallExpression(expression)) {
|
|
95
67
|
for (const part of expression.slice(1)) {
|
|
@@ -102,7 +74,7 @@ const collectFieldExpressions = (memo, expression) => {
|
|
|
102
74
|
}
|
|
103
75
|
}
|
|
104
76
|
}
|
|
105
|
-
} else if (isFieldExpression(expression)) {
|
|
77
|
+
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
106
78
|
memo.push(expression);
|
|
107
79
|
} else if (expression["q/from"] && isFieldExpression(expression["q/from"])) {
|
|
108
80
|
const innerMemo = [];
|
|
@@ -139,15 +111,21 @@ const createExpressionVisitor = visitor => {
|
|
|
139
111
|
"q/where": whereExpression,
|
|
140
112
|
"q/order-by": orderByExpression
|
|
141
113
|
} = subQueryExpression;
|
|
142
|
-
return
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
114
|
+
return {
|
|
115
|
+
...subQueryExpression,
|
|
116
|
+
...(fromExpression ? {
|
|
117
|
+
"q/from": visitorWithDefault.visitFieldExpression(fromExpression)
|
|
118
|
+
} : null),
|
|
119
|
+
...(selectExpression ? {
|
|
120
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
|
|
121
|
+
} : null),
|
|
122
|
+
...(whereExpression ? {
|
|
123
|
+
"q/where": visitorWithDefault.visitExpression(whereExpression)
|
|
124
|
+
} : null),
|
|
125
|
+
...(orderByExpression ? {
|
|
126
|
+
"q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
|
|
127
|
+
} : null)
|
|
128
|
+
};
|
|
151
129
|
},
|
|
152
130
|
visitExpression: expression => {
|
|
153
131
|
if (expression === null) {
|
|
@@ -158,7 +136,7 @@ const createExpressionVisitor = visitor => {
|
|
|
158
136
|
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
159
137
|
} else if (isFunctionCallExpression(expression)) {
|
|
160
138
|
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
161
|
-
} else if (isFieldExpression(expression)) {
|
|
139
|
+
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
162
140
|
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
163
141
|
} else if (isQueryExpression(expression)) {
|
|
164
142
|
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
@@ -167,7 +145,10 @@ const createExpressionVisitor = visitor => {
|
|
|
167
145
|
}
|
|
168
146
|
}
|
|
169
147
|
};
|
|
170
|
-
visitorWithDefault =
|
|
148
|
+
visitorWithDefault = {
|
|
149
|
+
...visitorDefault,
|
|
150
|
+
...visitor
|
|
151
|
+
};
|
|
171
152
|
return visitorWithDefault;
|
|
172
153
|
};
|
|
173
154
|
|
|
@@ -184,7 +165,8 @@ exports.isDateRangeFunctionExpression = isDateRangeFunctionExpression;
|
|
|
184
165
|
exports.isFieldExpression = isFieldExpression;
|
|
185
166
|
exports.isFromRootFieldExpression = isFromRootFieldExpression;
|
|
186
167
|
exports.isFunctionCallExpression = isFunctionCallExpression;
|
|
187
|
-
exports.
|
|
168
|
+
exports.isMultiFieldAccess = isMultiFieldAccess;
|
|
169
|
+
exports.isMultiFieldExpression = isMultiFieldExpression;
|
|
188
170
|
exports.isNaryExpression = isNaryExpression;
|
|
189
171
|
exports.isQueryExpression = isQueryExpression;
|
|
190
172
|
exports.isVariableExpression = isVariableExpression;
|
package/lib/visitors.js
CHANGED
|
@@ -5,21 +5,6 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
5
5
|
|
|
6
6
|
var ___default = /*#__PURE__*/_interopDefaultLegacy(_);
|
|
7
7
|
|
|
8
|
-
function _extends() {
|
|
9
|
-
_extends = Object.assign ? Object.assign.bind() : function (target) {
|
|
10
|
-
for (var i = 1; i < arguments.length; i++) {
|
|
11
|
-
var source = arguments[i];
|
|
12
|
-
for (var key in source) {
|
|
13
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
14
|
-
target[key] = source[key];
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
return target;
|
|
19
|
-
};
|
|
20
|
-
return _extends.apply(this, arguments);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
8
|
const stringify = x => {
|
|
24
9
|
if (x === undefined) {
|
|
25
10
|
return "undefined";
|
|
@@ -50,12 +35,14 @@ const isCollectionFunctionExpression = expression =>
|
|
|
50
35
|
//expression has length 3 in case of q/join
|
|
51
36
|
(expression.length === 2 || expression.length === 3) && collectionOps.has(expression[0]);
|
|
52
37
|
const isVariableExpression = expression => ___default["default"].isString(expression) && expression.startsWith("$");
|
|
53
|
-
const
|
|
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));
|
|
54
41
|
const isQueryExpression = expression => {
|
|
55
42
|
if (___default["default"].isObject(expression) && "q/from" in expression) {
|
|
56
43
|
const fromExpression = expression["q/from"];
|
|
57
44
|
//asc: fromExpression === null for denormalizeSelect for reference collection case
|
|
58
|
-
return fromExpression === null || isFieldExpression(fromExpression);
|
|
45
|
+
return fromExpression === null || isFieldExpression(fromExpression) || isFromRootFieldExpression(fromExpression) || isMultiFieldExpression(fromExpression);
|
|
59
46
|
}
|
|
60
47
|
return false;
|
|
61
48
|
};
|
|
@@ -78,15 +65,21 @@ const createExpressionVisitor = visitor => {
|
|
|
78
65
|
"q/where": whereExpression,
|
|
79
66
|
"q/order-by": orderByExpression
|
|
80
67
|
} = subQueryExpression;
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
+
};
|
|
90
83
|
},
|
|
91
84
|
visitExpression: expression => {
|
|
92
85
|
if (expression === null) {
|
|
@@ -97,7 +90,7 @@ const createExpressionVisitor = visitor => {
|
|
|
97
90
|
return visitorWithDefault.visitFromRootFieldExpression(expression, visitorDefault);
|
|
98
91
|
} else if (isFunctionCallExpression(expression)) {
|
|
99
92
|
return visitorWithDefault.visitFunctionCallExpression(expression, visitorDefault);
|
|
100
|
-
} else if (isFieldExpression(expression)) {
|
|
93
|
+
} else if (isFieldExpression(expression) || isMultiFieldExpression(expression)) {
|
|
101
94
|
return visitorWithDefault.visitFieldExpression(expression, visitorDefault);
|
|
102
95
|
} else if (isQueryExpression(expression)) {
|
|
103
96
|
return visitorWithDefault.visitQueryExpression(expression, visitorDefault);
|
|
@@ -106,7 +99,10 @@ const createExpressionVisitor = visitor => {
|
|
|
106
99
|
}
|
|
107
100
|
}
|
|
108
101
|
};
|
|
109
|
-
visitorWithDefault =
|
|
102
|
+
visitorWithDefault = {
|
|
103
|
+
...visitorDefault,
|
|
104
|
+
...visitor
|
|
105
|
+
};
|
|
110
106
|
return visitorWithDefault;
|
|
111
107
|
};
|
|
112
108
|
|
|
@@ -127,7 +123,24 @@ const visitFieldExpressionForReplaceIdsWithNamesVisitor = ({
|
|
|
127
123
|
currentTypeObject,
|
|
128
124
|
fieldExpressionInNamesTerms
|
|
129
125
|
}, fieldId) => {
|
|
130
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
126
|
+
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
127
|
+
var _fieldObject$multiRel;
|
|
128
|
+
const typeId = fieldId[1];
|
|
129
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
130
|
+
const nextTypeObject = (_fieldObject$multiRel = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel.holderTypeObject;
|
|
131
|
+
if (!nextTypeObject) {
|
|
132
|
+
return onFieldNotFound({
|
|
133
|
+
currentTypeObject,
|
|
134
|
+
fieldExpressionInNamesTerms,
|
|
135
|
+
fieldId: fieldId,
|
|
136
|
+
expression
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
currentTypeObject: nextTypeObject,
|
|
141
|
+
fieldExpressionInNamesTerms: [...fieldExpressionInNamesTerms, [fieldObject.name, nextTypeObject.name]]
|
|
142
|
+
};
|
|
143
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
131
144
|
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
132
145
|
return {
|
|
133
146
|
currentTypeObject: fieldObject.typeObject,
|
|
@@ -166,14 +179,19 @@ const replaceIdsWithNamesVisitor = (typeObject, onFieldNotFound = defaultIdsWith
|
|
|
166
179
|
}).currentTypeObject;
|
|
167
180
|
if (subQueryTypeObject) {
|
|
168
181
|
const subQueryVisitor = replaceIdsWithNamesVisitor(subQueryTypeObject, onFieldNotFound);
|
|
169
|
-
return
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
182
|
+
return {
|
|
183
|
+
...subQueryExpression,
|
|
184
|
+
...{
|
|
185
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
186
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
187
|
+
},
|
|
188
|
+
...(whereExpression ? {
|
|
189
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
190
|
+
} : null),
|
|
191
|
+
...(orderByExpression ? {
|
|
192
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
193
|
+
} : null)
|
|
194
|
+
};
|
|
177
195
|
}
|
|
178
196
|
return subQueryExpression;
|
|
179
197
|
}
|
|
@@ -197,7 +215,24 @@ const visitFieldExpressionForReplaceNamesWithIdsVisitor = ({
|
|
|
197
215
|
currentTypeObject,
|
|
198
216
|
fieldExpressionInIdsTerms
|
|
199
217
|
}, field) => {
|
|
200
|
-
if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
218
|
+
if (currentTypeObject && isMultiFieldAccess(field) && currentTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
219
|
+
var _fieldObject$multiRel2;
|
|
220
|
+
const type = field[1];
|
|
221
|
+
const fieldObject = currentTypeObject.fieldObjectsByName[field[0]];
|
|
222
|
+
const nextTypeObject = (_fieldObject$multiRel2 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel2.holderTypeObject;
|
|
223
|
+
if (!nextTypeObject) {
|
|
224
|
+
return onFieldNotFound({
|
|
225
|
+
currentTypeObject,
|
|
226
|
+
fieldExpressionInIdsTerms,
|
|
227
|
+
field,
|
|
228
|
+
expression
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
return {
|
|
232
|
+
currentTypeObject: nextTypeObject,
|
|
233
|
+
fieldExpressionInIdsTerms: [...fieldExpressionInIdsTerms, [fieldObject.id, nextTypeObject.id]]
|
|
234
|
+
};
|
|
235
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
201
236
|
const fieldObject = currentTypeObject.fieldObjectsByName[field];
|
|
202
237
|
return {
|
|
203
238
|
currentTypeObject: fieldObject.typeObject,
|
|
@@ -236,14 +271,19 @@ const replaceNamesWithIdsVisitor = (typeObject, onFieldNotFound = defaultNamesWi
|
|
|
236
271
|
}).currentTypeObject;
|
|
237
272
|
if (subQueryTypeObject) {
|
|
238
273
|
const subQueryVisitor = replaceNamesWithIdsVisitor(subQueryTypeObject, onFieldNotFound);
|
|
239
|
-
return
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
274
|
+
return {
|
|
275
|
+
...subQueryExpression,
|
|
276
|
+
...{
|
|
277
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
278
|
+
"q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
|
|
279
|
+
},
|
|
280
|
+
...(whereExpression ? {
|
|
281
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
282
|
+
} : null),
|
|
283
|
+
...(orderByExpression ? {
|
|
284
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
285
|
+
} : null)
|
|
286
|
+
};
|
|
247
287
|
}
|
|
248
288
|
return subQueryExpression;
|
|
249
289
|
}
|
|
@@ -264,7 +304,22 @@ const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
|
264
304
|
}
|
|
265
305
|
},
|
|
266
306
|
visitFieldExpression: expression => {
|
|
267
|
-
const fieldTypeObject = expression.reduce((holderTypeObject, field) =>
|
|
307
|
+
const fieldTypeObject = expression.reduce((holderTypeObject, field) => {
|
|
308
|
+
if (holderTypeObject && isMultiFieldAccess(field) && holderTypeObject.fieldObjectsByName.hasOwnProperty(field[0])) {
|
|
309
|
+
var _fieldObject$multiRel3;
|
|
310
|
+
const type = field[1];
|
|
311
|
+
const fieldObject = holderTypeObject.fieldObjectsByName[field[0]];
|
|
312
|
+
const nextTypeObject = (_fieldObject$multiRel3 = fieldObject.multiRelatedFieldObjects.find(f => f.holderType === type)) == null ? void 0 : _fieldObject$multiRel3.holderTypeObject;
|
|
313
|
+
if (!nextTypeObject) {
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
return nextTypeObject;
|
|
317
|
+
} else if (holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field)) {
|
|
318
|
+
return holderTypeObject.fieldObjectsByName[field].typeObject;
|
|
319
|
+
} else {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
}, typeObject);
|
|
268
323
|
return fieldTypeObject && expression;
|
|
269
324
|
},
|
|
270
325
|
visitOrderByExpression: orderByExpression => {
|
|
@@ -284,14 +339,19 @@ const deleteExpressionsWithNotFoundFieldsVisitor = typeObject => {
|
|
|
284
339
|
const subQueryTypeObject = fromExpression.reduce((typeObject, field) => typeObject && typeObject.fieldObjectsByName.hasOwnProperty(field) ? typeObject.fieldObjectsByName[field].typeObject : null, typeObject);
|
|
285
340
|
if (subQueryTypeObject) {
|
|
286
341
|
const subQueryVisitor = deleteExpressionsWithNotFoundFieldsVisitor(subQueryTypeObject);
|
|
287
|
-
const subQueryExpressionNew = ___default["default"].pickBy(
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
342
|
+
const subQueryExpressionNew = ___default["default"].pickBy({
|
|
343
|
+
...subQueryExpression,
|
|
344
|
+
...{
|
|
345
|
+
"q/from": visitor.visitFieldExpression(fromExpression),
|
|
346
|
+
"q/select": subQueryVisitor.visitExpression(selectExpression)
|
|
347
|
+
},
|
|
348
|
+
...(whereExpression ? {
|
|
349
|
+
"q/where": subQueryVisitor.visitExpression(whereExpression)
|
|
350
|
+
} : null),
|
|
351
|
+
...(orderByExpression ? {
|
|
352
|
+
"q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
|
|
353
|
+
} : null)
|
|
354
|
+
});
|
|
295
355
|
const {
|
|
296
356
|
"q/select": selectExpressionNew
|
|
297
357
|
} = subQueryExpressionNew;
|
|
@@ -339,8 +399,22 @@ const getFieldAccessExpressionTypeObject = ({
|
|
|
339
399
|
const reduced = expression.reduce(({
|
|
340
400
|
currentTypeObject
|
|
341
401
|
}, fieldId, index) => {
|
|
342
|
-
|
|
343
|
-
|
|
402
|
+
if (currentTypeObject && isMultiFieldAccess(fieldId) && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId[0])) {
|
|
403
|
+
var _fieldObject$multiRel4;
|
|
404
|
+
const typeId = fieldId[1];
|
|
405
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId[0]];
|
|
406
|
+
const nextTypeObject = (_fieldObject$multiRel4 = fieldObject.multiRelatedFieldObjects.find(f => f.holderTypeObject.id === typeId)) == null ? void 0 : _fieldObject$multiRel4.holderTypeObject;
|
|
407
|
+
if (!nextTypeObject) {
|
|
408
|
+
return onFieldNotFound({
|
|
409
|
+
currentTypeObject,
|
|
410
|
+
fieldId
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
currentTypeObject: nextTypeObject
|
|
415
|
+
};
|
|
416
|
+
} else if (currentTypeObject && currentTypeObject.fieldObjectsById.hasOwnProperty(fieldId)) {
|
|
417
|
+
const fieldObject = currentTypeObject.fieldObjectsById[fieldId];
|
|
344
418
|
if (returnRefTypeInsteadOfId && index === expression.length - 1 && fieldObject.isId) {
|
|
345
419
|
return {
|
|
346
420
|
currentTypeObject
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fibery/expression-utils",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.0",
|
|
4
4
|
"description": "utils for working with fibery api expressions",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./lib/expression-utils.js",
|
|
@@ -29,16 +29,16 @@
|
|
|
29
29
|
"@fibery/helpers": "1.2.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"@babel/core": "7.
|
|
32
|
+
"@babel/core": "7.23.9",
|
|
33
33
|
"@swc/jest": "0.2.29",
|
|
34
34
|
"jest": "27.5.1",
|
|
35
35
|
"jest-junit": "13.0.0",
|
|
36
|
-
"microbundle": "0.15.
|
|
37
|
-
"@fibery/babel-preset": "7.
|
|
38
|
-
"@fibery/eslint-config": "8.5.
|
|
36
|
+
"microbundle": "0.15.1",
|
|
37
|
+
"@fibery/babel-preset": "7.4.0",
|
|
38
|
+
"@fibery/eslint-config": "8.5.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@fibery/schema": "10.0.
|
|
41
|
+
"@fibery/schema": "10.0.1"
|
|
42
42
|
},
|
|
43
43
|
"jest": {
|
|
44
44
|
"testEnvironment": "node",
|
package/index.js
DELETED