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