@stll/template-conditions 0.2.0 → 0.2.2
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/dist/index.js +16 -6
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -6,7 +6,14 @@ import { panic } from "better-result";
|
|
|
6
6
|
* the condition engine (index.ts) and the arithmetic evaluator (compute.ts) can
|
|
7
7
|
* import it without a dependency cycle.
|
|
8
8
|
*/
|
|
9
|
-
/**
|
|
9
|
+
/**
|
|
10
|
+
* Narrow `unknown` to something a path segment can be read from.
|
|
11
|
+
*
|
|
12
|
+
* Unlike the same-named predicates that screen JSON payload shapes, this one
|
|
13
|
+
* accepts arrays on purpose: a dotted path segment may be an array index
|
|
14
|
+
* (`parties.1.name`), and rejecting arrays would silently resolve those to
|
|
15
|
+
* `undefined`.
|
|
16
|
+
*/
|
|
10
17
|
const isRecord = (v) => typeof v === "object" && v !== null;
|
|
11
18
|
/** Resolve a dotted path like `company.name` against data. */
|
|
12
19
|
const resolvePath = (path, data) => {
|
|
@@ -101,7 +108,7 @@ const callFunction = (name, args) => {
|
|
|
101
108
|
const factor = 10 ** Math.trunc(digits);
|
|
102
109
|
return Math.round(value * factor) / factor;
|
|
103
110
|
}
|
|
104
|
-
default: return name;
|
|
111
|
+
default: return panic(`Unhandled name: ${String(name)}`);
|
|
105
112
|
}
|
|
106
113
|
};
|
|
107
114
|
const evaluateNumericExpression = (expression, data) => {
|
|
@@ -175,8 +182,6 @@ const evaluateNumericExpression = (expression, data) => {
|
|
|
175
182
|
};
|
|
176
183
|
//#endregion
|
|
177
184
|
//#region src/parse.ts
|
|
178
|
-
const NON_STRING_TOKEN_RE = /(?<token>==|!=|>=|<=|>|<|!(?!=)|and\b|or\b|contains\b|[()]|-?\d[\p{N}_.]*|[\p{L}\p{N}_.]+(?:-[\p{L}\p{N}_.]+)*)/uy;
|
|
179
|
-
const STARTS_WITH_DIGIT_RE = /^-?\d/u;
|
|
180
185
|
const COMPARE_SYMBOL_TO_OP = {
|
|
181
186
|
"==": "eq",
|
|
182
187
|
"!=": "neq",
|
|
@@ -185,6 +190,11 @@ const COMPARE_SYMBOL_TO_OP = {
|
|
|
185
190
|
">=": "gte",
|
|
186
191
|
"<=": "lte"
|
|
187
192
|
};
|
|
193
|
+
const escapeRegexLiteral = (value) => value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
194
|
+
const COMPARE_SYMBOL_PATTERN = Object.keys(COMPARE_SYMBOL_TO_OP).sort((left, right) => right.length - left.length).map(escapeRegexLiteral).join("|");
|
|
195
|
+
const NON_STRING_TOKEN_RE = new RegExp(String.raw`(?<token>${COMPARE_SYMBOL_PATTERN}|!(?!=)|and\b|or\b|contains\b|[()]|-?\d[\p{N}_.]*|[\p{L}\p{N}_.]+(?:-[\p{L}\p{N}_.]+)*)`, "uy");
|
|
196
|
+
const STARTS_WITH_DIGIT_RE = /^-?\d/u;
|
|
197
|
+
const isCompareSymbol = (raw) => Object.hasOwn(COMPARE_SYMBOL_TO_OP, raw);
|
|
188
198
|
/**
|
|
189
199
|
* Scan a `"..."` literal starting at `expr[start]` (the opening quote),
|
|
190
200
|
* honoring `\\`-escapes without interpreting them. A single linear pass:
|
|
@@ -213,7 +223,7 @@ const classifyNonString = (raw) => {
|
|
|
213
223
|
if (raw === "and") return { type: "and" };
|
|
214
224
|
if (raw === "or") return { type: "or" };
|
|
215
225
|
if (raw === "!") return { type: "not" };
|
|
216
|
-
if (raw === "contains" ||
|
|
226
|
+
if (raw === "contains" || isCompareSymbol(raw)) return {
|
|
217
227
|
type: "op",
|
|
218
228
|
raw
|
|
219
229
|
};
|
|
@@ -371,7 +381,7 @@ const parseCondition = (expression) => {
|
|
|
371
381
|
return {
|
|
372
382
|
type: "compare",
|
|
373
383
|
left,
|
|
374
|
-
op: COMPARE_SYMBOL_TO_OP[opTok.raw]
|
|
384
|
+
op: COMPARE_SYMBOL_TO_OP[opTok.raw],
|
|
375
385
|
right: operandFromToken(rightTok)
|
|
376
386
|
};
|
|
377
387
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stll/template-conditions",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "A document-template marker and condition engine: {{...}} marker grammar, parse, compute, serialize, field values.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"condition",
|
|
@@ -41,21 +41,21 @@
|
|
|
41
41
|
"build": "tsdown",
|
|
42
42
|
"pack:dry-run": "bun pm pack --dry-run",
|
|
43
43
|
"test": "bun test",
|
|
44
|
-
"test:property": "bun test $(grep -rlF 'fc.assert' src --include='*.test.ts')",
|
|
44
|
+
"test:property": "bun test --preload @stll/property-testing/preload $(grep -rlF 'fc.assert' src --include='*.test.ts')",
|
|
45
45
|
"typecheck": "bun ../../packages/scripts/src/tsc-native.ts --noEmit",
|
|
46
46
|
"lint": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --report-unused-disable-directives-severity=error --deny-warnings --type-aware packages/template-conditions",
|
|
47
47
|
"lint:fix": "cd ../.. && bun --bun oxlint -c oxlint.config.ts --type-aware --fix packages/template-conditions",
|
|
48
|
-
"format": "oxfmt .",
|
|
48
|
+
"format": "bun ../../scripts/run-oxfmt.ts .",
|
|
49
49
|
"prepack": "bun run build"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@stll/conditions": "^0.
|
|
52
|
+
"@stll/conditions": "^0.3.1",
|
|
53
53
|
"better-result": "3.0.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@stll/property-testing": "0.0.0",
|
|
57
57
|
"@stll/typescript-config": "0.0.0",
|
|
58
|
-
"
|
|
58
|
+
"bun-types": "1.4.2",
|
|
59
59
|
"fast-check": "^4.9.0",
|
|
60
60
|
"tsdown": "0.22.14"
|
|
61
61
|
},
|