@briza/illogical 1.5.5 → 1.5.8

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.
@@ -1,4 +1,19 @@
1
+ function _toPrimitive(t, r) {
2
+ if ("object" != typeof t || !t) return t;
3
+ var e = t[Symbol.toPrimitive];
4
+ if (void 0 !== e) {
5
+ var i = e.call(t, r || "default");
6
+ if ("object" != typeof i) return i;
7
+ throw new TypeError("@@toPrimitive must return a primitive value.");
8
+ }
9
+ return ("string" === r ? String : Number)(t);
10
+ }
11
+ function _toPropertyKey(t) {
12
+ var i = _toPrimitive(t, "string");
13
+ return "symbol" == typeof i ? i : String(i);
14
+ }
1
15
  function _defineProperty(obj, key, value) {
16
+ key = _toPropertyKey(key);
2
17
  if (key in obj) {
3
18
  Object.defineProperty(obj, key, {
4
19
  value: value,
@@ -9,7 +24,6 @@ function _defineProperty(obj, key, value) {
9
24
  } else {
10
25
  obj[key] = value;
11
26
  }
12
-
13
27
  return obj;
14
28
  }
15
29
 
@@ -20,45 +34,43 @@ function _defineProperty(obj, key, value) {
20
34
  function isNumber(value) {
21
35
  return typeof value === 'number' && isFinite(value);
22
36
  }
37
+
23
38
  /**
24
39
  * Is string type predicate.
25
40
  * @param value Tested value.
26
41
  */
27
-
28
42
  function isString(value) {
29
43
  return typeof value === 'string' || value instanceof String;
30
44
  }
45
+
31
46
  /**
32
47
  * Is Object
33
48
  * @param value tested value result of the test
34
49
  */
35
-
36
50
  function isObject(value) {
37
51
  if (value === null || value === undefined) {
38
52
  return false;
39
53
  }
40
-
41
54
  if (typeof value !== 'object' || (value === null || value === void 0 ? void 0 : value.constructor) !== Object) {
42
55
  return false;
43
56
  }
44
-
45
57
  return true;
46
58
  }
59
+
47
60
  /**
48
61
  * Is Boolean predicate.
49
62
  * @param value tested value.
50
63
  * @return result of the test
51
64
  */
52
-
53
65
  function isBoolean(value) {
54
66
  return typeof value === 'boolean';
55
67
  }
68
+
56
69
  /**
57
70
  * Check if a value is a an Evaluable
58
71
  * @param {Result | Evaluable} value value to check if is Evaluable
59
72
  * @returns {Evaluable}
60
73
  */
61
-
62
74
  function isEvaluable(value) {
63
75
  return typeof value === 'object' && value !== null && !Array.isArray(value) && typeof value.evaluate === 'function' && typeof value.simplify === 'function' && typeof value.serialize === 'function' && typeof value.toString === 'function';
64
76
  }
@@ -76,15 +88,16 @@ function isEvaluable(value) {
76
88
  /**
77
89
  * Evaluation result
78
90
  */
79
- let EvaluableType;
80
- /**
81
- * Evaluable
82
- */
83
91
 
84
- (function (EvaluableType) {
92
+ let EvaluableType = /*#__PURE__*/function (EvaluableType) {
85
93
  EvaluableType["Operand"] = "Operand";
86
94
  EvaluableType["Expression"] = "Expression";
87
- })(EvaluableType || (EvaluableType = {}));
95
+ return EvaluableType;
96
+ }({});
97
+
98
+ /**
99
+ * Evaluable
100
+ */
88
101
 
89
102
  /**
90
103
  * Abstract comparison expression
@@ -101,26 +114,24 @@ class Comparison {
101
114
  this.operatorSymbol = operatorSymbol;
102
115
  this.left = left;
103
116
  this.right = right;
104
-
105
117
  _defineProperty(this, "type", EvaluableType.Expression);
106
118
  }
119
+
107
120
  /**
108
121
  * {@link Evaluable.evaluate}
109
122
  */
110
-
111
-
112
123
  evaluate(ctx) {
113
124
  return this.comparison(this.left.evaluate(ctx), this.right.evaluate(ctx));
114
125
  }
126
+
115
127
  /**
116
128
  * Get the strict representation of the expression.
117
129
  * @return {string}
118
130
  */
119
-
120
-
121
131
  toString() {
122
132
  return `(${this.left.toString()} ${this.operator} ${this.right.toString()})`;
123
133
  }
134
+
124
135
  /**
125
136
  * Compares left and right operands evaluated values.
126
137
  * @param {Result} left left operand result value
@@ -128,450 +139,469 @@ class Comparison {
128
139
  * @returns {boolean}
129
140
  */
130
141
 
131
-
132
142
  /**
133
143
  * {@link Evaluable.simplify}
134
144
  */
135
- simplify() {
136
- const left = this.left.simplify(...arguments);
137
- const right = this.right.simplify(...arguments);
138
-
145
+ simplify(...args) {
146
+ const left = this.left.simplify(...args);
147
+ const right = this.right.simplify(...args);
139
148
  if (!isEvaluable(left) && !isEvaluable(right)) {
140
149
  return this.comparison(left, right);
141
150
  }
142
-
143
151
  return this;
144
152
  }
153
+
145
154
  /**
146
155
  * {@link Evaluable.serialize}
147
156
  */
148
-
149
-
150
157
  serialize(options) {
151
158
  const {
152
159
  operatorMapping
153
160
  } = options;
154
161
  const operator = operatorMapping.get(this.operatorSymbol);
155
-
156
162
  if (operator === undefined) {
157
163
  throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
158
164
  }
159
-
160
165
  return [operator, this.left.serialize(options), this.right.serialize(options)];
161
166
  }
162
-
163
167
  }
164
168
 
169
+ // Operator key
165
170
  const OPERATOR$h = Symbol('EQ');
171
+
166
172
  /**
167
173
  * Equal comparison expression
168
174
  */
169
-
170
175
  class Equal extends Comparison {
171
176
  /**
172
177
  * @constructor
173
178
  * @param {Evaluable} left Left operand.
174
179
  * @param {Evaluable} right Right operand.
175
180
  */
181
+
176
182
  constructor(left, right) {
177
183
  if (arguments.length !== 2) {
178
184
  throw new Error('comparison expression expects left and right operands');
179
185
  }
180
-
181
186
  super('==', OPERATOR$h, left, right);
182
187
  }
188
+
183
189
  /**
184
190
  * {@link Comparison.comparison}
185
191
  */
186
-
187
-
188
192
  comparison(left, right) {
189
193
  return left === right;
190
194
  }
191
-
192
195
  }
193
196
 
197
+ /**
198
+ * Convert a value to number if possible, otherwise return undefined
199
+ * @param value value to be converted to number
200
+ */
201
+ const toNumber = value => {
202
+ const isValueNumber = isNumber(value);
203
+ if (isValueNumber) {
204
+ return value;
205
+ } else if (isString(value)) {
206
+ if (value.match(/^\d+\.\d+$/)) {
207
+ return parseFloat(value);
208
+ } else if (value.match(/^0$|^[1-9]\d*$/)) {
209
+ return parseInt(value);
210
+ }
211
+ }
212
+ return undefined;
213
+ };
214
+
215
+ /**
216
+ * Convert a value to string if possible, otherwise return undefined
217
+ * @param value value to be converted to string
218
+ */
219
+ const toString = value => {
220
+ if (isNumber(value)) {
221
+ return `${value}`;
222
+ } else if (isString(value)) {
223
+ return value;
224
+ }
225
+ return undefined;
226
+ };
227
+ /**
228
+ * Convert a value to number if it's type is string, otherwise return NaN
229
+ * @param value value to be converted to number
230
+ */
231
+ const toDateNumber = value => {
232
+ if (isString(value)) {
233
+ return Date.parse(value);
234
+ }
235
+ return NaN;
236
+ };
237
+
238
+ // Operator key
194
239
  const OPERATOR$g = Symbol('GE');
240
+
195
241
  /**
196
242
  * Greater than or equal comparison expression
197
243
  */
198
-
199
244
  class GreaterThanOrEqual extends Comparison {
200
245
  /**
201
246
  * @constructor
202
247
  * @param {Evaluable} left Left operand.
203
248
  * @param {Evaluable} right Right operand.
204
249
  */
250
+
205
251
  constructor(left, right) {
206
252
  if (arguments.length !== 2) {
207
253
  throw new Error('comparison expression expects left and right operands');
208
254
  }
209
-
210
255
  super('>=', OPERATOR$g, left, right);
211
256
  }
257
+
212
258
  /**
213
259
  * {@link Comparison.comparison}
214
260
  */
215
-
216
-
217
261
  comparison(left, right) {
218
262
  if (isNumber(left) && isNumber(right)) {
219
263
  return left >= right;
220
264
  }
221
-
265
+ const leftDate = toDateNumber(left),
266
+ rightDate = toDateNumber(right);
267
+ if (leftDate && rightDate) {
268
+ return leftDate >= rightDate;
269
+ }
222
270
  return false;
223
271
  }
224
-
225
272
  }
226
273
 
274
+ // Operator key
227
275
  const OPERATOR$f = Symbol('GT');
276
+
228
277
  /**
229
278
  * Greater than comparison expression
230
279
  */
231
-
232
280
  class GreaterThan extends Comparison {
233
281
  /**
234
282
  * @constructor
235
283
  * @param {Evaluable} left Left operand.
236
284
  * @param {Evaluable} right Right operand.
237
285
  */
286
+
238
287
  constructor(left, right) {
239
288
  if (arguments.length !== 2) {
240
289
  throw new Error('comparison expression expects left and right operands');
241
290
  }
242
-
243
291
  super('>', OPERATOR$f, left, right);
244
292
  }
293
+
245
294
  /**
246
295
  * {@link Comparison.comparison}
247
296
  */
248
-
249
-
250
297
  comparison(left, right) {
251
298
  if (isNumber(left) && isNumber(right)) {
252
299
  return left > right;
253
300
  }
254
-
301
+ const leftDate = toDateNumber(left),
302
+ rightDate = toDateNumber(right);
303
+ if (leftDate && rightDate) {
304
+ return leftDate > rightDate;
305
+ }
255
306
  return false;
256
307
  }
257
-
258
308
  }
259
309
 
310
+ // Operator key
260
311
  const OPERATOR$e = Symbol('IN');
312
+
261
313
  /**
262
314
  * In comparison expression
263
315
  */
264
-
265
316
  class In extends Comparison {
266
317
  /**
267
318
  * @constructor
268
319
  * @param {Evaluable} left Left operand.
269
320
  * @param {Evaluable} right Right operand.
270
321
  */
322
+
271
323
  constructor(left, right) {
272
324
  if (arguments.length !== 2) {
273
325
  throw new Error('comparison expression expects left and right operands');
274
326
  }
275
-
276
327
  super('in', OPERATOR$e, left, right);
277
328
  }
329
+
278
330
  /**
279
331
  * {@link Comparison.comparison}
280
332
  */
281
-
282
-
283
333
  comparison(left, right) {
284
334
  if (left === undefined || left === null || right === undefined || right === null) {
285
335
  return false;
286
336
  }
287
-
288
337
  const leftArray = Array.isArray(left);
289
338
  const rightArray = Array.isArray(right);
290
-
291
339
  if (leftArray && rightArray) {
292
340
  throw new Error('invalid IN expression, both operands are array');
293
341
  }
294
-
295
342
  if (!leftArray && !rightArray) {
296
343
  throw new Error('invalid IN expression, non of the operands is array');
297
344
  }
298
-
299
345
  if (leftArray) {
300
346
  return left.indexOf(right) > -1;
301
347
  }
302
-
303
348
  return right.indexOf(left) > -1;
304
349
  }
350
+
305
351
  /**
306
352
  * Get the strict representation of the expression.
307
353
  * @return {string}
308
354
  */
309
-
310
-
311
355
  toString() {
312
356
  const left = this.left.toString();
313
357
  const right = this.right.toString();
314
-
315
358
  if (left.startsWith('[')) {
316
359
  return `(${right} ${this.operator} ${left})`;
317
360
  }
318
-
319
361
  return `(${left} ${this.operator} ${right})`;
320
362
  }
321
-
322
363
  }
323
364
 
365
+ // Operator key
324
366
  const OPERATOR$d = Symbol('LE');
367
+
325
368
  /**
326
369
  * Less than or equal comparison expression
327
370
  */
328
-
329
371
  class LessThanOrEqual extends Comparison {
330
372
  /**
331
373
  * @constructor
332
374
  * @param {Evaluable} left Left operand.
333
375
  * @param {Evaluable} right Right operand.
334
376
  */
377
+
335
378
  constructor(left, right) {
336
379
  if (arguments.length !== 2) {
337
380
  throw new Error('comparison expression expects left and right operands');
338
381
  }
339
-
340
382
  super('<=', OPERATOR$d, left, right);
341
383
  }
384
+
342
385
  /**
343
386
  * {@link Comparison.comparison}
344
387
  */
345
-
346
-
347
388
  comparison(left, right) {
348
389
  if (isNumber(left) && isNumber(right)) {
349
390
  return left <= right;
350
391
  }
351
-
392
+ const leftDate = toDateNumber(left),
393
+ rightDate = toDateNumber(right);
394
+ if (leftDate && rightDate) {
395
+ return leftDate <= rightDate;
396
+ }
352
397
  return false;
353
398
  }
354
-
355
399
  }
356
400
 
401
+ // Operator key
357
402
  const OPERATOR$c = Symbol('LT');
403
+
358
404
  /**
359
405
  * Less than comparison expression
360
406
  */
361
-
362
407
  class LessThan extends Comparison {
363
408
  /**
364
409
  * @constructor
365
410
  * @param {Evaluable} left Left operand.
366
411
  * @param {Evaluable} right Right operand.
367
412
  */
413
+
368
414
  constructor(left, right) {
369
415
  if (arguments.length !== 2) {
370
416
  throw new Error('comparison expression expects left and right operands');
371
417
  }
372
-
373
418
  super('<', OPERATOR$c, left, right);
374
419
  }
420
+
375
421
  /**
376
422
  * {@link Comparison.comparison}
377
423
  */
378
-
379
-
380
424
  comparison(left, right) {
381
425
  if (isNumber(left) && isNumber(right)) {
382
426
  return left < right;
383
427
  }
384
-
428
+ const leftDate = toDateNumber(left),
429
+ rightDate = toDateNumber(right);
430
+ if (leftDate && rightDate) {
431
+ return leftDate < rightDate;
432
+ }
385
433
  return false;
386
434
  }
387
-
388
435
  }
389
436
 
437
+ // Operator key
390
438
  const OPERATOR$b = Symbol('NE');
439
+
391
440
  /**
392
441
  * Not equal comparison expression
393
442
  */
394
-
395
443
  class NotEqual extends Comparison {
396
444
  /**
397
445
  * @constructor
398
446
  * @param {Evaluable} left Left operand.
399
447
  * @param {Evaluable} right Right operand.
400
448
  */
449
+
401
450
  constructor(left, right) {
402
451
  if (arguments.length !== 2) {
403
452
  throw new Error('comparison expression expects left and right operands');
404
453
  }
405
-
406
454
  super('!=', OPERATOR$b, left, right);
407
455
  }
456
+
408
457
  /**
409
458
  * {@link Comparison.comparison}
410
459
  */
411
-
412
-
413
460
  comparison(left, right) {
414
461
  return left !== right;
415
462
  }
416
-
417
463
  }
418
464
 
465
+ // Operator key
419
466
  const OPERATOR$a = Symbol('NOT IN');
467
+
420
468
  /**
421
469
  * Not in comparison expression
422
470
  */
423
-
424
471
  class NotIn extends Comparison {
425
472
  /**
426
473
  * @constructor
427
474
  * @param {Evaluable} left Left operand.
428
475
  * @param {Evaluable} right Right operand.
429
476
  */
477
+
430
478
  constructor(left, right) {
431
479
  if (arguments.length !== 2) {
432
480
  throw new Error('comparison expression expects left and right operands');
433
481
  }
434
-
435
482
  super('not in', OPERATOR$a, left, right);
436
483
  }
484
+
437
485
  /**
438
486
  * {@link Comparison.comparison}
439
487
  */
440
-
441
-
442
488
  comparison(left, right) {
443
489
  if (left === undefined || left === null || right === undefined || right === null) {
444
490
  return true;
445
491
  }
446
-
447
492
  const leftArray = Array.isArray(left);
448
493
  const rightArray = Array.isArray(right);
449
-
450
494
  if (leftArray && rightArray) {
451
495
  throw new Error('invalid NOT IN expression, both operands are array');
452
496
  }
453
-
454
497
  if (!leftArray && !rightArray) {
455
498
  throw new Error('invalid NOT IN expression, one operand must be array');
456
499
  }
457
-
458
500
  if (leftArray) {
459
501
  return left.indexOf(right) === -1;
460
502
  }
461
-
462
503
  return right.indexOf(left) === -1;
463
504
  }
505
+
464
506
  /**
465
507
  * Get the strict representation of the expression
466
508
  * @return {string}
467
509
  */
468
-
469
-
470
510
  toString() {
471
511
  const left = this.left.toString();
472
512
  const right = this.right.toString();
473
-
474
513
  if (left.startsWith('[')) {
475
514
  return `(${right} ${this.operator} ${left})`;
476
515
  }
477
-
478
516
  return `(${left} ${this.operator} ${right})`;
479
517
  }
480
-
481
518
  }
482
519
 
520
+ // Operator key
483
521
  const OPERATOR$9 = Symbol('OVERLAP');
522
+
484
523
  /**
485
524
  * Overlap comparison expression
486
525
  */
487
-
488
526
  class Overlap extends Comparison {
489
527
  /**
490
528
  * @constructor
491
529
  * @param {Evaluable} left Left operand.
492
530
  * @param {Evaluable} right Right operand.
493
531
  */
532
+
494
533
  constructor(left, right) {
495
534
  if (arguments.length !== 2) {
496
535
  throw new Error('comparison expression expects left and right operands');
497
536
  }
498
-
499
537
  super('overlap', OPERATOR$9, left, right);
500
538
  }
539
+
501
540
  /**
502
541
  * {@link Comparison.comparison}
503
542
  */
504
-
505
-
506
543
  comparison(left, right) {
507
544
  if (left === undefined || left === null || right === undefined || right === null) {
508
545
  return false;
509
546
  }
510
-
511
547
  if (!Array.isArray(left) || !Array.isArray(right)) {
512
548
  throw new Error('invalid OVERLAP expression, both operands must be array');
513
549
  }
514
-
515
550
  const leftArray = left;
516
551
  const rightArray = right;
517
552
  return leftArray.some(element => rightArray.includes(element));
518
553
  }
554
+
519
555
  /**
520
556
  * Get the strict representation of the expression.
521
557
  * @return {string}
522
558
  */
523
-
524
-
525
559
  toString() {
526
560
  const left = this.left.toString();
527
561
  const right = this.right.toString();
528
562
  return `(${left} ${this.operator} ${right})`;
529
563
  }
530
-
531
564
  }
532
565
 
566
+ // Operator key
533
567
  const OPERATOR$8 = Symbol('PREFIX');
568
+
534
569
  /**
535
570
  * Prefix comparison expression
536
571
  */
537
-
538
572
  class Prefix extends Comparison {
539
573
  /**
540
574
  * @constructor
541
575
  * @param {Evaluable} left Left operand.
542
576
  * @param {Evaluable} right Right operand.
543
577
  */
578
+
544
579
  constructor(left, right) {
545
580
  if (arguments.length !== 2) {
546
581
  throw new Error('comparison expression expects left and right operands');
547
582
  }
548
-
549
583
  super('prefix', OPERATOR$8, left, right);
550
584
  }
585
+
551
586
  /**
552
587
  * {@link Comparison.comparison}
553
588
  */
554
-
555
-
556
589
  comparison(left, right) {
557
590
  if (isString(left) === false || isString(right) === false) {
558
591
  return false;
559
592
  }
560
-
561
593
  return right.startsWith(left);
562
594
  }
595
+
563
596
  /**
564
597
  * Get the strict representation of the expression.
565
598
  * @return {string}
566
599
  */
567
-
568
-
569
600
  toString() {
570
601
  const left = this.left.toString();
571
602
  const right = this.right.toString();
572
603
  return `(<${left}>${right})`;
573
604
  }
574
-
575
605
  }
576
606
 
577
607
  /**
@@ -581,14 +611,21 @@ class Operand {
581
611
  constructor() {
582
612
  _defineProperty(this, "type", EvaluableType.Operand);
583
613
  }
584
-
614
+ /**
615
+ * {@link Evaluable.evaluate}
616
+ */
617
+ /**
618
+ * {@link Evaluable.simplify}
619
+ */
620
+ /**
621
+ * {@link Evaluable.serialize}
622
+ */
585
623
  /**
586
624
  * Get the strict representation.
587
625
  */
588
626
  toString() {
589
627
  throw new Error('not implemented exception');
590
628
  }
591
-
592
629
  }
593
630
 
594
631
  /**
@@ -596,19 +633,16 @@ class Operand {
596
633
  * @param {Result} value
597
634
  * @return {string}
598
635
  */
599
-
600
636
  function printValue(value) {
601
637
  if (isString(value)) {
602
638
  return `"${value}"`;
603
639
  }
604
-
605
640
  return `${value}`;
606
641
  }
642
+
607
643
  /**
608
644
  * Static value operand
609
645
  */
610
-
611
-
612
646
  class Value extends Operand {
613
647
  /**
614
648
  * @constructor
@@ -618,195 +652,174 @@ class Value extends Operand {
618
652
  if (Array.isArray(value)) {
619
653
  throw new Error('deprecated direct usage of array, please use Collection operand');
620
654
  }
621
-
622
655
  super();
623
-
624
656
  _defineProperty(this, "value", void 0);
625
-
626
657
  this.value = value;
627
658
  }
659
+
628
660
  /**
629
661
  * {@link Evaluable.evaluate}
630
662
  */
631
-
632
-
633
663
  evaluate() {
634
664
  return this.value;
635
665
  }
666
+
636
667
  /**
637
668
  * {@link Evaluable.simplify}
638
669
  */
639
-
640
-
641
670
  simplify() {
642
671
  return this.value;
643
672
  }
673
+
644
674
  /**
645
675
  * {@link Evaluable.serialize}
646
676
  */
647
-
648
-
649
677
  serialize() {
650
678
  return this.value;
651
679
  }
680
+
652
681
  /**
653
682
  * Get the strict representation of the operand.
654
683
  * @return {string}
655
684
  */
656
-
657
-
658
685
  toString() {
659
686
  return printValue(this.value);
660
687
  }
661
-
662
688
  }
663
689
 
690
+ // Operator key
664
691
  const OPERATOR$7 = Symbol('PRESENT');
692
+
665
693
  /**
666
694
  * Present comparison expression
667
695
  */
668
-
669
696
  class Present extends Comparison {
670
697
  /**
671
698
  * @constructor
672
699
  * @param {Evaluable} operand
673
700
  */
701
+
674
702
  constructor(operand) {
675
703
  if (arguments.length !== 1) {
676
704
  throw new Error('comparison expression PRESENT expects exactly one operand');
677
705
  }
678
-
679
706
  super('PRESENT', OPERATOR$7, operand, new Value(true));
680
707
  }
708
+
681
709
  /**
682
710
  * {@link Comparison.comparison}
683
711
  */
684
-
685
-
686
712
  comparison(left) {
687
713
  return left !== undefined && left !== null;
688
714
  }
715
+
689
716
  /**
690
717
  * Get the strict representation of the expression.
691
718
  * @return {string}
692
719
  */
693
-
694
-
695
720
  toString() {
696
721
  return `(${this.left.toString()} is ${this.operator})`;
697
722
  }
698
-
699
723
  serialize(options) {
700
724
  const {
701
725
  operatorMapping
702
726
  } = options;
703
727
  const operator = operatorMapping.get(this.operatorSymbol);
704
-
705
728
  if (operator === undefined) {
706
729
  throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
707
730
  }
708
-
709
731
  return [operator, this.left.serialize(options)];
710
732
  }
711
-
712
733
  }
713
734
 
735
+ // Operator key
714
736
  const OPERATOR$6 = Symbol('PREFIX');
737
+
715
738
  /**
716
739
  * Suffix comparison expression
717
740
  */
718
-
719
741
  class Suffix extends Comparison {
720
742
  /**
721
743
  * @constructor
722
744
  * @param {Evaluable} left Left operand.
723
745
  * @param {Evaluable} right Right operand.
724
746
  */
747
+
725
748
  constructor(left, right) {
726
749
  if (arguments.length !== 2) {
727
750
  throw new Error('comparison expression expects left and right operands');
728
751
  }
729
-
730
752
  super('suffix', OPERATOR$6, left, right);
731
753
  }
754
+
732
755
  /**
733
756
  * {@link Comparison.comparison}
734
757
  */
735
-
736
-
737
758
  comparison(left, right) {
738
759
  if (isString(left) === false || isString(right) === false) {
739
760
  return false;
740
761
  }
741
-
742
762
  return left.endsWith(right);
743
763
  }
764
+
744
765
  /**
745
766
  * Get the strict representation of the expression.
746
767
  * @return {string}
747
768
  */
748
-
749
-
750
769
  toString() {
751
770
  const left = this.left.toString();
752
771
  const right = this.right.toString();
753
772
  return `(${left}<${right}>)`;
754
773
  }
755
-
756
774
  }
757
775
 
776
+ // Operator key
758
777
  const OPERATOR$5 = Symbol('UNDEFINED');
778
+
759
779
  /**
760
780
  * Undefined comparison expression
761
781
  */
762
-
763
782
  class Undefined extends Comparison {
764
783
  /**
765
784
  * @constructor
766
785
  * @param {Evaluable} operand
767
786
  */
787
+
768
788
  constructor(operand) {
769
789
  if (arguments.length !== 1) {
770
790
  throw new Error('comparison expression UNDEFINED expects exactly one operand');
771
791
  }
772
-
773
792
  super('UNDEFINED', OPERATOR$5, operand, new Value(true));
774
793
  }
794
+
775
795
  /**
776
796
  * {@link Comparison.comparison}
777
797
  */
778
-
779
-
780
798
  comparison(left) {
781
799
  return left === undefined;
782
800
  }
801
+
783
802
  /**
784
803
  * Get the strict representation of the expression.
785
804
  * @return {string}
786
805
  */
787
-
788
-
789
806
  toString() {
790
807
  return `(${this.left.toString()} is ${this.operator})`;
791
808
  }
809
+
792
810
  /**
793
811
  * {@link Evaluable.serialize}
794
812
  */
795
-
796
-
797
813
  serialize(options) {
798
814
  const {
799
815
  operatorMapping
800
816
  } = options;
801
817
  const operator = operatorMapping.get(this.operatorSymbol);
802
-
803
818
  if (operator === undefined) {
804
819
  throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
805
820
  }
806
-
807
821
  return [operator, this.left.serialize(options)];
808
822
  }
809
-
810
823
  }
811
824
 
812
825
  /**
@@ -822,13 +835,16 @@ class Logical {
822
835
  this.operator = operator;
823
836
  this.operatorSymbol = operatorSymbol;
824
837
  this.operands = operands;
825
-
826
838
  _defineProperty(this, "type", EvaluableType.Expression);
827
839
  }
840
+
828
841
  /**
829
842
  * {@link Evaluable.evaluate}
830
843
  */
831
844
 
845
+ /**
846
+ * {@link Evaluable.simplify}
847
+ */
832
848
 
833
849
  /**
834
850
  * Get the strict representation of the expression.
@@ -837,27 +853,24 @@ class Logical {
837
853
  toString() {
838
854
  return '(' + this.operands.map(operand => operand.toString()).join(` ${this.operator} `) + ')';
839
855
  }
840
-
841
856
  serialize(options) {
842
857
  const {
843
858
  operatorMapping
844
859
  } = options;
845
860
  const operator = operatorMapping.get(this.operatorSymbol);
846
-
847
861
  if (operator === undefined) {
848
862
  throw new Error(`missing operator ${this.operatorSymbol.toString()}`);
849
863
  }
850
-
851
864
  return [operator, ...this.operands.map(operand => operand.serialize(options))];
852
865
  }
853
-
854
866
  }
855
867
 
868
+ // Operator key
856
869
  const OPERATOR$4 = Symbol('AND');
870
+
857
871
  /**
858
872
  * And logical expression
859
873
  */
860
-
861
874
  class And extends Logical {
862
875
  /**
863
876
  * @constructor
@@ -867,127 +880,105 @@ class And extends Logical {
867
880
  if (operands.length < 2) {
868
881
  throw new Error('logical expression must have at least two operands');
869
882
  }
870
-
871
883
  super('AND', OPERATOR$4, operands);
872
884
  }
885
+
873
886
  /**
874
887
  * Evaluate in the given context.
875
888
  * @param {Context} ctx
876
889
  * @return {Result}
877
890
  */
878
-
879
-
880
891
  evaluate(ctx) {
881
892
  for (const operand of this.operands) {
882
893
  if (operand.evaluate(ctx) === false) {
883
894
  return false;
884
895
  }
885
896
  }
886
-
887
897
  return true;
888
898
  }
899
+
889
900
  /**
890
901
  * {@link Evaluable.simplify}
891
902
  */
892
-
893
-
894
- simplify() {
895
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
896
- args[_key] = arguments[_key];
897
- }
898
-
903
+ simplify(...args) {
899
904
  const simplified = this.operands.reduce((result, child) => {
900
905
  if (result !== false) {
901
906
  const childResult = child.simplify(...args);
902
-
903
907
  if (isEvaluable(childResult)) {
904
908
  if (isBoolean(result)) {
905
909
  return [childResult];
906
910
  }
907
-
908
911
  return [...result, childResult];
909
912
  }
910
-
911
913
  if (!childResult) {
912
914
  return false;
913
915
  }
914
916
  }
915
-
916
917
  return result;
917
918
  }, true);
918
-
919
919
  if (Array.isArray(simplified)) {
920
920
  if (simplified.length === 1) {
921
921
  return simplified[0];
922
922
  }
923
-
924
923
  return new And(simplified);
925
924
  }
926
-
927
925
  return simplified;
928
926
  }
929
-
930
927
  }
931
928
 
929
+ // Operator key
932
930
  const OPERATOR$3 = Symbol('NOT');
931
+
933
932
  /**
934
933
  * Not logical expression
935
934
  */
936
-
937
935
  class Not extends Logical {
938
936
  /**
939
937
  * @constructor
940
938
  * @param {Evaluable} operand
941
939
  */
940
+
942
941
  constructor(operand) {
943
942
  if (arguments.length !== 1) {
944
943
  throw new Error('logical NOT expression must have exactly one operand');
945
944
  }
946
-
947
945
  super('NOT', OPERATOR$3, [operand]);
948
946
  }
947
+
949
948
  /**
950
949
  * Evaluate in the given context.
951
950
  * @param {Context} ctx
952
951
  * @return {Result}
953
952
  */
954
-
955
-
956
953
  evaluate(ctx) {
957
954
  const result = this.operands[0].evaluate(ctx);
958
-
959
955
  if (result !== true && result !== false) {
960
956
  throw new Error("logical NOT expression's operand must be evaluated to boolean value");
961
957
  }
962
-
963
958
  return !result;
964
959
  }
960
+
965
961
  /**
966
962
  * {@link Evaluable.simplify}
967
963
  */
968
-
969
-
970
- simplify() {
971
- const simplified = this.operands[0].simplify(...arguments);
972
-
964
+ simplify(...args) {
965
+ const simplified = this.operands[0].simplify(...args);
973
966
  if (isBoolean(simplified)) {
974
967
  return !simplified;
975
968
  }
976
-
977
969
  if (isEvaluable(simplified)) {
978
970
  return new Not(simplified);
979
971
  }
980
-
981
972
  throw new Error("logical NOT expression's operand must be evaluated to boolean value");
982
973
  }
983
-
984
974
  }
985
975
 
976
+ // Operator key
986
977
  const OPERATOR$2 = Symbol('NOR');
978
+
987
979
  /**
988
980
  * Nor logical expression
989
981
  */
990
-
991
982
  class Nor extends Logical {
992
983
  /**
993
984
  * @constructor
@@ -997,73 +988,58 @@ class Nor extends Logical {
997
988
  if (operands.length < 2) {
998
989
  throw new Error('logical expression must have at least two operands');
999
990
  }
1000
-
1001
991
  super('NOR', OPERATOR$2, operands);
1002
992
  }
993
+
1003
994
  /**
1004
995
  * Evaluate in the given context.
1005
996
  * @param {Context} ctx
1006
997
  * @return {Result}
1007
998
  */
1008
-
1009
-
1010
999
  evaluate(ctx) {
1011
1000
  for (const operand of this.operands) {
1012
1001
  if (operand.evaluate(ctx) === true) {
1013
1002
  return false;
1014
1003
  }
1015
1004
  }
1016
-
1017
1005
  return true;
1018
1006
  }
1007
+
1019
1008
  /**
1020
1009
  * {@link Evaluable.simplify}
1021
1010
  */
1022
-
1023
-
1024
- simplify() {
1025
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1026
- args[_key] = arguments[_key];
1027
- }
1028
-
1011
+ simplify(...args) {
1029
1012
  const simplified = this.operands.reduce((result, child) => {
1030
1013
  if (result !== false) {
1031
1014
  const childResult = child.simplify(...args);
1032
-
1033
1015
  if (isEvaluable(childResult)) {
1034
1016
  if (isBoolean(result)) {
1035
1017
  return [childResult];
1036
1018
  }
1037
-
1038
1019
  return [...result, childResult];
1039
1020
  }
1040
-
1041
1021
  if (childResult) {
1042
1022
  return false;
1043
1023
  }
1044
1024
  }
1045
-
1046
1025
  return result;
1047
1026
  }, true);
1048
-
1049
1027
  if (Array.isArray(simplified)) {
1050
1028
  if (simplified.length === 1) {
1051
1029
  return new Not(...simplified);
1052
1030
  }
1053
-
1054
1031
  return new Nor(simplified);
1055
1032
  }
1056
-
1057
1033
  return simplified;
1058
1034
  }
1059
-
1060
1035
  }
1061
1036
 
1037
+ // Operator key
1062
1038
  const OPERATOR$1 = Symbol('OR');
1039
+
1063
1040
  /**
1064
1041
  * Or logical expression
1065
1042
  */
1066
-
1067
1043
  class Or extends Logical {
1068
1044
  /**
1069
1045
  * @constructor
@@ -1073,84 +1049,68 @@ class Or extends Logical {
1073
1049
  if (operands.length < 2) {
1074
1050
  throw new Error('logical expression must have at least two operands');
1075
1051
  }
1076
-
1077
1052
  super('OR', OPERATOR$1, operands);
1078
1053
  }
1054
+
1079
1055
  /**
1080
1056
  * Evaluate in the given context.
1081
1057
  * @param {Context} ctx
1082
1058
  * @return {Result}
1083
1059
  */
1084
-
1085
-
1086
1060
  evaluate(ctx) {
1087
1061
  for (const operand of this.operands) {
1088
1062
  if (operand.evaluate(ctx) === true) {
1089
1063
  return true;
1090
1064
  }
1091
1065
  }
1092
-
1093
1066
  return false;
1094
1067
  }
1068
+
1095
1069
  /**
1096
1070
  * {@link Evaluable.simplify}
1097
1071
  */
1098
-
1099
-
1100
- simplify() {
1101
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1102
- args[_key] = arguments[_key];
1103
- }
1104
-
1072
+ simplify(...args) {
1105
1073
  const simplified = this.operands.reduce((result, child) => {
1106
1074
  if (result !== true) {
1107
1075
  const childResult = child.simplify(...args);
1108
-
1109
1076
  if (isEvaluable(childResult)) {
1110
1077
  if (isBoolean(result)) {
1111
1078
  return [childResult];
1112
1079
  }
1113
-
1114
1080
  return [...result, childResult];
1115
1081
  }
1116
-
1117
1082
  if (childResult) {
1118
1083
  return true;
1119
1084
  }
1120
1085
  }
1121
-
1122
1086
  return result;
1123
1087
  }, false);
1124
-
1125
1088
  if (Array.isArray(simplified)) {
1126
1089
  if (simplified.length === 1) {
1127
1090
  return simplified[0];
1128
1091
  }
1129
-
1130
1092
  return new Or(simplified);
1131
1093
  }
1132
-
1133
1094
  return simplified;
1134
1095
  }
1135
-
1136
1096
  }
1137
1097
 
1098
+ // Operator key
1138
1099
  const OPERATOR = Symbol('XOR');
1100
+
1139
1101
  /**
1140
1102
  * Logical xor
1141
1103
  * @param {boolean} a
1142
1104
  * @param {boolean} b
1143
1105
  * @return {boolean}
1144
1106
  */
1145
-
1146
1107
  function xor(a, b) {
1147
1108
  return (a || b) && !(a && b);
1148
1109
  }
1110
+
1149
1111
  /**
1150
1112
  * Xor logical expression
1151
1113
  */
1152
-
1153
-
1154
1114
  class Xor extends Logical {
1155
1115
  /**
1156
1116
  * @constructor
@@ -1160,19 +1120,16 @@ class Xor extends Logical {
1160
1120
  if (operands.length < 2) {
1161
1121
  throw new Error('logical expression must have at least two operands');
1162
1122
  }
1163
-
1164
1123
  super('XOR', OPERATOR, operands);
1165
1124
  }
1125
+
1166
1126
  /**
1167
1127
  * Evaluate in the given context.
1168
1128
  * @param {Context} ctx
1169
1129
  * @return {Result}
1170
1130
  */
1171
-
1172
-
1173
1131
  evaluate(ctx) {
1174
1132
  let res = null;
1175
-
1176
1133
  for (const operand of this.operands) {
1177
1134
  if (res === null) {
1178
1135
  res = operand.evaluate(ctx);
@@ -1180,62 +1137,43 @@ class Xor extends Logical {
1180
1137
  res = xor(res, operand.evaluate(ctx));
1181
1138
  }
1182
1139
  }
1183
-
1184
1140
  return res;
1185
1141
  }
1142
+
1186
1143
  /**
1187
1144
  * {@link Evaluable.simplify}
1188
1145
  */
1189
-
1190
-
1191
- simplify() {
1192
- for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1193
- args[_key] = arguments[_key];
1194
- }
1195
-
1196
- const [evaluablesLeft, trueCount] = this.operands.reduce((_ref, child) => {
1197
- let [notSimplifiedConditions, trueCount] = _ref;
1198
-
1146
+ simplify(...args) {
1147
+ const [evaluablesLeft, trueCount] = this.operands.reduce(([notSimplifiedConditions, trueCount], child) => {
1199
1148
  if (trueCount > 1) {
1200
1149
  return [notSimplifiedConditions, trueCount];
1201
1150
  }
1202
-
1203
1151
  const childResult = child.simplify(...args);
1204
-
1205
1152
  if (isEvaluable(childResult)) {
1206
1153
  return [[...notSimplifiedConditions, childResult], trueCount];
1207
1154
  }
1208
-
1209
1155
  if (childResult) {
1210
1156
  return [notSimplifiedConditions, trueCount + 1];
1211
1157
  }
1212
-
1213
1158
  return [notSimplifiedConditions, trueCount];
1214
1159
  }, [[], 0]);
1215
-
1216
1160
  if (trueCount > 1) {
1217
1161
  return false;
1218
1162
  }
1219
-
1220
1163
  if (evaluablesLeft.length === 0) {
1221
1164
  return trueCount === 1;
1222
1165
  }
1223
-
1224
1166
  if (evaluablesLeft.length === 1) {
1225
1167
  if (trueCount === 1) {
1226
1168
  return new Not(...evaluablesLeft);
1227
1169
  }
1228
-
1229
1170
  return evaluablesLeft[0];
1230
1171
  }
1231
-
1232
1172
  if (trueCount === 1) {
1233
1173
  return new Nor(evaluablesLeft);
1234
1174
  }
1235
-
1236
1175
  return new Xor(evaluablesLeft);
1237
1176
  }
1238
-
1239
1177
  }
1240
1178
 
1241
1179
  /**
@@ -1248,152 +1186,97 @@ class Collection extends Operand {
1248
1186
  */
1249
1187
  constructor(items) {
1250
1188
  super();
1251
-
1252
1189
  _defineProperty(this, "items", void 0);
1253
-
1254
1190
  this.items = items;
1255
1191
  }
1192
+
1256
1193
  /**
1257
1194
  * Evaluate in the given context.
1258
1195
  * @param {Context} ctx
1259
1196
  * @return {boolean}
1260
1197
  */
1261
-
1262
-
1263
1198
  evaluate(ctx) {
1264
1199
  return this.items.map(item => item.evaluate(ctx));
1265
1200
  }
1201
+
1266
1202
  /**
1267
1203
  * {@link Evaluable.simplify}
1268
1204
  */
1269
-
1270
-
1271
- simplify() {
1205
+ simplify(...args) {
1272
1206
  const values = [];
1273
-
1274
1207
  for (const item of this.items) {
1275
- const simplifiedItem = item.simplify(...arguments);
1276
-
1208
+ const simplifiedItem = item.simplify(...args);
1277
1209
  if (isEvaluable(simplifiedItem)) {
1278
1210
  return this;
1279
1211
  }
1280
-
1281
1212
  values.push(simplifiedItem);
1282
1213
  }
1283
-
1284
1214
  return values;
1285
1215
  }
1216
+
1286
1217
  /**
1287
1218
  * {@link Evaluable.serialize}
1288
1219
  */
1289
-
1290
-
1291
1220
  serialize(options) {
1292
1221
  return this.items.map(item => isEvaluable(item) ? item.serialize(options) : item);
1293
1222
  }
1223
+
1294
1224
  /**
1295
1225
  * Get the strict representation of the operand.
1296
1226
  * @return {string}
1297
1227
  */
1298
-
1299
-
1300
1228
  toString() {
1301
1229
  return '[' + this.items.map(item => item.toString()).join(', ') + ']';
1302
1230
  }
1303
-
1304
1231
  }
1305
1232
 
1306
- /**
1307
- * Convert a value to number if possible, otherwise return undefined
1308
- * @param value value to be converted to number
1309
- */
1310
-
1311
- const toNumber = value => {
1312
- const isValueNumber = isNumber(value);
1313
-
1314
- if (isValueNumber) {
1315
- return value;
1316
- } else if (isString(value)) {
1317
- if (value.match(/^\d+\.\d+$/)) {
1318
- return parseFloat(value);
1319
- } else if (value.match(/^0$|^[1-9]\d*$/)) {
1320
- return parseInt(value);
1321
- }
1322
- }
1323
-
1324
- return undefined;
1325
- };
1326
- /**
1327
- * Convert a value to string if possible, otherwise return undefined
1328
- * @param value value to be converted to string
1329
- */
1330
-
1331
- const toString = value => {
1332
- if (isNumber(value)) {
1333
- return `${value}`;
1334
- } else if (isString(value)) {
1335
- return value;
1336
- }
1337
-
1338
- return undefined;
1339
- };
1340
-
1341
1233
  const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
1342
1234
  const arrayIndexRegex = /\[(\d+)]/g;
1343
-
1344
- const parseKey = key => key.split('.').flatMap(key => {
1345
- const parseResult = keyWithArrayIndexRegex.exec(key);
1346
- const keys = [];
1347
-
1348
- if (parseResult) {
1349
- var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
1350
-
1351
- keys.push((_parseResult$groups$c = parseResult === null || parseResult === void 0 ? void 0 : (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : key);
1352
- const rawIndexes = parseResult === null || parseResult === void 0 ? void 0 : (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
1353
-
1354
- if (rawIndexes) {
1355
- for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
1356
- keys.push(parseInt(indexResult[1]));
1235
+ const parseBacktickWrappedKey = key => key.startsWith('`') && key.endsWith('`') ? key.slice(1, -1) : key;
1236
+ const parseKey = key => {
1237
+ const keys = key.match(/(`[^[\]]+`(\[\d+\])*|[^`.]+)/g);
1238
+ return !keys ? [] : keys.flatMap(key => {
1239
+ const unwrappedKey = parseBacktickWrappedKey(key);
1240
+ const keys = [];
1241
+ const parseResult = keyWithArrayIndexRegex.exec(unwrappedKey);
1242
+ if (parseResult) {
1243
+ var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
1244
+ const extractedKey = parseBacktickWrappedKey((_parseResult$groups$c = parseResult === null || parseResult === void 0 || (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : unwrappedKey);
1245
+ keys.push(extractedKey);
1246
+ const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
1247
+ if (rawIndexes) {
1248
+ for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
1249
+ keys.push(parseInt(indexResult[1]));
1250
+ }
1357
1251
  }
1252
+ } else {
1253
+ keys.push(unwrappedKey);
1358
1254
  }
1359
- } else {
1360
- keys.push(key);
1361
- }
1362
-
1363
- return keys;
1364
- });
1365
-
1255
+ return keys;
1256
+ });
1257
+ };
1366
1258
  const complexKeyExpression = /{([^{}]+)}/;
1367
-
1368
1259
  function extractComplexKeys(ctx, key) {
1369
1260
  // Resolve complex keys
1370
1261
  let complexKeyMatches = complexKeyExpression.exec(key);
1371
-
1372
1262
  while (complexKeyMatches) {
1373
1263
  const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
1374
-
1375
1264
  if (resolvedValue === undefined) {
1376
1265
  return undefined;
1377
1266
  }
1378
-
1379
1267
  key = key.replace(complexKeyExpression, `${resolvedValue}`);
1380
1268
  complexKeyMatches = complexKeyExpression.exec(key);
1381
1269
  }
1382
-
1383
1270
  return parseKey(key);
1384
1271
  }
1385
-
1386
1272
  const isContext = value => isObject(value);
1387
-
1388
1273
  const simpleValueLookup = keys => ctx => {
1389
1274
  let pointer = ctx;
1390
-
1391
1275
  for (const key of keys) {
1392
1276
  if (typeof key === 'number') {
1393
1277
  if (!Array.isArray(pointer)) {
1394
1278
  return undefined;
1395
1279
  }
1396
-
1397
1280
  pointer = pointer[key];
1398
1281
  } else if (!isContext(pointer)) {
1399
1282
  return undefined;
@@ -1401,9 +1284,9 @@ const simpleValueLookup = keys => ctx => {
1401
1284
  pointer = pointer[key];
1402
1285
  }
1403
1286
  }
1404
-
1405
1287
  return pointer;
1406
1288
  };
1289
+
1407
1290
  /**
1408
1291
  * Lookup for the reference in the context.
1409
1292
  * The nested context value is annotated with "." delimiter.
@@ -1412,33 +1295,26 @@ const simpleValueLookup = keys => ctx => {
1412
1295
  * @param {string} key Context lookup key.
1413
1296
  * @return {Result}
1414
1297
  */
1415
-
1416
-
1417
1298
  function complexValueLookup(ctx, key) {
1418
1299
  const keys = extractComplexKeys(ctx, key);
1419
-
1420
1300
  if (!keys) {
1421
1301
  return undefined;
1422
1302
  }
1423
-
1424
1303
  return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
1425
1304
  }
1426
-
1427
- let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
1428
-
1429
- (function (DataType) {
1305
+ let DataType = /*#__PURE__*/function (DataType) {
1430
1306
  DataType["Number"] = "Number";
1431
1307
  DataType["String"] = "String";
1432
- })(DataType || (DataType = {}));
1308
+ return DataType;
1309
+ }({});
1433
1310
 
1311
+ // Equivalent to /^.+\.\((Number|String)\)$/
1434
1312
  const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
1435
-
1436
1313
  const isComplexKey = key => key.indexOf('{') > -1;
1314
+
1437
1315
  /**
1438
1316
  * Reference operand resolved within the context
1439
1317
  */
1440
-
1441
-
1442
1318
  class Reference extends Operand {
1443
1319
  /**
1444
1320
  * @constructor
@@ -1448,119 +1324,97 @@ class Reference extends Operand {
1448
1324
  if (key.trim() === '') {
1449
1325
  throw new Error('invalid reference key');
1450
1326
  }
1451
-
1452
1327
  super();
1453
-
1454
1328
  _defineProperty(this, "key", void 0);
1455
-
1456
1329
  _defineProperty(this, "dataType", void 0);
1457
-
1458
1330
  _defineProperty(this, "valueLookup", void 0);
1459
-
1460
1331
  _defineProperty(this, "getKeys", void 0);
1461
-
1462
1332
  this.key = key;
1463
1333
  const dataTypeMatch = dataTypeRegex.exec(this.key);
1464
-
1465
1334
  if (dataTypeMatch) {
1466
1335
  this.dataType = DataType[dataTypeMatch[1]];
1467
1336
  }
1468
-
1469
1337
  if (this.key.match(/.\(.+\)$/)) {
1470
1338
  this.key = this.key.replace(/.\(.+\)$/, '');
1471
1339
  }
1472
-
1473
1340
  if (isComplexKey(this.key)) {
1474
1341
  this.valueLookup = context => complexValueLookup(context, this.key);
1475
-
1476
1342
  this.getKeys = context => extractComplexKeys(context, this.key);
1477
1343
  } else {
1478
1344
  const keys = parseKey(this.key);
1479
1345
  this.valueLookup = simpleValueLookup(keys);
1480
-
1481
1346
  this.getKeys = () => keys;
1482
1347
  }
1483
1348
  }
1349
+
1484
1350
  /**
1485
1351
  * Evaluate in the given context.
1486
1352
  * @param {Context} ctx
1487
1353
  * @return {boolean}
1488
1354
  */
1489
-
1490
-
1491
1355
  evaluate(ctx) {
1492
1356
  return this.toDataType(this.valueLookup(ctx));
1493
1357
  }
1358
+
1494
1359
  /**
1495
1360
  * {@link Evaluable.simplify}
1496
1361
  */
1497
-
1498
-
1499
1362
  simplify(ctx, strictKeys, optionalKeys) {
1500
1363
  var _this$getKeys;
1501
-
1502
1364
  const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
1503
-
1504
1365
  if (ctx[key] !== undefined) {
1505
1366
  return this.evaluate(ctx);
1506
1367
  }
1507
-
1508
1368
  if (!key || typeof key === 'number') {
1509
1369
  return this;
1510
1370
  }
1511
-
1512
1371
  return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
1513
1372
  }
1373
+
1514
1374
  /**
1515
1375
  * {@link Evaluable.serialize}
1516
1376
  */
1517
-
1518
-
1519
- serialize(_ref) {
1520
- let {
1521
- referenceSerialization
1522
- } = _ref;
1377
+ serialize({
1378
+ referenceSerialization
1379
+ }) {
1523
1380
  const key = this.dataType ? `${this.key}.(${this.dataType})` : this.key;
1524
1381
  return referenceSerialization(key);
1525
1382
  }
1383
+
1526
1384
  /**
1527
1385
  * Get the strict representation of the operand.
1528
1386
  * @return {string}
1529
1387
  */
1530
-
1531
-
1532
1388
  toString() {
1533
1389
  return `{${this.key}}`;
1534
1390
  }
1391
+
1535
1392
  /**
1536
1393
  * Converts a value to a specified data type
1537
1394
  * Silently returns original value if data type conversion has not been implemented.
1538
1395
  * @param value value to cast as data type
1539
1396
  */
1540
-
1541
-
1542
1397
  toDataType(value) {
1543
1398
  let result = value;
1544
-
1545
1399
  switch (this.dataType) {
1546
1400
  case DataType.Number:
1547
1401
  result = toNumber(value);
1548
1402
  break;
1549
-
1550
1403
  case DataType.String:
1551
1404
  result = toString(value);
1552
1405
  break;
1553
1406
  }
1554
-
1555
1407
  if (value && result === undefined) {
1556
1408
  console.warn(`Casting ${value} to ${this.dataType} resulted in ${result}`);
1557
1409
  }
1558
-
1559
1410
  return result;
1560
1411
  }
1561
-
1562
1412
  }
1563
1413
 
1414
+ // Option value whitelist
1415
+
1416
+ // Parser options
1417
+
1564
1418
  /**
1565
1419
  * Default reference predicate.
1566
1420
  * The "$" symbol at the begging of the operand is used
@@ -1572,28 +1426,31 @@ class Reference extends Operand {
1572
1426
  function defaultReferencePredicate(key) {
1573
1427
  return isString(key) && key.startsWith('$');
1574
1428
  }
1429
+
1575
1430
  /**
1576
1431
  * Default reference transform.
1577
1432
  * It removes the "$" symbol at the begging of the operand name.
1578
1433
  * @param {string} key
1579
1434
  * @return {string}
1580
1435
  */
1581
-
1582
1436
  function defaultReferenceTransform(key) {
1583
1437
  return key.slice(1);
1584
1438
  }
1585
1439
  function defaultReferenceSerialization(key) {
1586
1440
  return `$${key}`;
1587
- } // Default operator mapping
1588
- // Unique operator key <-> raw expression key
1441
+ }
1589
1442
 
1590
- const defaultOperatorMapping = new Map([// Comparison
1591
- [OPERATOR$h, '=='], [OPERATOR$b, '!='], [OPERATOR$f, '>'], [OPERATOR$g, '>='], [OPERATOR$c, '<'], [OPERATOR$d, '<='], [OPERATOR$e, 'IN'], [OPERATOR$a, 'NOT IN'], [OPERATOR$8, 'PREFIX'], [OPERATOR$6, 'SUFFIX'], [OPERATOR$9, 'OVERLAP'], [OPERATOR$5, 'UNDEFINED'], [OPERATOR$7, 'PRESENT'], // Logical
1443
+ // Default operator mapping
1444
+ // Unique operator key <-> raw expression key
1445
+ const defaultOperatorMapping = new Map([
1446
+ // Comparison
1447
+ [OPERATOR$h, '=='], [OPERATOR$b, '!='], [OPERATOR$f, '>'], [OPERATOR$g, '>='], [OPERATOR$c, '<'], [OPERATOR$d, '<='], [OPERATOR$e, 'IN'], [OPERATOR$a, 'NOT IN'], [OPERATOR$8, 'PREFIX'], [OPERATOR$6, 'SUFFIX'], [OPERATOR$9, 'OVERLAP'], [OPERATOR$5, 'UNDEFINED'], [OPERATOR$7, 'PRESENT'],
1448
+ // Logical
1592
1449
  [OPERATOR$4, 'AND'], [OPERATOR$1, 'OR'], [OPERATOR$2, 'NOR'], [OPERATOR, 'XOR'], [OPERATOR$3, 'NOT']]);
1450
+
1593
1451
  /**
1594
1452
  * Default parser options
1595
1453
  */
1596
-
1597
1454
  const defaultOptions = {
1598
1455
  referencePredicate: defaultReferencePredicate,
1599
1456
  referenceTransform: defaultReferenceTransform,
@@ -1601,6 +1458,8 @@ const defaultOptions = {
1601
1458
  operatorMapping: defaultOperatorMapping
1602
1459
  };
1603
1460
 
1461
+ // Input types
1462
+
1604
1463
  /**
1605
1464
  * Parser of raw expressions into Evaluable expression
1606
1465
  */
@@ -1611,12 +1470,11 @@ class Parser {
1611
1470
  */
1612
1471
  constructor(options) {
1613
1472
  _defineProperty(this, "opts", void 0);
1614
-
1615
1473
  _defineProperty(this, "expectedOperators", void 0);
1616
-
1617
- this.opts = { ...defaultOptions
1618
- }; // Apply exclusive options overrides
1619
-
1474
+ this.opts = {
1475
+ ...defaultOptions
1476
+ };
1477
+ // Apply exclusive options overrides
1620
1478
  if (options) {
1621
1479
  for (const key of Object.keys(options)) {
1622
1480
  if (key in this.opts) {
@@ -1624,55 +1482,47 @@ class Parser {
1624
1482
  }
1625
1483
  }
1626
1484
  }
1627
-
1628
1485
  this.expectedOperators = new Set(this.opts.operatorMapping.values());
1629
1486
  }
1487
+
1630
1488
  /**
1631
1489
  * Parser options
1632
1490
  * @type {Options}
1633
1491
  */
1634
-
1635
-
1636
1492
  get options() {
1637
1493
  return this.opts;
1638
1494
  }
1495
+
1639
1496
  /**
1640
1497
  * Parse raw expression into evaluable expression.
1641
1498
  * @param {ExpressionInput} raw Raw expression.
1642
1499
  * @return {Evaluable}
1643
1500
  */
1644
-
1645
-
1646
1501
  parse(raw) {
1647
1502
  if (raw === undefined || raw === null || Array.isArray(raw) === false) {
1648
1503
  throw new Error('invalid expression');
1649
1504
  }
1650
-
1651
1505
  if (raw.length === 0 || !this.expectedOperators.has(`${raw[0]}`)) {
1652
1506
  throw new Error('invalid expression');
1653
1507
  }
1654
-
1655
1508
  return this.parseRawExp(raw);
1656
1509
  }
1510
+
1657
1511
  /**
1658
1512
  * Parse raw expression based on the expression type.
1659
1513
  * @param {Input} raw Raw expression.
1660
1514
  * @return {Evaluable}
1661
1515
  */
1662
-
1663
-
1664
1516
  parseRawExp(raw) {
1665
- var _this = this;
1666
-
1667
1517
  // Value / Reference
1668
1518
  if (!Array.isArray(raw)) {
1669
1519
  return this.getOperand(raw);
1670
1520
  }
1671
-
1672
1521
  let expression;
1673
1522
  let operandParser = this.getOperand;
1674
1523
  const operator = raw[0];
1675
1524
  const operands = raw.slice(1);
1525
+
1676
1526
  /**
1677
1527
  * Simplify the logical expression if possible.
1678
1528
  * - AND, OR with one operand is collapsed, i.e. reduced to inner expression
@@ -1684,149 +1534,101 @@ class Parser {
1684
1534
  * @param operands
1685
1535
  * @param collapsible
1686
1536
  */
1687
-
1688
- const logicalExpressionReducer = function (operands) {
1689
- let collapsible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1690
-
1537
+ const logicalExpressionReducer = (operands, collapsible = false) => {
1691
1538
  if (operands.length === 0 || operands.filter(operand => operand.type === EvaluableType.Expression).length === 0) {
1692
- return _this.getOperand(raw);
1539
+ return this.getOperand(raw);
1693
1540
  }
1694
-
1695
1541
  return collapsible && operands.length === 1 ? operands[0] : undefined;
1696
1542
  };
1697
-
1698
1543
  switch (operator) {
1699
1544
  /**
1700
1545
  * Logical
1701
1546
  */
1702
1547
  case this.opts.operatorMapping.get(OPERATOR$4):
1703
1548
  expression = operands => logicalExpressionReducer(operands, true) || new And(operands);
1704
-
1705
1549
  operandParser = this.parseRawExp;
1706
1550
  break;
1707
-
1708
1551
  case this.opts.operatorMapping.get(OPERATOR$1):
1709
1552
  expression = operands => logicalExpressionReducer(operands, true) || new Or(operands);
1710
-
1711
1553
  operandParser = this.parseRawExp;
1712
1554
  break;
1713
-
1714
1555
  case this.opts.operatorMapping.get(OPERATOR$2):
1715
1556
  expression = operands => logicalExpressionReducer(operands) || new Nor(operands);
1716
-
1717
1557
  operandParser = this.parseRawExp;
1718
1558
  break;
1719
-
1720
1559
  case this.opts.operatorMapping.get(OPERATOR):
1721
1560
  expression = operands => logicalExpressionReducer(operands) || new Xor(operands);
1722
-
1723
1561
  operandParser = this.parseRawExp;
1724
1562
  break;
1725
-
1726
1563
  case this.opts.operatorMapping.get(OPERATOR$3):
1727
1564
  expression = operands => logicalExpressionReducer(operands) || new Not(...operands);
1728
-
1729
1565
  operandParser = this.parseRawExp;
1730
1566
  break;
1731
-
1732
1567
  /**
1733
1568
  * Comparison
1734
1569
  */
1735
-
1736
1570
  case this.opts.operatorMapping.get(OPERATOR$h):
1737
1571
  expression = operands => new Equal(...operands);
1738
-
1739
1572
  break;
1740
-
1741
1573
  case this.opts.operatorMapping.get(OPERATOR$b):
1742
1574
  expression = operands => new NotEqual(...operands);
1743
-
1744
1575
  break;
1745
-
1746
1576
  case this.opts.operatorMapping.get(OPERATOR$f):
1747
1577
  expression = operands => new GreaterThan(...operands);
1748
-
1749
1578
  break;
1750
-
1751
1579
  case this.opts.operatorMapping.get(OPERATOR$g):
1752
1580
  expression = operands => new GreaterThanOrEqual(...operands);
1753
-
1754
1581
  break;
1755
-
1756
1582
  case this.opts.operatorMapping.get(OPERATOR$c):
1757
1583
  expression = operands => new LessThan(...operands);
1758
-
1759
1584
  break;
1760
-
1761
1585
  case this.opts.operatorMapping.get(OPERATOR$d):
1762
1586
  expression = operands => new LessThanOrEqual(...operands);
1763
-
1764
1587
  break;
1765
-
1766
1588
  case this.opts.operatorMapping.get(OPERATOR$e):
1767
1589
  expression = operands => new In(...operands);
1768
-
1769
1590
  break;
1770
-
1771
1591
  case this.opts.operatorMapping.get(OPERATOR$a):
1772
1592
  expression = operands => new NotIn(...operands);
1773
-
1774
1593
  break;
1775
-
1776
1594
  case this.opts.operatorMapping.get(OPERATOR$8):
1777
1595
  expression = operands => new Prefix(...operands);
1778
-
1779
1596
  break;
1780
-
1781
1597
  case this.opts.operatorMapping.get(OPERATOR$6):
1782
1598
  expression = operands => new Suffix(...operands);
1783
-
1784
1599
  break;
1785
-
1786
1600
  case this.opts.operatorMapping.get(OPERATOR$9):
1787
1601
  expression = operands => new Overlap(...operands);
1788
-
1789
1602
  break;
1790
-
1791
1603
  case this.opts.operatorMapping.get(OPERATOR$5):
1792
1604
  expression = operands => new Undefined(...operands);
1793
-
1794
1605
  break;
1795
-
1796
1606
  case this.opts.operatorMapping.get(OPERATOR$7):
1797
1607
  expression = operands => new Present(...operands);
1798
-
1799
1608
  break;
1800
1609
  // Collection
1801
-
1802
1610
  default:
1803
1611
  return this.getOperand(raw);
1804
1612
  }
1805
-
1806
1613
  return expression(operands.map(operandParser.bind(this)));
1807
1614
  }
1615
+
1808
1616
  /**
1809
1617
  * Get resolved operand
1810
1618
  * @param raw Raw data
1811
1619
  */
1812
-
1813
-
1814
1620
  getOperand(raw) {
1815
1621
  const resolve = raw => this.opts.referencePredicate(raw) ? new Reference(this.opts.referenceTransform(raw)) : new Value(raw);
1816
-
1817
1622
  if (Array.isArray(raw)) {
1818
1623
  return new Collection(raw.map(item => resolve(item)));
1819
1624
  }
1820
-
1821
1625
  return resolve(raw);
1822
1626
  }
1823
-
1824
1627
  }
1825
1628
 
1826
1629
  /**
1827
1630
  * Condition engine
1828
1631
  */
1829
-
1830
1632
  class Engine {
1831
1633
  /**
1832
1634
  * @constructor
@@ -1834,40 +1636,37 @@ class Engine {
1834
1636
  */
1835
1637
  constructor(options) {
1836
1638
  _defineProperty(this, "parser", void 0);
1837
-
1838
1639
  this.parser = new Parser(options);
1839
1640
  }
1641
+
1840
1642
  /**
1841
1643
  * Evaluate the expression.
1842
1644
  * @param {ExpressionInput} exp Raw expression.
1843
1645
  * @param {Context} ctx Evaluation data context.
1844
1646
  * @return {boolean}
1845
1647
  */
1846
-
1847
-
1848
1648
  evaluate(exp, ctx) {
1849
1649
  return this.parse(exp).evaluate(ctx);
1850
1650
  }
1651
+
1851
1652
  /**
1852
1653
  * Get expression statement
1853
1654
  * @param {ExpressionInput} exp Raw expression.
1854
1655
  * @return {string}
1855
1656
  */
1856
-
1857
-
1858
1657
  statement(exp) {
1859
1658
  return this.parse(exp).toString();
1860
1659
  }
1660
+
1861
1661
  /**
1862
1662
  * Parse expression.
1863
1663
  * @param {ExpressionInput} exp Raw expression.
1864
1664
  * @return {Evaluable}
1865
1665
  */
1866
-
1867
-
1868
1666
  parse(exp) {
1869
1667
  return this.parser.parse(exp);
1870
1668
  }
1669
+
1871
1670
  /**
1872
1671
  * Simplifies an expression with values in context.
1873
1672
  *
@@ -1883,22 +1682,16 @@ class Engine {
1883
1682
  * `optionalKeys` is considered to be present and thus will be evaluated
1884
1683
  * @returns {Inpunt | boolean}
1885
1684
  */
1886
-
1887
-
1888
1685
  simplify(exp, context, strictKeys, optionalKeys) {
1889
1686
  const result = this.parse(exp).simplify(context, strictKeys, optionalKeys);
1890
-
1891
1687
  if (isEvaluable(result)) {
1892
1688
  return result.serialize(this.parser.options);
1893
1689
  }
1894
-
1895
1690
  if (isBoolean(result)) {
1896
1691
  return result;
1897
1692
  }
1898
-
1899
1693
  throw new Error('non expression or boolean result should be returned');
1900
1694
  }
1901
-
1902
1695
  }
1903
1696
 
1904
1697
  export { OPERATOR$4 as OPERATOR_AND, OPERATOR$h as OPERATOR_EQ, OPERATOR$g as OPERATOR_GE, OPERATOR$f as OPERATOR_GT, OPERATOR$e as OPERATOR_IN, OPERATOR$d as OPERATOR_LE, OPERATOR$c as OPERATOR_LT, OPERATOR$b as OPERATOR_NE, OPERATOR$2 as OPERATOR_NOR, OPERATOR$3 as OPERATOR_NOT, OPERATOR$a as OPERATOR_NOT_IN, OPERATOR$1 as OPERATOR_OR, OPERATOR$9 as OPERATOR_OVERLAP, OPERATOR$8 as OPERATOR_PREFIX, OPERATOR$7 as OPERATOR_PRESENT, OPERATOR$6 as OPERATOR_SUFFIX, OPERATOR$5 as OPERATOR_UNDEFINED, OPERATOR as OPERATOR_XOR, Engine as default, defaultOptions, isEvaluable };