@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.
@@ -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 isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
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 _extends({}, subQueryExpression, fromExpression ? {
331
- "q/from": visitorWithDefault.visitFieldExpression(fromExpression)
332
- } : null, selectExpression ? {
333
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
334
- } : null, whereExpression ? {
335
- "q/where": visitorWithDefault.visitExpression(whereExpression)
336
- } : null, orderByExpression ? {
337
- "q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
338
- } : null);
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 = _extends({}, visitorDefault, visitor);
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 _extends({}, subQueryExpression, {
443
- "q/from": visitor.visitFieldExpression(fromExpression),
444
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
445
- }, whereExpression ? {
446
- "q/where": subQueryVisitor.visitExpression(whereExpression)
447
- } : null, orderByExpression ? {
448
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
449
- } : null);
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 _extends({}, subQueryExpression, {
513
- "q/from": visitor.visitFieldExpression(fromExpression),
514
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
515
- }, whereExpression ? {
516
- "q/where": subQueryVisitor.visitExpression(whereExpression)
517
- } : null, orderByExpression ? {
518
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
519
- } : null);
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) => holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field) ? holderTypeObject.fieldObjectsByName[field].typeObject : null, typeObject);
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(_extends({}, subQueryExpression, {
561
- "q/from": visitor.visitFieldExpression(fromExpression),
562
- "q/select": subQueryVisitor.visitExpression(selectExpression)
563
- }, whereExpression ? {
564
- "q/where": subQueryVisitor.visitExpression(whereExpression)
565
- } : null, orderByExpression ? {
566
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
567
- } : null));
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
- const fieldObject = currentTypeObject && currentTypeObject.fieldObjects.find(f => f.id === fieldId);
616
- if (fieldObject) {
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 isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
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 _extends({}, subQueryExpression, fromExpression ? {
143
- "q/from": visitorWithDefault.visitFieldExpression(fromExpression)
144
- } : null, selectExpression ? {
145
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
146
- } : null, whereExpression ? {
147
- "q/where": visitorWithDefault.visitExpression(whereExpression)
148
- } : null, orderByExpression ? {
149
- "q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
150
- } : null);
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 = _extends({}, visitorDefault, visitor);
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.isFunctionExpression = isFunctionExpression;
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 isFieldExpression = expression => Array.isArray(expression) && expression.every(x => !isVariableExpression(x) && !binaryOperations.has(x) && ___default["default"].isString(x));
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 _extends({}, subQueryExpression, fromExpression ? {
82
- "q/from": visitorWithDefault.visitFieldExpression(fromExpression)
83
- } : null, selectExpression ? {
84
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => visitorWithDefault.visitExpression(val)) : visitorWithDefault.visitExpression(selectExpression)
85
- } : null, whereExpression ? {
86
- "q/where": visitorWithDefault.visitExpression(whereExpression)
87
- } : null, orderByExpression ? {
88
- "q/order-by": visitorWithDefault.visitOrderByExpression(orderByExpression)
89
- } : null);
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 = _extends({}, visitorDefault, visitor);
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 _extends({}, subQueryExpression, {
170
- "q/from": visitor.visitFieldExpression(fromExpression),
171
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
172
- }, whereExpression ? {
173
- "q/where": subQueryVisitor.visitExpression(whereExpression)
174
- } : null, orderByExpression ? {
175
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
176
- } : null);
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 _extends({}, subQueryExpression, {
240
- "q/from": visitor.visitFieldExpression(fromExpression),
241
- "q/select": ___default["default"].isPlainObject(selectExpression) ? ___default["default"].mapValues(selectExpression, val => subQueryVisitor.visitExpression(val)) : subQueryVisitor.visitExpression(selectExpression)
242
- }, whereExpression ? {
243
- "q/where": subQueryVisitor.visitExpression(whereExpression)
244
- } : null, orderByExpression ? {
245
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
246
- } : null);
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) => holderTypeObject && holderTypeObject.fieldObjectsByName.hasOwnProperty(field) ? holderTypeObject.fieldObjectsByName[field].typeObject : null, typeObject);
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(_extends({}, subQueryExpression, {
288
- "q/from": visitor.visitFieldExpression(fromExpression),
289
- "q/select": subQueryVisitor.visitExpression(selectExpression)
290
- }, whereExpression ? {
291
- "q/where": subQueryVisitor.visitExpression(whereExpression)
292
- } : null, orderByExpression ? {
293
- "q/order-by": subQueryVisitor.visitOrderByExpression(orderByExpression)
294
- } : null));
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
- const fieldObject = currentTypeObject && currentTypeObject.fieldObjects.find(f => f.id === fieldId);
343
- if (fieldObject) {
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": "6.0.0",
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.20.5",
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.0",
37
- "@fibery/babel-preset": "7.3.0",
38
- "@fibery/eslint-config": "8.5.0"
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.0"
41
+ "@fibery/schema": "10.0.1"
42
42
  },
43
43
  "jest": {
44
44
  "testEnvironment": "node",
package/index.js DELETED
@@ -1,6 +0,0 @@
1
- import * as paramsPlaceholders from "./paramsPlaceholders";
2
- import * as utils from "./utils";
3
- import * as visitors from "./visitors";
4
- import * as contextVariables from "./contextVariables";
5
-
6
- export {utils, visitors, paramsPlaceholders, contextVariables};