@briza/illogical 1.5.2 → 1.5.5
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/changelog.md +14 -0
- package/lib/illogical.esm.js +116 -71
- package/lib/illogical.js +117 -70
- package/package.json +18 -18
- package/readme.md +1 -1
- package/types/common/evaluable.d.ts +1 -1
- package/types/index.d.ts +3 -1
- package/types/operand/reference.d.ts +2 -0
package/changelog.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# illogical changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.5
|
|
4
|
+
|
|
5
|
+
- Expose default options for parser
|
|
6
|
+
- Expose isEvaluable
|
|
7
|
+
- Performance improvements in references
|
|
8
|
+
|
|
9
|
+
## 1.5.4
|
|
10
|
+
|
|
11
|
+
- Update dependencies.
|
|
12
|
+
|
|
13
|
+
## 1.5.3
|
|
14
|
+
|
|
15
|
+
- Fixed an issue where conditions with object data were not being simplified correctly.
|
|
16
|
+
|
|
3
17
|
## 1.5.2
|
|
4
18
|
|
|
5
19
|
- Update dependencies.
|
package/lib/illogical.esm.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
function _defineProperty(obj, key, value) {
|
|
2
|
+
if (key in obj) {
|
|
3
|
+
Object.defineProperty(obj, key, {
|
|
4
|
+
value: value,
|
|
5
|
+
enumerable: true,
|
|
6
|
+
configurable: true,
|
|
7
|
+
writable: true
|
|
8
|
+
});
|
|
9
|
+
} else {
|
|
10
|
+
obj[key] = value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return obj;
|
|
14
|
+
}
|
|
15
|
+
|
|
1
16
|
/**
|
|
2
17
|
* Is number predicate.
|
|
3
18
|
* @param value Tested value.
|
|
@@ -45,22 +60,7 @@ function isBoolean(value) {
|
|
|
45
60
|
*/
|
|
46
61
|
|
|
47
62
|
function isEvaluable(value) {
|
|
48
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function _defineProperty(obj, key, value) {
|
|
52
|
-
if (key in obj) {
|
|
53
|
-
Object.defineProperty(obj, key, {
|
|
54
|
-
value: value,
|
|
55
|
-
enumerable: true,
|
|
56
|
-
configurable: true,
|
|
57
|
-
writable: true
|
|
58
|
-
});
|
|
59
|
-
} else {
|
|
60
|
-
obj[key] = value;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return obj;
|
|
63
|
+
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
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -97,12 +97,12 @@ class Comparison {
|
|
|
97
97
|
* @param {Operand} right Right operand.
|
|
98
98
|
*/
|
|
99
99
|
constructor(operator, operatorSymbol, left, right) {
|
|
100
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
101
|
-
|
|
102
100
|
this.operator = operator;
|
|
103
101
|
this.operatorSymbol = operatorSymbol;
|
|
104
102
|
this.left = left;
|
|
105
103
|
this.right = right;
|
|
104
|
+
|
|
105
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
106
106
|
}
|
|
107
107
|
/**
|
|
108
108
|
* {@link Evaluable.evaluate}
|
|
@@ -620,6 +620,9 @@ class Value extends Operand {
|
|
|
620
620
|
}
|
|
621
621
|
|
|
622
622
|
super();
|
|
623
|
+
|
|
624
|
+
_defineProperty(this, "value", void 0);
|
|
625
|
+
|
|
623
626
|
this.value = value;
|
|
624
627
|
}
|
|
625
628
|
/**
|
|
@@ -816,11 +819,11 @@ class Logical {
|
|
|
816
819
|
* @param {Evaluable[]} operands Collection of operands.
|
|
817
820
|
*/
|
|
818
821
|
constructor(operator, operatorSymbol, operands) {
|
|
819
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
820
|
-
|
|
821
822
|
this.operator = operator;
|
|
822
823
|
this.operatorSymbol = operatorSymbol;
|
|
823
824
|
this.operands = operands;
|
|
825
|
+
|
|
826
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
824
827
|
}
|
|
825
828
|
/**
|
|
826
829
|
* {@link Evaluable.evaluate}
|
|
@@ -1245,6 +1248,9 @@ class Collection extends Operand {
|
|
|
1245
1248
|
*/
|
|
1246
1249
|
constructor(items) {
|
|
1247
1250
|
super();
|
|
1251
|
+
|
|
1252
|
+
_defineProperty(this, "items", void 0);
|
|
1253
|
+
|
|
1248
1254
|
this.items = items;
|
|
1249
1255
|
}
|
|
1250
1256
|
/**
|
|
@@ -1332,13 +1338,39 @@ const toString = value => {
|
|
|
1332
1338
|
return undefined;
|
|
1333
1339
|
};
|
|
1334
1340
|
|
|
1335
|
-
|
|
1341
|
+
const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
|
|
1342
|
+
const arrayIndexRegex = /\[(\d+)]/g;
|
|
1343
|
+
|
|
1344
|
+
const parseKey = key => key.split('.').flatMap(key => {
|
|
1345
|
+
const parseResult = keyWithArrayIndexRegex.exec(key);
|
|
1346
|
+
const keys = [];
|
|
1347
|
+
|
|
1348
|
+
if (parseResult) {
|
|
1349
|
+
var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
|
|
1350
|
+
|
|
1351
|
+
keys.push((_parseResult$groups$c = parseResult === null || parseResult === void 0 ? void 0 : (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : key);
|
|
1352
|
+
const rawIndexes = parseResult === null || parseResult === void 0 ? void 0 : (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
|
|
1353
|
+
|
|
1354
|
+
if (rawIndexes) {
|
|
1355
|
+
for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
|
|
1356
|
+
keys.push(parseInt(indexResult[1]));
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
} else {
|
|
1360
|
+
keys.push(key);
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
return keys;
|
|
1364
|
+
});
|
|
1365
|
+
|
|
1366
|
+
const complexKeyExpression = /{([^{}]+)}/;
|
|
1367
|
+
|
|
1368
|
+
function extractComplexKeys(ctx, key) {
|
|
1336
1369
|
// Resolve complex keys
|
|
1337
|
-
const complexKeyExpression = /{([^{}]+)}/;
|
|
1338
1370
|
let complexKeyMatches = complexKeyExpression.exec(key);
|
|
1339
1371
|
|
|
1340
1372
|
while (complexKeyMatches) {
|
|
1341
|
-
const resolvedValue =
|
|
1373
|
+
const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
|
|
1342
1374
|
|
|
1343
1375
|
if (resolvedValue === undefined) {
|
|
1344
1376
|
return undefined;
|
|
@@ -1348,14 +1380,30 @@ function extractKeys(ctx, key) {
|
|
|
1348
1380
|
complexKeyMatches = complexKeyExpression.exec(key);
|
|
1349
1381
|
}
|
|
1350
1382
|
|
|
1351
|
-
|
|
1383
|
+
return parseKey(key);
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
const isContext = value => isObject(value);
|
|
1387
|
+
|
|
1388
|
+
const simpleValueLookup = keys => ctx => {
|
|
1389
|
+
let pointer = ctx;
|
|
1352
1390
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1391
|
+
for (const key of keys) {
|
|
1392
|
+
if (typeof key === 'number') {
|
|
1393
|
+
if (!Array.isArray(pointer)) {
|
|
1394
|
+
return undefined;
|
|
1395
|
+
}
|
|
1396
|
+
|
|
1397
|
+
pointer = pointer[key];
|
|
1398
|
+
} else if (!isContext(pointer)) {
|
|
1399
|
+
return undefined;
|
|
1400
|
+
} else {
|
|
1401
|
+
pointer = pointer[key];
|
|
1402
|
+
}
|
|
1355
1403
|
}
|
|
1356
1404
|
|
|
1357
|
-
return
|
|
1358
|
-
}
|
|
1405
|
+
return pointer;
|
|
1406
|
+
};
|
|
1359
1407
|
/**
|
|
1360
1408
|
* Lookup for the reference in the context.
|
|
1361
1409
|
* The nested context value is annotated with "." delimiter.
|
|
@@ -1366,42 +1414,14 @@ function extractKeys(ctx, key) {
|
|
|
1366
1414
|
*/
|
|
1367
1415
|
|
|
1368
1416
|
|
|
1369
|
-
function
|
|
1370
|
-
const keys =
|
|
1417
|
+
function complexValueLookup(ctx, key) {
|
|
1418
|
+
const keys = extractComplexKeys(ctx, key);
|
|
1371
1419
|
|
|
1372
1420
|
if (!keys) {
|
|
1373
1421
|
return undefined;
|
|
1374
|
-
} // Context pointer
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
let pointer = ctx;
|
|
1378
|
-
|
|
1379
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1380
|
-
var _keys$i$match;
|
|
1381
|
-
|
|
1382
|
-
const currentKey = keys[i].replace(/\[.+$/, '');
|
|
1383
|
-
let currentValue = pointer[currentKey]; // Resolve array notation
|
|
1384
|
-
|
|
1385
|
-
(_keys$i$match = keys[i].match(/\[\d+\]/g)) === null || _keys$i$match === void 0 ? void 0 : _keys$i$match.forEach(match => {
|
|
1386
|
-
const arrayIndex = parseInt(match.replace(/[[\]]/g, ''));
|
|
1387
|
-
|
|
1388
|
-
if (!Array.isArray(currentValue) || currentValue[arrayIndex] === undefined) {
|
|
1389
|
-
currentValue = undefined;
|
|
1390
|
-
} else {
|
|
1391
|
-
currentValue = currentValue[arrayIndex];
|
|
1392
|
-
}
|
|
1393
|
-
}); // Last node
|
|
1394
|
-
|
|
1395
|
-
if (i === keys.length - 1) {
|
|
1396
|
-
return currentValue; // Nested path
|
|
1397
|
-
} else if (currentValue !== undefined && isObject(currentValue)) {
|
|
1398
|
-
pointer = currentValue; // Invalid nested reference path
|
|
1399
|
-
} else {
|
|
1400
|
-
break;
|
|
1401
|
-
}
|
|
1402
1422
|
}
|
|
1403
1423
|
|
|
1404
|
-
return
|
|
1424
|
+
return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
|
|
1405
1425
|
}
|
|
1406
1426
|
|
|
1407
1427
|
let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
|
|
@@ -1412,10 +1432,13 @@ let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
|
|
|
1412
1432
|
})(DataType || (DataType = {}));
|
|
1413
1433
|
|
|
1414
1434
|
const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
|
|
1435
|
+
|
|
1436
|
+
const isComplexKey = key => key.indexOf('{') > -1;
|
|
1415
1437
|
/**
|
|
1416
1438
|
* Reference operand resolved within the context
|
|
1417
1439
|
*/
|
|
1418
1440
|
|
|
1441
|
+
|
|
1419
1442
|
class Reference extends Operand {
|
|
1420
1443
|
/**
|
|
1421
1444
|
* @constructor
|
|
@@ -1427,6 +1450,15 @@ class Reference extends Operand {
|
|
|
1427
1450
|
}
|
|
1428
1451
|
|
|
1429
1452
|
super();
|
|
1453
|
+
|
|
1454
|
+
_defineProperty(this, "key", void 0);
|
|
1455
|
+
|
|
1456
|
+
_defineProperty(this, "dataType", void 0);
|
|
1457
|
+
|
|
1458
|
+
_defineProperty(this, "valueLookup", void 0);
|
|
1459
|
+
|
|
1460
|
+
_defineProperty(this, "getKeys", void 0);
|
|
1461
|
+
|
|
1430
1462
|
this.key = key;
|
|
1431
1463
|
const dataTypeMatch = dataTypeRegex.exec(this.key);
|
|
1432
1464
|
|
|
@@ -1437,6 +1469,17 @@ class Reference extends Operand {
|
|
|
1437
1469
|
if (this.key.match(/.\(.+\)$/)) {
|
|
1438
1470
|
this.key = this.key.replace(/.\(.+\)$/, '');
|
|
1439
1471
|
}
|
|
1472
|
+
|
|
1473
|
+
if (isComplexKey(this.key)) {
|
|
1474
|
+
this.valueLookup = context => complexValueLookup(context, this.key);
|
|
1475
|
+
|
|
1476
|
+
this.getKeys = context => extractComplexKeys(context, this.key);
|
|
1477
|
+
} else {
|
|
1478
|
+
const keys = parseKey(this.key);
|
|
1479
|
+
this.valueLookup = simpleValueLookup(keys);
|
|
1480
|
+
|
|
1481
|
+
this.getKeys = () => keys;
|
|
1482
|
+
}
|
|
1440
1483
|
}
|
|
1441
1484
|
/**
|
|
1442
1485
|
* Evaluate in the given context.
|
|
@@ -1446,7 +1489,7 @@ class Reference extends Operand {
|
|
|
1446
1489
|
|
|
1447
1490
|
|
|
1448
1491
|
evaluate(ctx) {
|
|
1449
|
-
return this.toDataType(
|
|
1492
|
+
return this.toDataType(this.valueLookup(ctx));
|
|
1450
1493
|
}
|
|
1451
1494
|
/**
|
|
1452
1495
|
* {@link Evaluable.simplify}
|
|
@@ -1454,18 +1497,18 @@ class Reference extends Operand {
|
|
|
1454
1497
|
|
|
1455
1498
|
|
|
1456
1499
|
simplify(ctx, strictKeys, optionalKeys) {
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
if (!keys) {
|
|
1460
|
-
return this;
|
|
1461
|
-
}
|
|
1500
|
+
var _this$getKeys;
|
|
1462
1501
|
|
|
1463
|
-
const key =
|
|
1502
|
+
const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
|
|
1464
1503
|
|
|
1465
1504
|
if (ctx[key] !== undefined) {
|
|
1466
1505
|
return this.evaluate(ctx);
|
|
1467
1506
|
}
|
|
1468
1507
|
|
|
1508
|
+
if (!key || typeof key === 'number') {
|
|
1509
|
+
return this;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1469
1512
|
return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
|
|
1470
1513
|
}
|
|
1471
1514
|
/**
|
|
@@ -1567,6 +1610,10 @@ class Parser {
|
|
|
1567
1610
|
* @param {Options?} options Parser options.
|
|
1568
1611
|
*/
|
|
1569
1612
|
constructor(options) {
|
|
1613
|
+
_defineProperty(this, "opts", void 0);
|
|
1614
|
+
|
|
1615
|
+
_defineProperty(this, "expectedOperators", void 0);
|
|
1616
|
+
|
|
1570
1617
|
this.opts = { ...defaultOptions
|
|
1571
1618
|
}; // Apply exclusive options overrides
|
|
1572
1619
|
|
|
@@ -1776,10 +1823,6 @@ class Parser {
|
|
|
1776
1823
|
|
|
1777
1824
|
}
|
|
1778
1825
|
|
|
1779
|
-
/**
|
|
1780
|
-
* Main module.
|
|
1781
|
-
* @module illogical
|
|
1782
|
-
*/
|
|
1783
1826
|
/**
|
|
1784
1827
|
* Condition engine
|
|
1785
1828
|
*/
|
|
@@ -1790,6 +1833,8 @@ class Engine {
|
|
|
1790
1833
|
* @param {Options?} options Parser options.
|
|
1791
1834
|
*/
|
|
1792
1835
|
constructor(options) {
|
|
1836
|
+
_defineProperty(this, "parser", void 0);
|
|
1837
|
+
|
|
1793
1838
|
this.parser = new Parser(options);
|
|
1794
1839
|
}
|
|
1795
1840
|
/**
|
|
@@ -1856,4 +1901,4 @@ class Engine {
|
|
|
1856
1901
|
|
|
1857
1902
|
}
|
|
1858
1903
|
|
|
1859
|
-
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 };
|
|
1904
|
+
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 };
|
package/lib/illogical.js
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
+
function _defineProperty(obj, key, value) {
|
|
6
|
+
if (key in obj) {
|
|
7
|
+
Object.defineProperty(obj, key, {
|
|
8
|
+
value: value,
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true
|
|
12
|
+
});
|
|
13
|
+
} else {
|
|
14
|
+
obj[key] = value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return obj;
|
|
18
|
+
}
|
|
19
|
+
|
|
5
20
|
/**
|
|
6
21
|
* Is number predicate.
|
|
7
22
|
* @param value Tested value.
|
|
@@ -49,22 +64,7 @@ function isBoolean(value) {
|
|
|
49
64
|
*/
|
|
50
65
|
|
|
51
66
|
function isEvaluable(value) {
|
|
52
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function _defineProperty(obj, key, value) {
|
|
56
|
-
if (key in obj) {
|
|
57
|
-
Object.defineProperty(obj, key, {
|
|
58
|
-
value: value,
|
|
59
|
-
enumerable: true,
|
|
60
|
-
configurable: true,
|
|
61
|
-
writable: true
|
|
62
|
-
});
|
|
63
|
-
} else {
|
|
64
|
-
obj[key] = value;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return obj;
|
|
67
|
+
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
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
@@ -101,12 +101,12 @@ class Comparison {
|
|
|
101
101
|
* @param {Operand} right Right operand.
|
|
102
102
|
*/
|
|
103
103
|
constructor(operator, operatorSymbol, left, right) {
|
|
104
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
105
|
-
|
|
106
104
|
this.operator = operator;
|
|
107
105
|
this.operatorSymbol = operatorSymbol;
|
|
108
106
|
this.left = left;
|
|
109
107
|
this.right = right;
|
|
108
|
+
|
|
109
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
112
|
* {@link Evaluable.evaluate}
|
|
@@ -624,6 +624,9 @@ class Value extends Operand {
|
|
|
624
624
|
}
|
|
625
625
|
|
|
626
626
|
super();
|
|
627
|
+
|
|
628
|
+
_defineProperty(this, "value", void 0);
|
|
629
|
+
|
|
627
630
|
this.value = value;
|
|
628
631
|
}
|
|
629
632
|
/**
|
|
@@ -820,11 +823,11 @@ class Logical {
|
|
|
820
823
|
* @param {Evaluable[]} operands Collection of operands.
|
|
821
824
|
*/
|
|
822
825
|
constructor(operator, operatorSymbol, operands) {
|
|
823
|
-
_defineProperty(this, "type", EvaluableType.Expression);
|
|
824
|
-
|
|
825
826
|
this.operator = operator;
|
|
826
827
|
this.operatorSymbol = operatorSymbol;
|
|
827
828
|
this.operands = operands;
|
|
829
|
+
|
|
830
|
+
_defineProperty(this, "type", EvaluableType.Expression);
|
|
828
831
|
}
|
|
829
832
|
/**
|
|
830
833
|
* {@link Evaluable.evaluate}
|
|
@@ -1249,6 +1252,9 @@ class Collection extends Operand {
|
|
|
1249
1252
|
*/
|
|
1250
1253
|
constructor(items) {
|
|
1251
1254
|
super();
|
|
1255
|
+
|
|
1256
|
+
_defineProperty(this, "items", void 0);
|
|
1257
|
+
|
|
1252
1258
|
this.items = items;
|
|
1253
1259
|
}
|
|
1254
1260
|
/**
|
|
@@ -1336,13 +1342,39 @@ const toString = value => {
|
|
|
1336
1342
|
return undefined;
|
|
1337
1343
|
};
|
|
1338
1344
|
|
|
1339
|
-
|
|
1345
|
+
const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
|
|
1346
|
+
const arrayIndexRegex = /\[(\d+)]/g;
|
|
1347
|
+
|
|
1348
|
+
const parseKey = key => key.split('.').flatMap(key => {
|
|
1349
|
+
const parseResult = keyWithArrayIndexRegex.exec(key);
|
|
1350
|
+
const keys = [];
|
|
1351
|
+
|
|
1352
|
+
if (parseResult) {
|
|
1353
|
+
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
|
+
|
|
1358
|
+
if (rawIndexes) {
|
|
1359
|
+
for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
|
|
1360
|
+
keys.push(parseInt(indexResult[1]));
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
} else {
|
|
1364
|
+
keys.push(key);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
return keys;
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
const complexKeyExpression = /{([^{}]+)}/;
|
|
1371
|
+
|
|
1372
|
+
function extractComplexKeys(ctx, key) {
|
|
1340
1373
|
// Resolve complex keys
|
|
1341
|
-
const complexKeyExpression = /{([^{}]+)}/;
|
|
1342
1374
|
let complexKeyMatches = complexKeyExpression.exec(key);
|
|
1343
1375
|
|
|
1344
1376
|
while (complexKeyMatches) {
|
|
1345
|
-
const resolvedValue =
|
|
1377
|
+
const resolvedValue = complexValueLookup(ctx, complexKeyMatches[1]);
|
|
1346
1378
|
|
|
1347
1379
|
if (resolvedValue === undefined) {
|
|
1348
1380
|
return undefined;
|
|
@@ -1352,14 +1384,30 @@ function extractKeys(ctx, key) {
|
|
|
1352
1384
|
complexKeyMatches = complexKeyExpression.exec(key);
|
|
1353
1385
|
}
|
|
1354
1386
|
|
|
1355
|
-
|
|
1387
|
+
return parseKey(key);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
const isContext = value => isObject(value);
|
|
1391
|
+
|
|
1392
|
+
const simpleValueLookup = keys => ctx => {
|
|
1393
|
+
let pointer = ctx;
|
|
1356
1394
|
|
|
1357
|
-
|
|
1358
|
-
|
|
1395
|
+
for (const key of keys) {
|
|
1396
|
+
if (typeof key === 'number') {
|
|
1397
|
+
if (!Array.isArray(pointer)) {
|
|
1398
|
+
return undefined;
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
pointer = pointer[key];
|
|
1402
|
+
} else if (!isContext(pointer)) {
|
|
1403
|
+
return undefined;
|
|
1404
|
+
} else {
|
|
1405
|
+
pointer = pointer[key];
|
|
1406
|
+
}
|
|
1359
1407
|
}
|
|
1360
1408
|
|
|
1361
|
-
return
|
|
1362
|
-
}
|
|
1409
|
+
return pointer;
|
|
1410
|
+
};
|
|
1363
1411
|
/**
|
|
1364
1412
|
* Lookup for the reference in the context.
|
|
1365
1413
|
* The nested context value is annotated with "." delimiter.
|
|
@@ -1370,42 +1418,14 @@ function extractKeys(ctx, key) {
|
|
|
1370
1418
|
*/
|
|
1371
1419
|
|
|
1372
1420
|
|
|
1373
|
-
function
|
|
1374
|
-
const keys =
|
|
1421
|
+
function complexValueLookup(ctx, key) {
|
|
1422
|
+
const keys = extractComplexKeys(ctx, key);
|
|
1375
1423
|
|
|
1376
1424
|
if (!keys) {
|
|
1377
1425
|
return undefined;
|
|
1378
|
-
} // Context pointer
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
let pointer = ctx;
|
|
1382
|
-
|
|
1383
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1384
|
-
var _keys$i$match;
|
|
1385
|
-
|
|
1386
|
-
const currentKey = keys[i].replace(/\[.+$/, '');
|
|
1387
|
-
let currentValue = pointer[currentKey]; // Resolve array notation
|
|
1388
|
-
|
|
1389
|
-
(_keys$i$match = keys[i].match(/\[\d+\]/g)) === null || _keys$i$match === void 0 ? void 0 : _keys$i$match.forEach(match => {
|
|
1390
|
-
const arrayIndex = parseInt(match.replace(/[[\]]/g, ''));
|
|
1391
|
-
|
|
1392
|
-
if (!Array.isArray(currentValue) || currentValue[arrayIndex] === undefined) {
|
|
1393
|
-
currentValue = undefined;
|
|
1394
|
-
} else {
|
|
1395
|
-
currentValue = currentValue[arrayIndex];
|
|
1396
|
-
}
|
|
1397
|
-
}); // Last node
|
|
1398
|
-
|
|
1399
|
-
if (i === keys.length - 1) {
|
|
1400
|
-
return currentValue; // Nested path
|
|
1401
|
-
} else if (currentValue !== undefined && isObject(currentValue)) {
|
|
1402
|
-
pointer = currentValue; // Invalid nested reference path
|
|
1403
|
-
} else {
|
|
1404
|
-
break;
|
|
1405
|
-
}
|
|
1406
1426
|
}
|
|
1407
1427
|
|
|
1408
|
-
return
|
|
1428
|
+
return simpleValueLookup(keys !== null && keys !== void 0 ? keys : [])(ctx);
|
|
1409
1429
|
}
|
|
1410
1430
|
|
|
1411
1431
|
let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
|
|
@@ -1416,10 +1436,13 @@ let DataType; // Equivalent to /^.+\.\((Number|String)\)$/
|
|
|
1416
1436
|
})(DataType || (DataType = {}));
|
|
1417
1437
|
|
|
1418
1438
|
const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
|
|
1439
|
+
|
|
1440
|
+
const isComplexKey = key => key.indexOf('{') > -1;
|
|
1419
1441
|
/**
|
|
1420
1442
|
* Reference operand resolved within the context
|
|
1421
1443
|
*/
|
|
1422
1444
|
|
|
1445
|
+
|
|
1423
1446
|
class Reference extends Operand {
|
|
1424
1447
|
/**
|
|
1425
1448
|
* @constructor
|
|
@@ -1431,6 +1454,15 @@ class Reference extends Operand {
|
|
|
1431
1454
|
}
|
|
1432
1455
|
|
|
1433
1456
|
super();
|
|
1457
|
+
|
|
1458
|
+
_defineProperty(this, "key", void 0);
|
|
1459
|
+
|
|
1460
|
+
_defineProperty(this, "dataType", void 0);
|
|
1461
|
+
|
|
1462
|
+
_defineProperty(this, "valueLookup", void 0);
|
|
1463
|
+
|
|
1464
|
+
_defineProperty(this, "getKeys", void 0);
|
|
1465
|
+
|
|
1434
1466
|
this.key = key;
|
|
1435
1467
|
const dataTypeMatch = dataTypeRegex.exec(this.key);
|
|
1436
1468
|
|
|
@@ -1441,6 +1473,17 @@ class Reference extends Operand {
|
|
|
1441
1473
|
if (this.key.match(/.\(.+\)$/)) {
|
|
1442
1474
|
this.key = this.key.replace(/.\(.+\)$/, '');
|
|
1443
1475
|
}
|
|
1476
|
+
|
|
1477
|
+
if (isComplexKey(this.key)) {
|
|
1478
|
+
this.valueLookup = context => complexValueLookup(context, this.key);
|
|
1479
|
+
|
|
1480
|
+
this.getKeys = context => extractComplexKeys(context, this.key);
|
|
1481
|
+
} else {
|
|
1482
|
+
const keys = parseKey(this.key);
|
|
1483
|
+
this.valueLookup = simpleValueLookup(keys);
|
|
1484
|
+
|
|
1485
|
+
this.getKeys = () => keys;
|
|
1486
|
+
}
|
|
1444
1487
|
}
|
|
1445
1488
|
/**
|
|
1446
1489
|
* Evaluate in the given context.
|
|
@@ -1450,7 +1493,7 @@ class Reference extends Operand {
|
|
|
1450
1493
|
|
|
1451
1494
|
|
|
1452
1495
|
evaluate(ctx) {
|
|
1453
|
-
return this.toDataType(
|
|
1496
|
+
return this.toDataType(this.valueLookup(ctx));
|
|
1454
1497
|
}
|
|
1455
1498
|
/**
|
|
1456
1499
|
* {@link Evaluable.simplify}
|
|
@@ -1458,18 +1501,18 @@ class Reference extends Operand {
|
|
|
1458
1501
|
|
|
1459
1502
|
|
|
1460
1503
|
simplify(ctx, strictKeys, optionalKeys) {
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
if (!keys) {
|
|
1464
|
-
return this;
|
|
1465
|
-
}
|
|
1504
|
+
var _this$getKeys;
|
|
1466
1505
|
|
|
1467
|
-
const key =
|
|
1506
|
+
const [key] = (_this$getKeys = this.getKeys(ctx)) !== null && _this$getKeys !== void 0 ? _this$getKeys : [];
|
|
1468
1507
|
|
|
1469
1508
|
if (ctx[key] !== undefined) {
|
|
1470
1509
|
return this.evaluate(ctx);
|
|
1471
1510
|
}
|
|
1472
1511
|
|
|
1512
|
+
if (!key || typeof key === 'number') {
|
|
1513
|
+
return this;
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1473
1516
|
return strictKeys && strictKeys.includes(key) || optionalKeys && !optionalKeys.includes(key) ? undefined : this;
|
|
1474
1517
|
}
|
|
1475
1518
|
/**
|
|
@@ -1571,6 +1614,10 @@ class Parser {
|
|
|
1571
1614
|
* @param {Options?} options Parser options.
|
|
1572
1615
|
*/
|
|
1573
1616
|
constructor(options) {
|
|
1617
|
+
_defineProperty(this, "opts", void 0);
|
|
1618
|
+
|
|
1619
|
+
_defineProperty(this, "expectedOperators", void 0);
|
|
1620
|
+
|
|
1574
1621
|
this.opts = { ...defaultOptions
|
|
1575
1622
|
}; // Apply exclusive options overrides
|
|
1576
1623
|
|
|
@@ -1780,10 +1827,6 @@ class Parser {
|
|
|
1780
1827
|
|
|
1781
1828
|
}
|
|
1782
1829
|
|
|
1783
|
-
/**
|
|
1784
|
-
* Main module.
|
|
1785
|
-
* @module illogical
|
|
1786
|
-
*/
|
|
1787
1830
|
/**
|
|
1788
1831
|
* Condition engine
|
|
1789
1832
|
*/
|
|
@@ -1794,6 +1837,8 @@ class Engine {
|
|
|
1794
1837
|
* @param {Options?} options Parser options.
|
|
1795
1838
|
*/
|
|
1796
1839
|
constructor(options) {
|
|
1840
|
+
_defineProperty(this, "parser", void 0);
|
|
1841
|
+
|
|
1797
1842
|
this.parser = new Parser(options);
|
|
1798
1843
|
}
|
|
1799
1844
|
/**
|
|
@@ -1879,3 +1924,5 @@ exports.OPERATOR_SUFFIX = OPERATOR$6;
|
|
|
1879
1924
|
exports.OPERATOR_UNDEFINED = OPERATOR$5;
|
|
1880
1925
|
exports.OPERATOR_XOR = OPERATOR;
|
|
1881
1926
|
exports["default"] = Engine;
|
|
1927
|
+
exports.defaultOptions = defaultOptions;
|
|
1928
|
+
exports.isEvaluable = isEvaluable;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@briza/illogical",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.5",
|
|
4
4
|
"description": "A micro conditional javascript engine used to parse the raw logical and comparison expressions, evaluate the expression in the given data context, and provide access to a text form of the given expressions.",
|
|
5
5
|
"main": "lib/illogical.js",
|
|
6
6
|
"module": "lib/illogical.esm.js",
|
|
@@ -42,31 +42,31 @@
|
|
|
42
42
|
"rules"
|
|
43
43
|
],
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@babel/core": "^7.
|
|
45
|
+
"@babel/core": "^7.17.9",
|
|
46
46
|
"@babel/plugin-proposal-class-properties": "^7.16.7",
|
|
47
47
|
"@babel/preset-env": "^7.16.11",
|
|
48
48
|
"@babel/preset-typescript": "^7.16.7",
|
|
49
|
-
"@rollup/plugin-babel": "^5.
|
|
50
|
-
"@rollup/plugin-commonjs": "^21.0.
|
|
51
|
-
"@rollup/plugin-node-resolve": "^13.
|
|
52
|
-
"@types/jest": "^27.4.
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
54
|
-
"@typescript-eslint/parser": "^5.
|
|
55
|
-
"eslint": "^8.
|
|
56
|
-
"eslint-config-prettier": "^8.
|
|
57
|
-
"eslint-import-resolver-typescript": "^2.
|
|
58
|
-
"eslint-plugin-import": "^2.
|
|
49
|
+
"@rollup/plugin-babel": "^5.3.1",
|
|
50
|
+
"@rollup/plugin-commonjs": "^21.0.3",
|
|
51
|
+
"@rollup/plugin-node-resolve": "^13.2.0",
|
|
52
|
+
"@types/jest": "^27.4.1",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
|
54
|
+
"@typescript-eslint/parser": "^5.19.0",
|
|
55
|
+
"eslint": "^8.13.0",
|
|
56
|
+
"eslint-config-prettier": "^8.5.0",
|
|
57
|
+
"eslint-import-resolver-typescript": "^2.7.1",
|
|
58
|
+
"eslint-plugin-import": "^2.26.0",
|
|
59
59
|
"eslint-plugin-node": "^11.1.0",
|
|
60
60
|
"eslint-plugin-prettier": "^3.4.1",
|
|
61
61
|
"eslint-plugin-promise": "^6.0.0",
|
|
62
62
|
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
63
|
-
"jest": "^27.
|
|
63
|
+
"jest": "^27.5.1",
|
|
64
64
|
"license-checker": "^25.0.1",
|
|
65
|
-
"prettier": "^2.
|
|
66
|
-
"rollup": "^2.
|
|
65
|
+
"prettier": "^2.6.2",
|
|
66
|
+
"rollup": "^2.70.1",
|
|
67
67
|
"rollup-plugin-eslint": "^7.0.0",
|
|
68
|
-
"ts-jest": "^27.1.
|
|
69
|
-
"typedoc": "^0.22.
|
|
70
|
-
"typescript": "
|
|
68
|
+
"ts-jest": "^27.1.4",
|
|
69
|
+
"typedoc": "^0.22.15",
|
|
70
|
+
"typescript": "4.6.3"
|
|
71
71
|
}
|
|
72
72
|
}
|
package/readme.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
A micro conditional javascript engine used to parse the raw logical and comparison expressions, evaluate the expression in the given data context, and provide access to a text form of the given expressions.
|
|
4
4
|
|
|
5
|
-
> Revision:
|
|
5
|
+
> Revision: March 22, 2022.
|
|
6
6
|
|
|
7
7
|
## About
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ export interface Context {
|
|
|
15
15
|
/**
|
|
16
16
|
* Evaluation result
|
|
17
17
|
*/
|
|
18
|
-
export declare type Result = undefined | null | string | number | boolean | Array<Result>;
|
|
18
|
+
export declare type Result = undefined | null | string | number | boolean | Array<Result> | Record<string, unknown>;
|
|
19
19
|
export declare enum EvaluableType {
|
|
20
20
|
Operand = "Operand",
|
|
21
21
|
Expression = "Expression"
|
package/types/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* @module illogical
|
|
4
4
|
*/
|
|
5
5
|
import { Context, Evaluable } from './common/evaluable';
|
|
6
|
+
import { isEvaluable } from './common/type-check';
|
|
6
7
|
import { OPERATOR as OPERATOR_EQ } from './expression/comparison/eq';
|
|
7
8
|
import { OPERATOR as OPERATOR_GE } from './expression/comparison/ge';
|
|
8
9
|
import { OPERATOR as OPERATOR_GT } from './expression/comparison/gt';
|
|
@@ -23,7 +24,8 @@ import { OPERATOR as OPERATOR_OR } from './expression/logical/or';
|
|
|
23
24
|
import { OPERATOR as OPERATOR_XOR } from './expression/logical/xor';
|
|
24
25
|
import { ExpressionInput, Input } from './parser';
|
|
25
26
|
import { Options } from './parser/options';
|
|
26
|
-
export {
|
|
27
|
+
export { defaultOptions } from './parser/options';
|
|
28
|
+
export { isEvaluable, OPERATOR_EQ, OPERATOR_NE, OPERATOR_GT, OPERATOR_GE, OPERATOR_LT, OPERATOR_LE, OPERATOR_IN, OPERATOR_NOT_IN, OPERATOR_PREFIX, OPERATOR_SUFFIX, OPERATOR_OVERLAP, OPERATOR_UNDEFINED, OPERATOR_PRESENT, OPERATOR_AND, OPERATOR_OR, OPERATOR_NOR, OPERATOR_XOR, OPERATOR_NOT, };
|
|
27
29
|
/**
|
|
28
30
|
* Condition engine
|
|
29
31
|
*/
|
|
@@ -11,6 +11,8 @@ export declare enum DataType {
|
|
|
11
11
|
export declare class Reference extends Operand {
|
|
12
12
|
private readonly key;
|
|
13
13
|
private readonly dataType;
|
|
14
|
+
private readonly valueLookup;
|
|
15
|
+
private readonly getKeys;
|
|
14
16
|
/**
|
|
15
17
|
* @constructor
|
|
16
18
|
* @param {string} key Context key.
|