@the-trybe/formula-engine 1.0.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.
Files changed (43) hide show
  1. package/.claude/settings.local.json +6 -0
  2. package/PRD_FORMULA_ENGINE.md +1863 -0
  3. package/README.md +382 -0
  4. package/dist/decimal-utils.d.ts +180 -0
  5. package/dist/decimal-utils.js +355 -0
  6. package/dist/dependency-extractor.d.ts +20 -0
  7. package/dist/dependency-extractor.js +103 -0
  8. package/dist/dependency-graph.d.ts +60 -0
  9. package/dist/dependency-graph.js +252 -0
  10. package/dist/errors.d.ts +161 -0
  11. package/dist/errors.js +260 -0
  12. package/dist/evaluator.d.ts +51 -0
  13. package/dist/evaluator.js +494 -0
  14. package/dist/formula-engine.d.ts +79 -0
  15. package/dist/formula-engine.js +355 -0
  16. package/dist/functions.d.ts +3 -0
  17. package/dist/functions.js +720 -0
  18. package/dist/index.d.ts +10 -0
  19. package/dist/index.js +61 -0
  20. package/dist/lexer.d.ts +25 -0
  21. package/dist/lexer.js +357 -0
  22. package/dist/parser.d.ts +32 -0
  23. package/dist/parser.js +372 -0
  24. package/dist/types.d.ts +228 -0
  25. package/dist/types.js +62 -0
  26. package/jest.config.js +23 -0
  27. package/package.json +35 -0
  28. package/src/decimal-utils.ts +408 -0
  29. package/src/dependency-extractor.ts +117 -0
  30. package/src/dependency-graph.test.ts +238 -0
  31. package/src/dependency-graph.ts +288 -0
  32. package/src/errors.ts +296 -0
  33. package/src/evaluator.ts +604 -0
  34. package/src/formula-engine.test.ts +660 -0
  35. package/src/formula-engine.ts +430 -0
  36. package/src/functions.ts +770 -0
  37. package/src/index.ts +103 -0
  38. package/src/lexer.test.ts +288 -0
  39. package/src/lexer.ts +394 -0
  40. package/src/parser.test.ts +349 -0
  41. package/src/parser.ts +449 -0
  42. package/src/types.ts +347 -0
  43. package/tsconfig.json +29 -0
@@ -0,0 +1,355 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Decimal = exports.decimalUtils = exports.DecimalUtils = void 0;
7
+ const decimal_js_1 = __importDefault(require("decimal.js"));
8
+ exports.Decimal = decimal_js_1.default;
9
+ const types_1 = require("./types");
10
+ const errors_1 = require("./errors");
11
+ // Map our rounding modes to decimal.js rounding modes
12
+ const ROUNDING_MODE_MAP = {
13
+ [types_1.DecimalRoundingMode.CEIL]: decimal_js_1.default.ROUND_CEIL,
14
+ [types_1.DecimalRoundingMode.FLOOR]: decimal_js_1.default.ROUND_FLOOR,
15
+ [types_1.DecimalRoundingMode.DOWN]: decimal_js_1.default.ROUND_DOWN,
16
+ [types_1.DecimalRoundingMode.UP]: decimal_js_1.default.ROUND_UP,
17
+ [types_1.DecimalRoundingMode.HALF_UP]: decimal_js_1.default.ROUND_HALF_UP,
18
+ [types_1.DecimalRoundingMode.HALF_DOWN]: decimal_js_1.default.ROUND_HALF_DOWN,
19
+ [types_1.DecimalRoundingMode.HALF_EVEN]: decimal_js_1.default.ROUND_HALF_EVEN,
20
+ [types_1.DecimalRoundingMode.HALF_ODD]: decimal_js_1.default.ROUND_HALF_CEIL, // decimal.js doesn't have HALF_ODD, use HALF_CEIL as approximation
21
+ };
22
+ const DEFAULT_CONFIG = {
23
+ precision: 20,
24
+ roundingMode: types_1.DecimalRoundingMode.HALF_UP,
25
+ divisionScale: 10,
26
+ maxExponent: 1000,
27
+ minExponent: -1000,
28
+ };
29
+ class DecimalUtils {
30
+ constructor(config) {
31
+ this.config = {
32
+ ...DEFAULT_CONFIG,
33
+ ...config,
34
+ };
35
+ // Configure decimal.js globally
36
+ decimal_js_1.default.set({
37
+ precision: this.config.precision,
38
+ rounding: ROUNDING_MODE_MAP[this.config.roundingMode],
39
+ toExpNeg: this.config.minExponent,
40
+ toExpPos: this.config.maxExponent,
41
+ });
42
+ }
43
+ /**
44
+ * Create a Decimal from various input types
45
+ */
46
+ from(value) {
47
+ if (value instanceof decimal_js_1.default) {
48
+ return value;
49
+ }
50
+ try {
51
+ if (typeof value === 'bigint') {
52
+ return new decimal_js_1.default(value.toString());
53
+ }
54
+ return new decimal_js_1.default(value);
55
+ }
56
+ catch {
57
+ throw new errors_1.InvalidDecimalError(String(value));
58
+ }
59
+ }
60
+ /**
61
+ * Check if a value is a Decimal
62
+ */
63
+ isDecimal(value) {
64
+ return value instanceof decimal_js_1.default;
65
+ }
66
+ /**
67
+ * Convert a value to Decimal if it's numeric
68
+ */
69
+ toDecimal(value) {
70
+ if (value instanceof decimal_js_1.default) {
71
+ return value;
72
+ }
73
+ if (typeof value === 'number' && !isNaN(value) && isFinite(value)) {
74
+ return new decimal_js_1.default(value);
75
+ }
76
+ if (typeof value === 'string') {
77
+ const trimmed = value.trim();
78
+ if (/^-?\d+\.?\d*$/.test(trimmed) || /^-?\d*\.?\d+$/.test(trimmed)) {
79
+ try {
80
+ return new decimal_js_1.default(trimmed);
81
+ }
82
+ catch {
83
+ return value;
84
+ }
85
+ }
86
+ }
87
+ if (typeof value === 'bigint') {
88
+ return new decimal_js_1.default(value.toString());
89
+ }
90
+ return value;
91
+ }
92
+ /**
93
+ * Addition
94
+ */
95
+ add(a, b) {
96
+ return this.from(a).plus(this.from(b));
97
+ }
98
+ /**
99
+ * Subtraction
100
+ */
101
+ subtract(a, b) {
102
+ return this.from(a).minus(this.from(b));
103
+ }
104
+ /**
105
+ * Multiplication
106
+ */
107
+ multiply(a, b) {
108
+ return this.from(a).times(this.from(b));
109
+ }
110
+ /**
111
+ * Division with scale
112
+ */
113
+ divide(a, b, scale, roundingMode) {
114
+ const divisor = this.from(b);
115
+ if (divisor.isZero()) {
116
+ throw new errors_1.DecimalDivisionByZeroError();
117
+ }
118
+ const result = this.from(a).dividedBy(divisor);
119
+ if (scale !== undefined) {
120
+ const rounding = roundingMode
121
+ ? ROUNDING_MODE_MAP[roundingMode]
122
+ : ROUNDING_MODE_MAP[this.config.roundingMode];
123
+ return result.toDecimalPlaces(scale, rounding);
124
+ }
125
+ return result.toDecimalPlaces(this.config.divisionScale, ROUNDING_MODE_MAP[this.config.roundingMode]);
126
+ }
127
+ /**
128
+ * Modulo
129
+ */
130
+ modulo(a, b) {
131
+ const divisor = this.from(b);
132
+ if (divisor.isZero()) {
133
+ throw new errors_1.DecimalDivisionByZeroError();
134
+ }
135
+ return this.from(a).modulo(divisor);
136
+ }
137
+ /**
138
+ * Power
139
+ */
140
+ power(base, exponent) {
141
+ return this.from(base).pow(exponent);
142
+ }
143
+ /**
144
+ * Negation
145
+ */
146
+ negate(value) {
147
+ return this.from(value).negated();
148
+ }
149
+ /**
150
+ * Absolute value
151
+ */
152
+ abs(value) {
153
+ return this.from(value).absoluteValue();
154
+ }
155
+ /**
156
+ * Round to specified decimal places
157
+ */
158
+ round(value, scale, roundingMode) {
159
+ const rounding = roundingMode
160
+ ? ROUNDING_MODE_MAP[roundingMode]
161
+ : ROUNDING_MODE_MAP[this.config.roundingMode];
162
+ return this.from(value).toDecimalPlaces(scale, rounding);
163
+ }
164
+ /**
165
+ * Floor to specified decimal places
166
+ */
167
+ floor(value, scale = 0) {
168
+ return this.from(value).toDecimalPlaces(scale, decimal_js_1.default.ROUND_FLOOR);
169
+ }
170
+ /**
171
+ * Ceiling to specified decimal places
172
+ */
173
+ ceil(value, scale = 0) {
174
+ return this.from(value).toDecimalPlaces(scale, decimal_js_1.default.ROUND_CEIL);
175
+ }
176
+ /**
177
+ * Truncate to specified decimal places
178
+ */
179
+ truncate(value, scale = 0) {
180
+ return this.from(value).toDecimalPlaces(scale, decimal_js_1.default.ROUND_DOWN);
181
+ }
182
+ /**
183
+ * Square root
184
+ */
185
+ sqrt(value) {
186
+ return this.from(value).sqrt();
187
+ }
188
+ /**
189
+ * Natural logarithm
190
+ */
191
+ ln(value) {
192
+ return this.from(value).ln();
193
+ }
194
+ /**
195
+ * Base-10 logarithm
196
+ */
197
+ log10(value) {
198
+ return this.from(value).log(10);
199
+ }
200
+ /**
201
+ * Comparison: returns -1, 0, or 1
202
+ */
203
+ compare(a, b) {
204
+ const result = this.from(a).comparedTo(this.from(b));
205
+ return result;
206
+ }
207
+ /**
208
+ * Equality check
209
+ */
210
+ equals(a, b) {
211
+ return this.from(a).equals(this.from(b));
212
+ }
213
+ /**
214
+ * Greater than
215
+ */
216
+ greaterThan(a, b) {
217
+ return this.from(a).greaterThan(this.from(b));
218
+ }
219
+ /**
220
+ * Greater than or equal
221
+ */
222
+ greaterThanOrEqual(a, b) {
223
+ return this.from(a).greaterThanOrEqualTo(this.from(b));
224
+ }
225
+ /**
226
+ * Less than
227
+ */
228
+ lessThan(a, b) {
229
+ return this.from(a).lessThan(this.from(b));
230
+ }
231
+ /**
232
+ * Less than or equal
233
+ */
234
+ lessThanOrEqual(a, b) {
235
+ return this.from(a).lessThanOrEqualTo(this.from(b));
236
+ }
237
+ /**
238
+ * Check if zero
239
+ */
240
+ isZero(value) {
241
+ return this.from(value).isZero();
242
+ }
243
+ /**
244
+ * Check if positive
245
+ */
246
+ isPositive(value) {
247
+ return this.from(value).isPositive();
248
+ }
249
+ /**
250
+ * Check if negative
251
+ */
252
+ isNegative(value) {
253
+ return this.from(value).isNegative();
254
+ }
255
+ /**
256
+ * Check if integer
257
+ */
258
+ isInteger(value) {
259
+ return this.from(value).isInteger();
260
+ }
261
+ /**
262
+ * Get sign: -1, 0, or 1
263
+ */
264
+ sign(value) {
265
+ const d = this.from(value);
266
+ if (d.isZero())
267
+ return 0;
268
+ return d.isNegative() ? -1 : 1;
269
+ }
270
+ /**
271
+ * Get precision (total significant digits)
272
+ */
273
+ precision(value) {
274
+ return this.from(value).precision();
275
+ }
276
+ /**
277
+ * Get scale (decimal places)
278
+ */
279
+ scale(value) {
280
+ return this.from(value).decimalPlaces();
281
+ }
282
+ /**
283
+ * Convert to JavaScript number (may lose precision)
284
+ */
285
+ toNumber(value) {
286
+ return this.from(value).toNumber();
287
+ }
288
+ /**
289
+ * Convert to string
290
+ */
291
+ toString(value) {
292
+ return this.from(value).toString();
293
+ }
294
+ /**
295
+ * Convert to fixed decimal places string
296
+ */
297
+ toFixed(value, scale) {
298
+ return this.from(value).toFixed(scale);
299
+ }
300
+ /**
301
+ * Minimum of values
302
+ */
303
+ min(...values) {
304
+ if (values.length === 0) {
305
+ throw new Error('min requires at least one argument');
306
+ }
307
+ return decimal_js_1.default.min(...values.map(v => this.from(v)));
308
+ }
309
+ /**
310
+ * Maximum of values
311
+ */
312
+ max(...values) {
313
+ if (values.length === 0) {
314
+ throw new Error('max requires at least one argument');
315
+ }
316
+ return decimal_js_1.default.max(...values.map(v => this.from(v)));
317
+ }
318
+ /**
319
+ * Sum of values
320
+ */
321
+ sum(values) {
322
+ return values.reduce((acc, v) => acc.plus(this.from(v)), new decimal_js_1.default(0));
323
+ }
324
+ /**
325
+ * Average of values
326
+ */
327
+ avg(values) {
328
+ if (values.length === 0) {
329
+ throw new Error('avg requires at least one value');
330
+ }
331
+ return this.sum(values).dividedBy(values.length);
332
+ }
333
+ /**
334
+ * Product of values
335
+ */
336
+ product(values) {
337
+ return values.reduce((acc, v) => acc.times(this.from(v)), new decimal_js_1.default(1));
338
+ }
339
+ /**
340
+ * Create zero
341
+ */
342
+ zero() {
343
+ return new decimal_js_1.default(0);
344
+ }
345
+ /**
346
+ * Create one
347
+ */
348
+ one() {
349
+ return new decimal_js_1.default(1);
350
+ }
351
+ }
352
+ exports.DecimalUtils = DecimalUtils;
353
+ // Export a default instance
354
+ exports.decimalUtils = new DecimalUtils();
355
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVjaW1hbC11dGlscy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZWNpbWFsLXV0aWxzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLDREQUFpQztBQXVaeEIsa0JBdlpGLG9CQUFPLENBdVpFO0FBdFpoQixtQ0FBNkQ7QUFDN0QscUNBQTJFO0FBRTNFLHNEQUFzRDtBQUN0RCxNQUFNLGlCQUFpQixHQUFrRDtJQUN2RSxDQUFDLDJCQUFtQixDQUFDLElBQUksQ0FBQyxFQUFFLG9CQUFPLENBQUMsVUFBVTtJQUM5QyxDQUFDLDJCQUFtQixDQUFDLEtBQUssQ0FBQyxFQUFFLG9CQUFPLENBQUMsV0FBVztJQUNoRCxDQUFDLDJCQUFtQixDQUFDLElBQUksQ0FBQyxFQUFFLG9CQUFPLENBQUMsVUFBVTtJQUM5QyxDQUFDLDJCQUFtQixDQUFDLEVBQUUsQ0FBQyxFQUFFLG9CQUFPLENBQUMsUUFBUTtJQUMxQyxDQUFDLDJCQUFtQixDQUFDLE9BQU8sQ0FBQyxFQUFFLG9CQUFPLENBQUMsYUFBYTtJQUNwRCxDQUFDLDJCQUFtQixDQUFDLFNBQVMsQ0FBQyxFQUFFLG9CQUFPLENBQUMsZUFBZTtJQUN4RCxDQUFDLDJCQUFtQixDQUFDLFNBQVMsQ0FBQyxFQUFFLG9CQUFPLENBQUMsZUFBZTtJQUN4RCxDQUFDLDJCQUFtQixDQUFDLFFBQVEsQ0FBQyxFQUFFLG9CQUFPLENBQUMsZUFBZSxFQUFFLG1FQUFtRTtDQUM3SCxDQUFDO0FBWUYsTUFBTSxjQUFjLEdBQXVCO0lBQ3pDLFNBQVMsRUFBRSxFQUFFO0lBQ2IsWUFBWSxFQUFFLDJCQUFtQixDQUFDLE9BQU87SUFDekMsYUFBYSxFQUFFLEVBQUU7SUFDakIsV0FBVyxFQUFFLElBQUk7SUFDakIsV0FBVyxFQUFFLENBQUMsSUFBSTtDQUNuQixDQUFDO0FBRUYsTUFBYSxZQUFZO0lBR3ZCLFlBQVksTUFBK0I7UUFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRztZQUNaLEdBQUcs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QUMsQ0FBQztJQUNuRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxPQUFPLENBQUMsTUFBcUI7UUFDM0IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxvQkFBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckYsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSTtRQUNGLE9BQU8sSUFBSSxvQkFBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hCLENBQUM7SUFFRDs7T0FFRztJQUNILEdBQUc7UUFDRCxPQUFPLElBQUksb0JBQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixDQUFDO0NBQ0Y7QUEvV0Qsb0NBK1dDO0FBRUQsNEJBQTRCO0FBQ2YsUUFBQSxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBEZWNpbWFsIGZyb20gJ2RlY2ltYWwuanMnO1xuaW1wb3J0IHsgRGVjaW1hbENvbmZpZywgRGVjaW1hbFJvdW5kaW5nTW9kZSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgSW52YWxpZERlY2ltYWxFcnJvciwgRGVjaW1hbERpdmlzaW9uQnlaZXJvRXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5cbi8vIE1hcCBvdXIgcm91bmRpbmcgbW9kZXMgdG8gZGVjaW1hbC5qcyByb3VuZGluZyBtb2Rlc1xuY29uc3QgUk9VTkRJTkdfTU9ERV9NQVA6IFJlY29yZDxEZWNpbWFsUm91bmRpbmdNb2RlLCBEZWNpbWFsLlJvdW5kaW5nPiA9IHtcbiAgW0RlY2ltYWxSb3VuZGluZ01vZGUuQ0VJTF06IERlY2ltYWwuUk9VTkRfQ0VJTCxcbiAgW0RlY2ltYWxSb3VuZGluZ01vZGUuRkxPT1JdOiBEZWNpbWFsLlJPVU5EX0ZMT09SLFxuICBbRGVjaW1hbFJvdW5kaW5nTW9kZS5ET1dOXTogRGVjaW1hbC5ST1VORF9ET1dOLFxuICBbRGVjaW1hbFJvdW5kaW5nTW9kZS5VUF06IERlY2ltYWwuUk9VTkRfVVAsXG4gIFtEZWNpbWFsUm91bmRpbmdNb2RlLkhBTEZfVVBdOiBEZWNpbWFsLlJPVU5EX0hBTEZfVVAsXG4gIFtEZWNpbWFsUm91bmRpbmdNb2RlLkhBTEZfRE9XTl06IERlY2ltYWwuUk9VTkRfSEFMRl9ET1dOLFxuICBbRGVjaW1hbFJvdW5kaW5nTW9kZS5IQUxGX0VWRU5dOiBEZWNpbWFsLlJPVU5EX0hBTEZfRVZFTixcbiAgW0RlY2ltYWxSb3VuZGluZ01vZGUuSEFMRl9PRERdOiBEZWNpbWFsLlJPVU5EX0hBTEZfQ0VJTCwgLy8gZGVjaW1hbC5qcyBkb2Vzbid0IGhhdmUgSEFMRl9PREQsIHVzZSBIQUxGX0NFSUwgYXMgYXBwcm94aW1hdGlvblxufTtcblxuZXhwb3J0IHR5cGUgRGVjaW1hbExpa2UgPSBEZWNpbWFsIHwgc3RyaW5nIHwgbnVtYmVyIHwgYmlnaW50O1xuXG5leHBvcnQgaW50ZXJmYWNlIERlY2ltYWxVdGlsc0NvbmZpZyB7XG4gIHByZWNpc2lvbjogbnVtYmVyO1xuICByb3VuZGluZ01vZGU6IERlY2ltYWxSb3VuZGluZ01vZGU7XG4gIGRpdmlzaW9uU2NhbGU6IG51bWJlcjtcbiAgbWF4RXhwb25lbnQ6IG51bWJlcjtcbiAgbWluRXhwb25lbnQ6IG51bWJlcjtcbn1cblxuY29uc3QgREVGQVVMVF9DT05GSUc6IERlY2ltYWxVdGlsc0NvbmZpZyA9IHtcbiAgcHJlY2lzaW9uOiAyMCxcbiAgcm91bmRpbmdNb2RlOiBEZWNpbWFsUm91bmRpbmdNb2RlLkhBTEZfVVAsXG4gIGRpdmlzaW9uU2NhbGU6IDEwLFxuICBtYXhFeHBvbmVudDogMTAwMCxcbiAgbWluRXhwb25lbnQ6IC0xMDAwLFxufTtcblxuZXhwb3J0IGNsYXNzIERlY2ltYWxVdGlscyB7XG4gIHByaXZhdGUgY29uZmlnOiBEZWNpbWFsVXRpbHNDb25maWc7XG5cbiAgY29uc3RydWN0b3IoY29uZmlnPzogUGFydGlhbDxEZWNpbWFsQ29uZmlnPikge1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgLi4uREVGQVVMVF9DT05GSUcsXG4gICAgICAuLi5jb25maWcsXG4gICAgfTtcblxuICAgIC8vIENvbmZpZ3VyZSBkZWNpbWFsLmpzIGdsb2JhbGx5XG4gICAgRGVjaW1hbC5zZXQoe1xuICAgICAgcHJlY2lzaW9uOiB0aGlzLmNvbmZpZy5wcmVjaXNpb24sXG4gICAgICByb3VuZGluZzogUk9VTkRJTkdfTU9ERV9NQVBbdGhpcy5jb25maWcucm91bmRpbmdNb2RlXSxcbiAgICAgIHRvRXhwTmVnOiB0aGlzLmNvbmZpZy5taW5FeHBvbmVudCxcbiAgICAgIHRvRXhwUG9zOiB0aGlzLmNvbmZpZy5tYXhFeHBvbmVudCxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEZWNpbWFsIGZyb20gdmFyaW91cyBpbnB1dCB0eXBlc1xuICAgKi9cbiAgZnJvbSh2YWx1ZTogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBEZWNpbWFsKSB7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdiaWdpbnQnKSB7XG4gICAgICAgIHJldHVybiBuZXcgRGVjaW1hbCh2YWx1ZS50b1N0cmluZygpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBuZXcgRGVjaW1hbCh2YWx1ZSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZERlY2ltYWxFcnJvcihTdHJpbmcodmFsdWUpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgYSB2YWx1ZSBpcyBhIERlY2ltYWxcbiAgICovXG4gIGlzRGVjaW1hbCh2YWx1ZTogdW5rbm93bik6IHZhbHVlIGlzIERlY2ltYWwge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERlY2ltYWw7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBhIHZhbHVlIHRvIERlY2ltYWwgaWYgaXQncyBudW1lcmljXG4gICAqL1xuICB0b0RlY2ltYWwodmFsdWU6IHVua25vd24pOiBEZWNpbWFsIHwgdW5rbm93biB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgRGVjaW1hbCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhaXNOYU4odmFsdWUpICYmIGlzRmluaXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIG5ldyBEZWNpbWFsKHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKCk7XG4gICAgICBpZiAoL14tP1xcZCtcXC4/XFxkKiQvLnRlc3QodHJpbW1lZCkgfHwgL14tP1xcZCpcXC4/XFxkKyQvLnRlc3QodHJpbW1lZCkpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gbmV3IERlY2ltYWwodHJpbW1lZCk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYmlnaW50Jykge1xuICAgICAgcmV0dXJuIG5ldyBEZWNpbWFsKHZhbHVlLnRvU3RyaW5nKCkpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQWRkaXRpb25cbiAgICovXG4gIGFkZChhOiBEZWNpbWFsTGlrZSwgYjogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKGEpLnBsdXModGhpcy5mcm9tKGIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdWJ0cmFjdGlvblxuICAgKi9cbiAgc3VidHJhY3QoYTogRGVjaW1hbExpa2UsIGI6IERlY2ltYWxMaWtlKTogRGVjaW1hbCB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbShhKS5taW51cyh0aGlzLmZyb20oYikpO1xuICB9XG5cbiAgLyoqXG4gICAqIE11bHRpcGxpY2F0aW9uXG4gICAqL1xuICBtdWx0aXBseShhOiBEZWNpbWFsTGlrZSwgYjogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKGEpLnRpbWVzKHRoaXMuZnJvbShiKSk7XG4gIH1cblxuICAvKipcbiAgICogRGl2aXNpb24gd2l0aCBzY2FsZVxuICAgKi9cbiAgZGl2aWRlKGE6IERlY2ltYWxMaWtlLCBiOiBEZWNpbWFsTGlrZSwgc2NhbGU/OiBudW1iZXIsIHJvdW5kaW5nTW9kZT86IERlY2ltYWxSb3VuZGluZ01vZGUpOiBEZWNpbWFsIHtcbiAgICBjb25zdCBkaXZpc29yID0gdGhpcy5mcm9tKGIpO1xuICAgIGlmIChkaXZpc29yLmlzWmVybygpKSB7XG4gICAgICB0aHJvdyBuZXcgRGVjaW1hbERpdmlzaW9uQnlaZXJvRXJyb3IoKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLmZyb20oYSkuZGl2aWRlZEJ5KGRpdmlzb3IpO1xuXG4gICAgaWYgKHNjYWxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IHJvdW5kaW5nID0gcm91bmRpbmdNb2RlXG4gICAgICAgID8gUk9VTkRJTkdfTU9ERV9NQVBbcm91bmRpbmdNb2RlXVxuICAgICAgICA6IFJPVU5ESU5HX01PREVfTUFQW3RoaXMuY29uZmlnLnJvdW5kaW5nTW9kZV07XG4gICAgICByZXR1cm4gcmVzdWx0LnRvRGVjaW1hbFBsYWNlcyhzY2FsZSwgcm91bmRpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQudG9EZWNpbWFsUGxhY2VzKHRoaXMuY29uZmlnLmRpdmlzaW9uU2NhbGUsIFJPVU5ESU5HX01PREVfTUFQW3RoaXMuY29uZmlnLnJvdW5kaW5nTW9kZV0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vZHVsb1xuICAgKi9cbiAgbW9kdWxvKGE6IERlY2ltYWxMaWtlLCBiOiBEZWNpbWFsTGlrZSk6IERlY2ltYWwge1xuICAgIGNvbnN0IGRpdmlzb3IgPSB0aGlzLmZyb20oYik7XG4gICAgaWYgKGRpdmlzb3IuaXNaZXJvKCkpIHtcbiAgICAgIHRocm93IG5ldyBEZWNpbWFsRGl2aXNpb25CeVplcm9FcnJvcigpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5mcm9tKGEpLm1vZHVsbyhkaXZpc29yKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQb3dlclxuICAgKi9cbiAgcG93ZXIoYmFzZTogRGVjaW1hbExpa2UsIGV4cG9uZW50OiBudW1iZXIpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKGJhc2UpLnBvdyhleHBvbmVudCk7XG4gIH1cblxuICAvKipcbiAgICogTmVnYXRpb25cbiAgICovXG4gIG5lZ2F0ZSh2YWx1ZTogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKHZhbHVlKS5uZWdhdGVkKCk7XG4gIH1cblxuICAvKipcbiAgICogQWJzb2x1dGUgdmFsdWVcbiAgICovXG4gIGFicyh2YWx1ZTogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKHZhbHVlKS5hYnNvbHV0ZVZhbHVlKCk7XG4gIH1cblxuICAvKipcbiAgICogUm91bmQgdG8gc3BlY2lmaWVkIGRlY2ltYWwgcGxhY2VzXG4gICAqL1xuICByb3VuZCh2YWx1ZTogRGVjaW1hbExpa2UsIHNjYWxlOiBudW1iZXIsIHJvdW5kaW5nTW9kZT86IERlY2ltYWxSb3VuZGluZ01vZGUpOiBEZWNpbWFsIHtcbiAgICBjb25zdCByb3VuZGluZyA9IHJvdW5kaW5nTW9kZVxuICAgICAgPyBST1VORElOR19NT0RFX01BUFtyb3VuZGluZ01vZGVdXG4gICAgICA6IFJPVU5ESU5HX01PREVfTUFQW3RoaXMuY29uZmlnLnJvdW5kaW5nTW9kZV07XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkudG9EZWNpbWFsUGxhY2VzKHNjYWxlLCByb3VuZGluZyk7XG4gIH1cblxuICAvKipcbiAgICogRmxvb3IgdG8gc3BlY2lmaWVkIGRlY2ltYWwgcGxhY2VzXG4gICAqL1xuICBmbG9vcih2YWx1ZTogRGVjaW1hbExpa2UsIHNjYWxlOiBudW1iZXIgPSAwKTogRGVjaW1hbCB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkudG9EZWNpbWFsUGxhY2VzKHNjYWxlLCBEZWNpbWFsLlJPVU5EX0ZMT09SKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDZWlsaW5nIHRvIHNwZWNpZmllZCBkZWNpbWFsIHBsYWNlc1xuICAgKi9cbiAgY2VpbCh2YWx1ZTogRGVjaW1hbExpa2UsIHNjYWxlOiBudW1iZXIgPSAwKTogRGVjaW1hbCB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkudG9EZWNpbWFsUGxhY2VzKHNjYWxlLCBEZWNpbWFsLlJPVU5EX0NFSUwpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRydW5jYXRlIHRvIHNwZWNpZmllZCBkZWNpbWFsIHBsYWNlc1xuICAgKi9cbiAgdHJ1bmNhdGUodmFsdWU6IERlY2ltYWxMaWtlLCBzY2FsZTogbnVtYmVyID0gMCk6IERlY2ltYWwge1xuICAgIHJldHVybiB0aGlzLmZyb20odmFsdWUpLnRvRGVjaW1hbFBsYWNlcyhzY2FsZSwgRGVjaW1hbC5ST1VORF9ET1dOKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcXVhcmUgcm9vdFxuICAgKi9cbiAgc3FydCh2YWx1ZTogRGVjaW1hbExpa2UpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKHZhbHVlKS5zcXJ0KCk7XG4gIH1cblxuICAvKipcbiAgICogTmF0dXJhbCBsb2dhcml0aG1cbiAgICovXG4gIGxuKHZhbHVlOiBEZWNpbWFsTGlrZSk6IERlY2ltYWwge1xuICAgIHJldHVybiB0aGlzLmZyb20odmFsdWUpLmxuKCk7XG4gIH1cblxuICAvKipcbiAgICogQmFzZS0xMCBsb2dhcml0aG1cbiAgICovXG4gIGxvZzEwKHZhbHVlOiBEZWNpbWFsTGlrZSk6IERlY2ltYWwge1xuICAgIHJldHVybiB0aGlzLmZyb20odmFsdWUpLmxvZygxMCk7XG4gIH1cblxuICAvKipcbiAgICogQ29tcGFyaXNvbjogcmV0dXJucyAtMSwgMCwgb3IgMVxuICAgKi9cbiAgY29tcGFyZShhOiBEZWNpbWFsTGlrZSwgYjogRGVjaW1hbExpa2UpOiAtMSB8IDAgfCAxIHtcbiAgICBjb25zdCByZXN1bHQgPSB0aGlzLmZyb20oYSkuY29tcGFyZWRUbyh0aGlzLmZyb20oYikpO1xuICAgIHJldHVybiByZXN1bHQgYXMgLTEgfCAwIHwgMTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFcXVhbGl0eSBjaGVja1xuICAgKi9cbiAgZXF1YWxzKGE6IERlY2ltYWxMaWtlLCBiOiBEZWNpbWFsTGlrZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZyb20oYSkuZXF1YWxzKHRoaXMuZnJvbShiKSk7XG4gIH1cblxuICAvKipcbiAgICogR3JlYXRlciB0aGFuXG4gICAqL1xuICBncmVhdGVyVGhhbihhOiBEZWNpbWFsTGlrZSwgYjogRGVjaW1hbExpa2UpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKGEpLmdyZWF0ZXJUaGFuKHRoaXMuZnJvbShiKSk7XG4gIH1cblxuICAvKipcbiAgICogR3JlYXRlciB0aGFuIG9yIGVxdWFsXG4gICAqL1xuICBncmVhdGVyVGhhbk9yRXF1YWwoYTogRGVjaW1hbExpa2UsIGI6IERlY2ltYWxMaWtlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbShhKS5ncmVhdGVyVGhhbk9yRXF1YWxUbyh0aGlzLmZyb20oYikpO1xuICB9XG5cbiAgLyoqXG4gICAqIExlc3MgdGhhblxuICAgKi9cbiAgbGVzc1RoYW4oYTogRGVjaW1hbExpa2UsIGI6IERlY2ltYWxMaWtlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbShhKS5sZXNzVGhhbih0aGlzLmZyb20oYikpO1xuICB9XG5cbiAgLyoqXG4gICAqIExlc3MgdGhhbiBvciBlcXVhbFxuICAgKi9cbiAgbGVzc1RoYW5PckVxdWFsKGE6IERlY2ltYWxMaWtlLCBiOiBEZWNpbWFsTGlrZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZyb20oYSkubGVzc1RoYW5PckVxdWFsVG8odGhpcy5mcm9tKGIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB6ZXJvXG4gICAqL1xuICBpc1plcm8odmFsdWU6IERlY2ltYWxMaWtlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkuaXNaZXJvKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2hlY2sgaWYgcG9zaXRpdmVcbiAgICovXG4gIGlzUG9zaXRpdmUodmFsdWU6IERlY2ltYWxMaWtlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkuaXNQb3NpdGl2ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIG5lZ2F0aXZlXG4gICAqL1xuICBpc05lZ2F0aXZlKHZhbHVlOiBEZWNpbWFsTGlrZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmZyb20odmFsdWUpLmlzTmVnYXRpdmUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBpbnRlZ2VyXG4gICAqL1xuICBpc0ludGVnZXIodmFsdWU6IERlY2ltYWxMaWtlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkuaXNJbnRlZ2VyKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNpZ246IC0xLCAwLCBvciAxXG4gICAqL1xuICBzaWduKHZhbHVlOiBEZWNpbWFsTGlrZSk6IC0xIHwgMCB8IDEge1xuICAgIGNvbnN0IGQgPSB0aGlzLmZyb20odmFsdWUpO1xuICAgIGlmIChkLmlzWmVybygpKSByZXR1cm4gMDtcbiAgICByZXR1cm4gZC5pc05lZ2F0aXZlKCkgPyAtMSA6IDE7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHByZWNpc2lvbiAodG90YWwgc2lnbmlmaWNhbnQgZGlnaXRzKVxuICAgKi9cbiAgcHJlY2lzaW9uKHZhbHVlOiBEZWNpbWFsTGlrZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkucHJlY2lzaW9uKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHNjYWxlIChkZWNpbWFsIHBsYWNlcylcbiAgICovXG4gIHNjYWxlKHZhbHVlOiBEZWNpbWFsTGlrZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkuZGVjaW1hbFBsYWNlcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdG8gSmF2YVNjcmlwdCBudW1iZXIgKG1heSBsb3NlIHByZWNpc2lvbilcbiAgICovXG4gIHRvTnVtYmVyKHZhbHVlOiBEZWNpbWFsTGlrZSk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkudG9OdW1iZXIoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRvIHN0cmluZ1xuICAgKi9cbiAgdG9TdHJpbmcodmFsdWU6IERlY2ltYWxMaWtlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5mcm9tKHZhbHVlKS50b1N0cmluZygpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdG8gZml4ZWQgZGVjaW1hbCBwbGFjZXMgc3RyaW5nXG4gICAqL1xuICB0b0ZpeGVkKHZhbHVlOiBEZWNpbWFsTGlrZSwgc2NhbGU6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbSh2YWx1ZSkudG9GaXhlZChzY2FsZSk7XG4gIH1cblxuICAvKipcbiAgICogTWluaW11bSBvZiB2YWx1ZXNcbiAgICovXG4gIG1pbiguLi52YWx1ZXM6IERlY2ltYWxMaWtlW10pOiBEZWNpbWFsIHtcbiAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtaW4gcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50Jyk7XG4gICAgfVxuICAgIHJldHVybiBEZWNpbWFsLm1pbiguLi52YWx1ZXMubWFwKHYgPT4gdGhpcy5mcm9tKHYpKSk7XG4gIH1cblxuICAvKipcbiAgICogTWF4aW11bSBvZiB2YWx1ZXNcbiAgICovXG4gIG1heCguLi52YWx1ZXM6IERlY2ltYWxMaWtlW10pOiBEZWNpbWFsIHtcbiAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXggcmVxdWlyZXMgYXQgbGVhc3Qgb25lIGFyZ3VtZW50Jyk7XG4gICAgfVxuICAgIHJldHVybiBEZWNpbWFsLm1heCguLi52YWx1ZXMubWFwKHYgPT4gdGhpcy5mcm9tKHYpKSk7XG4gIH1cblxuICAvKipcbiAgICogU3VtIG9mIHZhbHVlc1xuICAgKi9cbiAgc3VtKHZhbHVlczogRGVjaW1hbExpa2VbXSk6IERlY2ltYWwge1xuICAgIHJldHVybiB2YWx1ZXMucmVkdWNlPERlY2ltYWw+KChhY2MsIHYpID0+IGFjYy5wbHVzKHRoaXMuZnJvbSh2KSksIG5ldyBEZWNpbWFsKDApKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBdmVyYWdlIG9mIHZhbHVlc1xuICAgKi9cbiAgYXZnKHZhbHVlczogRGVjaW1hbExpa2VbXSk6IERlY2ltYWwge1xuICAgIGlmICh2YWx1ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2F2ZyByZXF1aXJlcyBhdCBsZWFzdCBvbmUgdmFsdWUnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3VtKHZhbHVlcykuZGl2aWRlZEJ5KHZhbHVlcy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb2R1Y3Qgb2YgdmFsdWVzXG4gICAqL1xuICBwcm9kdWN0KHZhbHVlczogRGVjaW1hbExpa2VbXSk6IERlY2ltYWwge1xuICAgIHJldHVybiB2YWx1ZXMucmVkdWNlPERlY2ltYWw+KChhY2MsIHYpID0+IGFjYy50aW1lcyh0aGlzLmZyb20odikpLCBuZXcgRGVjaW1hbCgxKSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHplcm9cbiAgICovXG4gIHplcm8oKTogRGVjaW1hbCB7XG4gICAgcmV0dXJuIG5ldyBEZWNpbWFsKDApO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBvbmVcbiAgICovXG4gIG9uZSgpOiBEZWNpbWFsIHtcbiAgICByZXR1cm4gbmV3IERlY2ltYWwoMSk7XG4gIH1cbn1cblxuLy8gRXhwb3J0IGEgZGVmYXVsdCBpbnN0YW5jZVxuZXhwb3J0IGNvbnN0IGRlY2ltYWxVdGlscyA9IG5ldyBEZWNpbWFsVXRpbHMoKTtcblxuLy8gUmUtZXhwb3J0IERlY2ltYWwgdHlwZSBmb3IgY29udmVuaWVuY2VcbmV4cG9ydCB7IERlY2ltYWwgfTtcbiJdfQ==
@@ -0,0 +1,20 @@
1
+ import { ASTNode } from './types';
2
+ export declare class DependencyExtractor {
3
+ private parser;
4
+ constructor();
5
+ /**
6
+ * Extract all variable dependencies from an expression string
7
+ * Returns a set of variable names (without the $ or @ prefix)
8
+ */
9
+ extract(expression: string): Set<string>;
10
+ /**
11
+ * Extract dependencies from an AST node
12
+ */
13
+ extractFromNode(node: ASTNode): Set<string>;
14
+ private visit;
15
+ /**
16
+ * Visit the root of a member/index access chain
17
+ * For $product.price.value, we want to extract 'product'
18
+ */
19
+ private visitMemberRoot;
20
+ }
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DependencyExtractor = void 0;
4
+ const parser_1 = require("./parser");
5
+ class DependencyExtractor {
6
+ constructor() {
7
+ this.parser = new parser_1.Parser();
8
+ }
9
+ /**
10
+ * Extract all variable dependencies from an expression string
11
+ * Returns a set of variable names (without the $ or @ prefix)
12
+ */
13
+ extract(expression) {
14
+ const ast = this.parser.parse(expression);
15
+ return this.extractFromNode(ast);
16
+ }
17
+ /**
18
+ * Extract dependencies from an AST node
19
+ */
20
+ extractFromNode(node) {
21
+ const dependencies = new Set();
22
+ this.visit(node, dependencies);
23
+ return dependencies;
24
+ }
25
+ visit(node, dependencies) {
26
+ switch (node.type) {
27
+ case 'VariableReference':
28
+ // Only extract $ prefixed variables (not @ context variables)
29
+ // Context variables are considered external and don't form part of the dependency graph
30
+ if (node.prefix === '$') {
31
+ dependencies.add(node.name);
32
+ }
33
+ break;
34
+ case 'BinaryOperation':
35
+ this.visit(node.left, dependencies);
36
+ this.visit(node.right, dependencies);
37
+ break;
38
+ case 'UnaryOperation':
39
+ this.visit(node.operand, dependencies);
40
+ break;
41
+ case 'ConditionalExpression':
42
+ this.visit(node.condition, dependencies);
43
+ this.visit(node.consequent, dependencies);
44
+ this.visit(node.alternate, dependencies);
45
+ break;
46
+ case 'FunctionCall':
47
+ // Visit all function arguments
48
+ for (const arg of node.arguments) {
49
+ this.visit(arg, dependencies);
50
+ }
51
+ break;
52
+ case 'MemberAccess':
53
+ // For member access like $product.price, we want to extract 'product'
54
+ // The root variable is what matters for dependency tracking
55
+ this.visitMemberRoot(node.object, dependencies);
56
+ break;
57
+ case 'IndexAccess':
58
+ // Similar to MemberAccess - extract the root variable
59
+ this.visitMemberRoot(node.object, dependencies);
60
+ // Also visit the index expression as it might contain variables
61
+ this.visit(node.index, dependencies);
62
+ break;
63
+ case 'ArrayLiteral':
64
+ for (const element of node.elements) {
65
+ this.visit(element, dependencies);
66
+ }
67
+ break;
68
+ // Literals don't have dependencies
69
+ case 'DecimalLiteral':
70
+ case 'NumberLiteral':
71
+ case 'StringLiteral':
72
+ case 'BooleanLiteral':
73
+ case 'NullLiteral':
74
+ break;
75
+ }
76
+ }
77
+ /**
78
+ * Visit the root of a member/index access chain
79
+ * For $product.price.value, we want to extract 'product'
80
+ */
81
+ visitMemberRoot(node, dependencies) {
82
+ switch (node.type) {
83
+ case 'VariableReference':
84
+ if (node.prefix === '$') {
85
+ dependencies.add(node.name);
86
+ }
87
+ break;
88
+ case 'MemberAccess':
89
+ this.visitMemberRoot(node.object, dependencies);
90
+ break;
91
+ case 'IndexAccess':
92
+ this.visitMemberRoot(node.object, dependencies);
93
+ this.visit(node.index, dependencies);
94
+ break;
95
+ default:
96
+ // For other node types (like function calls), visit normally
97
+ this.visit(node, dependencies);
98
+ break;
99
+ }
100
+ }
101
+ }
102
+ exports.DependencyExtractor = DependencyExtractor;
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS1leHRyYWN0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZGVwZW5kZW5jeS1leHRyYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EscUNBQWtDO0FBRWxDLE1BQWEsbUJBQW1CO0lBRzlCO1FBQ0UsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLGVBQU0sRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsVUFBa0I7UUFDeEIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUMsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNILGVBQWUsQ0FBQyxJQUFhO1FBQzNCLE1BQU0sWUFBWSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDdkMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0IsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQztJQUVPLEtBQUssQ0FBQyxJQUFhLEVBQUUsWUFBeUI7UUFDcEQsUUFBUSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsS0FBSyxtQkFBbUI7Z0JBQ3RCLDhEQUE4RDtnQkFDOUQsd0ZBQXdGO2dCQUN4RixJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFLENBQUM7b0JBQ3hCLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUM5QixDQUFDO2dCQUNELE1BQU07WUFFUixLQUFLLGlCQUFpQjtnQkFDcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNwQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ3JDLE1BQU07WUFFUixLQUFLLGdCQUFnQjtnQkFDbkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUN2QyxNQUFNO1lBRVIsS0FBSyx1QkFBdUI7Z0JBQzFCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDekMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUMxQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ3pDLE1BQU07WUFFUixLQUFLLGNBQWM7Z0JBQ2pCLCtCQUErQjtnQkFDL0IsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQ2pDLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO2dCQUNELE1BQU07WUFFUixLQUFLLGNBQWM7Z0JBQ2pCLHNFQUFzRTtnQkFDdEUsNERBQTREO2dCQUM1RCxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ2hELE1BQU07WUFFUixLQUFLLGFBQWE7Z0JBQ2hCLHNEQUFzRDtnQkFDdEQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNoRCxnRUFBZ0U7Z0JBQ2hFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDckMsTUFBTTtZQUVSLEtBQUssY0FBYztnQkFDakIsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQ3BDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO2dCQUNELE1BQU07WUFFUixtQ0FBbUM7WUFDbkMsS0FBSyxnQkFBZ0IsQ0FBQztZQUN0QixLQUFLLGVBQWUsQ0FBQztZQUNyQixLQUFLLGVBQWUsQ0FBQztZQUNyQixLQUFLLGdCQUFnQixDQUFDO1lBQ3RCLEtBQUssYUFBYTtnQkFDaEIsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDO0lBRUQ7OztPQUdHO0lBQ0ssZUFBZSxDQUFDLElBQWEsRUFBRSxZQUF5QjtRQUM5RCxRQUFRLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUNsQixLQUFLLG1CQUFtQjtnQkFDdEIsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUN4QixZQUFZLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDOUIsQ0FBQztnQkFDRCxNQUFNO1lBRVIsS0FBSyxjQUFjO2dCQUNqQixJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ2hELE1BQU07WUFFUixLQUFLLGFBQWE7Z0JBQ2hCLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDaEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxDQUFDO2dCQUNyQyxNQUFNO1lBRVI7Z0JBQ0UsNkRBQTZEO2dCQUM3RCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDL0IsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDO0NBQ0Y7QUFqSEQsa0RBaUhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQVNUTm9kZSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgUGFyc2VyIH0gZnJvbSAnLi9wYXJzZXInO1xuXG5leHBvcnQgY2xhc3MgRGVwZW5kZW5jeUV4dHJhY3RvciB7XG4gIHByaXZhdGUgcGFyc2VyOiBQYXJzZXI7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5wYXJzZXIgPSBuZXcgUGFyc2VyKCk7XG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdCBhbGwgdmFyaWFibGUgZGVwZW5kZW5jaWVzIGZyb20gYW4gZXhwcmVzc2lvbiBzdHJpbmdcbiAgICogUmV0dXJucyBhIHNldCBvZiB2YXJpYWJsZSBuYW1lcyAod2l0aG91dCB0aGUgJCBvciBAIHByZWZpeClcbiAgICovXG4gIGV4dHJhY3QoZXhwcmVzc2lvbjogc3RyaW5nKTogU2V0PHN0cmluZz4ge1xuICAgIGNvbnN0IGFzdCA9IHRoaXMucGFyc2VyLnBhcnNlKGV4cHJlc3Npb24pO1xuICAgIHJldHVybiB0aGlzLmV4dHJhY3RGcm9tTm9kZShhc3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgZGVwZW5kZW5jaWVzIGZyb20gYW4gQVNUIG5vZGVcbiAgICovXG4gIGV4dHJhY3RGcm9tTm9kZShub2RlOiBBU1ROb2RlKTogU2V0PHN0cmluZz4ge1xuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHRoaXMudmlzaXQobm9kZSwgZGVwZW5kZW5jaWVzKTtcbiAgICByZXR1cm4gZGVwZW5kZW5jaWVzO1xuICB9XG5cbiAgcHJpdmF0ZSB2aXNpdChub2RlOiBBU1ROb2RlLCBkZXBlbmRlbmNpZXM6IFNldDxzdHJpbmc+KTogdm9pZCB7XG4gICAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICAgIGNhc2UgJ1ZhcmlhYmxlUmVmZXJlbmNlJzpcbiAgICAgICAgLy8gT25seSBleHRyYWN0ICQgcHJlZml4ZWQgdmFyaWFibGVzIChub3QgQCBjb250ZXh0IHZhcmlhYmxlcylcbiAgICAgICAgLy8gQ29udGV4dCB2YXJpYWJsZXMgYXJlIGNvbnNpZGVyZWQgZXh0ZXJuYWwgYW5kIGRvbid0IGZvcm0gcGFydCBvZiB0aGUgZGVwZW5kZW5jeSBncmFwaFxuICAgICAgICBpZiAobm9kZS5wcmVmaXggPT09ICckJykge1xuICAgICAgICAgIGRlcGVuZGVuY2llcy5hZGQobm9kZS5uYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnQmluYXJ5T3BlcmF0aW9uJzpcbiAgICAgICAgdGhpcy52aXNpdChub2RlLmxlZnQsIGRlcGVuZGVuY2llcyk7XG4gICAgICAgIHRoaXMudmlzaXQobm9kZS5yaWdodCwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ1VuYXJ5T3BlcmF0aW9uJzpcbiAgICAgICAgdGhpcy52aXNpdChub2RlLm9wZXJhbmQsIGRlcGVuZGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdDb25kaXRpb25hbEV4cHJlc3Npb24nOlxuICAgICAgICB0aGlzLnZpc2l0KG5vZGUuY29uZGl0aW9uLCBkZXBlbmRlbmNpZXMpO1xuICAgICAgICB0aGlzLnZpc2l0KG5vZGUuY29uc2VxdWVudCwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgdGhpcy52aXNpdChub2RlLmFsdGVybmF0ZSwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ0Z1bmN0aW9uQ2FsbCc6XG4gICAgICAgIC8vIFZpc2l0IGFsbCBmdW5jdGlvbiBhcmd1bWVudHNcbiAgICAgICAgZm9yIChjb25zdCBhcmcgb2Ygbm9kZS5hcmd1bWVudHMpIHtcbiAgICAgICAgICB0aGlzLnZpc2l0KGFyZywgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnTWVtYmVyQWNjZXNzJzpcbiAgICAgICAgLy8gRm9yIG1lbWJlciBhY2Nlc3MgbGlrZSAkcHJvZHVjdC5wcmljZSwgd2Ugd2FudCB0byBleHRyYWN0ICdwcm9kdWN0J1xuICAgICAgICAvLyBUaGUgcm9vdCB2YXJpYWJsZSBpcyB3aGF0IG1hdHRlcnMgZm9yIGRlcGVuZGVuY3kgdHJhY2tpbmdcbiAgICAgICAgdGhpcy52aXNpdE1lbWJlclJvb3Qobm9kZS5vYmplY3QsIGRlcGVuZGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdJbmRleEFjY2Vzcyc6XG4gICAgICAgIC8vIFNpbWlsYXIgdG8gTWVtYmVyQWNjZXNzIC0gZXh0cmFjdCB0aGUgcm9vdCB2YXJpYWJsZVxuICAgICAgICB0aGlzLnZpc2l0TWVtYmVyUm9vdChub2RlLm9iamVjdCwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgLy8gQWxzbyB2aXNpdCB0aGUgaW5kZXggZXhwcmVzc2lvbiBhcyBpdCBtaWdodCBjb250YWluIHZhcmlhYmxlc1xuICAgICAgICB0aGlzLnZpc2l0KG5vZGUuaW5kZXgsIGRlcGVuZGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdBcnJheUxpdGVyYWwnOlxuICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2Ygbm9kZS5lbGVtZW50cykge1xuICAgICAgICAgIHRoaXMudmlzaXQoZWxlbWVudCwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgLy8gTGl0ZXJhbHMgZG9uJ3QgaGF2ZSBkZXBlbmRlbmNpZXNcbiAgICAgIGNhc2UgJ0RlY2ltYWxMaXRlcmFsJzpcbiAgICAgIGNhc2UgJ051bWJlckxpdGVyYWwnOlxuICAgICAgY2FzZSAnU3RyaW5nTGl0ZXJhbCc6XG4gICAgICBjYXNlICdCb29sZWFuTGl0ZXJhbCc6XG4gICAgICBjYXNlICdOdWxsTGl0ZXJhbCc6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBWaXNpdCB0aGUgcm9vdCBvZiBhIG1lbWJlci9pbmRleCBhY2Nlc3MgY2hhaW5cbiAgICogRm9yICRwcm9kdWN0LnByaWNlLnZhbHVlLCB3ZSB3YW50IHRvIGV4dHJhY3QgJ3Byb2R1Y3QnXG4gICAqL1xuICBwcml2YXRlIHZpc2l0TWVtYmVyUm9vdChub2RlOiBBU1ROb2RlLCBkZXBlbmRlbmNpZXM6IFNldDxzdHJpbmc+KTogdm9pZCB7XG4gICAgc3dpdGNoIChub2RlLnR5cGUpIHtcbiAgICAgIGNhc2UgJ1ZhcmlhYmxlUmVmZXJlbmNlJzpcbiAgICAgICAgaWYgKG5vZGUucHJlZml4ID09PSAnJCcpIHtcbiAgICAgICAgICBkZXBlbmRlbmNpZXMuYWRkKG5vZGUubmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgJ01lbWJlckFjY2Vzcyc6XG4gICAgICAgIHRoaXMudmlzaXRNZW1iZXJSb290KG5vZGUub2JqZWN0LCBkZXBlbmRlbmNpZXMpO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnSW5kZXhBY2Nlc3MnOlxuICAgICAgICB0aGlzLnZpc2l0TWVtYmVyUm9vdChub2RlLm9iamVjdCwgZGVwZW5kZW5jaWVzKTtcbiAgICAgICAgdGhpcy52aXNpdChub2RlLmluZGV4LCBkZXBlbmRlbmNpZXMpO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gRm9yIG90aGVyIG5vZGUgdHlwZXMgKGxpa2UgZnVuY3Rpb24gY2FsbHMpLCB2aXNpdCBub3JtYWxseVxuICAgICAgICB0aGlzLnZpc2l0KG5vZGUsIGRlcGVuZGVuY2llcyk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxufVxuIl19
@@ -0,0 +1,60 @@
1
+ import { DependencyGraph as IDependencyGraph, FormulaDefinition } from './types';
2
+ export declare class DependencyGraph implements IDependencyGraph {
3
+ nodes: Set<string>;
4
+ edges: Map<string, Set<string>>;
5
+ constructor();
6
+ /**
7
+ * Add a node to the graph
8
+ */
9
+ addNode(id: string): void;
10
+ /**
11
+ * Add an edge from source to target (source depends on target)
12
+ */
13
+ addEdge(source: string, target: string): void;
14
+ /**
15
+ * Check if the graph has any cycles
16
+ */
17
+ hasCycles(): boolean;
18
+ /**
19
+ * Get all root nodes (nodes with no dependencies)
20
+ */
21
+ getRoots(): Set<string>;
22
+ /**
23
+ * Get all nodes that depend on the given node
24
+ */
25
+ getDependents(nodeId: string): Set<string>;
26
+ /**
27
+ * Get direct dependencies of a node
28
+ */
29
+ getDependencies(nodeId: string): Set<string>;
30
+ /**
31
+ * Get all transitive dependencies of a node
32
+ */
33
+ getTransitiveDependencies(nodeId: string): Set<string>;
34
+ private collectTransitiveDependencies;
35
+ /**
36
+ * Perform topological sort using Kahn's algorithm
37
+ * Returns nodes in evaluation order (dependencies first)
38
+ * Throws CircularDependencyError if a cycle is detected
39
+ */
40
+ topologicalSort(): string[];
41
+ /**
42
+ * Find a cycle in the graph using DFS
43
+ */
44
+ private findCycle;
45
+ }
46
+ /**
47
+ * Build a dependency graph from formula definitions
48
+ */
49
+ export declare class DependencyGraphBuilder {
50
+ private extractor;
51
+ constructor();
52
+ /**
53
+ * Build a dependency graph from formula definitions
54
+ */
55
+ build(formulas: FormulaDefinition[]): DependencyGraph;
56
+ /**
57
+ * Get the evaluation order for a set of formulas
58
+ */
59
+ getEvaluationOrder(formulas: FormulaDefinition[]): string[];
60
+ }