@briza/illogical 1.5.5 → 1.5.6

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,109 +1186,59 @@ 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
1235
  const parseKey = key => key.split('.').flatMap(key => {
1345
1236
  const parseResult = keyWithArrayIndexRegex.exec(key);
1346
1237
  const keys = [];
1347
-
1348
1238
  if (parseResult) {
1349
1239
  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
-
1240
+ keys.push((_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 : key);
1241
+ const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
1354
1242
  if (rawIndexes) {
1355
1243
  for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
1356
1244
  keys.push(parseInt(indexResult[1]));
@@ -1359,41 +1247,30 @@ const parseKey = key => key.split('.').flatMap(key => {
1359
1247
  } else {
1360
1248
  keys.push(key);
1361
1249
  }
1362
-
1363
1250
  return keys;
1364
1251
  });
1365
-
1366
1252
  const complexKeyExpression = /{([^{}]+)}/;
1367
-
1368
1253
  function extractComplexKeys(ctx, key) {
1369
1254
  // Resolve complex keys
1370
1255
  let complexKeyMatches = complexKeyExpression.exec(key);
1371
-
1372
1256
  while (complexKeyMatches) {
1373
1257
  const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
1374
-
1375
1258
  if (resolvedValue === undefined) {
1376
1259
  return undefined;
1377
1260
  }
1378
-
1379
1261
  key = key.replace(complexKeyExpression, `${resolvedValue}`);
1380
1262
  complexKeyMatches = complexKeyExpression.exec(key);
1381
1263
  }
1382
-
1383
1264
  return parseKey(key);
1384
1265
  }
1385
-
1386
1266
  const isContext = value => isObject(value);
1387
-
1388
1267
  const simpleValueLookup = keys => ctx => {
1389
1268
  let pointer = ctx;
1390
-
1391
1269
  for (const key of keys) {
1392
1270
  if (typeof key === 'number') {
1393
1271
  if (!Array.isArray(pointer)) {
1394
1272
  return undefined;
1395
1273
  }
1396
-
1397
1274
  pointer = pointer[key];
1398
1275
  } else if (!isContext(pointer)) {
1399
1276
  return undefined;
@@ -1401,9 +1278,9 @@ const simpleValueLookup = keys => ctx => {
1401
1278
  pointer = pointer[key];
1402
1279
  }
1403
1280
  }
1404
-
1405
1281
  return pointer;
1406
1282
  };
1283
+
1407
1284
  /**
1408
1285
  * Lookup for the reference in the context.
1409
1286
  * The nested context value is annotated with "." delimiter.
@@ -1412,33 +1289,26 @@ const simpleValueLookup = keys => ctx => {
1412
1289
  * @param {string} key Context lookup key.
1413
1290
  * @return {Result}
1414
1291
  */
1415
-
1416
-
1417
1292
  function complexValueLookup(ctx, key) {
1418
1293
  const keys = extractComplexKeys(ctx, key);
1419
-
1420
1294
  if (!keys) {
1421
1295
  return undefined;
1422
1296
  }
1423
-
1424
1297
  return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
1425
1298
  }
1426
-
1427
- let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
1428
-
1429
- (function (DataType) {
1299
+ let DataType = /*#__PURE__*/function (DataType) {
1430
1300
  DataType["Number"] = "Number";
1431
1301
  DataType["String"] = "String";
1432
- })(DataType || (DataType = {}));
1302
+ return DataType;
1303
+ }({});
1433
1304
 
1305
+ // Equivalent to /^.+\.\((Number|String)\)$/
1434
1306
  const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
1435
-
1436
1307
  const isComplexKey = key => key.indexOf('{') > -1;
1308
+
1437
1309
  /**
1438
1310
  * Reference operand resolved within the context
1439
1311
  */
1440
-
1441
-
1442
1312
  class Reference extends Operand {
1443
1313
  /**
1444
1314
  * @constructor
@@ -1448,119 +1318,97 @@ class Reference extends Operand {
1448
1318
  if (key.trim() === '') {
1449
1319
  throw new Error('invalid reference key');
1450
1320
  }
1451
-
1452
1321
  super();
1453
-
1454
1322
  _defineProperty(this, "key", void 0);
1455
-
1456
1323
  _defineProperty(this, "dataType", void 0);
1457
-
1458
1324
  _defineProperty(this, "valueLookup", void 0);
1459
-
1460
1325
  _defineProperty(this, "getKeys", void 0);
1461
-
1462
1326
  this.key = key;
1463
1327
  const dataTypeMatch = dataTypeRegex.exec(this.key);
1464
-
1465
1328
  if (dataTypeMatch) {
1466
1329
  this.dataType = DataType[dataTypeMatch[1]];
1467
1330
  }
1468
-
1469
1331
  if (this.key.match(/.\(.+\)$/)) {
1470
1332
  this.key = this.key.replace(/.\(.+\)$/, '');
1471
1333
  }
1472
-
1473
1334
  if (isComplexKey(this.key)) {
1474
1335
  this.valueLookup = context => complexValueLookup(context, this.key);
1475
-
1476
1336
  this.getKeys = context => extractComplexKeys(context, this.key);
1477
1337
  } else {
1478
1338
  const keys = parseKey(this.key);
1479
1339
  this.valueLookup = simpleValueLookup(keys);
1480
-
1481
1340
  this.getKeys = () => keys;
1482
1341
  }
1483
1342
  }
1343
+
1484
1344
  /**
1485
1345
  * Evaluate in the given context.
1486
1346
  * @param {Context} ctx
1487
1347
  * @return {boolean}
1488
1348
  */
1489
-
1490
-
1491
1349
  evaluate(ctx) {
1492
1350
  return this.toDataType(this.valueLookup(ctx));
1493
1351
  }
1352
+
1494
1353
  /**
1495
1354
  * {@link Evaluable.simplify}
1496
1355
  */
1497
-
1498
-
1499
1356
  simplify(ctx, strictKeys, optionalKeys) {
1500
1357
  var _this$getKeys;
1501
-
1502
1358
  const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
1503
-
1504
1359
  if (ctx[key] !== undefined) {
1505
1360
  return this.evaluate(ctx);
1506
1361
  }
1507
-
1508
1362
  if (!key || typeof key === 'number') {
1509
1363
  return this;
1510
1364
  }
1511
-
1512
1365
  return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
1513
1366
  }
1367
+
1514
1368
  /**
1515
1369
  * {@link Evaluable.serialize}
1516
1370
  */
1517
-
1518
-
1519
- serialize(_ref) {
1520
- let {
1521
- referenceSerialization
1522
- } = _ref;
1371
+ serialize({
1372
+ referenceSerialization
1373
+ }) {
1523
1374
  const key = this.dataType ? `${this.key}.(${this.dataType})` : this.key;
1524
1375
  return referenceSerialization(key);
1525
1376
  }
1377
+
1526
1378
  /**
1527
1379
  * Get the strict representation of the operand.
1528
1380
  * @return {string}
1529
1381
  */
1530
-
1531
-
1532
1382
  toString() {
1533
1383
  return `{${this.key}}`;
1534
1384
  }
1385
+
1535
1386
  /**
1536
1387
  * Converts a value to a specified data type
1537
1388
  * Silently returns original value if data type conversion has not been implemented.
1538
1389
  * @param value value to cast as data type
1539
1390
  */
1540
-
1541
-
1542
1391
  toDataType(value) {
1543
1392
  let result = value;
1544
-
1545
1393
  switch (this.dataType) {
1546
1394
  case DataType.Number:
1547
1395
  result = toNumber(value);
1548
1396
  break;
1549
-
1550
1397
  case DataType.String:
1551
1398
  result = toString(value);
1552
1399
  break;
1553
1400
  }
1554
-
1555
1401
  if (value && result === undefined) {
1556
1402
  console.warn(`Casting ${value} to ${this.dataType} resulted in ${result}`);
1557
1403
  }
1558
-
1559
1404
  return result;
1560
1405
  }
1561
-
1562
1406
  }
1563
1407
 
1408
+ // Option value whitelist
1409
+
1410
+ // Parser options
1411
+
1564
1412
  /**
1565
1413
  * Default reference predicate.
1566
1414
  * The "$" symbol at the begging of the operand is used
@@ -1572,28 +1420,31 @@ class Reference extends Operand {
1572
1420
  function defaultReferencePredicate(key) {
1573
1421
  return isString(key) && key.startsWith('$');
1574
1422
  }
1423
+
1575
1424
  /**
1576
1425
  * Default reference transform.
1577
1426
  * It removes the "$" symbol at the begging of the operand name.
1578
1427
  * @param {string} key
1579
1428
  * @return {string}
1580
1429
  */
1581
-
1582
1430
  function defaultReferenceTransform(key) {
1583
1431
  return key.slice(1);
1584
1432
  }
1585
1433
  function defaultReferenceSerialization(key) {
1586
1434
  return `$${key}`;
1587
- } // Default operator mapping
1588
- // Unique operator key <-> raw expression key
1435
+ }
1589
1436
 
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
1437
+ // Default operator mapping
1438
+ // Unique operator key <-> raw expression key
1439
+ const defaultOperatorMapping = new Map([
1440
+ // Comparison
1441
+ [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'],
1442
+ // Logical
1592
1443
  [OPERATOR$4, 'AND'], [OPERATOR$1, 'OR'], [OPERATOR$2, 'NOR'], [OPERATOR, 'XOR'], [OPERATOR$3, 'NOT']]);
1444
+
1593
1445
  /**
1594
1446
  * Default parser options
1595
1447
  */
1596
-
1597
1448
  const defaultOptions = {
1598
1449
  referencePredicate: defaultReferencePredicate,
1599
1450
  referenceTransform: defaultReferenceTransform,
@@ -1601,6 +1452,8 @@ const defaultOptions = {
1601
1452
  operatorMapping: defaultOperatorMapping
1602
1453
  };
1603
1454
 
1455
+ // Input types
1456
+
1604
1457
  /**
1605
1458
  * Parser of raw expressions into Evaluable expression
1606
1459
  */
@@ -1611,12 +1464,11 @@ class Parser {
1611
1464
  */
1612
1465
  constructor(options) {
1613
1466
  _defineProperty(this, "opts", void 0);
1614
-
1615
1467
  _defineProperty(this, "expectedOperators", void 0);
1616
-
1617
- this.opts = { ...defaultOptions
1618
- }; // Apply exclusive options overrides
1619
-
1468
+ this.opts = {
1469
+ ...defaultOptions
1470
+ };
1471
+ // Apply exclusive options overrides
1620
1472
  if (options) {
1621
1473
  for (const key of Object.keys(options)) {
1622
1474
  if (key in this.opts) {
@@ -1624,55 +1476,47 @@ class Parser {
1624
1476
  }
1625
1477
  }
1626
1478
  }
1627
-
1628
1479
  this.expectedOperators = new Set(this.opts.operatorMapping.values());
1629
1480
  }
1481
+
1630
1482
  /**
1631
1483
  * Parser options
1632
1484
  * @type {Options}
1633
1485
  */
1634
-
1635
-
1636
1486
  get options() {
1637
1487
  return this.opts;
1638
1488
  }
1489
+
1639
1490
  /**
1640
1491
  * Parse raw expression into evaluable expression.
1641
1492
  * @param {ExpressionInput} raw Raw expression.
1642
1493
  * @return {Evaluable}
1643
1494
  */
1644
-
1645
-
1646
1495
  parse(raw) {
1647
1496
  if (raw === undefined || raw === null || Array.isArray(raw) === false) {
1648
1497
  throw new Error('invalid expression');
1649
1498
  }
1650
-
1651
1499
  if (raw.length === 0 || !this.expectedOperators.has(`${raw[0]}`)) {
1652
1500
  throw new Error('invalid expression');
1653
1501
  }
1654
-
1655
1502
  return this.parseRawExp(raw);
1656
1503
  }
1504
+
1657
1505
  /**
1658
1506
  * Parse raw expression based on the expression type.
1659
1507
  * @param {Input} raw Raw expression.
1660
1508
  * @return {Evaluable}
1661
1509
  */
1662
-
1663
-
1664
1510
  parseRawExp(raw) {
1665
- var _this = this;
1666
-
1667
1511
  // Value / Reference
1668
1512
  if (!Array.isArray(raw)) {
1669
1513
  return this.getOperand(raw);
1670
1514
  }
1671
-
1672
1515
  let expression;
1673
1516
  let operandParser = this.getOperand;
1674
1517
  const operator = raw[0];
1675
1518
  const operands = raw.slice(1);
1519
+
1676
1520
  /**
1677
1521
  * Simplify the logical expression if possible.
1678
1522
  * - AND, OR with one operand is collapsed, i.e. reduced to inner expression
@@ -1684,149 +1528,101 @@ class Parser {
1684
1528
  * @param operands
1685
1529
  * @param collapsible
1686
1530
  */
1687
-
1688
- const logicalExpressionReducer = function (operands) {
1689
- let collapsible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
1690
-
1531
+ const logicalExpressionReducer = (operands, collapsible = false) => {
1691
1532
  if (operands.length === 0 || operands.filter(operand => operand.type === EvaluableType.Expression).length === 0) {
1692
- return _this.getOperand(raw);
1533
+ return this.getOperand(raw);
1693
1534
  }
1694
-
1695
1535
  return collapsible && operands.length === 1 ? operands[0] : undefined;
1696
1536
  };
1697
-
1698
1537
  switch (operator) {
1699
1538
  /**
1700
1539
  * Logical
1701
1540
  */
1702
1541
  case this.opts.operatorMapping.get(OPERATOR$4):
1703
1542
  expression = operands => logicalExpressionReducer(operands, true) || new And(operands);
1704
-
1705
1543
  operandParser = this.parseRawExp;
1706
1544
  break;
1707
-
1708
1545
  case this.opts.operatorMapping.get(OPERATOR$1):
1709
1546
  expression = operands => logicalExpressionReducer(operands, true) || new Or(operands);
1710
-
1711
1547
  operandParser = this.parseRawExp;
1712
1548
  break;
1713
-
1714
1549
  case this.opts.operatorMapping.get(OPERATOR$2):
1715
1550
  expression = operands => logicalExpressionReducer(operands) || new Nor(operands);
1716
-
1717
1551
  operandParser = this.parseRawExp;
1718
1552
  break;
1719
-
1720
1553
  case this.opts.operatorMapping.get(OPERATOR):
1721
1554
  expression = operands => logicalExpressionReducer(operands) || new Xor(operands);
1722
-
1723
1555
  operandParser = this.parseRawExp;
1724
1556
  break;
1725
-
1726
1557
  case this.opts.operatorMapping.get(OPERATOR$3):
1727
1558
  expression = operands => logicalExpressionReducer(operands) || new Not(...operands);
1728
-
1729
1559
  operandParser = this.parseRawExp;
1730
1560
  break;
1731
-
1732
1561
  /**
1733
1562
  * Comparison
1734
1563
  */
1735
-
1736
1564
  case this.opts.operatorMapping.get(OPERATOR$h):
1737
1565
  expression = operands => new Equal(...operands);
1738
-
1739
1566
  break;
1740
-
1741
1567
  case this.opts.operatorMapping.get(OPERATOR$b):
1742
1568
  expression = operands => new NotEqual(...operands);
1743
-
1744
1569
  break;
1745
-
1746
1570
  case this.opts.operatorMapping.get(OPERATOR$f):
1747
1571
  expression = operands => new GreaterThan(...operands);
1748
-
1749
1572
  break;
1750
-
1751
1573
  case this.opts.operatorMapping.get(OPERATOR$g):
1752
1574
  expression = operands => new GreaterThanOrEqual(...operands);
1753
-
1754
1575
  break;
1755
-
1756
1576
  case this.opts.operatorMapping.get(OPERATOR$c):
1757
1577
  expression = operands => new LessThan(...operands);
1758
-
1759
1578
  break;
1760
-
1761
1579
  case this.opts.operatorMapping.get(OPERATOR$d):
1762
1580
  expression = operands => new LessThanOrEqual(...operands);
1763
-
1764
1581
  break;
1765
-
1766
1582
  case this.opts.operatorMapping.get(OPERATOR$e):
1767
1583
  expression = operands => new In(...operands);
1768
-
1769
1584
  break;
1770
-
1771
1585
  case this.opts.operatorMapping.get(OPERATOR$a):
1772
1586
  expression = operands => new NotIn(...operands);
1773
-
1774
1587
  break;
1775
-
1776
1588
  case this.opts.operatorMapping.get(OPERATOR$8):
1777
1589
  expression = operands => new Prefix(...operands);
1778
-
1779
1590
  break;
1780
-
1781
1591
  case this.opts.operatorMapping.get(OPERATOR$6):
1782
1592
  expression = operands => new Suffix(...operands);
1783
-
1784
1593
  break;
1785
-
1786
1594
  case this.opts.operatorMapping.get(OPERATOR$9):
1787
1595
  expression = operands => new Overlap(...operands);
1788
-
1789
1596
  break;
1790
-
1791
1597
  case this.opts.operatorMapping.get(OPERATOR$5):
1792
1598
  expression = operands => new Undefined(...operands);
1793
-
1794
1599
  break;
1795
-
1796
1600
  case this.opts.operatorMapping.get(OPERATOR$7):
1797
1601
  expression = operands => new Present(...operands);
1798
-
1799
1602
  break;
1800
1603
  // Collection
1801
-
1802
1604
  default:
1803
1605
  return this.getOperand(raw);
1804
1606
  }
1805
-
1806
1607
  return expression(operands.map(operandParser.bind(this)));
1807
1608
  }
1609
+
1808
1610
  /**
1809
1611
  * Get resolved operand
1810
1612
  * @param raw Raw data
1811
1613
  */
1812
-
1813
-
1814
1614
  getOperand(raw) {
1815
1615
  const resolve = raw => this.opts.referencePredicate(raw) ? new Reference(this.opts.referenceTransform(raw)) : new Value(raw);
1816
-
1817
1616
  if (Array.isArray(raw)) {
1818
1617
  return new Collection(raw.map(item => resolve(item)));
1819
1618
  }
1820
-
1821
1619
  return resolve(raw);
1822
1620
  }
1823
-
1824
1621
  }
1825
1622
 
1826
1623
  /**
1827
1624
  * Condition engine
1828
1625
  */
1829
-
1830
1626
  class Engine {
1831
1627
  /**
1832
1628
  * @constructor
@@ -1834,40 +1630,37 @@ class Engine {
1834
1630
  */
1835
1631
  constructor(options) {
1836
1632
  _defineProperty(this, "parser", void 0);
1837
-
1838
1633
  this.parser = new Parser(options);
1839
1634
  }
1635
+
1840
1636
  /**
1841
1637
  * Evaluate the expression.
1842
1638
  * @param {ExpressionInput} exp Raw expression.
1843
1639
  * @param {Context} ctx Evaluation data context.
1844
1640
  * @return {boolean}
1845
1641
  */
1846
-
1847
-
1848
1642
  evaluate(exp, ctx) {
1849
1643
  return this.parse(exp).evaluate(ctx);
1850
1644
  }
1645
+
1851
1646
  /**
1852
1647
  * Get expression statement
1853
1648
  * @param {ExpressionInput} exp Raw expression.
1854
1649
  * @return {string}
1855
1650
  */
1856
-
1857
-
1858
1651
  statement(exp) {
1859
1652
  return this.parse(exp).toString();
1860
1653
  }
1654
+
1861
1655
  /**
1862
1656
  * Parse expression.
1863
1657
  * @param {ExpressionInput} exp Raw expression.
1864
1658
  * @return {Evaluable}
1865
1659
  */
1866
-
1867
-
1868
1660
  parse(exp) {
1869
1661
  return this.parser.parse(exp);
1870
1662
  }
1663
+
1871
1664
  /**
1872
1665
  * Simplifies an expression with values in context.
1873
1666
  *
@@ -1883,22 +1676,16 @@ class Engine {
1883
1676
  * `optionalKeys` is considered to be present and thus will be evaluated
1884
1677
  * @returns {Inpunt | boolean}
1885
1678
  */
1886
-
1887
-
1888
1679
  simplify(exp, context, strictKeys, optionalKeys) {
1889
1680
  const result = this.parse(exp).simplify(context, strictKeys, optionalKeys);
1890
-
1891
1681
  if (isEvaluable(result)) {
1892
1682
  return result.serialize(this.parser.options);
1893
1683
  }
1894
-
1895
1684
  if (isBoolean(result)) {
1896
1685
  return result;
1897
1686
  }
1898
-
1899
1687
  throw new Error('non expression or boolean result should be returned');
1900
1688
  }
1901
-
1902
1689
  }
1903
1690
 
1904
1691
  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 };