@legalplace/lplogic 2.3.0 → 2.3.2-staging.0
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/.gitlab-automator +7 -0
- package/.gitlab-ci.yml +1 -0
- package/.vscode/settings.json +4 -5
- package/CHANGELOG.md +7 -0
- package/dist/LpLogic.js +156 -8
- package/dist/Parser.js +6 -6
- package/dist/definitions/model-v1-schema.d.ts +4 -4
- package/jest.config.js +9 -12
- package/package.json +12 -9
- package/tests/LpLogic.test.ts +153 -27
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
GITLAB_PRIVATE_TOKEN=glpat-BOv5W1i6MoAAvHjzkmc5nW86MQp1OjkH.01.0w119catf
|
|
2
|
+
GITLAB_BASE_URL=https://git.legalplace.eu
|
|
3
|
+
GITLAB_API_PROJECT_ID=28
|
|
4
|
+
GITLAB_USER_ID=9
|
|
5
|
+
CURRENT_PROJECT_ID=39
|
|
6
|
+
SLACK_USER_ID=U0B3SNBV3
|
|
7
|
+
CLICKUP_PRIVATE_TOKEN=pk_32519579_K5W4L4KEVXY03A3D2WFA46D07HVGTL5L
|
package/.gitlab-ci.yml
CHANGED
package/.vscode/settings.json
CHANGED
|
@@ -14,10 +14,9 @@
|
|
|
14
14
|
"files.autoSave": "onFocusChange",
|
|
15
15
|
"editor.formatOnSave": false,
|
|
16
16
|
"editor.formatOnType": true,
|
|
17
|
-
"prettier.singleQuote": true,
|
|
18
|
-
"eslint.packageManager": "yarn",
|
|
19
17
|
"eslint.quiet": true,
|
|
20
18
|
"editor.codeActionsOnSave": {
|
|
21
|
-
"source.fixAll.eslint":
|
|
22
|
-
}
|
|
23
|
-
|
|
19
|
+
"source.fixAll.eslint": "explicit"
|
|
20
|
+
},
|
|
21
|
+
"typescript.tsdk": "node_modules/typescript/lib"
|
|
22
|
+
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [2.3.1](https://git.legalplace.eu/legalplace/lplogic/compare/v2.3.0...v2.3.1) (2024-01-12)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* delete trim when check with regex operator ([e437be5](https://git.legalplace.eu/legalplace/lplogic/commit/e437be5f936cd5cd92fcf25fa97dc5b6491b6012))
|
|
11
|
+
|
|
5
12
|
## [2.3.0](https://git.legalplace.eu/legalplace/lplogic/compare/v2.2.0...v2.3.0) (2024-01-09)
|
|
6
13
|
|
|
7
14
|
|
package/dist/LpLogic.js
CHANGED
|
@@ -6,9 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
var json_logic_js_1 = __importDefault(require("@legalplace/json-logic-js"));
|
|
7
7
|
var reduceParents = function (parents, length) {
|
|
8
8
|
var reducedParents = [];
|
|
9
|
-
parents.
|
|
9
|
+
var safeParents = parents.filter(function (entry) { return Array.isArray(entry); });
|
|
10
|
+
safeParents.sort(function (a, b) { return b.length - a.length; });
|
|
10
11
|
var _loop_1 = function (index) {
|
|
11
|
-
var currentIndexResult =
|
|
12
|
+
var currentIndexResult = safeParents.reduce(function (previousValue, currentValue) {
|
|
12
13
|
if (currentValue.length === 1)
|
|
13
14
|
return previousValue && currentValue[0];
|
|
14
15
|
if (currentValue[index] === undefined)
|
|
@@ -23,7 +24,7 @@ var reduceParents = function (parents, length) {
|
|
|
23
24
|
return reducedParents;
|
|
24
25
|
};
|
|
25
26
|
var reduceValues = function (values, parents, compareFunction) {
|
|
26
|
-
if (parents
|
|
27
|
+
if (!Array.isArray(parents) || parents.length === 0) {
|
|
27
28
|
return values.map(function (currentValue) {
|
|
28
29
|
return compareFunction(currentValue, true);
|
|
29
30
|
});
|
|
@@ -141,7 +142,6 @@ var is = function (values, comparator, parents) {
|
|
|
141
142
|
return reducedValues.length === filter.length;
|
|
142
143
|
};
|
|
143
144
|
json_logic_js_1.default.add_operation("is", is);
|
|
144
|
-
json_logic_js_1.default.add_operation("contains", is);
|
|
145
145
|
var not = function (values, comparator, parents) {
|
|
146
146
|
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
147
147
|
var cleanValue = (typeof value === "number"
|
|
@@ -156,7 +156,52 @@ var not = function (values, comparator, parents) {
|
|
|
156
156
|
return reducedValues.length === filter.length;
|
|
157
157
|
};
|
|
158
158
|
json_logic_js_1.default.add_operation("not", not);
|
|
159
|
-
|
|
159
|
+
var contains = function (values, comparator, parents) {
|
|
160
|
+
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
161
|
+
if (Array.isArray(value)) {
|
|
162
|
+
return value.some(function (val) {
|
|
163
|
+
return (typeof val === "string" ? val.trim() : val.toString())
|
|
164
|
+
.toLowerCase()
|
|
165
|
+
.includes((typeof comparator === "string"
|
|
166
|
+
? comparator.trim()
|
|
167
|
+
: comparator.toString()).toLowerCase()) && parent;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
var cleanValue = (typeof value === "number" ? value.toString() : value.trim()).toLowerCase();
|
|
172
|
+
var cleanComparator = (typeof comparator === "number"
|
|
173
|
+
? comparator.toString()
|
|
174
|
+
: comparator.trim()).toLowerCase();
|
|
175
|
+
return cleanValue.includes(cleanComparator) && parent;
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
var filter = reducedValues.filter(function (value) { return value === true; });
|
|
179
|
+
return reducedValues.length === filter.length;
|
|
180
|
+
};
|
|
181
|
+
json_logic_js_1.default.add_operation("contains", contains);
|
|
182
|
+
var doesNotContain = function (values, comparator, parents) {
|
|
183
|
+
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
184
|
+
if (Array.isArray(value)) {
|
|
185
|
+
return value.every(function (val) {
|
|
186
|
+
return !(typeof val === "string" ? val.trim() : val.toString())
|
|
187
|
+
.toLowerCase()
|
|
188
|
+
.includes((typeof comparator === "string"
|
|
189
|
+
? comparator.trim()
|
|
190
|
+
: comparator.toString()).toLowerCase()) && parent;
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
var cleanValue = (typeof value === "number" ? value.toString() : value.trim()).toLowerCase();
|
|
195
|
+
var cleanComparator = (typeof comparator === "number"
|
|
196
|
+
? comparator.toString()
|
|
197
|
+
: comparator.trim()).toLowerCase();
|
|
198
|
+
return !cleanValue.includes(cleanComparator) && parent;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
var filter = reducedValues.filter(function (value) { return value === true; });
|
|
202
|
+
return reducedValues.length === filter.length;
|
|
203
|
+
};
|
|
204
|
+
json_logic_js_1.default.add_operation("does-not-contain", doesNotContain);
|
|
160
205
|
json_logic_js_1.default.add_operation("empty", function (values, comparator, parents) {
|
|
161
206
|
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
162
207
|
var stringValue = typeof value === "number" ? value.toString() : value;
|
|
@@ -181,7 +226,7 @@ var like = function (values, comparator, parents) {
|
|
|
181
226
|
var cleanComparator = (typeof comparator === "number"
|
|
182
227
|
? comparator.toString()
|
|
183
228
|
: comparator.trim()).toLowerCase();
|
|
184
|
-
return (new RegExp("( |^)"
|
|
229
|
+
return (new RegExp("( |^)".concat(cleanComparator, "( |$)"), "i").test(cleanValue) && parent);
|
|
185
230
|
});
|
|
186
231
|
var filter = reducedValues.filter(function (_value) { return _value === true; });
|
|
187
232
|
return reducedValues.length === filter.length;
|
|
@@ -195,7 +240,7 @@ var notLike = function (values, comparator, parents) {
|
|
|
195
240
|
var cleanComparator = (typeof comparator === "number"
|
|
196
241
|
? comparator.toString()
|
|
197
242
|
: comparator.trim()).toLowerCase();
|
|
198
|
-
return (!new RegExp("( |^)"
|
|
243
|
+
return (!new RegExp("( |^)".concat(cleanComparator, "( |$)"), "i").test(cleanValue) &&
|
|
199
244
|
parent);
|
|
200
245
|
});
|
|
201
246
|
var filter = reducedValues.filter(function (_value) { return _value === true; });
|
|
@@ -204,7 +249,7 @@ var notLike = function (values, comparator, parents) {
|
|
|
204
249
|
json_logic_js_1.default.add_operation("not-like", notLike);
|
|
205
250
|
var regexMatch = function (values, comparator, parents) {
|
|
206
251
|
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
207
|
-
var cleanValue = typeof value === "number" ? value.toString() : value
|
|
252
|
+
var cleanValue = typeof value === "number" ? value.toString() : value;
|
|
208
253
|
var regex;
|
|
209
254
|
if (typeof comparator === 'string') {
|
|
210
255
|
try {
|
|
@@ -226,5 +271,108 @@ var regexMatch = function (values, comparator, parents) {
|
|
|
226
271
|
return reducedValues.length === filter.length;
|
|
227
272
|
};
|
|
228
273
|
json_logic_js_1.default.add_operation("regex-match", regexMatch);
|
|
274
|
+
var aggregateAny = function (reducedValues) {
|
|
275
|
+
return reducedValues.includes(true);
|
|
276
|
+
};
|
|
277
|
+
var aggregateFirst = function (reducedValues) {
|
|
278
|
+
return reducedValues[0] === true;
|
|
279
|
+
};
|
|
280
|
+
var cleanString = function (value) {
|
|
281
|
+
return (typeof value === "number" ? value.toString() : value.trim()).toLowerCase();
|
|
282
|
+
};
|
|
283
|
+
var registerScopedBooleanOp = function (baseName, compareFn) {
|
|
284
|
+
json_logic_js_1.default.add_operation("".concat(baseName, "-first"), function (values, _comparator, parents) {
|
|
285
|
+
var reducedValue = reduceValues(values, parents, compareFn);
|
|
286
|
+
return aggregateFirst(reducedValue);
|
|
287
|
+
});
|
|
288
|
+
json_logic_js_1.default.add_operation("".concat(baseName, "-any"), function (values, _comparator, parents) {
|
|
289
|
+
var reducedValue = reduceValues(values, parents, compareFn);
|
|
290
|
+
return aggregateAny(reducedValue);
|
|
291
|
+
});
|
|
292
|
+
};
|
|
293
|
+
registerScopedBooleanOp("selected", function (value, parent) { return value && parent; });
|
|
294
|
+
registerScopedBooleanOp("not-selected", function (value, parent) { return !value && parent; });
|
|
295
|
+
var conditionMet = function (value, parent) {
|
|
296
|
+
return value === true && parent;
|
|
297
|
+
};
|
|
298
|
+
var conditionNotMet = function (value, parent) {
|
|
299
|
+
return value !== true && parent;
|
|
300
|
+
};
|
|
301
|
+
json_logic_js_1.default.add_operation("conditions-met", function (values, comparator, parents) {
|
|
302
|
+
return reduceValues(values, parents, conditionMet).every(function (value) { return value === true; });
|
|
303
|
+
});
|
|
304
|
+
json_logic_js_1.default.add_operation("conditions-not-met", function (values, comparator, parents) {
|
|
305
|
+
return reduceValues(values, parents, conditionNotMet).every(function (value) { return value === true; });
|
|
306
|
+
});
|
|
307
|
+
registerScopedBooleanOp("conditions-met", conditionMet);
|
|
308
|
+
registerScopedBooleanOp("conditions-not-met", conditionNotMet);
|
|
309
|
+
var registerScopedComparisonOp = function (baseName, compareFn) {
|
|
310
|
+
json_logic_js_1.default.add_operation("".concat(baseName, "-any"), function (values, comparator, parents) {
|
|
311
|
+
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
312
|
+
return compareFn(value, comparator, parent);
|
|
313
|
+
});
|
|
314
|
+
return aggregateAny(reducedValues);
|
|
315
|
+
});
|
|
316
|
+
json_logic_js_1.default.add_operation("".concat(baseName, "-first"), function (values, comparator, parents) {
|
|
317
|
+
var reducedValues = reduceValues(values, parents, function (value, parent) {
|
|
318
|
+
return compareFn(value, comparator, parent);
|
|
319
|
+
});
|
|
320
|
+
return aggregateFirst(reducedValues);
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
registerScopedComparisonOp("=", function (value, comparator, parent) {
|
|
324
|
+
return safeEqual(value, comparator) && parent;
|
|
325
|
+
});
|
|
326
|
+
registerScopedComparisonOp("<>", function (value, comparator, parent) {
|
|
327
|
+
return !safeEqual(value, comparator) && parent;
|
|
328
|
+
});
|
|
329
|
+
registerScopedComparisonOp("==", function (value, comparator, parent) {
|
|
330
|
+
return parseNumber(value) === parseNumber(comparator) && parent;
|
|
331
|
+
});
|
|
332
|
+
registerScopedComparisonOp(">=", function (value, comparator, parent) {
|
|
333
|
+
return parseNumber(value) >= parseNumber(comparator) && parent;
|
|
334
|
+
});
|
|
335
|
+
registerScopedComparisonOp("<=", function (value, comparator, parent) {
|
|
336
|
+
return parseNumber(value) <= parseNumber(comparator) && parent;
|
|
337
|
+
});
|
|
338
|
+
registerScopedComparisonOp(">", function (value, comparator, parent) {
|
|
339
|
+
return parseNumber(value) > parseNumber(comparator) && parent;
|
|
340
|
+
});
|
|
341
|
+
registerScopedComparisonOp("<", function (value, comparator, parent) {
|
|
342
|
+
return parseNumber(value) < parseNumber(comparator) && parent;
|
|
343
|
+
});
|
|
344
|
+
registerScopedComparisonOp("is", function (value, comparator, parent) {
|
|
345
|
+
return cleanString(value) === cleanString(comparator) && parent;
|
|
346
|
+
});
|
|
347
|
+
registerScopedComparisonOp("not", function (value, comparator, parent) {
|
|
348
|
+
return cleanString(value) !== cleanString(comparator) && parent;
|
|
349
|
+
});
|
|
350
|
+
registerScopedComparisonOp("contains", function (value, comparator, parent) {
|
|
351
|
+
return cleanString(value).includes(cleanString(comparator)) && parent;
|
|
352
|
+
});
|
|
353
|
+
registerScopedComparisonOp("does-not-contain", function (value, comparator, parent) {
|
|
354
|
+
return !cleanString(value).includes(cleanString(comparator)) && parent;
|
|
355
|
+
});
|
|
356
|
+
registerScopedComparisonOp("like", function (value, comparator, parent) {
|
|
357
|
+
return new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent;
|
|
358
|
+
});
|
|
359
|
+
registerScopedComparisonOp("not-like", function (value, comparator, parent) {
|
|
360
|
+
return !new RegExp("( |^)".concat(cleanString(comparator), "( |$)"), "i").test(cleanString(value)) && parent;
|
|
361
|
+
});
|
|
362
|
+
registerScopedComparisonOp("regex-match", function (value, comparator, parent) {
|
|
363
|
+
if (typeof comparator !== "string")
|
|
364
|
+
return false;
|
|
365
|
+
var regex;
|
|
366
|
+
try {
|
|
367
|
+
regex = new RegExp(comparator);
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
var stringValue = typeof value === "number" ? value.toString() : value;
|
|
373
|
+
return regex.test(stringValue) && parent;
|
|
374
|
+
});
|
|
375
|
+
registerScopedComparisonOp("empty", function (value, _comparator, parent) { return cleanString(value).length === 0 && parent; });
|
|
376
|
+
registerScopedComparisonOp("not-empty", function (value, _comparator, parent) { return cleanString(value).length > 0 && parent; });
|
|
229
377
|
var LpLogic = json_logic_js_1.default.apply;
|
|
230
378
|
exports.default = LpLogic;
|
package/dist/Parser.js
CHANGED
|
@@ -16,7 +16,7 @@ var Parser = (function () {
|
|
|
16
16
|
Parser.prototype.validateCondition = function (condition) {
|
|
17
17
|
var result = (0, jsonschema_1.validate)(condition, condition_v1_schema_1.default);
|
|
18
18
|
if (result.errors.length > 0) {
|
|
19
|
-
throw new Error(JSON.stringify(condition)
|
|
19
|
+
throw new Error("".concat(JSON.stringify(condition), " is not a valid condition"));
|
|
20
20
|
}
|
|
21
21
|
};
|
|
22
22
|
Parser.prototype.convertConditions = function (conditions) {
|
|
@@ -31,7 +31,7 @@ var Parser = (function () {
|
|
|
31
31
|
operator = value.t;
|
|
32
32
|
}
|
|
33
33
|
else if (value.t !== operator) {
|
|
34
|
-
throw new Error("Conditions object is not valid, "
|
|
34
|
+
throw new Error("Conditions object is not valid, ".concat(operator, " is not equal to ").concat(value.t, " at index ").concat(index, " in ").concat(JSON.stringify(conditions)));
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -57,7 +57,7 @@ var Parser = (function () {
|
|
|
57
57
|
logic = logicConditions[0];
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
|
-
throw new Error("Invalid condition "
|
|
60
|
+
throw new Error("Invalid condition ".concat(conditions));
|
|
61
61
|
}
|
|
62
62
|
return logic;
|
|
63
63
|
};
|
|
@@ -70,18 +70,18 @@ var Parser = (function () {
|
|
|
70
70
|
var dataReference;
|
|
71
71
|
if (condition.o !== false && condition.o !== undefined) {
|
|
72
72
|
dataReference = {
|
|
73
|
-
var: "o."
|
|
73
|
+
var: "o.".concat(condition.o)
|
|
74
74
|
};
|
|
75
75
|
rule[operation] = [dataReference];
|
|
76
76
|
}
|
|
77
77
|
else if (condition.v !== false && condition.v !== undefined) {
|
|
78
78
|
dataReference = {
|
|
79
|
-
var: "v."
|
|
79
|
+
var: "v.".concat(condition.v)
|
|
80
80
|
};
|
|
81
81
|
rule[operation] = [dataReference, condition.value];
|
|
82
82
|
}
|
|
83
83
|
else {
|
|
84
|
-
throw new Error("Invalid condition "
|
|
84
|
+
throw new Error("Invalid condition ".concat(condition));
|
|
85
85
|
}
|
|
86
86
|
return rule;
|
|
87
87
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type ConditionV1Single = {
|
|
2
2
|
c?: "selected" | "not-selected" | "has-one" | "at-least-one" | "has-many" | "contains" | "does-not-contain" | "=" | ">" | "<" | "!=" | ">=" | "<=" | "<>";
|
|
3
3
|
o?: false | number | string;
|
|
4
4
|
p?: string | number;
|
|
@@ -8,11 +8,11 @@ export declare type ConditionV1Single = {
|
|
|
8
8
|
m?: boolean;
|
|
9
9
|
t?: "and" | "or";
|
|
10
10
|
};
|
|
11
|
-
export
|
|
11
|
+
export type ConditionV1Array = {
|
|
12
12
|
condition_array?: ConditionV1Compose[];
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
export
|
|
14
|
+
type ConditionV1Compose = ConditionV1Array & ConditionV1Single;
|
|
15
|
+
export type CompiledConditionV1 = ConditionV1Compose[];
|
|
16
16
|
export interface ModelV1 {
|
|
17
17
|
contract_name: string;
|
|
18
18
|
sections: SectionV1[];
|
package/jest.config.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
}
|
|
2
|
+
roots: [
|
|
3
|
+
"./tests"
|
|
4
|
+
],
|
|
5
|
+
transform: {
|
|
6
|
+
"^.+\\.tsx?$": ['ts-jest', {
|
|
7
|
+
tsconfig: "tsconfig.json"
|
|
8
|
+
}],
|
|
9
|
+
},
|
|
10
|
+
};
|
package/package.json
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@legalplace/lplogic",
|
|
3
|
-
"version": "2.3.0",
|
|
3
|
+
"version": "2.3.2-staging.0",
|
|
4
4
|
"description": "LegalPlace LpLogic",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "
|
|
8
|
-
"build": "
|
|
7
|
+
"test": "jest",
|
|
8
|
+
"build": "tsc",
|
|
9
9
|
"release": "standard-version -a --no-verify"
|
|
10
10
|
},
|
|
11
11
|
"outDir": "./dist",
|
|
12
12
|
"author": "Moncef Hammou <moncef@legalplace.fr>",
|
|
13
13
|
"license": "ISC",
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@legalplace/models-v3-types": "5.1.24",
|
|
16
15
|
"@legalplace/json-logic-js": "^1.2.3",
|
|
16
|
+
"@legalplace/models-v3-types": "5.1.24",
|
|
17
17
|
"jsonschema": "^1.2.4"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@babel/core": "^7.7.2",
|
|
21
21
|
"@babel/preset-typescript": "^7.7.2",
|
|
22
|
+
"@commitlint/cli": "^9.0.1",
|
|
23
|
+
"@commitlint/config-conventional": "^9.0.1",
|
|
24
|
+
"@types/jest": "^29.5.14",
|
|
22
25
|
"@types/node": "^12.12.6",
|
|
23
26
|
"@typescript-eslint/eslint-plugin": "^2.6.1",
|
|
24
27
|
"@typescript-eslint/parser": "^2.6.1",
|
|
@@ -26,12 +29,12 @@
|
|
|
26
29
|
"eslint": "^6.6.0",
|
|
27
30
|
"eslint-config-airbnb-base": "^14.0.0",
|
|
28
31
|
"eslint-plugin-import": "^2.18.2",
|
|
29
|
-
"typescript": "4.4.3",
|
|
30
|
-
"semantic-release": "^17.1.1",
|
|
31
32
|
"husky": "^4.2.5",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"standard-version": "^8.0.0"
|
|
33
|
+
"jest": "^29.7.0",
|
|
34
|
+
"semantic-release": "^17.1.1",
|
|
35
|
+
"standard-version": "^8.0.0",
|
|
36
|
+
"ts-jest": "^29.2.5",
|
|
37
|
+
"typescript": "5.6.3"
|
|
35
38
|
},
|
|
36
39
|
"husky": {
|
|
37
40
|
"hooks": {
|
package/tests/LpLogic.test.ts
CHANGED
|
@@ -1,131 +1,257 @@
|
|
|
1
1
|
import LpLogic from "../lib/index"
|
|
2
2
|
|
|
3
3
|
test('Testing "selected" operator on a boolean `true`', async () => {
|
|
4
|
-
|
|
4
|
+
expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[true]}})).toBe(true)
|
|
5
5
|
})
|
|
6
6
|
|
|
7
7
|
test('Testing "selected" operator on an array of boolean `true`', async () => {
|
|
8
|
-
|
|
8
|
+
expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[true, true]}})).toBe(true)
|
|
9
9
|
})
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
test('Testing "selected" operator on an array of boolean `false`', async () => {
|
|
13
|
-
|
|
13
|
+
expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[false]}})).toBe(false)
|
|
14
14
|
})
|
|
15
15
|
|
|
16
16
|
test('Testing "selected" operator on an array containing a boolean `false`', async () => {
|
|
17
|
-
|
|
17
|
+
expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[true, false]}})).toBe(false)
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
test('Testing "not-selected" operator on a boolean `false`', async () => {
|
|
21
|
-
|
|
21
|
+
expect(LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[false]}})).toBe(true)
|
|
22
22
|
})
|
|
23
23
|
|
|
24
24
|
test('Testing "not-selected" operator on an array of boolean `false`', async () => {
|
|
25
|
-
|
|
25
|
+
expect(LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[false, false]}})).toBe(true)
|
|
26
26
|
})
|
|
27
27
|
|
|
28
28
|
// Returns false
|
|
29
29
|
|
|
30
30
|
test('Testing "not-selected" operator on a boolean `true`', async () => {
|
|
31
|
-
|
|
31
|
+
expect( LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[true]}}) ).toBe(false)
|
|
32
32
|
})
|
|
33
33
|
|
|
34
34
|
test('Testing "not-selected" operator on an array containing a boolean `true`', async () => {
|
|
35
|
-
|
|
35
|
+
expect( LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[true, false]}}) ).toBe(false)
|
|
36
36
|
})
|
|
37
37
|
|
|
38
38
|
// Returns true
|
|
39
39
|
test('Testing "has-one" on an array of one element', async () => {
|
|
40
|
-
|
|
40
|
+
expect(LpLogic({"has-one":[{"var":"o.1"}]}, {"o":{"1":[true]}})).toBe(true)
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
// Returns false
|
|
44
44
|
test('Testing "has-one" on an array of two elements', async () => {
|
|
45
|
-
|
|
45
|
+
expect( LpLogic({"has-one":[{"var":"o.1"}]}, {"o":{"1":[true, true]}}) ).toBe(false)
|
|
46
46
|
})
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
// Returns true
|
|
50
50
|
test('Testing "has-many" on an array of two elements', async () => {
|
|
51
|
-
|
|
51
|
+
expect( LpLogic({"has-many":[{"var":"o.1"}]}, {"o":{"1":[true, true]}}) ).toBe(true)
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
// Returns false
|
|
56
56
|
test('Testing "has-many" on an array of one element', async () => {
|
|
57
|
-
|
|
57
|
+
expect( LpLogic({"has-many":[{"var":"o.1"}]}, {"o":{"1":[true]}}) ).toBe(false)
|
|
58
58
|
})
|
|
59
59
|
|
|
60
60
|
// Returns true
|
|
61
61
|
test('Testing "at-least-one" on a array of three elements with one as true', async () => {
|
|
62
|
-
|
|
62
|
+
expect( LpLogic({"at-least-one":[{"var":"o.1"}]}, {"o":{"1":[false, false, true]}}) ).toBe(true)
|
|
63
63
|
})
|
|
64
64
|
|
|
65
65
|
// Returns false
|
|
66
66
|
test('Testing "at-least-one" on an array of three elements with all elements as false', async () => {
|
|
67
|
-
|
|
67
|
+
expect( LpLogic({"at-least-one":[{"var":"o.1"}]}, {"o":{"1":[false, false, false]}}) ).toBe(false)
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
|
|
71
71
|
// Returns true
|
|
72
72
|
test('Testing "contains" Hello on a value `Hello`', async () => {
|
|
73
|
-
|
|
73
|
+
expect( LpLogic({"contains":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Hello"]}}) ).toBe(true)
|
|
74
74
|
})
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
// Returns false
|
|
78
78
|
test('Testing "contains" Hello on a value `Bye`', async () => {
|
|
79
|
-
|
|
79
|
+
expect( LpLogic({"contains":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Bye"]}}) ).toBe(false)
|
|
80
80
|
})
|
|
81
81
|
|
|
82
82
|
// Returns true
|
|
83
83
|
test('Testing "is" Hello on a value `Hello`', async () => {
|
|
84
|
-
|
|
84
|
+
expect( LpLogic({"is":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Hello"]}}) ).toBe(true)
|
|
85
85
|
})
|
|
86
86
|
|
|
87
87
|
|
|
88
88
|
// Returns false
|
|
89
89
|
test('Testing "is" Hello on a value `Bye`', async () => {
|
|
90
|
-
|
|
90
|
+
expect( LpLogic({"is":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Bye"]}}) ).toBe(false)
|
|
91
91
|
})
|
|
92
92
|
|
|
93
93
|
// Returns true
|
|
94
94
|
test('Testing "does-not-contain" Hello on a value `Bye`', async () => {
|
|
95
|
-
|
|
95
|
+
expect( LpLogic({"does-not-contain":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Bye"]}}) ).toBe(true)
|
|
96
96
|
})
|
|
97
97
|
|
|
98
98
|
// Returns false
|
|
99
99
|
test('Testing "does-not-contain" Hello on a value `Hello`', async () => {
|
|
100
|
-
|
|
100
|
+
expect( LpLogic({"does-not-contain":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Hello"]}}) ).toBe(false)
|
|
101
101
|
})
|
|
102
102
|
|
|
103
103
|
// Returns true
|
|
104
104
|
test('Testing "not" Hello on a value `Bye`', async () => {
|
|
105
|
-
|
|
105
|
+
expect( LpLogic({"not":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Bye"]}}) ).toBe(true)
|
|
106
106
|
})
|
|
107
107
|
|
|
108
108
|
// Returns false
|
|
109
109
|
test('Testing "not" Hello on a value `Hello`', async () => {
|
|
110
|
-
|
|
110
|
+
expect( LpLogic({"not":[{"var":"v.1"}, "Hello"]}, {"v":{"1":["Hello"]}}) ).toBe(false)
|
|
111
111
|
})
|
|
112
112
|
|
|
113
113
|
// Returns true
|
|
114
114
|
test('Testing "like" World on a value `Hello world`', async () => {
|
|
115
|
-
|
|
115
|
+
expect( LpLogic({"like":[{"var":"v.1"}, "World"]}, {"v":{"1":["Hello world"]}}) ).toBe(true)
|
|
116
116
|
})
|
|
117
117
|
|
|
118
118
|
// Returns false
|
|
119
119
|
test('Testing "like" Bye on a value `Hello world`', async () => {
|
|
120
|
-
|
|
120
|
+
expect( LpLogic({"like":[{"var":"v.1"}, "Bye"]}, {"v":{"1":["Hello world"]}}) ).toBe(false)
|
|
121
121
|
})
|
|
122
122
|
|
|
123
123
|
// Returns true
|
|
124
124
|
test('Testing "not-like" Bye on a value `Hello world`', async () => {
|
|
125
|
-
|
|
125
|
+
expect( LpLogic({"not-like":[{"var":"v.1"}, "Bye"]}, {"v":{"1":["Hello world"]}}) ).toBe(true)
|
|
126
126
|
})
|
|
127
127
|
|
|
128
128
|
// Returns false
|
|
129
129
|
test('Testing "not-like" World on a value `Hello world`', async () => {
|
|
130
|
-
|
|
131
|
-
})
|
|
130
|
+
expect( LpLogic({"not-like":[{"var":"v.1"}, "World"]}, {"v":{"1":["Hello world"]}}) ).toBe(false)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
test('Testing "selected-first" on first occurrence only', async () => {
|
|
134
|
+
expect(LpLogic({"selected-first":[{"var":"o.1"}]}, {"o":{"1":[true, false]}})).toBe(true)
|
|
135
|
+
expect(LpLogic({"selected-first":[{"var":"o.1"}]}, {"o":{"1":[false, true]}})).toBe(false)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('Testing "=-any" on multiple values', async () => {
|
|
139
|
+
expect(LpLogic({"=-any":[{"var":"v.1"}, "a"]}, {"v":{"1":["a", "b"]}})).toBe(true)
|
|
140
|
+
expect(LpLogic({"=-any":[{"var":"v.1"}, "a"]}, {"v":{"1":["b", "c"]}})).toBe(false)
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* empty-any / not-empty-any cover occurrence scope "at least one" for emptiness checks.
|
|
145
|
+
*/
|
|
146
|
+
test('Testing "empty-any" on multiple values', async () => {
|
|
147
|
+
expect(LpLogic({"empty-any":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
|
|
148
|
+
expect(LpLogic({"empty-any":[{"var":"v.1"}]}, {"v":{"1":["x", "y"]}})).toBe(false)
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
test('Testing "empty-first" on multiple values', async () => {
|
|
152
|
+
expect(LpLogic({"empty-first":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
|
|
153
|
+
expect(LpLogic({"empty-first":[{"var":"v.1"}]}, {"v":{"1":["x", ""]}})).toBe(false)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
test('Testing "not-empty-any" on multiple values', async () => {
|
|
157
|
+
expect(LpLogic({"not-empty-any":[{"var":"v.1"}]}, {"v":{"1":["", "x"]}})).toBe(true)
|
|
158
|
+
expect(LpLogic({"not-empty-any":[{"var":"v.1"}]}, {"v":{"1":["", ""]}})).toBe(false)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('Testing "=-first" on multiple values', async () => {
|
|
162
|
+
expect(LpLogic({"=-first":[{"var":"v.1"}, "a"]}, {"v":{"1":["a", "b"]}})).toBe(true)
|
|
163
|
+
expect(LpLogic({"=-first":[{"var":"v.1"}, "a"]}, {"v":{"1":["b", "a"]}})).toBe(false)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
test('Testing "conditions-met" without parents', async () => {
|
|
167
|
+
expect(
|
|
168
|
+
LpLogic({"conditions-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, true]}}})
|
|
169
|
+
).toBe(true)
|
|
170
|
+
expect(
|
|
171
|
+
LpLogic({"conditions-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
|
|
172
|
+
).toBe(false)
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
test('Testing "conditions-met" with parents', async () => {
|
|
176
|
+
expect(
|
|
177
|
+
LpLogic(
|
|
178
|
+
{"conditions-met":[{"var":"c.o.2"}, undefined, [{"var":"o.1"}]]},
|
|
179
|
+
{"c":{"o":{"2":[true, true]}}, "o":{"1":[true, true]}}
|
|
180
|
+
)
|
|
181
|
+
).toBe(true)
|
|
182
|
+
expect(
|
|
183
|
+
LpLogic(
|
|
184
|
+
{"conditions-met":[{"var":"c.o.2"}, undefined, [{"var":"o.1"}]]},
|
|
185
|
+
{"c":{"o":{"2":[true, true]}}, "o":{"1":[true, false]}}
|
|
186
|
+
)
|
|
187
|
+
).toBe(false)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('Testing "conditions-met-first" on first occurrence only', async () => {
|
|
191
|
+
expect(
|
|
192
|
+
LpLogic({"conditions-met-first":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
|
|
193
|
+
).toBe(true)
|
|
194
|
+
expect(
|
|
195
|
+
LpLogic({"conditions-met-first":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, true]}}})
|
|
196
|
+
).toBe(false)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
test('Testing "conditions-met-any" on multiple values', async () => {
|
|
200
|
+
expect(
|
|
201
|
+
LpLogic({"conditions-met-any":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, true]}}})
|
|
202
|
+
).toBe(true)
|
|
203
|
+
expect(
|
|
204
|
+
LpLogic({"conditions-met-any":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, false]}}})
|
|
205
|
+
).toBe(false)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
test('Testing "conditions-not-met"', async () => {
|
|
209
|
+
expect(
|
|
210
|
+
LpLogic({"conditions-not-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[false, false]}}})
|
|
211
|
+
).toBe(true)
|
|
212
|
+
expect(
|
|
213
|
+
LpLogic({"conditions-not-met":[{"var":"c.o.1"}]}, {"c":{"o":{"1":[true, false]}}})
|
|
214
|
+
).toBe(false)
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Regression: when a condition tree containing `undefined` parents is passed
|
|
219
|
+
* through any JSON serialization (e.g. Redux DevTools), `undefined` becomes
|
|
220
|
+
* `null` (`JSON.stringify([a, undefined])` → `'[a,null]'`). LpLogic must
|
|
221
|
+
* treat a `null` parents arg as "no parents" instead of throwing on
|
|
222
|
+
* `null.length`.
|
|
223
|
+
*/
|
|
224
|
+
test('Testing "conditions-met" with null parents (JSON round-trip safety)', async () => {
|
|
225
|
+
expect(
|
|
226
|
+
LpLogic(
|
|
227
|
+
{ "conditions-met": [{ var: "c.o.1" }, null, null] },
|
|
228
|
+
{ "c": { "o": { "1": [true, true] } } }
|
|
229
|
+
)
|
|
230
|
+
).toBe(true)
|
|
231
|
+
expect(
|
|
232
|
+
LpLogic(
|
|
233
|
+
{ "conditions-met-first": [{ var: "c.o.1" }, null, null] },
|
|
234
|
+
{ "c": { "o": { "1": [true, false] } } }
|
|
235
|
+
)
|
|
236
|
+
).toBe(true)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
test('Testing "selected" with null parents (JSON round-trip safety)', async () => {
|
|
240
|
+
expect(
|
|
241
|
+
LpLogic(
|
|
242
|
+
{ "selected": [{ var: "o.1" }, null, null] },
|
|
243
|
+
{ "o": { "1": [true, true] } }
|
|
244
|
+
)
|
|
245
|
+
).toBe(true)
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
test('Testing "conditions-met" with parents containing missing refs (null entries)', async () => {
|
|
249
|
+
// `{ var: "o.999" }` resolves to `null` because `o.999` is absent from data.
|
|
250
|
+
// Parents array is `[null]`; LpLogic must not throw.
|
|
251
|
+
expect(
|
|
252
|
+
LpLogic(
|
|
253
|
+
{ "conditions-met": [{ var: "c.o.1" }, undefined, [{ var: "o.999" }]] },
|
|
254
|
+
{ "c": { "o": { "1": [true] } } }
|
|
255
|
+
)
|
|
256
|
+
).toBe(true)
|
|
257
|
+
})
|