@revisium/formula 0.4.0 → 0.6.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.
@@ -1,1266 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkQ7SFCCGT_cjs = require('./chunk-Q7SFCCGT.cjs');
4
-
5
- // node_modules/subscript/src/parse.js
6
- var parse_exports = {};
7
- chunkQ7SFCCGT_cjs.__export(parse_exports, {
8
- access: () => access,
9
- binary: () => binary,
10
- cur: () => cur,
11
- default: () => parse_default,
12
- err: () => err2,
13
- expr: () => expr,
14
- group: () => group,
15
- id: () => id,
16
- idx: () => idx,
17
- lookup: () => lookup,
18
- nary: () => nary,
19
- next: () => next,
20
- parse: () => parse,
21
- skip: () => skip,
22
- space: () => space,
23
- token: () => token,
24
- unary: () => unary
25
- });
26
-
27
- // node_modules/subscript/src/const.js
28
- var PERIOD = 46;
29
- var SPACE = 32;
30
- var DQUOTE = 34;
31
- var QUOTE = 39;
32
- var _0 = 48;
33
- var _9 = 57;
34
- var _E = 69;
35
- var _e = 101;
36
- var BSLASH = 92;
37
- var PREC_STATEMENT = 5;
38
- var PREC_SEQ = 10;
39
- var PREC_ASSIGN = 20;
40
- var PREC_LOR = 30;
41
- var PREC_LAND = 40;
42
- var PREC_OR = 50;
43
- var PREC_XOR = 60;
44
- var PREC_AND = 70;
45
- var PREC_EQ = 80;
46
- var PREC_COMP = 90;
47
- var PREC_SHIFT = 100;
48
- var PREC_ADD = 110;
49
- var PREC_MULT = 120;
50
- var PREC_PREFIX = 140;
51
- var PREC_POSTFIX = 150;
52
- var PREC_ACCESS = 170;
53
- var unsafe = (k) => k?.[0] === "_" && k[1] === "_" || k === "constructor" || k === "prototype";
54
-
55
- // node_modules/subscript/src/parse.js
56
- var idx;
57
- var cur;
58
- var parse = (s) => (idx = 0, cur = s, s = expr(), cur[idx] ? err2() : s || "");
59
- var err2 = (msg = "Unexpected token", lines = cur.slice(0, idx).split("\n"), last2 = lines.pop(), before = cur.slice(Math.max(0, idx - 40), idx), after = cur.slice(idx, idx + 20)) => {
60
- throw SyntaxError(`${msg} at ${lines.length + 1}:${last2.length + 1} \u2014 ${before}^${after}`);
61
- };
62
- var next = (is, from = idx, l) => {
63
- while (l = is(cur.charCodeAt(idx))) idx += l;
64
- return cur.slice(from, idx);
65
- };
66
- var skip = () => cur[idx++];
67
- var expr = (prec = 0, end) => {
68
- let cc, token2, newNode, fn;
69
- while ((cc = space()) && // till not end
70
- // NOTE: when lookup bails on lower precedence, parent expr re-calls space() — acceptable overhead
71
- (newNode = ((fn = lookup[cc]) && fn(token2, prec)) ?? // if operator with higher precedence isn't found
72
- (!token2 && next(parse.id)))) token2 = newNode;
73
- if (end) cc == end ? idx++ : err2("Unclosed " + String.fromCharCode(end - (end > 42 ? 2 : 1)));
74
- return token2;
75
- };
76
- var space = (cc) => {
77
- while ((cc = cur.charCodeAt(idx)) <= SPACE) idx++;
78
- return cc;
79
- };
80
- var id = parse.id = (c) => c >= 48 && c <= 57 || // 0..9
81
- c >= 65 && c <= 90 || // A...Z
82
- c >= 97 && c <= 122 || // a...z
83
- c == 36 || c == 95 || // $, _,
84
- c >= 192 && c != 215 && c != 247;
85
- var lookup = [];
86
- var token = (op, prec = SPACE, map, c = op.charCodeAt(0), l = op.length, prev = lookup[c], word = op.toUpperCase() !== op) => lookup[c] = (a, curPrec, curOp, from = idx) => (curOp ? op == curOp : (l < 2 || cur.substr(idx, l) == op) && (curOp = op)) && curPrec < prec && // matches precedence AFTER operator matched
87
- !(word && parse.id(cur.charCodeAt(idx + l))) && // finished word, not part of bigger word
88
- (idx += l, map(a) || (idx = from, !prev && err2())) || prev?.(a, curPrec, curOp);
89
- var binary = (op, prec, right = false) => token(op, prec, (a, b) => a && (b = expr(prec - (right ? 0.5 : 0))) && [op, a, b]);
90
- var unary = (op, prec, post) => token(op, prec, (a) => post ? a && [op, a] : !a && (a = expr(prec - 0.5)) && [op, a]);
91
- var nary = (op, prec, right) => {
92
- token(
93
- op,
94
- prec,
95
- (a, b) => (b = expr(prec - (right ? 0.5 : 0)), a?.[0] !== op && (a = [op, a || null]), // if beginning of sequence - init node
96
- b?.[0] === op ? a.push(...b.slice(1)) : a.push(b || null), // comments can return same-token expr
97
- a)
98
- );
99
- };
100
- var group = (op, prec) => token(op[0], prec, (a) => !a && [op, expr(0, op.charCodeAt(1))]);
101
- var access = (op, prec) => token(op[0], prec, (a) => a && [op, a, expr(0, op.charCodeAt(1)) || null]);
102
- var parse_default = parse;
103
-
104
- // node_modules/subscript/feature/number.js
105
- var _b = 98;
106
- var _B = 66;
107
- var _o = 111;
108
- var _O = 79;
109
- var _x = 120;
110
- var _X = 88;
111
- var _a = 97;
112
- var _f = 102;
113
- var _A = 65;
114
- var _F = 70;
115
- var num = (a, _) => [, (a = +next((c) => c === PERIOD || c >= _0 && c <= _9 || (c === _E || c === _e ? 2 : 0))) != a ? err2() : a];
116
- lookup[PERIOD] = (a) => !a && num();
117
- for (let i = _0 + 1; i <= _9; i++) lookup[i] = (a) => a ? err2() : num();
118
- lookup[_0] = (a) => {
119
- if (a) return err2();
120
- const nextChar = cur.charCodeAt(idx + 1);
121
- if (nextChar === _b || nextChar === _B) {
122
- skip();
123
- skip();
124
- const s = next((c) => c === 48 || c === 49);
125
- return [, parseInt(s, 2)];
126
- }
127
- if (nextChar === _o || nextChar === _O) {
128
- skip();
129
- skip();
130
- const s = next((c) => c >= 48 && c <= 55);
131
- return [, parseInt(s, 8)];
132
- }
133
- if (nextChar === _x || nextChar === _X) {
134
- skip();
135
- skip();
136
- const s = next((c) => c >= _0 && c <= _9 || c >= _a && c <= _f || c >= _A && c <= _F);
137
- return [, parseInt(s, 16)];
138
- }
139
- return num();
140
- };
141
-
142
- // node_modules/subscript/feature/string.js
143
- var escape = { n: "\n", r: "\r", t: " ", b: "\b", f: "\f", v: "\v" };
144
- var string = (q) => (qc, prec, str = "") => {
145
- qc && err2("Unexpected string");
146
- skip();
147
- next((c) => c - q && (c === BSLASH ? (str += escape[cur[idx + 1]] || cur[idx + 1], 2) : (str += cur[idx], 1)));
148
- skip() || err2("Bad string");
149
- return [, str];
150
- };
151
- lookup[DQUOTE] = string(DQUOTE);
152
- lookup[QUOTE] = string(QUOTE);
153
-
154
- // node_modules/subscript/src/compile.js
155
- var compile = (node) => !Array.isArray(node) ? compile.id(node) : !node[0] ? () => node[1] : operators[node[0]].call(...node);
156
- compile.id = (name) => (ctx) => ctx?.[name];
157
- var operators = {};
158
- var operator = (op, fn, prev = operators[op]) => operators[op] = (...args) => fn(...args) || prev?.(...args);
159
- var prop2 = (a, fn, generic, obj, path) => (
160
- // (((x))) => x
161
- a[0] === "()" && a.length == 2 ? prop2(a[1], fn, generic) : (
162
- // (_, name, ctx) => ctx[path]
163
- typeof a === "string" ? (ctx) => fn(ctx, a, ctx) : (
164
- // (container, path, ctx) => container(ctx)[path]
165
- a[0] === "." ? (obj = compile(a[1]), path = a[2], (ctx) => fn(obj(ctx), path, ctx)) : (
166
- // (container, path, ctx) => container(ctx)[path(ctx)]
167
- a[0] === "[]" && a.length === 3 ? (obj = compile(a[1]), path = compile(a[2]), (ctx) => fn(obj(ctx), path(ctx), ctx)) : (
168
- // (src, _, ctx) => src(ctx)
169
- generic ? (a = compile(a), (ctx) => fn([a(ctx)], 0, ctx)) : () => err2("Bad left value")
170
- )
171
- )
172
- )
173
- )
174
- );
175
- var compile_default = compile;
176
-
177
- // node_modules/subscript/feature/call.js
178
- access("()", PREC_ACCESS);
179
- operator(
180
- "()",
181
- (a, b, args) => b !== void 0 && (args = !b ? () => [] : (
182
- // a()
183
- b[0] === "," ? (b = b.slice(1).map((b2) => !b2 ? err() : compile(b2)), (ctx) => b.map((arg) => arg(ctx))) : (
184
- // a(b,c)
185
- (b = compile(b), (ctx) => [b(ctx)])
186
- )
187
- ), // a(b)
188
- // a(...args), a.b(...args), a[b](...args)
189
- prop2(a, (obj, path, ctx) => obj[path](...args(ctx)), true))
190
- );
191
-
192
- // node_modules/subscript/feature/access.js
193
- access("[]", PREC_ACCESS);
194
- operator("[]", (a, b) => !b ? err2() : (a = compile(a), b = compile(b), (ctx) => {
195
- const k = b(ctx);
196
- return unsafe(k) ? void 0 : a(ctx)[k];
197
- }));
198
- binary(".", PREC_ACCESS);
199
- operator(".", (a, b) => (a = compile(a), b = !b[0] ? b[1] : b, unsafe(b) ? () => void 0 : (ctx) => a(ctx)[b]));
200
-
201
- // node_modules/subscript/feature/group.js
202
- group("()", PREC_ACCESS);
203
- operator("()", (a, b) => b === void 0 && (!a && err2("Empty ()"), compile(a)));
204
- var last = (...args) => (args = args.map(compile), (ctx) => args.map((arg) => arg(ctx)).pop());
205
- nary(",", PREC_SEQ), operator(",", last);
206
- nary(";", PREC_STATEMENT, true), operator(";", last);
207
-
208
- // node_modules/subscript/feature/assign.js
209
- binary("=", PREC_ASSIGN, true);
210
- operator("=", (a, b) => (b = compile(b), // a = x, ((a)) = x, a.b = x, a['b'] = x
211
- prop2(a, (container, path, ctx) => container[path] = b(ctx))));
212
-
213
- // node_modules/subscript/feature/mult.js
214
- binary("*", PREC_MULT), operator("*", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) * b(ctx)));
215
- binary("/", PREC_MULT), operator("/", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) / b(ctx)));
216
- binary("%", PREC_MULT), operator("%", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) % b(ctx)));
217
- binary("*=", PREC_ASSIGN, true);
218
- operator("*=", (a, b) => (b = compile(b), prop2(a, (container, path, ctx) => container[path] *= b(ctx))));
219
- binary("/=", PREC_ASSIGN, true);
220
- operator("/=", (a, b) => (b = compile(b), prop2(a, (container, path, ctx) => container[path] /= b(ctx))));
221
- binary("%=", PREC_ASSIGN, true);
222
- operator("%=", (a, b) => (b = compile(b), prop2(a, (container, path, ctx) => container[path] %= b(ctx))));
223
-
224
- // node_modules/subscript/feature/add.js
225
- binary("+", PREC_ADD), operator("+", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) + b(ctx)));
226
- binary("-", PREC_ADD), operator("-", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) - b(ctx)));
227
- unary("+", PREC_PREFIX), operator("+", (a, b) => !b && (a = compile(a), (ctx) => +a(ctx)));
228
- unary("-", PREC_PREFIX), operator("-", (a, b) => !b && (a = compile(a), (ctx) => -a(ctx)));
229
- binary("+=", PREC_ASSIGN, true);
230
- operator("+=", (a, b) => (b = compile(b), prop2(a, (container, path, ctx) => container[path] += b(ctx))));
231
- binary("-=", PREC_ASSIGN, true);
232
- operator("-=", (a, b) => (b = compile(b), prop2(a, (container, path, ctx) => container[path] -= b(ctx))));
233
-
234
- // node_modules/subscript/feature/increment.js
235
- token("++", PREC_POSTFIX, (a) => a ? ["++", a, null] : ["++", expr(PREC_POSTFIX - 1)]);
236
- operator("++", (a, b) => prop2(a, b === null ? (obj, path) => obj[path]++ : (obj, path) => ++obj[path]));
237
- token("--", PREC_POSTFIX, (a) => a ? ["--", a, null] : ["--", expr(PREC_POSTFIX - 1)]);
238
- operator("--", (a, b) => prop2(a, b === null ? (obj, path) => obj[path]-- : (obj, path) => --obj[path]));
239
-
240
- // node_modules/subscript/feature/bitwise.js
241
- unary("~", PREC_PREFIX), operator("~", (a, b) => !b && (a = compile(a), (ctx) => ~a(ctx)));
242
- binary("|", PREC_OR), operator("|", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) | b(ctx)));
243
- binary("&", PREC_AND), operator("&", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) & b(ctx)));
244
- binary("^", PREC_XOR), operator("^", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) ^ b(ctx)));
245
-
246
- // node_modules/subscript/feature/logic.js
247
- unary("!", PREC_PREFIX), operator("!", (a, b) => !b && (a = compile(a), (ctx) => !a(ctx)));
248
- binary("||", PREC_LOR);
249
- operator("||", (a, b) => (a = compile(a), b = compile(b), (ctx) => a(ctx) || b(ctx)));
250
- binary("&&", PREC_LAND);
251
- operator("&&", (a, b) => (a = compile(a), b = compile(b), (ctx) => a(ctx) && b(ctx)));
252
-
253
- // node_modules/subscript/feature/compare.js
254
- binary("==", PREC_EQ), operator("==", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) == b(ctx)));
255
- binary("!=", PREC_EQ), operator("!=", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) != b(ctx)));
256
- binary(">", PREC_COMP), operator(">", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) > b(ctx)));
257
- binary("<", PREC_COMP), operator("<", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) < b(ctx)));
258
- binary(">=", PREC_COMP), operator(">=", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) >= b(ctx)));
259
- binary("<=", PREC_COMP), operator("<=", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) <= b(ctx)));
260
-
261
- // node_modules/subscript/feature/shift.js
262
- binary(">>", PREC_SHIFT), operator(">>", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) >> b(ctx)));
263
- binary("<<", PREC_SHIFT), operator("<<", (a, b) => b && (a = compile(a), b = compile(b), (ctx) => a(ctx) << b(ctx)));
264
- binary(">>=", PREC_ASSIGN, true);
265
- operator(">>=", (a, b) => (b = compile(b), prop(a, (obj, path, ctx) => obj[path] >>= b(ctx))));
266
- binary("<<=", PREC_ASSIGN, true);
267
- operator("<<=", (a, b) => (b = compile(b), prop(a, (obj, path, ctx) => obj[path] <<= b(ctx))));
268
-
269
- // node_modules/subscript/subscript.js
270
- var subscript_default = (s) => compile_default(parse_default(s));
271
-
272
- // src/parser.ts
273
- var { next: next2 } = parse_exports;
274
- var isIdChar = (c) => c >= 97 && c <= 122 || // a-z
275
- c >= 65 && c <= 90 || // A-Z
276
- c >= 48 && c <= 57 || // 0-9
277
- c === 95 ? 1 : 0;
278
- token("@", 200, (a) => {
279
- if (a) return;
280
- const name = next2(isIdChar);
281
- if (!name) return;
282
- return "@" + name;
283
- });
284
- token("#", 200, (a) => {
285
- if (a) return;
286
- const name = next2(isIdChar);
287
- if (!name) return;
288
- return "#" + name;
289
- });
290
- var createWildcardLiteral = () => {
291
- const arr = [];
292
- arr[1] = "*";
293
- return arr;
294
- };
295
- token("*", 200, (a) => {
296
- if (!a) return createWildcardLiteral();
297
- return void 0;
298
- });
299
- token("/", 200, (a) => {
300
- if (a) return;
301
- const name = next2(isIdChar);
302
- if (!name) return;
303
- return "/" + name;
304
- });
305
- var isRelativePathChar = (c) => isIdChar(c) || c === 47 || c === 46 ? 1 : 0;
306
- token(".", 200, (a) => {
307
- if (a) return;
308
- const second = next2((c) => c === 46 ? 1 : 0);
309
- if (!second) return;
310
- const rest = next2(isRelativePathChar);
311
- if (!rest) return;
312
- return ".." + rest;
313
- });
314
- var BUILTIN_FUNCTIONS = {
315
- and: (a, b) => Boolean(a) && Boolean(b),
316
- or: (a, b) => Boolean(a) || Boolean(b),
317
- not: (a) => !a,
318
- concat: (...args) => args.map(String).join(""),
319
- upper: (s) => String(s).toUpperCase(),
320
- lower: (s) => String(s).toLowerCase(),
321
- trim: (s) => String(s).trim(),
322
- left: (s, n) => {
323
- const count = Math.max(0, Math.floor(Number(n)));
324
- return String(s).slice(0, count);
325
- },
326
- right: (s, n) => {
327
- const str = String(s);
328
- const count = Math.max(0, Math.floor(Number(n)));
329
- return count === 0 ? "" : str.slice(-count);
330
- },
331
- replace: (s, search, replacement) => String(s).replace(String(search), String(replacement)),
332
- tostring: String,
333
- length: (s) => {
334
- if (Array.isArray(s)) return s.length;
335
- if (typeof s === "string") return s.length;
336
- if (s !== null && typeof s === "object") return Object.keys(s).length;
337
- return String(s).length;
338
- },
339
- contains: (s, search) => String(s).includes(String(search)),
340
- startswith: (s, search) => String(s).startsWith(String(search)),
341
- endswith: (s, search) => String(s).endsWith(String(search)),
342
- tonumber: Number,
343
- toboolean: Boolean,
344
- isnull: (v) => v === null || v === void 0,
345
- coalesce: (...args) => args.find((v) => v !== null && v !== void 0) ?? null,
346
- round: (n, decimals) => {
347
- const num2 = Number(n);
348
- const dec = decimals === void 0 ? 0 : Number(decimals);
349
- const factor = 10 ** dec;
350
- return Math.round(num2 * factor) / factor;
351
- },
352
- floor: (n) => Math.floor(Number(n)),
353
- ceil: (n) => Math.ceil(Number(n)),
354
- abs: (n) => Math.abs(Number(n)),
355
- sqrt: (n) => Math.sqrt(Number(n)),
356
- pow: (base, exp) => Math.pow(Number(base), Number(exp)),
357
- min: (...args) => args.length === 0 ? Number.NaN : Math.min(...args.map(Number)),
358
- max: (...args) => args.length === 0 ? Number.NaN : Math.max(...args.map(Number)),
359
- log: (n) => Math.log(Number(n)),
360
- log10: (n) => Math.log10(Number(n)),
361
- exp: (n) => Math.exp(Number(n)),
362
- sign: (n) => Math.sign(Number(n)),
363
- sum: (arr) => Array.isArray(arr) ? arr.reduce((a, b) => a + Number(b), 0) : 0,
364
- avg: (arr) => Array.isArray(arr) && arr.length > 0 ? arr.reduce((a, b) => a + Number(b), 0) / arr.length : 0,
365
- count: (arr) => Array.isArray(arr) ? arr.length : 0,
366
- first: (arr) => Array.isArray(arr) ? arr[0] : void 0,
367
- last: (arr) => Array.isArray(arr) ? arr.at(-1) : void 0,
368
- join: (arr, separator) => {
369
- if (!Array.isArray(arr)) return "";
370
- if (separator === void 0) return arr.join(",");
371
- if (typeof separator === "string") return arr.join(separator);
372
- if (typeof separator === "number") return arr.join(String(separator));
373
- return arr.join(",");
374
- },
375
- includes: (arr, value) => Array.isArray(arr) ? arr.includes(value) : false,
376
- if: (condition, ifTrue, ifFalse) => condition ? ifTrue : ifFalse
377
- };
378
- function extractCallArgs(argsNode) {
379
- if (!argsNode) return [];
380
- if (!Array.isArray(argsNode)) return [argsNode];
381
- if (argsNode[0] === ",") {
382
- return argsNode.slice(1);
383
- }
384
- return [argsNode];
385
- }
386
- function compileNode(node) {
387
- return compile(node);
388
- }
389
- function createGroupingEvaluator(fn) {
390
- const compiledExpr = compileNode(fn);
391
- return (ctx) => compiledExpr(ctx);
392
- }
393
- function createFunctionCallEvaluator(fn, argsNode) {
394
- const args = extractCallArgs(argsNode);
395
- const compiledArgs = args.map((arg) => compileNode(arg));
396
- return (ctx) => {
397
- const argValues = compiledArgs.map((a) => a(ctx));
398
- if (typeof fn === "string") {
399
- const builtinFn = BUILTIN_FUNCTIONS[fn.toLowerCase()];
400
- if (builtinFn) {
401
- return builtinFn(...argValues);
402
- }
403
- }
404
- const fnValue = compileNode(fn)(ctx);
405
- if (typeof fnValue === "function") {
406
- return fnValue(...argValues);
407
- }
408
- const fnName = typeof fn === "string" ? fn : String(fn);
409
- throw new Error(`'${fnName}' is not a function`);
410
- };
411
- }
412
- operator("()", (fn, argsNode) => {
413
- if (argsNode === void 0) {
414
- return createGroupingEvaluator(fn);
415
- }
416
- return createFunctionCallEvaluator(fn, argsNode);
417
- });
418
- var KEYWORDS = /* @__PURE__ */ new Set([
419
- "true",
420
- "false",
421
- "null",
422
- "and",
423
- "or",
424
- "not",
425
- "if",
426
- "round",
427
- "floor",
428
- "ceil",
429
- "abs",
430
- "sqrt",
431
- "pow",
432
- "min",
433
- "max",
434
- "log",
435
- "log10",
436
- "exp",
437
- "sign",
438
- "concat",
439
- "upper",
440
- "lower",
441
- "length",
442
- "trim",
443
- "left",
444
- "right",
445
- "replace",
446
- "contains",
447
- "startswith",
448
- "endswith",
449
- "tostring",
450
- "tonumber",
451
- "toboolean",
452
- "isnull",
453
- "coalesce",
454
- "sum",
455
- "avg",
456
- "count",
457
- "first",
458
- "last",
459
- "join",
460
- "includes"
461
- ]);
462
- var ARRAY_FUNCTIONS = /* @__PURE__ */ new Set([
463
- "sum",
464
- "avg",
465
- "count",
466
- "first",
467
- "last",
468
- "join",
469
- "includes"
470
- ]);
471
- function isKeyword(name) {
472
- return KEYWORDS.has(name.toLowerCase());
473
- }
474
- function isArrayFunction(name) {
475
- return ARRAY_FUNCTIONS.has(name.toLowerCase());
476
- }
477
- function isContextToken(name) {
478
- return name.startsWith("@") || name.startsWith("#");
479
- }
480
- function isRootPath(name) {
481
- return name.startsWith("/");
482
- }
483
- function isRelativePath(name) {
484
- return name.startsWith("..");
485
- }
486
- function isValidIdentifierRoot(rootName) {
487
- return !isKeyword(rootName) && !isContextToken(rootName);
488
- }
489
- function extractRootName(path) {
490
- return path.split(".")[0]?.split("[")[0] ?? "";
491
- }
492
- function addPathIfValid(path, identifiers) {
493
- if (path && isValidIdentifierRoot(extractRootName(path))) {
494
- identifiers.add(path);
495
- }
496
- }
497
- function collectStringIdentifier(node, identifiers) {
498
- if (isRootPath(node) || isRelativePath(node)) {
499
- identifiers.add(node);
500
- return;
501
- }
502
- if (!isContextToken(node) && !isKeyword(node)) {
503
- identifiers.add(node);
504
- }
505
- }
506
- function collectFunctionCallIdentifiers(args, identifiers) {
507
- for (let i = 1; i < args.length; i++) {
508
- collectIdentifiers(args[i], identifiers);
509
- }
510
- const funcName = args[0];
511
- if (typeof funcName !== "string") {
512
- collectIdentifiers(funcName, identifiers);
513
- }
514
- }
515
- function collectPathOrFallback(node, identifiers) {
516
- const path = buildDotPath(node);
517
- if (path) {
518
- addPathIfValid(path, identifiers);
519
- } else {
520
- const [, ...args] = node;
521
- for (const arg of args) {
522
- collectIdentifiers(arg, identifiers);
523
- }
524
- }
525
- }
526
- function collectIdentifiers(node, identifiers) {
527
- if (typeof node === "string") {
528
- collectStringIdentifier(node, identifiers);
529
- return;
530
- }
531
- if (!Array.isArray(node)) {
532
- return;
533
- }
534
- if (isLiteralArray(node)) {
535
- return;
536
- }
537
- const [op, ...args] = node;
538
- if (op === "." || op === "[]") {
539
- collectPathOrFallback(node, identifiers);
540
- return;
541
- }
542
- if (op === "()") {
543
- collectFunctionCallIdentifiers(args, identifiers);
544
- return;
545
- }
546
- for (const arg of args) {
547
- collectIdentifiers(arg, identifiers);
548
- }
549
- }
550
- function isLiteralArray(arr) {
551
- return !(0 in arr);
552
- }
553
- function buildPropertyAccessPath(left, right) {
554
- const leftPath = buildDotPath(left);
555
- const rightPath = typeof right === "string" ? right : null;
556
- if (leftPath && rightPath) {
557
- return `${leftPath}.${rightPath}`;
558
- }
559
- return null;
560
- }
561
- function getNegativeIndexValue(index) {
562
- if (!Array.isArray(index) || index[0] !== "-" || index.length !== 2) {
563
- return null;
564
- }
565
- const inner = index[1];
566
- if (Array.isArray(inner) && isLiteralArray(inner) && typeof inner[1] === "number") {
567
- return -inner[1];
568
- }
569
- return null;
570
- }
571
- function buildArrayAccessPath(left, right) {
572
- const leftPath = buildDotPath(left);
573
- if (!leftPath) {
574
- return null;
575
- }
576
- if (Array.isArray(right) && isLiteralArray(right)) {
577
- if (right[1] === "*") {
578
- return `${leftPath}[*]`;
579
- }
580
- if (typeof right[1] === "number") {
581
- return `${leftPath}[${right[1]}]`;
582
- }
583
- }
584
- const negativeIndex = getNegativeIndexValue(right);
585
- if (negativeIndex !== null) {
586
- return `${leftPath}[${negativeIndex}]`;
587
- }
588
- const rightPath = buildDotPath(right);
589
- if (rightPath) {
590
- return `${leftPath}[${rightPath}]`;
591
- }
592
- return null;
593
- }
594
- function buildDotPath(node) {
595
- if (typeof node === "string") {
596
- return node;
597
- }
598
- if (!Array.isArray(node) || isLiteralArray(node)) {
599
- return null;
600
- }
601
- const [op, left, right] = node;
602
- if (op === ".") {
603
- return buildPropertyAccessPath(left, right);
604
- }
605
- if (op === "[]") {
606
- return buildArrayAccessPath(left, right);
607
- }
608
- return null;
609
- }
610
- function isNegativeIndexLiteral(index) {
611
- if (!Array.isArray(index) || index[0] !== "-" || index.length !== 2) {
612
- return false;
613
- }
614
- const inner = index[1];
615
- return Array.isArray(inner) && isLiteralArray(inner) && typeof inner[1] === "number";
616
- }
617
- function detectArrayAccessFeatures(index, features) {
618
- if (Array.isArray(index) && isLiteralArray(index)) {
619
- if (index[1] === "*") {
620
- features.add("array_wildcard");
621
- } else if (typeof index[1] === "number") {
622
- features.add("array_index");
623
- }
624
- }
625
- if (isNegativeIndexLiteral(index)) {
626
- features.add("array_index");
627
- }
628
- }
629
- function detectFunctionCallFeatures(funcName, features) {
630
- if (typeof funcName === "string" && isArrayFunction(funcName)) {
631
- features.add("array_function");
632
- }
633
- }
634
- function detectStringFeatures(node, features) {
635
- if (isContextToken(node)) {
636
- features.add("context_token");
637
- }
638
- if (isRootPath(node)) {
639
- features.add("root_path");
640
- if (node.includes(".")) {
641
- features.add("nested_path");
642
- }
643
- }
644
- if (isRelativePath(node)) {
645
- features.add("relative_path");
646
- const withoutPrefix = node.replace(/^(\.\.\/)+/, "");
647
- if (withoutPrefix.includes(".")) {
648
- features.add("nested_path");
649
- }
650
- }
651
- }
652
- function detectOperatorFeatures(node, features) {
653
- const op = node[0];
654
- if (op === ".") {
655
- features.add("nested_path");
656
- }
657
- if (op === "[]") {
658
- detectArrayAccessFeatures(node[2], features);
659
- }
660
- if (op === "()") {
661
- detectFunctionCallFeatures(node[1], features);
662
- }
663
- }
664
- function detectFeatures(node, features) {
665
- if (typeof node === "string") {
666
- detectStringFeatures(node, features);
667
- return;
668
- }
669
- if (!Array.isArray(node) || isLiteralArray(node)) {
670
- return;
671
- }
672
- detectOperatorFeatures(node, features);
673
- for (let i = 1; i < node.length; i++) {
674
- detectFeatures(node[i], features);
675
- }
676
- }
677
- function parseFormula(expression) {
678
- const trimmed = expression.trim();
679
- if (!trimmed) {
680
- throw new Error("Empty expression");
681
- }
682
- const ast = parse(trimmed);
683
- const identifiers = /* @__PURE__ */ new Set();
684
- collectIdentifiers(ast, identifiers);
685
- const featuresSet = /* @__PURE__ */ new Set();
686
- detectFeatures(ast, featuresSet);
687
- const features = Array.from(featuresSet);
688
- const minVersion = features.length > 0 ? "1.1" : "1.0";
689
- return {
690
- ast,
691
- dependencies: Array.from(identifiers),
692
- features,
693
- minVersion
694
- };
695
- }
696
- function validateSyntax(expression) {
697
- const trimmed = expression.trim();
698
- if (!trimmed) {
699
- return { isValid: false, error: "Empty expression" };
700
- }
701
- try {
702
- parse(trimmed);
703
- return { isValid: true };
704
- } catch (e) {
705
- const error = e;
706
- const match = /at (\d+):(\d+)/.exec(error.message);
707
- const position = match ? Number.parseInt(match[2] ?? "0", 10) - 1 : void 0;
708
- return {
709
- isValid: false,
710
- error: error.message,
711
- position
712
- };
713
- }
714
- }
715
- function evaluate(expression, context) {
716
- const trimmed = expression.trim();
717
- if (!trimmed) {
718
- throw new Error("Empty expression");
719
- }
720
- const fn = subscript_default(trimmed);
721
- const safeContext = {};
722
- for (const [key, value] of Object.entries(context)) {
723
- if (typeof value !== "function") {
724
- safeContext[key] = value;
725
- }
726
- }
727
- return fn(safeContext);
728
- }
729
- function getValueByPath(data, path) {
730
- const segments = path.split(".");
731
- let current = data;
732
- for (const segment of segments) {
733
- if (current === null || current === void 0) {
734
- return void 0;
735
- }
736
- if (typeof current !== "object") {
737
- return void 0;
738
- }
739
- current = current[segment];
740
- }
741
- return current;
742
- }
743
- function buildPathReferences(rootData, dependencies) {
744
- const refs = {};
745
- for (const dep of dependencies) {
746
- if (dep.startsWith("/")) {
747
- const fieldPath = dep.slice(1);
748
- const rootField = fieldPath.split(".")[0] ?? fieldPath;
749
- const contextKey = "/" + rootField;
750
- if (!(contextKey in refs)) {
751
- refs[contextKey] = getValueByPath(rootData, rootField);
752
- }
753
- } else if (dep.startsWith("../")) {
754
- const fieldPath = dep.slice(3);
755
- refs[dep] = getValueByPath(rootData, fieldPath);
756
- }
757
- }
758
- return refs;
759
- }
760
- function evaluateWithContext(expression, options) {
761
- const { rootData, itemData } = options;
762
- const trimmed = expression.trim();
763
- if (!trimmed) {
764
- throw new Error("Empty expression");
765
- }
766
- const parsed = parseFormula(trimmed);
767
- const pathRefs = buildPathReferences(rootData, parsed.dependencies);
768
- const context = {
769
- ...rootData,
770
- ...itemData ?? {},
771
- ...pathRefs
772
- };
773
- return evaluate(trimmed, context);
774
- }
775
- var ARITHMETIC_OPS = /* @__PURE__ */ new Set(["+", "-", "*", "/", "%"]);
776
- var COMPARISON_OPS = /* @__PURE__ */ new Set(["<", ">", "<=", ">=", "==", "!="]);
777
- var LOGICAL_OPS = /* @__PURE__ */ new Set(["&&", "||", "!"]);
778
- var NUMERIC_FUNCTIONS = /* @__PURE__ */ new Set([
779
- "round",
780
- "floor",
781
- "ceil",
782
- "abs",
783
- "sqrt",
784
- "pow",
785
- "min",
786
- "max",
787
- "log",
788
- "log10",
789
- "exp",
790
- "sign",
791
- "sum",
792
- "avg",
793
- "count",
794
- "tonumber",
795
- "length"
796
- ]);
797
- var STRING_FUNCTIONS = /* @__PURE__ */ new Set([
798
- "concat",
799
- "upper",
800
- "lower",
801
- "trim",
802
- "left",
803
- "right",
804
- "replace",
805
- "tostring",
806
- "join"
807
- ]);
808
- var BOOLEAN_FUNCTIONS = /* @__PURE__ */ new Set([
809
- "and",
810
- "or",
811
- "not",
812
- "contains",
813
- "startswith",
814
- "endswith",
815
- "isnull",
816
- "toboolean",
817
- "includes"
818
- ]);
819
- function getFieldType(path, fieldTypes) {
820
- const rootField = path.split(".")[0]?.split("[")[0] || path;
821
- const schemaType = fieldTypes[rootField];
822
- if (schemaType === "number") return "number";
823
- if (schemaType === "string") return "string";
824
- if (schemaType === "boolean") return "boolean";
825
- return "unknown";
826
- }
827
- function inferPrimitiveType(node, fieldTypes) {
828
- if (typeof node === "number") return "number";
829
- if (typeof node === "boolean") return "boolean";
830
- if (typeof node === "string") return getFieldType(node, fieldTypes);
831
- if (node === null) return "unknown";
832
- return null;
833
- }
834
- function inferLiteralArrayType(node) {
835
- const val = node[1];
836
- if (typeof val === "number") return "number";
837
- if (typeof val === "string") return "string";
838
- if (typeof val === "boolean") return "boolean";
839
- return "unknown";
840
- }
841
- function inferOperatorType(op, argsLength, argTypes) {
842
- if (op === "+" && argTypes) {
843
- if (argTypes.includes("string")) return "string";
844
- if (argTypes.includes("unknown")) return "unknown";
845
- return "number";
846
- }
847
- if (ARITHMETIC_OPS.has(op)) return "number";
848
- if (COMPARISON_OPS.has(op)) return "boolean";
849
- if (LOGICAL_OPS.has(op)) return "boolean";
850
- if (op === "-" && argsLength === 1) return "number";
851
- return null;
852
- }
853
- function inferPropertyAccessType(node, fieldTypes) {
854
- const path = buildDotPath(node);
855
- return path ? getFieldType(path, fieldTypes) : "unknown";
856
- }
857
- function inferFunctionCallType(funcName) {
858
- if (typeof funcName !== "string") return "unknown";
859
- const lowerName = funcName.toLowerCase();
860
- if (NUMERIC_FUNCTIONS.has(lowerName)) return "number";
861
- if (STRING_FUNCTIONS.has(lowerName)) return "string";
862
- if (BOOLEAN_FUNCTIONS.has(lowerName)) return "boolean";
863
- return "unknown";
864
- }
865
- function inferTypeFromNode(node, fieldTypes) {
866
- const primitiveType = inferPrimitiveType(node, fieldTypes);
867
- if (primitiveType !== null) return primitiveType;
868
- if (!Array.isArray(node)) return "unknown";
869
- if (isLiteralArray(node)) return inferLiteralArrayType(node);
870
- const [op, ...args] = node;
871
- const argTypes = op === "+" ? args.map((arg) => inferTypeFromNode(arg, fieldTypes)) : void 0;
872
- const operatorType = inferOperatorType(op, args.length, argTypes);
873
- if (operatorType !== null) return operatorType;
874
- if (op === "." || op === "[]") {
875
- return inferPropertyAccessType(node, fieldTypes);
876
- }
877
- if (op === "()") {
878
- return inferFunctionCallType(args[0]);
879
- }
880
- return "unknown";
881
- }
882
- function inferFormulaType(expression, fieldTypes = {}) {
883
- const trimmed = expression.trim();
884
- if (!trimmed) {
885
- return "unknown";
886
- }
887
- try {
888
- const ast = parse(trimmed);
889
- return inferTypeFromNode(ast, fieldTypes);
890
- } catch {
891
- return "unknown";
892
- }
893
- }
894
-
895
- // src/parse-formula.ts
896
- function parseExpression(expression) {
897
- const result = parseFormula(expression);
898
- return {
899
- expression,
900
- dependencies: result.dependencies,
901
- minVersion: result.minVersion,
902
- features: result.features
903
- };
904
- }
905
-
906
- // src/validate-syntax.ts
907
- function validateFormulaSyntax(expression) {
908
- const result = validateSyntax(expression);
909
- if (result.isValid) {
910
- return { isValid: true };
911
- }
912
- return {
913
- isValid: false,
914
- error: result.error,
915
- position: result.position
916
- };
917
- }
918
-
919
- // src/dependency-graph.ts
920
- function buildDependencyGraph(dependencies) {
921
- const nodes = /* @__PURE__ */ new Set();
922
- const edges = /* @__PURE__ */ new Map();
923
- for (const [node, deps] of Object.entries(dependencies)) {
924
- nodes.add(node);
925
- edges.set(node, new Set(deps));
926
- for (const dep of deps) {
927
- nodes.add(dep);
928
- }
929
- }
930
- return { nodes, edges };
931
- }
932
- function detectCircularDependencies(graph) {
933
- const visited = /* @__PURE__ */ new Set();
934
- const recursionStack = /* @__PURE__ */ new Set();
935
- const path = [];
936
- for (const node of graph.nodes) {
937
- if (!visited.has(node)) {
938
- const cycle = dfsVisit(node, graph, visited, recursionStack, path);
939
- if (cycle) {
940
- return { hasCircular: true, cycle };
941
- }
942
- }
943
- }
944
- return { hasCircular: false, cycle: null };
945
- }
946
- function dfsVisit(node, graph, visited, recursionStack, path) {
947
- visited.add(node);
948
- recursionStack.add(node);
949
- path.push(node);
950
- const deps = graph.edges.get(node);
951
- if (deps) {
952
- for (const dep of deps) {
953
- if (!visited.has(dep)) {
954
- const cycle = dfsVisit(dep, graph, visited, recursionStack, path);
955
- if (cycle) {
956
- return cycle;
957
- }
958
- } else if (recursionStack.has(dep)) {
959
- const cycleStart = path.indexOf(dep);
960
- return [...path.slice(cycleStart), dep];
961
- }
962
- }
963
- }
964
- path.pop();
965
- recursionStack.delete(node);
966
- return null;
967
- }
968
- function getTopologicalOrder(graph) {
969
- const circularCheck = detectCircularDependencies(graph);
970
- if (circularCheck.hasCircular && circularCheck.cycle) {
971
- return {
972
- success: false,
973
- order: [],
974
- error: `Circular dependency detected: ${circularCheck.cycle.join(" -> ")}`
975
- };
976
- }
977
- const inDegree = initializeInDegree(graph);
978
- const queue = findZeroInDegreeNodes(inDegree);
979
- const order = processQueue(queue, graph, inDegree);
980
- order.reverse();
981
- return { success: true, order };
982
- }
983
- function initializeInDegree(graph) {
984
- const inDegree = /* @__PURE__ */ new Map();
985
- for (const node of graph.nodes) {
986
- inDegree.set(node, 0);
987
- }
988
- for (const deps of graph.edges.values()) {
989
- for (const dep of deps) {
990
- inDegree.set(dep, (inDegree.get(dep) ?? 0) + 1);
991
- }
992
- }
993
- return inDegree;
994
- }
995
- function findZeroInDegreeNodes(inDegree) {
996
- const result = [];
997
- for (const [node, degree] of inDegree) {
998
- if (degree === 0) {
999
- result.push(node);
1000
- }
1001
- }
1002
- return result;
1003
- }
1004
- function processQueue(queue, graph, inDegree) {
1005
- const order = [];
1006
- let head = 0;
1007
- while (head < queue.length) {
1008
- const node = queue[head];
1009
- head++;
1010
- order.push(node);
1011
- const deps = graph.edges.get(node);
1012
- if (deps) {
1013
- for (const dep of deps) {
1014
- const newDegree = (inDegree.get(dep) ?? 0) - 1;
1015
- inDegree.set(dep, newDegree);
1016
- if (newDegree === 0) {
1017
- queue.push(dep);
1018
- }
1019
- }
1020
- }
1021
- }
1022
- return order;
1023
- }
1024
-
1025
- // src/extract-schema.ts
1026
- function extractSchemaFormulas(schema) {
1027
- const formulas = [];
1028
- extractFormulasRecursive(schema, "", formulas);
1029
- return formulas;
1030
- }
1031
- function extractFormulasRecursive(schema, pathPrefix, formulas) {
1032
- if (schema.type === "array" && schema.items) {
1033
- extractFormulasRecursive(schema.items, `${pathPrefix}[]`, formulas);
1034
- return;
1035
- }
1036
- const properties = schema.properties ?? {};
1037
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
1038
- const fullPath = pathPrefix ? `${pathPrefix}.${fieldName}` : fieldName;
1039
- const xFormula = fieldSchema["x-formula"];
1040
- if (xFormula) {
1041
- formulas.push({
1042
- fieldName: fullPath,
1043
- expression: xFormula.expression,
1044
- fieldType: fieldSchema.type ?? "string"
1045
- });
1046
- }
1047
- if (fieldSchema.type === "object" && fieldSchema.properties) {
1048
- extractFormulasRecursive(fieldSchema, fullPath, formulas);
1049
- }
1050
- if (fieldSchema.type === "array" && fieldSchema.items) {
1051
- extractFormulasRecursive(fieldSchema.items, `${fullPath}[]`, formulas);
1052
- }
1053
- }
1054
- }
1055
-
1056
- // src/validate-schema.ts
1057
- function resolveSubSchema(schema, fieldPath) {
1058
- if (!fieldPath) {
1059
- return schema;
1060
- }
1061
- const segments = parsePathSegments(fieldPath);
1062
- let current = schema;
1063
- for (const segment of segments) {
1064
- if (segment === "[]") {
1065
- if (current.type === "array" && current.items) {
1066
- current = current.items;
1067
- } else {
1068
- return null;
1069
- }
1070
- } else {
1071
- if (current.properties?.[segment]) {
1072
- current = current.properties[segment];
1073
- } else {
1074
- return null;
1075
- }
1076
- }
1077
- }
1078
- return current;
1079
- }
1080
- function parsePathSegments(path) {
1081
- const segments = [];
1082
- let current = "";
1083
- let inBracket = false;
1084
- for (const char of path) {
1085
- if (char === "[") {
1086
- if (current) {
1087
- segments.push(current);
1088
- current = "";
1089
- }
1090
- inBracket = true;
1091
- } else if (char === "]") {
1092
- inBracket = false;
1093
- segments.push("[]");
1094
- } else if (char === "." && !inBracket) {
1095
- if (current) {
1096
- segments.push(current);
1097
- current = "";
1098
- }
1099
- } else if (!inBracket) {
1100
- current += char;
1101
- }
1102
- }
1103
- if (current) {
1104
- segments.push(current);
1105
- }
1106
- return segments;
1107
- }
1108
- function getParentPath(fieldPath) {
1109
- const lastDotIndex = fieldPath.lastIndexOf(".");
1110
- const lastBracketIndex = fieldPath.lastIndexOf("[");
1111
- const splitIndex = Math.max(lastDotIndex, lastBracketIndex);
1112
- if (splitIndex <= 0) {
1113
- return "";
1114
- }
1115
- return fieldPath.substring(0, splitIndex);
1116
- }
1117
- function getFieldName(fieldPath) {
1118
- const lastDotIndex = fieldPath.lastIndexOf(".");
1119
- const lastBracketIndex = fieldPath.lastIndexOf("]");
1120
- const splitIndex = Math.max(lastDotIndex, lastBracketIndex);
1121
- if (splitIndex === -1) {
1122
- return fieldPath;
1123
- }
1124
- return fieldPath.substring(splitIndex + 1);
1125
- }
1126
- function getSchemaFields(schema) {
1127
- const fields = /* @__PURE__ */ new Set();
1128
- const properties = schema.properties ?? {};
1129
- for (const fieldName of Object.keys(properties)) {
1130
- fields.add(fieldName);
1131
- }
1132
- return fields;
1133
- }
1134
- function getSchemaFieldTypes(schema) {
1135
- const fieldTypes = {};
1136
- const properties = schema.properties ?? {};
1137
- for (const [fieldName, fieldSchema] of Object.entries(properties)) {
1138
- const schemaType = fieldSchema.type;
1139
- if (schemaType === "number" || schemaType === "string" || schemaType === "boolean" || schemaType === "object" || schemaType === "array") {
1140
- fieldTypes[fieldName] = schemaType;
1141
- }
1142
- }
1143
- return fieldTypes;
1144
- }
1145
- function schemaTypeToInferred(schemaType) {
1146
- if (schemaType === "number") return "number";
1147
- if (schemaType === "string") return "string";
1148
- if (schemaType === "boolean") return "boolean";
1149
- return null;
1150
- }
1151
- function isTypeCompatible(inferredType, expectedType) {
1152
- if (expectedType === null) return true;
1153
- if (inferredType === "unknown") return true;
1154
- return inferredType === expectedType;
1155
- }
1156
- function extractFieldRoot(dependency) {
1157
- const root = dependency.split(".")[0]?.split("[")[0];
1158
- return root || dependency;
1159
- }
1160
- function validateFormulaInContext(expression, fieldPath, rootSchema) {
1161
- const syntaxResult = validateFormulaSyntax(expression);
1162
- if (!syntaxResult.isValid) {
1163
- return {
1164
- field: fieldPath,
1165
- error: syntaxResult.error,
1166
- position: syntaxResult.position
1167
- };
1168
- }
1169
- const parentPath = getParentPath(fieldPath);
1170
- const localFieldName = getFieldName(fieldPath);
1171
- const contextSchema = resolveSubSchema(rootSchema, parentPath);
1172
- if (!contextSchema) {
1173
- return {
1174
- field: fieldPath,
1175
- error: `Cannot resolve schema context for path '${parentPath}'`
1176
- };
1177
- }
1178
- const parseResult = parseExpression(expression);
1179
- const schemaFields = getSchemaFields(contextSchema);
1180
- for (const dep of parseResult.dependencies) {
1181
- const rootField = extractFieldRoot(dep);
1182
- if (!schemaFields.has(rootField)) {
1183
- return {
1184
- field: fieldPath,
1185
- error: `Unknown field '${rootField}' in formula`
1186
- };
1187
- }
1188
- }
1189
- if (parseResult.dependencies.some((d) => extractFieldRoot(d) === localFieldName)) {
1190
- return {
1191
- field: fieldPath,
1192
- error: `Formula cannot reference itself`
1193
- };
1194
- }
1195
- const fieldSchema = contextSchema.properties?.[localFieldName];
1196
- const expectedType = schemaTypeToInferred(fieldSchema?.type);
1197
- const fieldTypes = getSchemaFieldTypes(contextSchema);
1198
- const inferredType = inferFormulaType(expression, fieldTypes);
1199
- if (!isTypeCompatible(inferredType, expectedType)) {
1200
- return {
1201
- field: fieldPath,
1202
- error: `Type mismatch: formula returns '${inferredType}' but field expects '${expectedType}'`
1203
- };
1204
- }
1205
- return null;
1206
- }
1207
- function validateFormulaAgainstSchema(expression, fieldName, schema) {
1208
- return validateFormulaInContext(expression, fieldName, schema);
1209
- }
1210
- function validateSchemaFormulas(schema) {
1211
- const errors = [];
1212
- const formulas = extractSchemaFormulas(schema);
1213
- for (const formula of formulas) {
1214
- const error = validateFormulaAgainstSchema(
1215
- formula.expression,
1216
- formula.fieldName,
1217
- schema
1218
- );
1219
- if (error) {
1220
- errors.push(error);
1221
- }
1222
- }
1223
- if (errors.length > 0) {
1224
- return { isValid: false, errors };
1225
- }
1226
- const dependencies = {};
1227
- for (const formula of formulas) {
1228
- const parseResult = parseExpression(formula.expression);
1229
- const parentPath = getParentPath(formula.fieldName);
1230
- const prefix = parentPath ? `${parentPath}.` : "";
1231
- dependencies[formula.fieldName] = parseResult.dependencies.map((dep) => {
1232
- const rootField = extractFieldRoot(dep);
1233
- return `${prefix}${rootField}`;
1234
- });
1235
- }
1236
- const graph = buildDependencyGraph(dependencies);
1237
- const circularCheck = detectCircularDependencies(graph);
1238
- const cycle = circularCheck.cycle;
1239
- if (circularCheck.hasCircular && cycle && cycle.length > 0) {
1240
- const firstField = cycle[0];
1241
- if (firstField) {
1242
- errors.push({
1243
- field: firstField,
1244
- error: `Circular dependency: ${cycle.join(" \u2192 ")}`
1245
- });
1246
- return { isValid: false, errors };
1247
- }
1248
- }
1249
- return { isValid: true, errors: [] };
1250
- }
1251
-
1252
- exports.buildDependencyGraph = buildDependencyGraph;
1253
- exports.detectCircularDependencies = detectCircularDependencies;
1254
- exports.evaluate = evaluate;
1255
- exports.evaluateWithContext = evaluateWithContext;
1256
- exports.extractSchemaFormulas = extractSchemaFormulas;
1257
- exports.getTopologicalOrder = getTopologicalOrder;
1258
- exports.inferFormulaType = inferFormulaType;
1259
- exports.parseExpression = parseExpression;
1260
- exports.parseFormula = parseFormula;
1261
- exports.validateFormulaAgainstSchema = validateFormulaAgainstSchema;
1262
- exports.validateFormulaSyntax = validateFormulaSyntax;
1263
- exports.validateSchemaFormulas = validateSchemaFormulas;
1264
- exports.validateSyntax = validateSyntax;
1265
- //# sourceMappingURL=chunk-AGBOCJGV.cjs.map
1266
- //# sourceMappingURL=chunk-AGBOCJGV.cjs.map