@manifesto-ai/core 2.6.0 → 2.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/README.md +4 -4
- package/dist/index.d.ts +1750 -19
- package/dist/index.js +18480 -36
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/dist/__tests__/apply.test.d.ts +0 -2
- package/dist/__tests__/apply.test.d.ts.map +0 -1
- package/dist/__tests__/apply.test.js +0 -320
- package/dist/__tests__/apply.test.js.map +0 -1
- package/dist/__tests__/defaults.test.d.ts +0 -2
- package/dist/__tests__/defaults.test.d.ts.map +0 -1
- package/dist/__tests__/defaults.test.js +0 -74
- package/dist/__tests__/defaults.test.js.map +0 -1
- package/dist/__tests__/jcs.test.d.ts +0 -2
- package/dist/__tests__/jcs.test.d.ts.map +0 -1
- package/dist/__tests__/jcs.test.js +0 -45
- package/dist/__tests__/jcs.test.js.map +0 -1
- package/dist/core/apply.d.ts +0 -17
- package/dist/core/apply.d.ts.map +0 -1
- package/dist/core/apply.js +0 -198
- package/dist/core/apply.js.map +0 -1
- package/dist/core/compute.d.ts +0 -17
- package/dist/core/compute.d.ts.map +0 -1
- package/dist/core/compute.js +0 -305
- package/dist/core/compute.js.map +0 -1
- package/dist/core/compute.test.d.ts +0 -2
- package/dist/core/compute.test.d.ts.map +0 -1
- package/dist/core/compute.test.js +0 -950
- package/dist/core/compute.test.js.map +0 -1
- package/dist/core/explain.d.ts +0 -14
- package/dist/core/explain.d.ts.map +0 -1
- package/dist/core/explain.js +0 -78
- package/dist/core/explain.js.map +0 -1
- package/dist/core/index.d.ts +0 -5
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -5
- package/dist/core/index.js.map +0 -1
- package/dist/core/validate.d.ts +0 -16
- package/dist/core/validate.d.ts.map +0 -1
- package/dist/core/validate.js +0 -361
- package/dist/core/validate.js.map +0 -1
- package/dist/core/validate.test.d.ts +0 -2
- package/dist/core/validate.test.d.ts.map +0 -1
- package/dist/core/validate.test.js +0 -719
- package/dist/core/validate.test.js.map +0 -1
- package/dist/core/validation-utils.d.ts +0 -20
- package/dist/core/validation-utils.d.ts.map +0 -1
- package/dist/core/validation-utils.js +0 -351
- package/dist/core/validation-utils.js.map +0 -1
- package/dist/errors.d.ts +0 -30
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -51
- package/dist/errors.js.map +0 -1
- package/dist/evaluator/computed.d.ts +0 -14
- package/dist/evaluator/computed.d.ts.map +0 -1
- package/dist/evaluator/computed.js +0 -60
- package/dist/evaluator/computed.js.map +0 -1
- package/dist/evaluator/context.d.ts +0 -62
- package/dist/evaluator/context.d.ts.map +0 -1
- package/dist/evaluator/context.js +0 -44
- package/dist/evaluator/context.js.map +0 -1
- package/dist/evaluator/dag.d.ts +0 -30
- package/dist/evaluator/dag.d.ts.map +0 -1
- package/dist/evaluator/dag.js +0 -121
- package/dist/evaluator/dag.js.map +0 -1
- package/dist/evaluator/expr.d.ts +0 -11
- package/dist/evaluator/expr.d.ts.map +0 -1
- package/dist/evaluator/expr.js +0 -1030
- package/dist/evaluator/expr.js.map +0 -1
- package/dist/evaluator/expr.test.d.ts +0 -2
- package/dist/evaluator/expr.test.d.ts.map +0 -1
- package/dist/evaluator/expr.test.js +0 -1235
- package/dist/evaluator/expr.test.js.map +0 -1
- package/dist/evaluator/flow.d.ts +0 -36
- package/dist/evaluator/flow.d.ts.map +0 -1
- package/dist/evaluator/flow.js +0 -390
- package/dist/evaluator/flow.js.map +0 -1
- package/dist/evaluator/flow.test.d.ts +0 -2
- package/dist/evaluator/flow.test.d.ts.map +0 -1
- package/dist/evaluator/flow.test.js +0 -499
- package/dist/evaluator/flow.test.js.map +0 -1
- package/dist/evaluator/index.d.ts +0 -6
- package/dist/evaluator/index.d.ts.map +0 -1
- package/dist/evaluator/index.js +0 -6
- package/dist/evaluator/index.js.map +0 -1
- package/dist/factories.d.ts +0 -22
- package/dist/factories.d.ts.map +0 -1
- package/dist/factories.js +0 -44
- package/dist/factories.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -14
- package/dist/index.test.js.map +0 -1
- package/dist/schema/action.d.ts +0 -14
- package/dist/schema/action.d.ts.map +0 -1
- package/dist/schema/action.js +0 -30
- package/dist/schema/action.js.map +0 -1
- package/dist/schema/common.d.ts +0 -37
- package/dist/schema/common.d.ts.map +0 -1
- package/dist/schema/common.js +0 -20
- package/dist/schema/common.js.map +0 -1
- package/dist/schema/computed.d.ts +0 -23
- package/dist/schema/computed.d.ts.map +0 -1
- package/dist/schema/computed.js +0 -34
- package/dist/schema/computed.js.map +0 -1
- package/dist/schema/defaults.d.ts +0 -12
- package/dist/schema/defaults.d.ts.map +0 -1
- package/dist/schema/defaults.js +0 -19
- package/dist/schema/defaults.js.map +0 -1
- package/dist/schema/domain.d.ts +0 -50
- package/dist/schema/domain.d.ts.map +0 -1
- package/dist/schema/domain.js +0 -60
- package/dist/schema/domain.js.map +0 -1
- package/dist/schema/expr.d.ts +0 -483
- package/dist/schema/expr.d.ts.map +0 -1
- package/dist/schema/expr.js +0 -445
- package/dist/schema/expr.js.map +0 -1
- package/dist/schema/field.d.ts +0 -48
- package/dist/schema/field.d.ts.map +0 -1
- package/dist/schema/field.js +0 -31
- package/dist/schema/field.js.map +0 -1
- package/dist/schema/flow.d.ts +0 -103
- package/dist/schema/flow.d.ts.map +0 -1
- package/dist/schema/flow.js +0 -82
- package/dist/schema/flow.js.map +0 -1
- package/dist/schema/host-context.d.ts +0 -12
- package/dist/schema/host-context.d.ts.map +0 -1
- package/dist/schema/host-context.js +0 -23
- package/dist/schema/host-context.js.map +0 -1
- package/dist/schema/index.d.ts +0 -15
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js +0 -28
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/patch.d.ts +0 -59
- package/dist/schema/patch.d.ts.map +0 -1
- package/dist/schema/patch.js +0 -60
- package/dist/schema/patch.js.map +0 -1
- package/dist/schema/result.d.ts +0 -142
- package/dist/schema/result.d.ts.map +0 -1
- package/dist/schema/result.js +0 -94
- package/dist/schema/result.js.map +0 -1
- package/dist/schema/snapshot.d.ts +0 -153
- package/dist/schema/snapshot.d.ts.map +0 -1
- package/dist/schema/snapshot.js +0 -160
- package/dist/schema/snapshot.js.map +0 -1
- package/dist/schema/trace.d.ts +0 -98
- package/dist/schema/trace.d.ts.map +0 -1
- package/dist/schema/trace.js +0 -90
- package/dist/schema/trace.js.map +0 -1
- package/dist/schema/type-spec.d.ts +0 -34
- package/dist/schema/type-spec.d.ts.map +0 -1
- package/dist/schema/type-spec.js +0 -40
- package/dist/schema/type-spec.js.map +0 -1
- package/dist/utils/canonical.d.ts +0 -37
- package/dist/utils/canonical.d.ts.map +0 -1
- package/dist/utils/canonical.js +0 -122
- package/dist/utils/canonical.js.map +0 -1
- package/dist/utils/canonical.test.d.ts +0 -2
- package/dist/utils/canonical.test.d.ts.map +0 -1
- package/dist/utils/canonical.test.js +0 -183
- package/dist/utils/canonical.test.js.map +0 -1
- package/dist/utils/hash.d.ts +0 -55
- package/dist/utils/hash.d.ts.map +0 -1
- package/dist/utils/hash.js +0 -183
- package/dist/utils/hash.js.map +0 -1
- package/dist/utils/hash.test.d.ts +0 -2
- package/dist/utils/hash.test.d.ts.map +0 -1
- package/dist/utils/hash.test.js +0 -253
- package/dist/utils/hash.test.js.map +0 -1
- package/dist/utils/index.d.ts +0 -4
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js +0 -4
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/path.d.ts +0 -42
- package/dist/utils/path.d.ts.map +0 -1
- package/dist/utils/path.js +0 -170
- package/dist/utils/path.js.map +0 -1
- package/dist/utils/path.test.d.ts +0 -2
- package/dist/utils/path.test.d.ts.map +0 -1
- package/dist/utils/path.test.js +0 -248
- package/dist/utils/path.test.js.map +0 -1
package/dist/evaluator/expr.js
DELETED
|
@@ -1,1030 +0,0 @@
|
|
|
1
|
-
import { ok, err } from "../schema/common.js";
|
|
2
|
-
import { createError } from "../errors.js";
|
|
3
|
-
import { getByPath } from "../utils/path.js";
|
|
4
|
-
import { withCollectionContext } from "./context.js";
|
|
5
|
-
/**
|
|
6
|
-
* Evaluate an expression node
|
|
7
|
-
* All expressions are pure and total (always return a value or error)
|
|
8
|
-
*/
|
|
9
|
-
export function evaluateExpr(expr, ctx) {
|
|
10
|
-
switch (expr.kind) {
|
|
11
|
-
// Literals
|
|
12
|
-
case "lit":
|
|
13
|
-
return ok(expr.value);
|
|
14
|
-
case "get":
|
|
15
|
-
return evaluateGet(expr.path, ctx);
|
|
16
|
-
// Comparison
|
|
17
|
-
case "eq":
|
|
18
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => a === b);
|
|
19
|
-
case "neq":
|
|
20
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => a !== b);
|
|
21
|
-
case "gt":
|
|
22
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) > toNumber(b));
|
|
23
|
-
case "gte":
|
|
24
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) >= toNumber(b));
|
|
25
|
-
case "lt":
|
|
26
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) < toNumber(b));
|
|
27
|
-
case "lte":
|
|
28
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) <= toNumber(b));
|
|
29
|
-
// Logical
|
|
30
|
-
case "and":
|
|
31
|
-
return evaluateAnd(expr.args, ctx);
|
|
32
|
-
case "or":
|
|
33
|
-
return evaluateOr(expr.args, ctx);
|
|
34
|
-
case "not":
|
|
35
|
-
return evaluateNot(expr.arg, ctx);
|
|
36
|
-
// Conditional
|
|
37
|
-
case "if":
|
|
38
|
-
return evaluateIf(expr, ctx);
|
|
39
|
-
// Arithmetic
|
|
40
|
-
case "add":
|
|
41
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) + toNumber(b));
|
|
42
|
-
case "sub":
|
|
43
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) - toNumber(b));
|
|
44
|
-
case "mul":
|
|
45
|
-
return evaluateBinary(expr.left, expr.right, ctx, (a, b) => toNumber(a) * toNumber(b));
|
|
46
|
-
case "div":
|
|
47
|
-
return evaluateDiv(expr.left, expr.right, ctx);
|
|
48
|
-
case "mod":
|
|
49
|
-
return evaluateMod(expr.left, expr.right, ctx);
|
|
50
|
-
case "min":
|
|
51
|
-
return evaluateMin(expr.args, ctx);
|
|
52
|
-
case "max":
|
|
53
|
-
return evaluateMax(expr.args, ctx);
|
|
54
|
-
case "abs":
|
|
55
|
-
return evaluateAbs(expr.arg, ctx);
|
|
56
|
-
case "neg":
|
|
57
|
-
return evaluateNeg(expr.arg, ctx);
|
|
58
|
-
case "floor":
|
|
59
|
-
return evaluateFloor(expr.arg, ctx);
|
|
60
|
-
case "ceil":
|
|
61
|
-
return evaluateCeil(expr.arg, ctx);
|
|
62
|
-
case "round":
|
|
63
|
-
return evaluateRound(expr.arg, ctx);
|
|
64
|
-
case "sqrt":
|
|
65
|
-
return evaluateSqrt(expr.arg, ctx);
|
|
66
|
-
case "pow":
|
|
67
|
-
return evaluatePow(expr.base, expr.exponent, ctx);
|
|
68
|
-
case "sumArray":
|
|
69
|
-
return evaluateSumArray(expr.array, ctx);
|
|
70
|
-
case "minArray":
|
|
71
|
-
return evaluateMinArray(expr.array, ctx);
|
|
72
|
-
case "maxArray":
|
|
73
|
-
return evaluateMaxArray(expr.array, ctx);
|
|
74
|
-
// String
|
|
75
|
-
case "concat":
|
|
76
|
-
return evaluateConcat(expr.args, ctx);
|
|
77
|
-
case "substring":
|
|
78
|
-
return evaluateSubstring(expr, ctx);
|
|
79
|
-
case "trim":
|
|
80
|
-
return evaluateTrim(expr.str, ctx);
|
|
81
|
-
case "toLowerCase":
|
|
82
|
-
return evaluateToLowerCase(expr.str, ctx);
|
|
83
|
-
case "toUpperCase":
|
|
84
|
-
return evaluateToUpperCase(expr.str, ctx);
|
|
85
|
-
case "strLen":
|
|
86
|
-
return evaluateStrLen(expr.str, ctx);
|
|
87
|
-
case "startsWith":
|
|
88
|
-
return evaluateStartsWith(expr.str, expr.prefix, ctx);
|
|
89
|
-
case "endsWith":
|
|
90
|
-
return evaluateEndsWith(expr.str, expr.suffix, ctx);
|
|
91
|
-
case "strIncludes":
|
|
92
|
-
return evaluateStrIncludes(expr.str, expr.search, ctx);
|
|
93
|
-
case "indexOf":
|
|
94
|
-
return evaluateIndexOf(expr.str, expr.search, ctx);
|
|
95
|
-
case "replace":
|
|
96
|
-
return evaluateReplace(expr.str, expr.search, expr.replacement, ctx);
|
|
97
|
-
case "split":
|
|
98
|
-
return evaluateSplit(expr.str, expr.delimiter, ctx);
|
|
99
|
-
// Collection
|
|
100
|
-
case "len":
|
|
101
|
-
return evaluateLen(expr.arg, ctx);
|
|
102
|
-
case "at":
|
|
103
|
-
return evaluateAt(expr.array, expr.index, ctx);
|
|
104
|
-
case "first":
|
|
105
|
-
return evaluateFirst(expr.array, ctx);
|
|
106
|
-
case "last":
|
|
107
|
-
return evaluateLast(expr.array, ctx);
|
|
108
|
-
case "slice":
|
|
109
|
-
return evaluateSlice(expr, ctx);
|
|
110
|
-
case "includes":
|
|
111
|
-
return evaluateIncludes(expr.array, expr.item, ctx);
|
|
112
|
-
case "filter":
|
|
113
|
-
return evaluateFilter(expr.array, expr.predicate, ctx);
|
|
114
|
-
case "map":
|
|
115
|
-
return evaluateMap(expr.array, expr.mapper, ctx);
|
|
116
|
-
case "find":
|
|
117
|
-
return evaluateFind(expr.array, expr.predicate, ctx);
|
|
118
|
-
case "every":
|
|
119
|
-
return evaluateEvery(expr.array, expr.predicate, ctx);
|
|
120
|
-
case "some":
|
|
121
|
-
return evaluateSome(expr.array, expr.predicate, ctx);
|
|
122
|
-
case "append":
|
|
123
|
-
return evaluateAppend(expr.array, expr.items, ctx);
|
|
124
|
-
case "reverse":
|
|
125
|
-
return evaluateReverse(expr.array, ctx);
|
|
126
|
-
case "unique":
|
|
127
|
-
return evaluateUnique(expr.array, ctx);
|
|
128
|
-
case "flat":
|
|
129
|
-
return evaluateFlat(expr.array, ctx);
|
|
130
|
-
// Object
|
|
131
|
-
case "object":
|
|
132
|
-
return evaluateObject(expr.fields, ctx);
|
|
133
|
-
case "field":
|
|
134
|
-
return evaluateField(expr.object, expr.property, ctx);
|
|
135
|
-
case "keys":
|
|
136
|
-
return evaluateKeys(expr.obj, ctx);
|
|
137
|
-
case "values":
|
|
138
|
-
return evaluateValues(expr.obj, ctx);
|
|
139
|
-
case "entries":
|
|
140
|
-
return evaluateEntries(expr.obj, ctx);
|
|
141
|
-
case "merge":
|
|
142
|
-
return evaluateMerge(expr.objects, ctx);
|
|
143
|
-
case "hasKey":
|
|
144
|
-
return evaluateHasKey(expr.obj, expr.key, ctx);
|
|
145
|
-
case "pick":
|
|
146
|
-
return evaluatePick(expr.obj, expr.keys, ctx);
|
|
147
|
-
case "omit":
|
|
148
|
-
return evaluateOmit(expr.obj, expr.keys, ctx);
|
|
149
|
-
case "fromEntries":
|
|
150
|
-
return evaluateFromEntries(expr.entries, ctx);
|
|
151
|
-
// Type
|
|
152
|
-
case "typeof":
|
|
153
|
-
return evaluateTypeof(expr.arg, ctx);
|
|
154
|
-
case "isNull":
|
|
155
|
-
return evaluateIsNull(expr.arg, ctx);
|
|
156
|
-
case "coalesce":
|
|
157
|
-
return evaluateCoalesce(expr.args, ctx);
|
|
158
|
-
// Conversion
|
|
159
|
-
case "toString":
|
|
160
|
-
return evaluateToString(expr.arg, ctx);
|
|
161
|
-
case "toNumber":
|
|
162
|
-
return evaluateToNumber(expr.arg, ctx);
|
|
163
|
-
case "toBoolean":
|
|
164
|
-
return evaluateToBoolean(expr.arg, ctx);
|
|
165
|
-
default:
|
|
166
|
-
return err(createError("INTERNAL_ERROR", `Unknown expression kind: ${expr.kind}`, ctx.currentAction ?? "", ctx.nodePath, ctx.trace.timestamp));
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
// ============ Helper Functions ============
|
|
170
|
-
function toNumber(value) {
|
|
171
|
-
if (typeof value === "number")
|
|
172
|
-
return value;
|
|
173
|
-
if (typeof value === "string")
|
|
174
|
-
return parseFloat(value) || 0;
|
|
175
|
-
if (typeof value === "boolean")
|
|
176
|
-
return value ? 1 : 0;
|
|
177
|
-
return 0;
|
|
178
|
-
}
|
|
179
|
-
function toBoolean(value) {
|
|
180
|
-
if (value === null || value === undefined)
|
|
181
|
-
return false;
|
|
182
|
-
if (typeof value === "boolean")
|
|
183
|
-
return value;
|
|
184
|
-
if (typeof value === "number")
|
|
185
|
-
return value !== 0;
|
|
186
|
-
if (typeof value === "string")
|
|
187
|
-
return value.length > 0;
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
function toString(value) {
|
|
191
|
-
if (value === null || value === undefined)
|
|
192
|
-
return "";
|
|
193
|
-
if (typeof value === "string")
|
|
194
|
-
return value;
|
|
195
|
-
return String(value);
|
|
196
|
-
}
|
|
197
|
-
// ============ Get ============
|
|
198
|
-
/**
|
|
199
|
-
* Generate a deterministic UUID from intentId and counter
|
|
200
|
-
* Uses a simple hash to create reproducible UUIDs
|
|
201
|
-
*/
|
|
202
|
-
function generateDeterministicUuid(intentId, counter) {
|
|
203
|
-
// Create a simple hash-based UUID from intentId and counter
|
|
204
|
-
// This ensures the same intentId + counter always produces the same UUID
|
|
205
|
-
const seed = `${intentId}-${counter}`;
|
|
206
|
-
let hash = 0;
|
|
207
|
-
for (let i = 0; i < seed.length; i++) {
|
|
208
|
-
const char = seed.charCodeAt(i);
|
|
209
|
-
hash = ((hash << 5) - hash) + char;
|
|
210
|
-
hash = hash & hash; // Convert to 32-bit integer
|
|
211
|
-
}
|
|
212
|
-
// Convert hash to hex string and format as UUID
|
|
213
|
-
const hex = Math.abs(hash).toString(16).padStart(8, '0');
|
|
214
|
-
const hex2 = Math.abs(hash * 31).toString(16).padStart(4, '0');
|
|
215
|
-
const hex3 = Math.abs(hash * 37).toString(16).padStart(4, '0');
|
|
216
|
-
const hex4 = Math.abs(hash * 41).toString(16).padStart(4, '0');
|
|
217
|
-
const hex5 = Math.abs(hash * 43).toString(16).padStart(12, '0');
|
|
218
|
-
return `${hex.slice(0, 8)}-${hex2.slice(0, 4)}-4${hex3.slice(1, 4)}-${hex4.slice(0, 4)}-${hex5.slice(0, 12)}`;
|
|
219
|
-
}
|
|
220
|
-
function evaluateGet(path, ctx) {
|
|
221
|
-
// Handle collection context variables
|
|
222
|
-
if (path.startsWith("$item")) {
|
|
223
|
-
if (ctx.$item === undefined) {
|
|
224
|
-
return ok(undefined);
|
|
225
|
-
}
|
|
226
|
-
if (path === "$item") {
|
|
227
|
-
return ok(ctx.$item);
|
|
228
|
-
}
|
|
229
|
-
// e.g., $item.completed
|
|
230
|
-
const subPath = path.slice(6); // Remove "$item."
|
|
231
|
-
return ok(getByPath(ctx.$item, subPath));
|
|
232
|
-
}
|
|
233
|
-
if (path === "$index") {
|
|
234
|
-
return ok(ctx.$index);
|
|
235
|
-
}
|
|
236
|
-
if (path === "$array") {
|
|
237
|
-
return ok(ctx.$array);
|
|
238
|
-
}
|
|
239
|
-
// Handle $system paths (special runtime values)
|
|
240
|
-
if (path.startsWith("$system.")) {
|
|
241
|
-
const systemPath = path.slice(8); // Remove "$system."
|
|
242
|
-
if (systemPath === "uuid") {
|
|
243
|
-
// Generate deterministic UUID from intentId + counter
|
|
244
|
-
const intentId = ctx.intentId ?? "no-intent";
|
|
245
|
-
const counter = ctx.uuidCounter ?? 0;
|
|
246
|
-
// Increment counter for next uuid call (mutable on purpose for determinism across calls)
|
|
247
|
-
if (ctx.uuidCounter !== undefined) {
|
|
248
|
-
ctx.uuidCounter = counter + 1;
|
|
249
|
-
}
|
|
250
|
-
return ok(generateDeterministicUuid(intentId, counter));
|
|
251
|
-
}
|
|
252
|
-
if (systemPath === "timestamp") {
|
|
253
|
-
// Return the snapshot's timestamp (set by Host)
|
|
254
|
-
return ok(new Date(ctx.snapshot.meta.timestamp).toISOString());
|
|
255
|
-
}
|
|
256
|
-
// Unknown $system path
|
|
257
|
-
return ok(undefined);
|
|
258
|
-
}
|
|
259
|
-
// Handle meta path (snapshot metadata)
|
|
260
|
-
if (path.startsWith("meta.")) {
|
|
261
|
-
const metaPath = path.slice(5); // Remove "meta."
|
|
262
|
-
if (metaPath === "intentId") {
|
|
263
|
-
return ok(ctx.intentId);
|
|
264
|
-
}
|
|
265
|
-
if (metaPath === "actionName") {
|
|
266
|
-
return ok(ctx.currentAction);
|
|
267
|
-
}
|
|
268
|
-
return ok(getByPath(ctx.snapshot.meta, metaPath));
|
|
269
|
-
}
|
|
270
|
-
// Handle input path
|
|
271
|
-
if (path.startsWith("input.") || path === "input") {
|
|
272
|
-
const subPath = path === "input" ? "" : path.slice(6);
|
|
273
|
-
return ok(subPath ? getByPath(ctx.snapshot.input, subPath) : ctx.snapshot.input);
|
|
274
|
-
}
|
|
275
|
-
// Handle computed path
|
|
276
|
-
if (path.startsWith("computed.")) {
|
|
277
|
-
return ok(ctx.snapshot.computed[path]);
|
|
278
|
-
}
|
|
279
|
-
// Handle system path (snapshot.system, not $system)
|
|
280
|
-
if (path.startsWith("system.")) {
|
|
281
|
-
const subPath = path.slice(7);
|
|
282
|
-
return ok(getByPath(ctx.snapshot.system, subPath));
|
|
283
|
-
}
|
|
284
|
-
// Default: get from data
|
|
285
|
-
return ok(getByPath(ctx.snapshot.data, path));
|
|
286
|
-
}
|
|
287
|
-
// ============ Binary Operations ============
|
|
288
|
-
function evaluateBinary(left, right, ctx, op) {
|
|
289
|
-
const leftResult = evaluateExpr(left, ctx);
|
|
290
|
-
if (!leftResult.ok)
|
|
291
|
-
return leftResult;
|
|
292
|
-
const rightResult = evaluateExpr(right, ctx);
|
|
293
|
-
if (!rightResult.ok)
|
|
294
|
-
return rightResult;
|
|
295
|
-
return ok(op(leftResult.value, rightResult.value));
|
|
296
|
-
}
|
|
297
|
-
// ============ Logical ============
|
|
298
|
-
function evaluateAnd(args, ctx) {
|
|
299
|
-
for (const arg of args) {
|
|
300
|
-
const result = evaluateExpr(arg, ctx);
|
|
301
|
-
if (!result.ok)
|
|
302
|
-
return result;
|
|
303
|
-
if (!toBoolean(result.value))
|
|
304
|
-
return ok(false);
|
|
305
|
-
}
|
|
306
|
-
return ok(true);
|
|
307
|
-
}
|
|
308
|
-
function evaluateOr(args, ctx) {
|
|
309
|
-
for (const arg of args) {
|
|
310
|
-
const result = evaluateExpr(arg, ctx);
|
|
311
|
-
if (!result.ok)
|
|
312
|
-
return result;
|
|
313
|
-
if (toBoolean(result.value))
|
|
314
|
-
return ok(true);
|
|
315
|
-
}
|
|
316
|
-
return ok(false);
|
|
317
|
-
}
|
|
318
|
-
function evaluateNot(arg, ctx) {
|
|
319
|
-
const result = evaluateExpr(arg, ctx);
|
|
320
|
-
if (!result.ok)
|
|
321
|
-
return result;
|
|
322
|
-
return ok(!toBoolean(result.value));
|
|
323
|
-
}
|
|
324
|
-
// ============ Conditional ============
|
|
325
|
-
function evaluateIf(expr, ctx) {
|
|
326
|
-
const condResult = evaluateExpr(expr.cond, ctx);
|
|
327
|
-
if (!condResult.ok)
|
|
328
|
-
return condResult;
|
|
329
|
-
return evaluateExpr(toBoolean(condResult.value) ? expr.then : expr.else, ctx);
|
|
330
|
-
}
|
|
331
|
-
// ============ Arithmetic ============
|
|
332
|
-
function evaluateDiv(left, right, ctx) {
|
|
333
|
-
const leftResult = evaluateExpr(left, ctx);
|
|
334
|
-
if (!leftResult.ok)
|
|
335
|
-
return leftResult;
|
|
336
|
-
const rightResult = evaluateExpr(right, ctx);
|
|
337
|
-
if (!rightResult.ok)
|
|
338
|
-
return rightResult;
|
|
339
|
-
const divisor = toNumber(rightResult.value);
|
|
340
|
-
if (divisor === 0)
|
|
341
|
-
return ok(null); // Division by zero returns null, not error
|
|
342
|
-
return ok(toNumber(leftResult.value) / divisor);
|
|
343
|
-
}
|
|
344
|
-
function evaluateMod(left, right, ctx) {
|
|
345
|
-
const leftResult = evaluateExpr(left, ctx);
|
|
346
|
-
if (!leftResult.ok)
|
|
347
|
-
return leftResult;
|
|
348
|
-
const rightResult = evaluateExpr(right, ctx);
|
|
349
|
-
if (!rightResult.ok)
|
|
350
|
-
return rightResult;
|
|
351
|
-
const divisor = toNumber(rightResult.value);
|
|
352
|
-
if (divisor === 0)
|
|
353
|
-
return ok(null);
|
|
354
|
-
return ok(toNumber(leftResult.value) % divisor);
|
|
355
|
-
}
|
|
356
|
-
function evaluateMin(args, ctx) {
|
|
357
|
-
if (args.length === 0)
|
|
358
|
-
return ok(null);
|
|
359
|
-
const values = [];
|
|
360
|
-
for (const arg of args) {
|
|
361
|
-
const result = evaluateExpr(arg, ctx);
|
|
362
|
-
if (!result.ok)
|
|
363
|
-
return result;
|
|
364
|
-
values.push(toNumber(result.value));
|
|
365
|
-
}
|
|
366
|
-
return ok(Math.min(...values));
|
|
367
|
-
}
|
|
368
|
-
function evaluateMax(args, ctx) {
|
|
369
|
-
if (args.length === 0)
|
|
370
|
-
return ok(null);
|
|
371
|
-
const values = [];
|
|
372
|
-
for (const arg of args) {
|
|
373
|
-
const result = evaluateExpr(arg, ctx);
|
|
374
|
-
if (!result.ok)
|
|
375
|
-
return result;
|
|
376
|
-
values.push(toNumber(result.value));
|
|
377
|
-
}
|
|
378
|
-
return ok(Math.max(...values));
|
|
379
|
-
}
|
|
380
|
-
function evaluateAbs(arg, ctx) {
|
|
381
|
-
const result = evaluateExpr(arg, ctx);
|
|
382
|
-
if (!result.ok)
|
|
383
|
-
return result;
|
|
384
|
-
return ok(Math.abs(toNumber(result.value)));
|
|
385
|
-
}
|
|
386
|
-
function evaluateNeg(arg, ctx) {
|
|
387
|
-
const result = evaluateExpr(arg, ctx);
|
|
388
|
-
if (!result.ok)
|
|
389
|
-
return result;
|
|
390
|
-
return ok(-toNumber(result.value));
|
|
391
|
-
}
|
|
392
|
-
// ============ String ============
|
|
393
|
-
function evaluateConcat(args, ctx) {
|
|
394
|
-
// First, evaluate all arguments to determine if this is array or string concat
|
|
395
|
-
const values = [];
|
|
396
|
-
for (const arg of args) {
|
|
397
|
-
const result = evaluateExpr(arg, ctx);
|
|
398
|
-
if (!result.ok)
|
|
399
|
-
return result;
|
|
400
|
-
values.push(result.value);
|
|
401
|
-
}
|
|
402
|
-
// If any argument is an array, treat as array concatenation
|
|
403
|
-
const hasArray = values.some(v => Array.isArray(v));
|
|
404
|
-
if (hasArray) {
|
|
405
|
-
const result = [];
|
|
406
|
-
for (const value of values) {
|
|
407
|
-
if (Array.isArray(value)) {
|
|
408
|
-
result.push(...value);
|
|
409
|
-
}
|
|
410
|
-
else if (value !== null && value !== undefined) {
|
|
411
|
-
// Single value gets added as element
|
|
412
|
-
result.push(value);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
return ok(result);
|
|
416
|
-
}
|
|
417
|
-
// Otherwise, string concatenation
|
|
418
|
-
const parts = values.map(v => toString(v));
|
|
419
|
-
return ok(parts.join(""));
|
|
420
|
-
}
|
|
421
|
-
function evaluateSubstring(expr, ctx) {
|
|
422
|
-
const strResult = evaluateExpr(expr.str, ctx);
|
|
423
|
-
if (!strResult.ok)
|
|
424
|
-
return strResult;
|
|
425
|
-
const startResult = evaluateExpr(expr.start, ctx);
|
|
426
|
-
if (!startResult.ok)
|
|
427
|
-
return startResult;
|
|
428
|
-
const str = toString(strResult.value);
|
|
429
|
-
const start = toNumber(startResult.value);
|
|
430
|
-
if (expr.end) {
|
|
431
|
-
const endResult = evaluateExpr(expr.end, ctx);
|
|
432
|
-
if (!endResult.ok)
|
|
433
|
-
return endResult;
|
|
434
|
-
return ok(str.substring(start, toNumber(endResult.value)));
|
|
435
|
-
}
|
|
436
|
-
return ok(str.substring(start));
|
|
437
|
-
}
|
|
438
|
-
function evaluateTrim(str, ctx) {
|
|
439
|
-
const result = evaluateExpr(str, ctx);
|
|
440
|
-
if (!result.ok)
|
|
441
|
-
return result;
|
|
442
|
-
return ok(toString(result.value).trim());
|
|
443
|
-
}
|
|
444
|
-
// ============ Collection ============
|
|
445
|
-
function evaluateLen(arg, ctx) {
|
|
446
|
-
const result = evaluateExpr(arg, ctx);
|
|
447
|
-
if (!result.ok)
|
|
448
|
-
return result;
|
|
449
|
-
const value = result.value;
|
|
450
|
-
if (Array.isArray(value))
|
|
451
|
-
return ok(value.length);
|
|
452
|
-
if (typeof value === "string")
|
|
453
|
-
return ok(value.length);
|
|
454
|
-
if (typeof value === "object" && value !== null)
|
|
455
|
-
return ok(Object.keys(value).length);
|
|
456
|
-
return ok(0);
|
|
457
|
-
}
|
|
458
|
-
function evaluateAt(array, index, ctx) {
|
|
459
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
460
|
-
if (!arrayResult.ok)
|
|
461
|
-
return arrayResult;
|
|
462
|
-
const indexResult = evaluateExpr(index, ctx);
|
|
463
|
-
if (!indexResult.ok)
|
|
464
|
-
return indexResult;
|
|
465
|
-
const base = arrayResult.value;
|
|
466
|
-
const key = indexResult.value;
|
|
467
|
-
// Array indexing: at(array, numericIndex)
|
|
468
|
-
if (Array.isArray(base)) {
|
|
469
|
-
const idx = toNumber(key);
|
|
470
|
-
if (idx < 0 || idx >= base.length)
|
|
471
|
-
return ok(null);
|
|
472
|
-
return ok(base[idx]);
|
|
473
|
-
}
|
|
474
|
-
// Record lookup: at(record, stringKey)
|
|
475
|
-
if (typeof base === "object" && base !== null && typeof key === "string") {
|
|
476
|
-
return ok(base[key] ?? null);
|
|
477
|
-
}
|
|
478
|
-
return ok(null);
|
|
479
|
-
}
|
|
480
|
-
function evaluateFirst(array, ctx) {
|
|
481
|
-
const result = evaluateExpr(array, ctx);
|
|
482
|
-
if (!result.ok)
|
|
483
|
-
return result;
|
|
484
|
-
const arr = result.value;
|
|
485
|
-
if (!Array.isArray(arr) || arr.length === 0)
|
|
486
|
-
return ok(null);
|
|
487
|
-
return ok(arr[0]);
|
|
488
|
-
}
|
|
489
|
-
function evaluateLast(array, ctx) {
|
|
490
|
-
const result = evaluateExpr(array, ctx);
|
|
491
|
-
if (!result.ok)
|
|
492
|
-
return result;
|
|
493
|
-
const arr = result.value;
|
|
494
|
-
if (!Array.isArray(arr) || arr.length === 0)
|
|
495
|
-
return ok(null);
|
|
496
|
-
return ok(arr[arr.length - 1]);
|
|
497
|
-
}
|
|
498
|
-
function evaluateSlice(expr, ctx) {
|
|
499
|
-
const arrayResult = evaluateExpr(expr.array, ctx);
|
|
500
|
-
if (!arrayResult.ok)
|
|
501
|
-
return arrayResult;
|
|
502
|
-
const startResult = evaluateExpr(expr.start, ctx);
|
|
503
|
-
if (!startResult.ok)
|
|
504
|
-
return startResult;
|
|
505
|
-
const arr = arrayResult.value;
|
|
506
|
-
if (!Array.isArray(arr))
|
|
507
|
-
return ok([]);
|
|
508
|
-
const start = toNumber(startResult.value);
|
|
509
|
-
if (expr.end) {
|
|
510
|
-
const endResult = evaluateExpr(expr.end, ctx);
|
|
511
|
-
if (!endResult.ok)
|
|
512
|
-
return endResult;
|
|
513
|
-
return ok(arr.slice(start, toNumber(endResult.value)));
|
|
514
|
-
}
|
|
515
|
-
return ok(arr.slice(start));
|
|
516
|
-
}
|
|
517
|
-
function evaluateIncludes(array, item, ctx) {
|
|
518
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
519
|
-
if (!arrayResult.ok)
|
|
520
|
-
return arrayResult;
|
|
521
|
-
const itemResult = evaluateExpr(item, ctx);
|
|
522
|
-
if (!itemResult.ok)
|
|
523
|
-
return itemResult;
|
|
524
|
-
const arr = arrayResult.value;
|
|
525
|
-
if (!Array.isArray(arr))
|
|
526
|
-
return ok(false);
|
|
527
|
-
return ok(arr.includes(itemResult.value));
|
|
528
|
-
}
|
|
529
|
-
function evaluateFilter(array, predicate, ctx) {
|
|
530
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
531
|
-
if (!arrayResult.ok)
|
|
532
|
-
return arrayResult;
|
|
533
|
-
const arr = arrayResult.value;
|
|
534
|
-
if (!Array.isArray(arr))
|
|
535
|
-
return ok([]);
|
|
536
|
-
const filtered = [];
|
|
537
|
-
for (let i = 0; i < arr.length; i++) {
|
|
538
|
-
const itemCtx = withCollectionContext(ctx, arr[i], i, arr);
|
|
539
|
-
const predicateResult = evaluateExpr(predicate, itemCtx);
|
|
540
|
-
if (!predicateResult.ok)
|
|
541
|
-
return predicateResult;
|
|
542
|
-
if (toBoolean(predicateResult.value)) {
|
|
543
|
-
filtered.push(arr[i]);
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
return ok(filtered);
|
|
547
|
-
}
|
|
548
|
-
function evaluateMap(array, mapper, ctx) {
|
|
549
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
550
|
-
if (!arrayResult.ok)
|
|
551
|
-
return arrayResult;
|
|
552
|
-
const arr = arrayResult.value;
|
|
553
|
-
if (!Array.isArray(arr))
|
|
554
|
-
return ok([]);
|
|
555
|
-
const mapped = [];
|
|
556
|
-
for (let i = 0; i < arr.length; i++) {
|
|
557
|
-
const itemCtx = withCollectionContext(ctx, arr[i], i, arr);
|
|
558
|
-
const mapResult = evaluateExpr(mapper, itemCtx);
|
|
559
|
-
if (!mapResult.ok)
|
|
560
|
-
return mapResult;
|
|
561
|
-
mapped.push(mapResult.value);
|
|
562
|
-
}
|
|
563
|
-
return ok(mapped);
|
|
564
|
-
}
|
|
565
|
-
function evaluateFind(array, predicate, ctx) {
|
|
566
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
567
|
-
if (!arrayResult.ok)
|
|
568
|
-
return arrayResult;
|
|
569
|
-
const arr = arrayResult.value;
|
|
570
|
-
if (!Array.isArray(arr))
|
|
571
|
-
return ok(null);
|
|
572
|
-
for (let i = 0; i < arr.length; i++) {
|
|
573
|
-
const itemCtx = withCollectionContext(ctx, arr[i], i, arr);
|
|
574
|
-
const predicateResult = evaluateExpr(predicate, itemCtx);
|
|
575
|
-
if (!predicateResult.ok)
|
|
576
|
-
return predicateResult;
|
|
577
|
-
if (toBoolean(predicateResult.value)) {
|
|
578
|
-
return ok(arr[i]);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
return ok(null);
|
|
582
|
-
}
|
|
583
|
-
function evaluateEvery(array, predicate, ctx) {
|
|
584
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
585
|
-
if (!arrayResult.ok)
|
|
586
|
-
return arrayResult;
|
|
587
|
-
const arr = arrayResult.value;
|
|
588
|
-
if (!Array.isArray(arr))
|
|
589
|
-
return ok(true);
|
|
590
|
-
for (let i = 0; i < arr.length; i++) {
|
|
591
|
-
const itemCtx = withCollectionContext(ctx, arr[i], i, arr);
|
|
592
|
-
const predicateResult = evaluateExpr(predicate, itemCtx);
|
|
593
|
-
if (!predicateResult.ok)
|
|
594
|
-
return predicateResult;
|
|
595
|
-
if (!toBoolean(predicateResult.value)) {
|
|
596
|
-
return ok(false);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
return ok(true);
|
|
600
|
-
}
|
|
601
|
-
function evaluateSome(array, predicate, ctx) {
|
|
602
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
603
|
-
if (!arrayResult.ok)
|
|
604
|
-
return arrayResult;
|
|
605
|
-
const arr = arrayResult.value;
|
|
606
|
-
if (!Array.isArray(arr))
|
|
607
|
-
return ok(false);
|
|
608
|
-
for (let i = 0; i < arr.length; i++) {
|
|
609
|
-
const itemCtx = withCollectionContext(ctx, arr[i], i, arr);
|
|
610
|
-
const predicateResult = evaluateExpr(predicate, itemCtx);
|
|
611
|
-
if (!predicateResult.ok)
|
|
612
|
-
return predicateResult;
|
|
613
|
-
if (toBoolean(predicateResult.value)) {
|
|
614
|
-
return ok(true);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
return ok(false);
|
|
618
|
-
}
|
|
619
|
-
function evaluateAppend(array, items, ctx) {
|
|
620
|
-
const arrayResult = evaluateExpr(array, ctx);
|
|
621
|
-
if (!arrayResult.ok)
|
|
622
|
-
return arrayResult;
|
|
623
|
-
const arr = arrayResult.value;
|
|
624
|
-
const baseArray = Array.isArray(arr) ? [...arr] : [];
|
|
625
|
-
for (const itemExpr of items) {
|
|
626
|
-
const itemResult = evaluateExpr(itemExpr, ctx);
|
|
627
|
-
if (!itemResult.ok)
|
|
628
|
-
return itemResult;
|
|
629
|
-
baseArray.push(itemResult.value);
|
|
630
|
-
}
|
|
631
|
-
return ok(baseArray);
|
|
632
|
-
}
|
|
633
|
-
// ============ Object ============
|
|
634
|
-
function evaluateObject(fields, ctx) {
|
|
635
|
-
const result = {};
|
|
636
|
-
for (const [key, valueExpr] of Object.entries(fields)) {
|
|
637
|
-
const valueResult = evaluateExpr(valueExpr, ctx);
|
|
638
|
-
if (!valueResult.ok)
|
|
639
|
-
return valueResult;
|
|
640
|
-
result[key] = valueResult.value;
|
|
641
|
-
}
|
|
642
|
-
return ok(result);
|
|
643
|
-
}
|
|
644
|
-
function evaluateField(objectExpr, property, ctx) {
|
|
645
|
-
const result = evaluateExpr(objectExpr, ctx);
|
|
646
|
-
if (!result.ok)
|
|
647
|
-
return result;
|
|
648
|
-
const obj = result.value;
|
|
649
|
-
if (typeof obj !== "object" || obj === null || Array.isArray(obj))
|
|
650
|
-
return ok(null);
|
|
651
|
-
return ok(obj[property] ?? null);
|
|
652
|
-
}
|
|
653
|
-
function evaluateKeys(obj, ctx) {
|
|
654
|
-
const result = evaluateExpr(obj, ctx);
|
|
655
|
-
if (!result.ok)
|
|
656
|
-
return result;
|
|
657
|
-
const value = result.value;
|
|
658
|
-
if (typeof value !== "object" || value === null)
|
|
659
|
-
return ok([]);
|
|
660
|
-
return ok(Object.keys(value));
|
|
661
|
-
}
|
|
662
|
-
function evaluateValues(obj, ctx) {
|
|
663
|
-
const result = evaluateExpr(obj, ctx);
|
|
664
|
-
if (!result.ok)
|
|
665
|
-
return result;
|
|
666
|
-
const value = result.value;
|
|
667
|
-
if (typeof value !== "object" || value === null)
|
|
668
|
-
return ok([]);
|
|
669
|
-
return ok(Object.values(value));
|
|
670
|
-
}
|
|
671
|
-
function evaluateEntries(obj, ctx) {
|
|
672
|
-
const result = evaluateExpr(obj, ctx);
|
|
673
|
-
if (!result.ok)
|
|
674
|
-
return result;
|
|
675
|
-
const value = result.value;
|
|
676
|
-
if (typeof value !== "object" || value === null)
|
|
677
|
-
return ok([]);
|
|
678
|
-
return ok(Object.entries(value));
|
|
679
|
-
}
|
|
680
|
-
function evaluateMerge(objects, ctx) {
|
|
681
|
-
const merged = {};
|
|
682
|
-
for (const objExpr of objects) {
|
|
683
|
-
const result = evaluateExpr(objExpr, ctx);
|
|
684
|
-
if (!result.ok)
|
|
685
|
-
return result;
|
|
686
|
-
const value = result.value;
|
|
687
|
-
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
688
|
-
Object.assign(merged, value);
|
|
689
|
-
}
|
|
690
|
-
}
|
|
691
|
-
return ok(merged);
|
|
692
|
-
}
|
|
693
|
-
// ============ Type ============
|
|
694
|
-
function evaluateTypeof(arg, ctx) {
|
|
695
|
-
const result = evaluateExpr(arg, ctx);
|
|
696
|
-
if (!result.ok)
|
|
697
|
-
return result;
|
|
698
|
-
const value = result.value;
|
|
699
|
-
if (value === null)
|
|
700
|
-
return ok("null");
|
|
701
|
-
if (Array.isArray(value))
|
|
702
|
-
return ok("array");
|
|
703
|
-
return ok(typeof value);
|
|
704
|
-
}
|
|
705
|
-
function evaluateIsNull(arg, ctx) {
|
|
706
|
-
const result = evaluateExpr(arg, ctx);
|
|
707
|
-
if (!result.ok)
|
|
708
|
-
return result;
|
|
709
|
-
return ok(result.value === null || result.value === undefined);
|
|
710
|
-
}
|
|
711
|
-
function evaluateCoalesce(args, ctx) {
|
|
712
|
-
for (const arg of args) {
|
|
713
|
-
const result = evaluateExpr(arg, ctx);
|
|
714
|
-
if (!result.ok)
|
|
715
|
-
return result;
|
|
716
|
-
if (result.value !== null && result.value !== undefined) {
|
|
717
|
-
return result;
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
return ok(null);
|
|
721
|
-
}
|
|
722
|
-
// ============ Arithmetic Extended (SPEC v2.0.0) ============
|
|
723
|
-
function evaluateFloor(arg, ctx) {
|
|
724
|
-
const result = evaluateExpr(arg, ctx);
|
|
725
|
-
if (!result.ok)
|
|
726
|
-
return result;
|
|
727
|
-
return ok(Math.floor(toNumber(result.value)));
|
|
728
|
-
}
|
|
729
|
-
function evaluateCeil(arg, ctx) {
|
|
730
|
-
const result = evaluateExpr(arg, ctx);
|
|
731
|
-
if (!result.ok)
|
|
732
|
-
return result;
|
|
733
|
-
return ok(Math.ceil(toNumber(result.value)));
|
|
734
|
-
}
|
|
735
|
-
function evaluateRound(arg, ctx) {
|
|
736
|
-
const result = evaluateExpr(arg, ctx);
|
|
737
|
-
if (!result.ok)
|
|
738
|
-
return result;
|
|
739
|
-
return ok(Math.round(toNumber(result.value)));
|
|
740
|
-
}
|
|
741
|
-
function evaluateSqrt(arg, ctx) {
|
|
742
|
-
const result = evaluateExpr(arg, ctx);
|
|
743
|
-
if (!result.ok)
|
|
744
|
-
return result;
|
|
745
|
-
const n = toNumber(result.value);
|
|
746
|
-
if (n < 0)
|
|
747
|
-
return ok(null);
|
|
748
|
-
return ok(Math.sqrt(n));
|
|
749
|
-
}
|
|
750
|
-
function evaluatePow(base, exponent, ctx) {
|
|
751
|
-
const baseResult = evaluateExpr(base, ctx);
|
|
752
|
-
if (!baseResult.ok)
|
|
753
|
-
return baseResult;
|
|
754
|
-
const expResult = evaluateExpr(exponent, ctx);
|
|
755
|
-
if (!expResult.ok)
|
|
756
|
-
return expResult;
|
|
757
|
-
const result = Math.pow(toNumber(baseResult.value), toNumber(expResult.value));
|
|
758
|
-
if (!Number.isFinite(result))
|
|
759
|
-
return ok(null);
|
|
760
|
-
return ok(result);
|
|
761
|
-
}
|
|
762
|
-
// ============ Array Aggregation (SPEC v2.0.0) ============
|
|
763
|
-
function evaluateSumArray(array, ctx) {
|
|
764
|
-
const result = evaluateExpr(array, ctx);
|
|
765
|
-
if (!result.ok)
|
|
766
|
-
return result;
|
|
767
|
-
const arr = result.value;
|
|
768
|
-
if (!Array.isArray(arr))
|
|
769
|
-
return ok(0);
|
|
770
|
-
let sum = 0;
|
|
771
|
-
for (const item of arr) {
|
|
772
|
-
sum += toNumber(item);
|
|
773
|
-
}
|
|
774
|
-
return ok(sum);
|
|
775
|
-
}
|
|
776
|
-
function evaluateMinArray(array, ctx) {
|
|
777
|
-
const result = evaluateExpr(array, ctx);
|
|
778
|
-
if (!result.ok)
|
|
779
|
-
return result;
|
|
780
|
-
const arr = result.value;
|
|
781
|
-
if (!Array.isArray(arr) || arr.length === 0)
|
|
782
|
-
return ok(null);
|
|
783
|
-
let min = toNumber(arr[0]);
|
|
784
|
-
for (let i = 1; i < arr.length; i++) {
|
|
785
|
-
const n = toNumber(arr[i]);
|
|
786
|
-
if (n < min)
|
|
787
|
-
min = n;
|
|
788
|
-
}
|
|
789
|
-
return ok(min);
|
|
790
|
-
}
|
|
791
|
-
function evaluateMaxArray(array, ctx) {
|
|
792
|
-
const result = evaluateExpr(array, ctx);
|
|
793
|
-
if (!result.ok)
|
|
794
|
-
return result;
|
|
795
|
-
const arr = result.value;
|
|
796
|
-
if (!Array.isArray(arr) || arr.length === 0)
|
|
797
|
-
return ok(null);
|
|
798
|
-
let max = toNumber(arr[0]);
|
|
799
|
-
for (let i = 1; i < arr.length; i++) {
|
|
800
|
-
const n = toNumber(arr[i]);
|
|
801
|
-
if (n > max)
|
|
802
|
-
max = n;
|
|
803
|
-
}
|
|
804
|
-
return ok(max);
|
|
805
|
-
}
|
|
806
|
-
// ============ String Extended (SPEC v2.0.0 + v2.0.3) ============
|
|
807
|
-
function evaluateToLowerCase(str, ctx) {
|
|
808
|
-
const result = evaluateExpr(str, ctx);
|
|
809
|
-
if (!result.ok)
|
|
810
|
-
return result;
|
|
811
|
-
return ok(toString(result.value).toLowerCase());
|
|
812
|
-
}
|
|
813
|
-
function evaluateToUpperCase(str, ctx) {
|
|
814
|
-
const result = evaluateExpr(str, ctx);
|
|
815
|
-
if (!result.ok)
|
|
816
|
-
return result;
|
|
817
|
-
return ok(toString(result.value).toUpperCase());
|
|
818
|
-
}
|
|
819
|
-
function evaluateStrLen(str, ctx) {
|
|
820
|
-
const result = evaluateExpr(str, ctx);
|
|
821
|
-
if (!result.ok)
|
|
822
|
-
return result;
|
|
823
|
-
return ok(toString(result.value).length);
|
|
824
|
-
}
|
|
825
|
-
function evaluateStartsWith(str, prefix, ctx) {
|
|
826
|
-
const strResult = evaluateExpr(str, ctx);
|
|
827
|
-
if (!strResult.ok)
|
|
828
|
-
return strResult;
|
|
829
|
-
const prefixResult = evaluateExpr(prefix, ctx);
|
|
830
|
-
if (!prefixResult.ok)
|
|
831
|
-
return prefixResult;
|
|
832
|
-
return ok(toString(strResult.value).startsWith(toString(prefixResult.value)));
|
|
833
|
-
}
|
|
834
|
-
function evaluateEndsWith(str, suffix, ctx) {
|
|
835
|
-
const strResult = evaluateExpr(str, ctx);
|
|
836
|
-
if (!strResult.ok)
|
|
837
|
-
return strResult;
|
|
838
|
-
const suffixResult = evaluateExpr(suffix, ctx);
|
|
839
|
-
if (!suffixResult.ok)
|
|
840
|
-
return suffixResult;
|
|
841
|
-
return ok(toString(strResult.value).endsWith(toString(suffixResult.value)));
|
|
842
|
-
}
|
|
843
|
-
function evaluateStrIncludes(str, search, ctx) {
|
|
844
|
-
const strResult = evaluateExpr(str, ctx);
|
|
845
|
-
if (!strResult.ok)
|
|
846
|
-
return strResult;
|
|
847
|
-
const searchResult = evaluateExpr(search, ctx);
|
|
848
|
-
if (!searchResult.ok)
|
|
849
|
-
return searchResult;
|
|
850
|
-
return ok(toString(strResult.value).includes(toString(searchResult.value)));
|
|
851
|
-
}
|
|
852
|
-
function evaluateIndexOf(str, search, ctx) {
|
|
853
|
-
const strResult = evaluateExpr(str, ctx);
|
|
854
|
-
if (!strResult.ok)
|
|
855
|
-
return strResult;
|
|
856
|
-
const searchResult = evaluateExpr(search, ctx);
|
|
857
|
-
if (!searchResult.ok)
|
|
858
|
-
return searchResult;
|
|
859
|
-
return ok(toString(strResult.value).indexOf(toString(searchResult.value)));
|
|
860
|
-
}
|
|
861
|
-
function evaluateReplace(str, search, replacement, ctx) {
|
|
862
|
-
const strResult = evaluateExpr(str, ctx);
|
|
863
|
-
if (!strResult.ok)
|
|
864
|
-
return strResult;
|
|
865
|
-
const searchResult = evaluateExpr(search, ctx);
|
|
866
|
-
if (!searchResult.ok)
|
|
867
|
-
return searchResult;
|
|
868
|
-
const replacementResult = evaluateExpr(replacement, ctx);
|
|
869
|
-
if (!replacementResult.ok)
|
|
870
|
-
return replacementResult;
|
|
871
|
-
// String.prototype.replace with string arg replaces only the first occurrence
|
|
872
|
-
return ok(toString(strResult.value).replace(toString(searchResult.value), toString(replacementResult.value)));
|
|
873
|
-
}
|
|
874
|
-
function evaluateSplit(str, delimiter, ctx) {
|
|
875
|
-
const strResult = evaluateExpr(str, ctx);
|
|
876
|
-
if (!strResult.ok)
|
|
877
|
-
return strResult;
|
|
878
|
-
const delimiterResult = evaluateExpr(delimiter, ctx);
|
|
879
|
-
if (!delimiterResult.ok)
|
|
880
|
-
return delimiterResult;
|
|
881
|
-
const result = toString(strResult.value).split(toString(delimiterResult.value));
|
|
882
|
-
// JS returns [] for "".split(""); SPEC requires at least one element
|
|
883
|
-
return ok(result.length === 0 ? [""] : result);
|
|
884
|
-
}
|
|
885
|
-
// ============ Collection Extended (SPEC v2.0.3) ============
|
|
886
|
-
function evaluateReverse(array, ctx) {
|
|
887
|
-
const result = evaluateExpr(array, ctx);
|
|
888
|
-
if (!result.ok)
|
|
889
|
-
return result;
|
|
890
|
-
const arr = result.value;
|
|
891
|
-
if (!Array.isArray(arr))
|
|
892
|
-
return ok([]);
|
|
893
|
-
return ok([...arr].reverse());
|
|
894
|
-
}
|
|
895
|
-
function evaluateUnique(array, ctx) {
|
|
896
|
-
const result = evaluateExpr(array, ctx);
|
|
897
|
-
if (!result.ok)
|
|
898
|
-
return result;
|
|
899
|
-
const arr = result.value;
|
|
900
|
-
if (!Array.isArray(arr))
|
|
901
|
-
return ok([]);
|
|
902
|
-
// SPEC: strict equality (===), preserve first-occurrence order
|
|
903
|
-
const seen = [];
|
|
904
|
-
const unique = [];
|
|
905
|
-
for (const item of arr) {
|
|
906
|
-
if (!seen.some(s => s === item)) {
|
|
907
|
-
seen.push(item);
|
|
908
|
-
unique.push(item);
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
return ok(unique);
|
|
912
|
-
}
|
|
913
|
-
function evaluateFlat(array, ctx) {
|
|
914
|
-
const result = evaluateExpr(array, ctx);
|
|
915
|
-
if (!result.ok)
|
|
916
|
-
return result;
|
|
917
|
-
const arr = result.value;
|
|
918
|
-
if (!Array.isArray(arr))
|
|
919
|
-
return ok([]);
|
|
920
|
-
// SPEC: flatten exactly one level
|
|
921
|
-
const flattened = [];
|
|
922
|
-
for (const item of arr) {
|
|
923
|
-
if (Array.isArray(item)) {
|
|
924
|
-
flattened.push(...item);
|
|
925
|
-
}
|
|
926
|
-
else {
|
|
927
|
-
flattened.push(item);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
return ok(flattened);
|
|
931
|
-
}
|
|
932
|
-
// ============ Object Extended (SPEC v2.0.3) ============
|
|
933
|
-
function evaluateHasKey(obj, key, ctx) {
|
|
934
|
-
const objResult = evaluateExpr(obj, ctx);
|
|
935
|
-
if (!objResult.ok)
|
|
936
|
-
return objResult;
|
|
937
|
-
const keyResult = evaluateExpr(key, ctx);
|
|
938
|
-
if (!keyResult.ok)
|
|
939
|
-
return keyResult;
|
|
940
|
-
const value = objResult.value;
|
|
941
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
942
|
-
return ok(false);
|
|
943
|
-
const k = keyResult.value;
|
|
944
|
-
if (typeof k !== "string")
|
|
945
|
-
return ok(false);
|
|
946
|
-
return ok(Object.prototype.hasOwnProperty.call(value, k));
|
|
947
|
-
}
|
|
948
|
-
function evaluatePick(obj, keys, ctx) {
|
|
949
|
-
const objResult = evaluateExpr(obj, ctx);
|
|
950
|
-
if (!objResult.ok)
|
|
951
|
-
return objResult;
|
|
952
|
-
const keysResult = evaluateExpr(keys, ctx);
|
|
953
|
-
if (!keysResult.ok)
|
|
954
|
-
return keysResult;
|
|
955
|
-
const value = objResult.value;
|
|
956
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
957
|
-
return ok({});
|
|
958
|
-
const keyList = keysResult.value;
|
|
959
|
-
if (!Array.isArray(keyList))
|
|
960
|
-
return ok({});
|
|
961
|
-
const result = {};
|
|
962
|
-
for (const k of keyList) {
|
|
963
|
-
if (typeof k === "string" && Object.prototype.hasOwnProperty.call(value, k)) {
|
|
964
|
-
result[k] = value[k];
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
return ok(result);
|
|
968
|
-
}
|
|
969
|
-
function evaluateOmit(obj, keys, ctx) {
|
|
970
|
-
const objResult = evaluateExpr(obj, ctx);
|
|
971
|
-
if (!objResult.ok)
|
|
972
|
-
return objResult;
|
|
973
|
-
const keysResult = evaluateExpr(keys, ctx);
|
|
974
|
-
if (!keysResult.ok)
|
|
975
|
-
return keysResult;
|
|
976
|
-
const value = objResult.value;
|
|
977
|
-
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
978
|
-
return ok({});
|
|
979
|
-
const keyList = keysResult.value;
|
|
980
|
-
const excludeSet = new Set();
|
|
981
|
-
if (Array.isArray(keyList)) {
|
|
982
|
-
for (const k of keyList) {
|
|
983
|
-
if (typeof k === "string")
|
|
984
|
-
excludeSet.add(k);
|
|
985
|
-
}
|
|
986
|
-
}
|
|
987
|
-
const result = {};
|
|
988
|
-
for (const [k, v] of Object.entries(value)) {
|
|
989
|
-
if (!excludeSet.has(k)) {
|
|
990
|
-
result[k] = v;
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
return ok(result);
|
|
994
|
-
}
|
|
995
|
-
function evaluateFromEntries(entries, ctx) {
|
|
996
|
-
const result = evaluateExpr(entries, ctx);
|
|
997
|
-
if (!result.ok)
|
|
998
|
-
return result;
|
|
999
|
-
const arr = result.value;
|
|
1000
|
-
if (!Array.isArray(arr))
|
|
1001
|
-
return ok({});
|
|
1002
|
-
const obj = {};
|
|
1003
|
-
for (const entry of arr) {
|
|
1004
|
-
// SPEC: skip entries that are not 2-element arrays with string key
|
|
1005
|
-
if (Array.isArray(entry) && entry.length === 2 && typeof entry[0] === "string") {
|
|
1006
|
-
obj[entry[0]] = entry[1];
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
return ok(obj);
|
|
1010
|
-
}
|
|
1011
|
-
// ============ Conversion (SPEC v2.0.0 + v2.0.3) ============
|
|
1012
|
-
function evaluateToString(arg, ctx) {
|
|
1013
|
-
const result = evaluateExpr(arg, ctx);
|
|
1014
|
-
if (!result.ok)
|
|
1015
|
-
return result;
|
|
1016
|
-
return ok(toString(result.value));
|
|
1017
|
-
}
|
|
1018
|
-
function evaluateToNumber(arg, ctx) {
|
|
1019
|
-
const result = evaluateExpr(arg, ctx);
|
|
1020
|
-
if (!result.ok)
|
|
1021
|
-
return result;
|
|
1022
|
-
return ok(toNumber(result.value));
|
|
1023
|
-
}
|
|
1024
|
-
function evaluateToBoolean(arg, ctx) {
|
|
1025
|
-
const result = evaluateExpr(arg, ctx);
|
|
1026
|
-
if (!result.ok)
|
|
1027
|
-
return result;
|
|
1028
|
-
return ok(toBoolean(result.value));
|
|
1029
|
-
}
|
|
1030
|
-
//# sourceMappingURL=expr.js.map
|