@briza/illogical 1.7.0 → 1.7.1
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 +4 -0
- package/lib/illogical.esm.js +47 -28
- package/lib/illogical.js +47 -28
- package/package.json +1 -1
- package/readme.md +0 -2
- package/types/parser/index.d.ts +3 -0
package/changelog.md
CHANGED
package/lib/illogical.esm.js
CHANGED
|
@@ -472,29 +472,33 @@ const toDateNumber = value => {
|
|
|
472
472
|
|
|
473
473
|
const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
|
|
474
474
|
const arrayIndexRegex = /\[(\d+)]/g;
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
}
|
|
475
|
+
function parseBacktickWrappedKey(key) {
|
|
476
|
+
return key[0] === '`' && key[key.length - 1] === '`' ? key.slice(1, -1) : key;
|
|
477
|
+
}
|
|
478
|
+
function parseKeyComponents(key) {
|
|
479
|
+
const unwrappedKey = parseBacktickWrappedKey(key);
|
|
480
|
+
const keys = [];
|
|
481
|
+
const parseResult = keyWithArrayIndexRegex.exec(unwrappedKey);
|
|
482
|
+
if (parseResult) {
|
|
483
|
+
var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
|
|
484
|
+
const extractedKey = parseBacktickWrappedKey((_parseResult$groups$c = parseResult === null || parseResult === void 0 || (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : unwrappedKey);
|
|
485
|
+
keys.push(extractedKey);
|
|
486
|
+
const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
|
|
487
|
+
if (rawIndexes) {
|
|
488
|
+
for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
|
|
489
|
+
keys.push(parseInt(indexResult[1]));
|
|
491
490
|
}
|
|
492
|
-
} else {
|
|
493
|
-
keys.push(unwrappedKey);
|
|
494
491
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
}
|
|
492
|
+
} else {
|
|
493
|
+
keys.push(unwrappedKey);
|
|
494
|
+
}
|
|
495
|
+
return keys;
|
|
496
|
+
}
|
|
497
|
+
const parseKeyRegex = /(`[^[\]]+`(\[\d+\])*|[^`.]+)/g;
|
|
498
|
+
function parseKey(key) {
|
|
499
|
+
const keys = key.match(parseKeyRegex);
|
|
500
|
+
return !keys ? [] : keys.flatMap(parseKeyComponents);
|
|
501
|
+
}
|
|
498
502
|
const complexKeyExpression = /{([^{}]+)}/;
|
|
499
503
|
function extractComplexKeys(ctx, key) {
|
|
500
504
|
// Resolve complex keys
|
|
@@ -551,6 +555,7 @@ let DataType = /*#__PURE__*/function (DataType) {
|
|
|
551
555
|
// Equivalent to /^.+\.\((Number|String)\)$/
|
|
552
556
|
const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
|
|
553
557
|
const isComplexKey = key => key.indexOf('{') > -1;
|
|
558
|
+
const castingRegex = /\.\(.+\)$/;
|
|
554
559
|
|
|
555
560
|
/**
|
|
556
561
|
* Reference operand resolved within the context
|
|
@@ -573,9 +578,7 @@ class Reference extends Operand {
|
|
|
573
578
|
const dataTypeMatch = dataTypeRegex.exec(this.key);
|
|
574
579
|
if (dataTypeMatch) {
|
|
575
580
|
this.dataType = DataType[dataTypeMatch[1]];
|
|
576
|
-
|
|
577
|
-
if (this.key.match(/.\(.+\)$/)) {
|
|
578
|
-
this.key = this.key.replace(/.\(.+\)$/, '');
|
|
581
|
+
this.key = this.key.replace(castingRegex, '');
|
|
579
582
|
}
|
|
580
583
|
if (isComplexKey(this.key)) {
|
|
581
584
|
this.valueLookup = context => complexValueLookup(context, this.key);
|
|
@@ -1690,7 +1693,7 @@ class Collection extends Operand {
|
|
|
1690
1693
|
* @return {boolean}
|
|
1691
1694
|
*/
|
|
1692
1695
|
function defaultReferencePredicate(key) {
|
|
1693
|
-
return
|
|
1696
|
+
return key[0] === '$';
|
|
1694
1697
|
}
|
|
1695
1698
|
|
|
1696
1699
|
/**
|
|
@@ -1748,6 +1751,7 @@ class Parser {
|
|
|
1748
1751
|
_defineProperty(this, "opts", void 0);
|
|
1749
1752
|
_defineProperty(this, "expectedRootOperators", void 0);
|
|
1750
1753
|
_defineProperty(this, "unexpectedRootSymbols", new Set([OPERATOR$i, OPERATOR$j, OPERATOR$k, OPERATOR$l]));
|
|
1754
|
+
_defineProperty(this, "referenceCache", new Map());
|
|
1751
1755
|
this.opts = {
|
|
1752
1756
|
...defaultOptions
|
|
1753
1757
|
};
|
|
@@ -1769,6 +1773,18 @@ class Parser {
|
|
|
1769
1773
|
get options() {
|
|
1770
1774
|
return this.opts;
|
|
1771
1775
|
}
|
|
1776
|
+
getReference(key) {
|
|
1777
|
+
const cached = this.referenceCache.get(key);
|
|
1778
|
+
if (cached !== undefined) {
|
|
1779
|
+
return cached;
|
|
1780
|
+
}
|
|
1781
|
+
const reference = new Reference(this.opts.referenceTransform(key));
|
|
1782
|
+
this.referenceCache.set(key, reference);
|
|
1783
|
+
return reference;
|
|
1784
|
+
}
|
|
1785
|
+
resolve(raw) {
|
|
1786
|
+
return isString(raw) && this.opts.referencePredicate(raw) ? this.getReference(raw) : new Value(raw);
|
|
1787
|
+
}
|
|
1772
1788
|
|
|
1773
1789
|
/**
|
|
1774
1790
|
* Parse raw expression into evaluable expression.
|
|
@@ -1927,11 +1943,14 @@ class Parser {
|
|
|
1927
1943
|
* @param raw Raw data
|
|
1928
1944
|
*/
|
|
1929
1945
|
getOperand(raw) {
|
|
1930
|
-
const resolve = raw => this.opts.referencePredicate(raw) ? new Reference(this.opts.referenceTransform(raw)) : new Value(raw);
|
|
1931
1946
|
if (Array.isArray(raw)) {
|
|
1932
|
-
|
|
1947
|
+
const collectionItems = [];
|
|
1948
|
+
for (const item of raw) {
|
|
1949
|
+
collectionItems.push(this.resolve(item));
|
|
1950
|
+
}
|
|
1951
|
+
return new Collection(collectionItems);
|
|
1933
1952
|
}
|
|
1934
|
-
return resolve(raw);
|
|
1953
|
+
return this.resolve(raw);
|
|
1935
1954
|
}
|
|
1936
1955
|
}
|
|
1937
1956
|
|
package/lib/illogical.js
CHANGED
|
@@ -476,29 +476,33 @@ const toDateNumber = value => {
|
|
|
476
476
|
|
|
477
477
|
const keyWithArrayIndexRegex = /^(?<currentKey>[^[\]]+?)(?<indexes>(?:\[\d+])+)?$/;
|
|
478
478
|
const arrayIndexRegex = /\[(\d+)]/g;
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
}
|
|
479
|
+
function parseBacktickWrappedKey(key) {
|
|
480
|
+
return key[0] === '`' && key[key.length - 1] === '`' ? key.slice(1, -1) : key;
|
|
481
|
+
}
|
|
482
|
+
function parseKeyComponents(key) {
|
|
483
|
+
const unwrappedKey = parseBacktickWrappedKey(key);
|
|
484
|
+
const keys = [];
|
|
485
|
+
const parseResult = keyWithArrayIndexRegex.exec(unwrappedKey);
|
|
486
|
+
if (parseResult) {
|
|
487
|
+
var _parseResult$groups$c, _parseResult$groups, _parseResult$groups2;
|
|
488
|
+
const extractedKey = parseBacktickWrappedKey((_parseResult$groups$c = parseResult === null || parseResult === void 0 || (_parseResult$groups = parseResult.groups) === null || _parseResult$groups === void 0 ? void 0 : _parseResult$groups.currentKey) !== null && _parseResult$groups$c !== void 0 ? _parseResult$groups$c : unwrappedKey);
|
|
489
|
+
keys.push(extractedKey);
|
|
490
|
+
const rawIndexes = parseResult === null || parseResult === void 0 || (_parseResult$groups2 = parseResult.groups) === null || _parseResult$groups2 === void 0 ? void 0 : _parseResult$groups2.indexes;
|
|
491
|
+
if (rawIndexes) {
|
|
492
|
+
for (const indexResult of rawIndexes.matchAll(arrayIndexRegex)) {
|
|
493
|
+
keys.push(parseInt(indexResult[1]));
|
|
495
494
|
}
|
|
496
|
-
} else {
|
|
497
|
-
keys.push(unwrappedKey);
|
|
498
495
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
496
|
+
} else {
|
|
497
|
+
keys.push(unwrappedKey);
|
|
498
|
+
}
|
|
499
|
+
return keys;
|
|
500
|
+
}
|
|
501
|
+
const parseKeyRegex = /(`[^[\]]+`(\[\d+\])*|[^`.]+)/g;
|
|
502
|
+
function parseKey(key) {
|
|
503
|
+
const keys = key.match(parseKeyRegex);
|
|
504
|
+
return !keys ? [] : keys.flatMap(parseKeyComponents);
|
|
505
|
+
}
|
|
502
506
|
const complexKeyExpression = /{([^{}]+)}/;
|
|
503
507
|
function extractComplexKeys(ctx, key) {
|
|
504
508
|
// Resolve complex keys
|
|
@@ -555,6 +559,7 @@ let DataType = /*#__PURE__*/function (DataType) {
|
|
|
555
559
|
// Equivalent to /^.+\.\((Number|String)\)$/
|
|
556
560
|
const dataTypeRegex = new RegExp(`^.+\\.\\((${Object.keys(DataType).join('|')})\\)$`);
|
|
557
561
|
const isComplexKey = key => key.indexOf('{') > -1;
|
|
562
|
+
const castingRegex = /\.\(.+\)$/;
|
|
558
563
|
|
|
559
564
|
/**
|
|
560
565
|
* Reference operand resolved within the context
|
|
@@ -577,9 +582,7 @@ class Reference extends Operand {
|
|
|
577
582
|
const dataTypeMatch = dataTypeRegex.exec(this.key);
|
|
578
583
|
if (dataTypeMatch) {
|
|
579
584
|
this.dataType = DataType[dataTypeMatch[1]];
|
|
580
|
-
|
|
581
|
-
if (this.key.match(/.\(.+\)$/)) {
|
|
582
|
-
this.key = this.key.replace(/.\(.+\)$/, '');
|
|
585
|
+
this.key = this.key.replace(castingRegex, '');
|
|
583
586
|
}
|
|
584
587
|
if (isComplexKey(this.key)) {
|
|
585
588
|
this.valueLookup = context => complexValueLookup(context, this.key);
|
|
@@ -1694,7 +1697,7 @@ class Collection extends Operand {
|
|
|
1694
1697
|
* @return {boolean}
|
|
1695
1698
|
*/
|
|
1696
1699
|
function defaultReferencePredicate(key) {
|
|
1697
|
-
return
|
|
1700
|
+
return key[0] === '$';
|
|
1698
1701
|
}
|
|
1699
1702
|
|
|
1700
1703
|
/**
|
|
@@ -1752,6 +1755,7 @@ class Parser {
|
|
|
1752
1755
|
_defineProperty(this, "opts", void 0);
|
|
1753
1756
|
_defineProperty(this, "expectedRootOperators", void 0);
|
|
1754
1757
|
_defineProperty(this, "unexpectedRootSymbols", new Set([OPERATOR$i, OPERATOR$j, OPERATOR$k, OPERATOR$l]));
|
|
1758
|
+
_defineProperty(this, "referenceCache", new Map());
|
|
1755
1759
|
this.opts = {
|
|
1756
1760
|
...defaultOptions
|
|
1757
1761
|
};
|
|
@@ -1773,6 +1777,18 @@ class Parser {
|
|
|
1773
1777
|
get options() {
|
|
1774
1778
|
return this.opts;
|
|
1775
1779
|
}
|
|
1780
|
+
getReference(key) {
|
|
1781
|
+
const cached = this.referenceCache.get(key);
|
|
1782
|
+
if (cached !== undefined) {
|
|
1783
|
+
return cached;
|
|
1784
|
+
}
|
|
1785
|
+
const reference = new Reference(this.opts.referenceTransform(key));
|
|
1786
|
+
this.referenceCache.set(key, reference);
|
|
1787
|
+
return reference;
|
|
1788
|
+
}
|
|
1789
|
+
resolve(raw) {
|
|
1790
|
+
return isString(raw) && this.opts.referencePredicate(raw) ? this.getReference(raw) : new Value(raw);
|
|
1791
|
+
}
|
|
1776
1792
|
|
|
1777
1793
|
/**
|
|
1778
1794
|
* Parse raw expression into evaluable expression.
|
|
@@ -1931,11 +1947,14 @@ class Parser {
|
|
|
1931
1947
|
* @param raw Raw data
|
|
1932
1948
|
*/
|
|
1933
1949
|
getOperand(raw) {
|
|
1934
|
-
const resolve = raw => this.opts.referencePredicate(raw) ? new Reference(this.opts.referenceTransform(raw)) : new Value(raw);
|
|
1935
1950
|
if (Array.isArray(raw)) {
|
|
1936
|
-
|
|
1951
|
+
const collectionItems = [];
|
|
1952
|
+
for (const item of raw) {
|
|
1953
|
+
collectionItems.push(this.resolve(item));
|
|
1954
|
+
}
|
|
1955
|
+
return new Collection(collectionItems);
|
|
1937
1956
|
}
|
|
1938
|
-
return resolve(raw);
|
|
1957
|
+
return this.resolve(raw);
|
|
1939
1958
|
}
|
|
1940
1959
|
}
|
|
1941
1960
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@briza/illogical",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.1",
|
|
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",
|
package/readme.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
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: March 22, 2022.
|
|
6
|
-
|
|
7
5
|
## About
|
|
8
6
|
|
|
9
7
|
This project has been developed to provide a shared conditional logic between front-end and back-end code, stored in JSON or in any other data serialization format.
|
package/types/parser/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare class Parser {
|
|
|
10
10
|
private readonly opts;
|
|
11
11
|
private readonly expectedRootOperators;
|
|
12
12
|
private readonly unexpectedRootSymbols;
|
|
13
|
+
private readonly referenceCache;
|
|
13
14
|
/**
|
|
14
15
|
* @constructor
|
|
15
16
|
* @param {Options?} options Parser options.
|
|
@@ -20,6 +21,8 @@ export declare class Parser {
|
|
|
20
21
|
* @type {Options}
|
|
21
22
|
*/
|
|
22
23
|
get options(): Options;
|
|
24
|
+
private getReference;
|
|
25
|
+
private resolve;
|
|
23
26
|
/**
|
|
24
27
|
* Parse raw expression into evaluable expression.
|
|
25
28
|
* @param {ExpressionInput} raw Raw expression.
|