@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
package/dist/parser.js ADDED
@@ -0,0 +1,372 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Parser = void 0;
4
+ const lexer_1 = require("./lexer");
5
+ const types_1 = require("./types");
6
+ const errors_1 = require("./errors");
7
+ // Operator precedence levels (higher = tighter binding)
8
+ const PRECEDENCE = {
9
+ LOWEST: 1,
10
+ TERNARY: 2, // ? :
11
+ OR: 3, // || OR
12
+ AND: 4, // && AND
13
+ EQUALITY: 5, // == !=
14
+ COMPARISON: 6, // < > <= >=
15
+ TERM: 7, // + -
16
+ FACTOR: 8, // * / %
17
+ POWER: 9, // ^
18
+ UNARY: 10, // - ! NOT
19
+ CALL: 11, // function calls
20
+ MEMBER: 12, // . []
21
+ };
22
+ class Parser {
23
+ constructor() {
24
+ this.tokens = [];
25
+ this.current = 0;
26
+ this.expression = '';
27
+ }
28
+ parse(expression) {
29
+ this.expression = expression;
30
+ const lexer = new lexer_1.Lexer(expression);
31
+ this.tokens = lexer.tokenize();
32
+ this.current = 0;
33
+ const ast = this.parseExpression(PRECEDENCE.LOWEST);
34
+ if (!this.isAtEnd()) {
35
+ const token = this.peek();
36
+ throw new errors_1.UnexpectedTokenError(String(token.value), ['end of expression'], token.position);
37
+ }
38
+ return ast;
39
+ }
40
+ parseExpression(precedence) {
41
+ let left = this.parsePrefixExpression();
42
+ while (!this.isAtEnd() && precedence < this.getPrecedence()) {
43
+ left = this.parseInfixExpression(left);
44
+ }
45
+ return left;
46
+ }
47
+ parsePrefixExpression() {
48
+ const token = this.peek();
49
+ switch (token.type) {
50
+ case types_1.TokenType.NUMBER:
51
+ return this.parseNumber();
52
+ case types_1.TokenType.STRING:
53
+ return this.parseString();
54
+ case types_1.TokenType.BOOLEAN:
55
+ return this.parseBoolean();
56
+ case types_1.TokenType.NULL:
57
+ return this.parseNull();
58
+ case types_1.TokenType.VARIABLE:
59
+ return this.parseVariable();
60
+ case types_1.TokenType.CONTEXT_VAR:
61
+ return this.parseContextVariable();
62
+ case types_1.TokenType.IDENTIFIER:
63
+ return this.parseIdentifierOrFunctionCall();
64
+ case types_1.TokenType.LPAREN:
65
+ return this.parseGroupedExpression();
66
+ case types_1.TokenType.LBRACKET:
67
+ return this.parseArrayLiteral();
68
+ case types_1.TokenType.MINUS:
69
+ case types_1.TokenType.NOT:
70
+ return this.parseUnaryExpression();
71
+ default:
72
+ throw new errors_1.UnexpectedTokenError(String(token.value), ['number', 'string', 'boolean', 'null', 'variable', 'identifier', '(', '[', '-', '!'], token.position);
73
+ }
74
+ }
75
+ parseInfixExpression(left) {
76
+ const token = this.peek();
77
+ switch (token.type) {
78
+ case types_1.TokenType.PLUS:
79
+ case types_1.TokenType.MINUS:
80
+ case types_1.TokenType.MULTIPLY:
81
+ case types_1.TokenType.DIVIDE:
82
+ case types_1.TokenType.MODULO:
83
+ case types_1.TokenType.POWER:
84
+ case types_1.TokenType.EQ:
85
+ case types_1.TokenType.NEQ:
86
+ case types_1.TokenType.LT:
87
+ case types_1.TokenType.GT:
88
+ case types_1.TokenType.LTE:
89
+ case types_1.TokenType.GTE:
90
+ case types_1.TokenType.AND:
91
+ case types_1.TokenType.OR:
92
+ return this.parseBinaryExpression(left);
93
+ case types_1.TokenType.QUESTION:
94
+ return this.parseTernaryExpression(left);
95
+ case types_1.TokenType.DOT:
96
+ return this.parseMemberAccess(left);
97
+ case types_1.TokenType.LBRACKET:
98
+ return this.parseIndexAccess(left);
99
+ case types_1.TokenType.LPAREN:
100
+ // This handles the case where we have an identifier followed by (
101
+ // But actually this should be handled in parseIdentifierOrFunctionCall
102
+ return left;
103
+ default:
104
+ return left;
105
+ }
106
+ }
107
+ parseNumber() {
108
+ const token = this.advance();
109
+ const value = token.value;
110
+ if (typeof value === 'number') {
111
+ // It's a float
112
+ return {
113
+ type: 'NumberLiteral',
114
+ value: value,
115
+ };
116
+ }
117
+ else {
118
+ // It's a decimal (stored as string)
119
+ return {
120
+ type: 'DecimalLiteral',
121
+ value: String(value),
122
+ raw: String(value),
123
+ };
124
+ }
125
+ }
126
+ parseString() {
127
+ const token = this.advance();
128
+ return {
129
+ type: 'StringLiteral',
130
+ value: String(token.value),
131
+ };
132
+ }
133
+ parseBoolean() {
134
+ const token = this.advance();
135
+ return {
136
+ type: 'BooleanLiteral',
137
+ value: token.value === true,
138
+ };
139
+ }
140
+ parseNull() {
141
+ this.advance();
142
+ return {
143
+ type: 'NullLiteral',
144
+ };
145
+ }
146
+ parseVariable() {
147
+ const token = this.advance();
148
+ return {
149
+ type: 'VariableReference',
150
+ prefix: '$',
151
+ name: String(token.value),
152
+ };
153
+ }
154
+ parseContextVariable() {
155
+ const token = this.advance();
156
+ return {
157
+ type: 'VariableReference',
158
+ prefix: '@',
159
+ name: String(token.value),
160
+ };
161
+ }
162
+ parseIdentifierOrFunctionCall() {
163
+ const token = this.advance();
164
+ const name = String(token.value);
165
+ // Check if it's a function call
166
+ if (this.peek().type === types_1.TokenType.LPAREN) {
167
+ return this.parseFunctionCall(name);
168
+ }
169
+ // Otherwise, check for keywords AND/OR/NOT used as standalone identifiers
170
+ const upperName = name.toUpperCase();
171
+ if (upperName === 'AND' || upperName === 'OR') {
172
+ // These should be handled as operators, but if we reach here,
173
+ // it means they were used in an invalid context
174
+ throw new errors_1.SyntaxError(`'${name}' cannot be used as an identifier`, token.position, token.line, token.column, this.expression);
175
+ }
176
+ // It's a bare identifier - could be a variable without prefix
177
+ // For now, treat it as an error - require explicit prefix
178
+ throw new errors_1.SyntaxError(`Unknown identifier '${name}'. Variables must be prefixed with $ or @`, token.position, token.line, token.column, this.expression);
179
+ }
180
+ parseFunctionCall(name) {
181
+ this.advance(); // consume '('
182
+ const args = [];
183
+ if (this.peek().type !== types_1.TokenType.RPAREN) {
184
+ do {
185
+ if (this.peek().type === types_1.TokenType.COMMA) {
186
+ this.advance();
187
+ }
188
+ args.push(this.parseExpression(PRECEDENCE.LOWEST));
189
+ } while (this.peek().type === types_1.TokenType.COMMA);
190
+ }
191
+ this.expect(types_1.TokenType.RPAREN, ')');
192
+ return {
193
+ type: 'FunctionCall',
194
+ name: name.toUpperCase(), // Functions are case-insensitive
195
+ arguments: args,
196
+ };
197
+ }
198
+ parseGroupedExpression() {
199
+ this.advance(); // consume '('
200
+ const expr = this.parseExpression(PRECEDENCE.LOWEST);
201
+ this.expect(types_1.TokenType.RPAREN, ')');
202
+ return expr;
203
+ }
204
+ parseArrayLiteral() {
205
+ this.advance(); // consume '['
206
+ const elements = [];
207
+ if (this.peek().type !== types_1.TokenType.RBRACKET) {
208
+ do {
209
+ if (this.peek().type === types_1.TokenType.COMMA) {
210
+ this.advance();
211
+ }
212
+ elements.push(this.parseExpression(PRECEDENCE.LOWEST));
213
+ } while (this.peek().type === types_1.TokenType.COMMA);
214
+ }
215
+ this.expect(types_1.TokenType.RBRACKET, ']');
216
+ return {
217
+ type: 'ArrayLiteral',
218
+ elements,
219
+ };
220
+ }
221
+ parseUnaryExpression() {
222
+ const token = this.advance();
223
+ const operator = this.getOperatorSymbol(token.type);
224
+ const operand = this.parseExpression(PRECEDENCE.UNARY);
225
+ return {
226
+ type: 'UnaryOperation',
227
+ operator,
228
+ operand,
229
+ };
230
+ }
231
+ parseBinaryExpression(left) {
232
+ const token = this.advance();
233
+ const operator = this.getOperatorSymbol(token.type);
234
+ const precedence = this.getTokenPrecedence(token.type);
235
+ // Right associativity for power operator
236
+ const nextPrecedence = token.type === types_1.TokenType.POWER ? precedence - 1 : precedence;
237
+ const right = this.parseExpression(nextPrecedence);
238
+ return {
239
+ type: 'BinaryOperation',
240
+ operator,
241
+ left,
242
+ right,
243
+ };
244
+ }
245
+ parseTernaryExpression(condition) {
246
+ this.advance(); // consume '?'
247
+ const consequent = this.parseExpression(PRECEDENCE.LOWEST);
248
+ this.expect(types_1.TokenType.COLON, ':');
249
+ const alternate = this.parseExpression(PRECEDENCE.TERNARY - 1);
250
+ return {
251
+ type: 'ConditionalExpression',
252
+ condition,
253
+ consequent,
254
+ alternate,
255
+ };
256
+ }
257
+ parseMemberAccess(object) {
258
+ this.advance(); // consume '.'
259
+ const token = this.peek();
260
+ if (token.type !== types_1.TokenType.IDENTIFIER && token.type !== types_1.TokenType.VARIABLE) {
261
+ throw new errors_1.UnexpectedTokenError(String(token.value), ['identifier'], token.position);
262
+ }
263
+ this.advance();
264
+ const property = String(token.value);
265
+ const node = {
266
+ type: 'MemberAccess',
267
+ object,
268
+ property,
269
+ };
270
+ // Check for chained access
271
+ if (this.peek().type === types_1.TokenType.DOT) {
272
+ return this.parseMemberAccess(node);
273
+ }
274
+ if (this.peek().type === types_1.TokenType.LBRACKET) {
275
+ return this.parseIndexAccess(node);
276
+ }
277
+ return node;
278
+ }
279
+ parseIndexAccess(object) {
280
+ this.advance(); // consume '['
281
+ const index = this.parseExpression(PRECEDENCE.LOWEST);
282
+ this.expect(types_1.TokenType.RBRACKET, ']');
283
+ const node = {
284
+ type: 'IndexAccess',
285
+ object,
286
+ index,
287
+ };
288
+ // Check for chained access
289
+ if (this.peek().type === types_1.TokenType.DOT) {
290
+ return this.parseMemberAccess(node);
291
+ }
292
+ if (this.peek().type === types_1.TokenType.LBRACKET) {
293
+ return this.parseIndexAccess(node);
294
+ }
295
+ return node;
296
+ }
297
+ getPrecedence() {
298
+ return this.getTokenPrecedence(this.peek().type);
299
+ }
300
+ getTokenPrecedence(type) {
301
+ switch (type) {
302
+ case types_1.TokenType.OR:
303
+ return PRECEDENCE.OR;
304
+ case types_1.TokenType.AND:
305
+ return PRECEDENCE.AND;
306
+ case types_1.TokenType.EQ:
307
+ case types_1.TokenType.NEQ:
308
+ return PRECEDENCE.EQUALITY;
309
+ case types_1.TokenType.LT:
310
+ case types_1.TokenType.GT:
311
+ case types_1.TokenType.LTE:
312
+ case types_1.TokenType.GTE:
313
+ return PRECEDENCE.COMPARISON;
314
+ case types_1.TokenType.PLUS:
315
+ case types_1.TokenType.MINUS:
316
+ return PRECEDENCE.TERM;
317
+ case types_1.TokenType.MULTIPLY:
318
+ case types_1.TokenType.DIVIDE:
319
+ case types_1.TokenType.MODULO:
320
+ return PRECEDENCE.FACTOR;
321
+ case types_1.TokenType.POWER:
322
+ return PRECEDENCE.POWER;
323
+ case types_1.TokenType.DOT:
324
+ case types_1.TokenType.LBRACKET:
325
+ return PRECEDENCE.MEMBER;
326
+ case types_1.TokenType.QUESTION:
327
+ return PRECEDENCE.TERNARY;
328
+ default:
329
+ return PRECEDENCE.LOWEST;
330
+ }
331
+ }
332
+ getOperatorSymbol(type) {
333
+ switch (type) {
334
+ case types_1.TokenType.PLUS: return '+';
335
+ case types_1.TokenType.MINUS: return '-';
336
+ case types_1.TokenType.MULTIPLY: return '*';
337
+ case types_1.TokenType.DIVIDE: return '/';
338
+ case types_1.TokenType.MODULO: return '%';
339
+ case types_1.TokenType.POWER: return '^';
340
+ case types_1.TokenType.EQ: return '==';
341
+ case types_1.TokenType.NEQ: return '!=';
342
+ case types_1.TokenType.LT: return '<';
343
+ case types_1.TokenType.GT: return '>';
344
+ case types_1.TokenType.LTE: return '<=';
345
+ case types_1.TokenType.GTE: return '>=';
346
+ case types_1.TokenType.AND: return '&&';
347
+ case types_1.TokenType.OR: return '||';
348
+ case types_1.TokenType.NOT: return '!';
349
+ default: return '';
350
+ }
351
+ }
352
+ peek() {
353
+ return this.tokens[this.current];
354
+ }
355
+ advance() {
356
+ if (!this.isAtEnd()) {
357
+ this.current++;
358
+ }
359
+ return this.tokens[this.current - 1];
360
+ }
361
+ isAtEnd() {
362
+ return this.peek().type === types_1.TokenType.EOF;
363
+ }
364
+ expect(type, expected) {
365
+ if (this.peek().type === type) {
366
+ return this.advance();
367
+ }
368
+ throw new errors_1.UnexpectedTokenError(String(this.peek().value), [expected], this.peek().position);
369
+ }
370
+ }
371
+ exports.Parser = Parser;
372
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3BhcnNlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxtQ0FBZ0M7QUFDaEMsbUNBQW9EO0FBQ3BELHFDQUE2RDtBQUU3RCx3REFBd0Q7QUFDeEQsTUFBTSxVQUFVLEdBQUc7SUFDakIsTUFBTSxFQUFFLENBQUM7SUFDVCxPQUFPLEVBQUUsQ0FBQyxFQUFNLE1BQU07SUFDdEIsRUFBRSxFQUFFLENBQUMsRUFBVyxRQUFRO0lBQ3hCLEdBQUcsRUFBRSxDQUFDLEVBQVUsU0FBUztJQUN6QixRQUFRLEVBQUUsQ0FBQyxFQUFLLFFBQVE7SUFDeEIsVUFBVSxFQUFFLENBQUMsRUFBRyxZQUFZO0lBQzVCLElBQUksRUFBRSxDQUFDLEVBQVMsTUFBTTtJQUN0QixNQUFNLEVBQUUsQ0FBQyxFQUFPLFFBQVE7SUFDeEIsS0FBSyxFQUFFLENBQUMsRUFBUSxJQUFJO0lBQ3BCLEtBQUssRUFBRSxFQUFFLEVBQU8sVUFBVTtJQUMxQixJQUFJLEVBQUUsRUFBRSxFQUFRLGlCQUFpQjtJQUNqQyxNQUFNLEVBQUUsRUFBRSxFQUFNLE9BQU87Q0FDeEIsQ0FBQztBQUVGLE1BQWEsTUFBTTtJQUFuQjtRQUNVLFdBQU0sR0FBWSxFQUFFLENBQUM7UUFDckIsWUFBTyxHQUFXLENBQUMsQ0FBQztRQUNwQixlQUFVLEdBQVcsRUFBRSxDQUFDO0lBeWFsQyxDQUFDO0lBdmFDLEtBQUssQ0FBQyxVQUFrQjtRQUN0QixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztRQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLGFBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUMvQixJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQztRQUVqQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLFVB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UyxDQUFDLEVBQUUsQ0FBQyxDQUFDLE9BQU8sSUFBSSxDQUFDO1lBQy9CLEtBQUssaUJBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQztZQUMvQixPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNyQixDQUFDO0lBQ0gsQ0FBQztJQUVPLElBQUk7UUFDVixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFTyxPQUFPO1FBQ2IsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQixDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLE9BQU87UUFDYixPQUFPLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxJQUFJLEtBQUssaUJBQVMsQ0FBQyxHQUFHLENBQUM7SUFDNUMsQ0FBQztJQUVPLE1BQU0sQ0FBQyxJQUFlLEVBQUUsUUFBZ0I7UUFDOUMsSUFBSSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLENBQUM7UUFDRCxNQUFNLElBQUksNkJBQW9CLENBQzVCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQ3pCLENBQUMsUUFBUSxDQUFDLEVBQ1YsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLFFBQVEsQ0FDckIsQ0FBQztJQUNKLENBQUM7Q0FDRjtBQTVhRCx3QkE0YUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBMZXhlciB9IGZyb20gJy4vbGV4ZXInO1xuaW1wb3J0IHsgVG9rZW4sIFRva2VuVHlwZSwgQVNUTm9kZSB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgU3ludGF4RXJyb3IsIFVuZXhwZWN0ZWRUb2tlbkVycm9yIH0gZnJvbSAnLi9lcnJvcnMnO1xuXG4vLyBPcGVyYXRvciBwcmVjZWRlbmNlIGxldmVscyAoaGlnaGVyID0gdGlnaHRlciBiaW5kaW5nKVxuY29uc3QgUFJFQ0VERU5DRSA9IHtcbiAgTE9XRVNUOiAxLFxuICBURVJOQVJZOiAyLCAgICAgLy8gPyA6XG4gIE9SOiAzLCAgICAgICAgICAvLyB8fCBPUlxuICBBTkQ6IDQsICAgICAgICAgLy8gJiYgQU5EXG4gIEVRVUFMSVRZOiA1LCAgICAvLyA9PSAhPVxuICBDT01QQVJJU09OOiA2LCAgLy8gPCA+IDw9ID49XG4gIFRFUk06IDcsICAgICAgICAvLyArIC1cbiAgRkFDVE9SOiA4LCAgICAgIC8vICogLyAlXG4gIFBPV0VSOiA5LCAgICAgICAvLyBeXG4gIFVOQVJZOiAxMCwgICAgICAvLyAtICEgTk9UXG4gIENBTEw6IDExLCAgICAgICAvLyBmdW5jdGlvbiBjYWxsc1xuICBNRU1CRVI6IDEyLCAgICAgLy8gLiBbXVxufTtcblxuZXhwb3J0IGNsYXNzIFBhcnNlciB7XG4gIHByaXZhdGUgdG9rZW5zOiBUb2tlbltdID0gW107XG4gIHByaXZhdGUgY3VycmVudDogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBleHByZXNzaW9uOiBzdHJpbmcgPSAnJztcblxuICBwYXJzZShleHByZXNzaW9uOiBzdHJpbmcpOiBBU1ROb2RlIHtcbiAgICB0aGlzLmV4cHJlc3Npb24gPSBleHByZXNzaW9uO1xuICAgIGNvbnN0IGxleGVyID0gbmV3IExleGVyKGV4cHJlc3Npb24pO1xuICAgIHRoaXMudG9rZW5zID0gbGV4ZXIudG9rZW5pemUoKTtcbiAgICB0aGlzLmN1cnJlbnQgPSAwO1xuXG4gICAgY29uc3QgYXN0ID0gdGhpcy5wYXJzZUV4cHJlc3Npb24oUFJFQ0VERU5DRS5MT1dFU1QpO1xuXG4gICAgaWYgKCF0aGlzLmlzQXRFbmQoKSkge1xuICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcbiAgICAgIHRocm93IG5ldyBVbmV4cGVjdGVkVG9rZW5FcnJvcihcbiAgICAgICAgU3RyaW5nKHRva2VuLnZhbHVlKSxcbiAgICAgICAgWydlbmQgb2YgZXhwcmVzc2lvbiddLFxuICAgICAgICB0b2tlbi5wb3NpdGlvblxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUV4cHJlc3Npb24ocHJlY2VkZW5jZTogbnVtYmVyKTogQVNUTm9kZSB7XG4gICAgbGV0IGxlZnQgPSB0aGlzLnBhcnNlUHJlZml4RXhwcmVzc2lvbigpO1xuXG4gICAgd2hpbGUgKCF0aGlzLmlzQXRFbmQoKSAmJiBwcmVjZWRlbmNlIDwgdGhpcy5nZXRQcmVjZWRlbmNlKCkpIHtcbiAgICAgIGxlZnQgPSB0aGlzLnBhcnNlSW5maXhFeHByZXNzaW9uKGxlZnQpO1xuICAgIH1cblxuICAgIHJldHVybiBsZWZ0O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVByZWZpeEV4cHJlc3Npb24oKTogQVNUTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcblxuICAgIHN3aXRjaCAodG9rZW4udHlwZSkge1xuICAgICAgY2FzZSBUb2tlblR5cGUuTlVNQkVSOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZU51bWJlcigpO1xuICAgICAgY2FzZSBUb2tlblR5cGUuU1RSSU5HOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZVN0cmluZygpO1xuICAgICAgY2FzZSBUb2tlblR5cGUuQk9PTEVBTjpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VCb29sZWFuKCk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5OVUxMOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZU51bGwoKTtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLlZBUklBQkxFOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZVZhcmlhYmxlKCk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5DT05URVhUX1ZBUjpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VDb250ZXh0VmFyaWFibGUoKTtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLklERU5USUZJRVI6XG4gICAgICAgIHJldHVybiB0aGlzLnBhcnNlSWRlbnRpZmllck9yRnVuY3Rpb25DYWxsKCk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5MUEFSRU46XG4gICAgICAgIHJldHVybiB0aGlzLnBhcnNlR3JvdXBlZEV4cHJlc3Npb24oKTtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkxCUkFDS0VUOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZUFycmF5TGl0ZXJhbCgpO1xuICAgICAgY2FzZSBUb2tlblR5cGUuTUlOVVM6XG4gICAgICBjYXNlIFRva2VuVHlwZS5OT1Q6XG4gICAgICAgIHJldHVybiB0aGlzLnBhcnNlVW5hcnlFeHByZXNzaW9uKCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgVW5leHBlY3RlZFRva2VuRXJyb3IoXG4gICAgICAgICAgU3RyaW5nKHRva2VuLnZhbHVlKSxcbiAgICAgICAgICBbJ251bWJlcicsICdzdHJpbmcnLCAnYm9vbGVhbicsICdudWxsJywgJ3ZhcmlhYmxlJywgJ2lkZW50aWZpZXInLCAnKCcsICdbJywgJy0nLCAnISddLFxuICAgICAgICAgIHRva2VuLnBvc2l0aW9uXG4gICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUluZml4RXhwcmVzc2lvbihsZWZ0OiBBU1ROb2RlKTogQVNUTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLnBlZWsoKTtcblxuICAgIHN3aXRjaCAodG9rZW4udHlwZSkge1xuICAgICAgY2FzZSBUb2tlblR5cGUuUExVUzpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLk1JTlVTOlxuICAgICAgY2FzZSBUb2tlblR5cGUuTVVMVElQTFk6XG4gICAgICBjYXNlIFRva2VuVHlwZS5ESVZJREU6XG4gICAgICBjYXNlIFRva2VuVHlwZS5NT0RVTE86XG4gICAgICBjYXNlIFRva2VuVHlwZS5QT1dFUjpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkVROlxuICAgICAgY2FzZSBUb2tlblR5cGUuTkVROlxuICAgICAgY2FzZSBUb2tlblR5cGUuTFQ6XG4gICAgICBjYXNlIFRva2VuVHlwZS5HVDpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkxURTpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkdURTpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkFORDpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLk9SOlxuICAgICAgICByZXR1cm4gdGhpcy5wYXJzZUJpbmFyeUV4cHJlc3Npb24obGVmdCk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5RVUVTVElPTjpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VUZXJuYXJ5RXhwcmVzc2lvbihsZWZ0KTtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkRPVDpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VNZW1iZXJBY2Nlc3MobGVmdCk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5MQlJBQ0tFVDpcbiAgICAgICAgcmV0dXJuIHRoaXMucGFyc2VJbmRleEFjY2VzcyhsZWZ0KTtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkxQQVJFTjpcbiAgICAgICAgLy8gVGhpcyBoYW5kbGVzIHRoZSBjYXNlIHdoZXJlIHdlIGhhdmUgYW4gaWRlbnRpZmllciBmb2xsb3dlZCBieSAoXG4gICAgICAgIC8vIEJ1dCBhY3R1YWxseSB0aGlzIHNob3VsZCBiZSBoYW5kbGVkIGluIHBhcnNlSWRlbnRpZmllck9yRnVuY3Rpb25DYWxsXG4gICAgICAgIHJldHVybiBsZWZ0O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIGxlZnQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZU51bWJlcigpOiBBU1ROb2RlIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYWR2YW5jZSgpO1xuICAgIGNvbnN0IHZhbHVlID0gdG9rZW4udmFsdWU7XG5cbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgLy8gSXQncyBhIGZsb2F0XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0eXBlOiAnTnVtYmVyTGl0ZXJhbCcsXG4gICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEl0J3MgYSBkZWNpbWFsIChzdG9yZWQgYXMgc3RyaW5nKVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ0RlY2ltYWxMaXRlcmFsJyxcbiAgICAgICAgdmFsdWU6IFN0cmluZyh2YWx1ZSksXG4gICAgICAgIHJhdzogU3RyaW5nKHZhbHVlKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVN0cmluZygpOiBBU1ROb2RlIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYWR2YW5jZSgpO1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnU3RyaW5nTGl0ZXJhbCcsXG4gICAgICB2YWx1ZTogU3RyaW5nKHRva2VuLnZhbHVlKSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUJvb2xlYW4oKTogQVNUTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLmFkdmFuY2UoKTtcbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ0Jvb2xlYW5MaXRlcmFsJyxcbiAgICAgIHZhbHVlOiB0b2tlbi52YWx1ZSA9PT0gdHJ1ZSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZU51bGwoKTogQVNUTm9kZSB7XG4gICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6ICdOdWxsTGl0ZXJhbCcsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VWYXJpYWJsZSgpOiBBU1ROb2RlIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYWR2YW5jZSgpO1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAnVmFyaWFibGVSZWZlcmVuY2UnLFxuICAgICAgcHJlZml4OiAnJCcsXG4gICAgICBuYW1lOiBTdHJpbmcodG9rZW4udmFsdWUpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHBhcnNlQ29udGV4dFZhcmlhYmxlKCk6IEFTVE5vZGUge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5hZHZhbmNlKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6ICdWYXJpYWJsZVJlZmVyZW5jZScsXG4gICAgICBwcmVmaXg6ICdAJyxcbiAgICAgIG5hbWU6IFN0cmluZyh0b2tlbi52YWx1ZSksXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJZGVudGlmaWVyT3JGdW5jdGlvbkNhbGwoKTogQVNUTm9kZSB7XG4gICAgY29uc3QgdG9rZW4gPSB0aGlzLmFkdmFuY2UoKTtcbiAgICBjb25zdCBuYW1lID0gU3RyaW5nKHRva2VuLnZhbHVlKTtcblxuICAgIC8vIENoZWNrIGlmIGl0J3MgYSBmdW5jdGlvbiBjYWxsXG4gICAgaWYgKHRoaXMucGVlaygpLnR5cGUgPT09IFRva2VuVHlwZS5MUEFSRU4pIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlRnVuY3Rpb25DYWxsKG5hbWUpO1xuICAgIH1cblxuICAgIC8vIE90aGVyd2lzZSwgY2hlY2sgZm9yIGtleXdvcmRzIEFORC9PUi9OT1QgdXNlZCBhcyBzdGFuZGFsb25lIGlkZW50aWZpZXJzXG4gICAgY29uc3QgdXBwZXJOYW1lID0gbmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIGlmICh1cHBlck5hbWUgPT09ICdBTkQnIHx8IHVwcGVyTmFtZSA9PT0gJ09SJykge1xuICAgICAgLy8gVGhlc2Ugc2hvdWxkIGJlIGhhbmRsZWQgYXMgb3BlcmF0b3JzLCBidXQgaWYgd2UgcmVhY2ggaGVyZSxcbiAgICAgIC8vIGl0IG1lYW5zIHRoZXkgd2VyZSB1c2VkIGluIGFuIGludmFsaWQgY29udGV4dFxuICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFxuICAgICAgICBgJyR7bmFtZX0nIGNhbm5vdCBiZSB1c2VkIGFzIGFuIGlkZW50aWZpZXJgLFxuICAgICAgICB0b2tlbi5wb3NpdGlvbixcbiAgICAgICAgdG9rZW4ubGluZSxcbiAgICAgICAgdG9rZW4uY29sdW1uLFxuICAgICAgICB0aGlzLmV4cHJlc3Npb25cbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gSXQncyBhIGJhcmUgaWRlbnRpZmllciAtIGNvdWxkIGJlIGEgdmFyaWFibGUgd2l0aG91dCBwcmVmaXhcbiAgICAvLyBGb3Igbm93LCB0cmVhdCBpdCBhcyBhbiBlcnJvciAtIHJlcXVpcmUgZXhwbGljaXQgcHJlZml4XG4gICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKFxuICAgICAgYFVua25vd24gaWRlbnRpZmllciAnJHtuYW1lfScuIFZhcmlhYmxlcyBtdXN0IGJlIHByZWZpeGVkIHdpdGggJCBvciBAYCxcbiAgICAgIHRva2VuLnBvc2l0aW9uLFxuICAgICAgdG9rZW4ubGluZSxcbiAgICAgIHRva2VuLmNvbHVtbixcbiAgICAgIHRoaXMuZXhwcmVzc2lvblxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlRnVuY3Rpb25DYWxsKG5hbWU6IHN0cmluZyk6IEFTVE5vZGUge1xuICAgIHRoaXMuYWR2YW5jZSgpOyAvLyBjb25zdW1lICcoJ1xuICAgIGNvbnN0IGFyZ3M6IEFTVE5vZGVbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMucGVlaygpLnR5cGUgIT09IFRva2VuVHlwZS5SUEFSRU4pIHtcbiAgICAgIGRvIHtcbiAgICAgICAgaWYgKHRoaXMucGVlaygpLnR5cGUgPT09IFRva2VuVHlwZS5DT01NQSkge1xuICAgICAgICAgIHRoaXMuYWR2YW5jZSgpO1xuICAgICAgICB9XG4gICAgICAgIGFyZ3MucHVzaCh0aGlzLnBhcnNlRXhwcmVzc2lvbihQUkVDRURFTkNFLkxPV0VTVCkpO1xuICAgICAgfSB3aGlsZSAodGhpcy5wZWVrKCkudHlwZSA9PT0gVG9rZW5UeXBlLkNPTU1BKTtcbiAgICB9XG5cbiAgICB0aGlzLmV4cGVjdChUb2tlblR5cGUuUlBBUkVOLCAnKScpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6ICdGdW5jdGlvbkNhbGwnLFxuICAgICAgbmFtZTogbmFtZS50b1VwcGVyQ2FzZSgpLCAvLyBGdW5jdGlvbnMgYXJlIGNhc2UtaW5zZW5zaXRpdmVcbiAgICAgIGFyZ3VtZW50czogYXJncyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUdyb3VwZWRFeHByZXNzaW9uKCk6IEFTVE5vZGUge1xuICAgIHRoaXMuYWR2YW5jZSgpOyAvLyBjb25zdW1lICcoJ1xuICAgIGNvbnN0IGV4cHIgPSB0aGlzLnBhcnNlRXhwcmVzc2lvbihQUkVDRURFTkNFLkxPV0VTVCk7XG4gICAgdGhpcy5leHBlY3QoVG9rZW5UeXBlLlJQQVJFTiwgJyknKTtcbiAgICByZXR1cm4gZXhwcjtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VBcnJheUxpdGVyYWwoKTogQVNUTm9kZSB7XG4gICAgdGhpcy5hZHZhbmNlKCk7IC8vIGNvbnN1bWUgJ1snXG4gICAgY29uc3QgZWxlbWVudHM6IEFTVE5vZGVbXSA9IFtdO1xuXG4gICAgaWYgKHRoaXMucGVlaygpLnR5cGUgIT09IFRva2VuVHlwZS5SQlJBQ0tFVCkge1xuICAgICAgZG8ge1xuICAgICAgICBpZiAodGhpcy5wZWVrKCkudHlwZSA9PT0gVG9rZW5UeXBlLkNPTU1BKSB7XG4gICAgICAgICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxlbWVudHMucHVzaCh0aGlzLnBhcnNlRXhwcmVzc2lvbihQUkVDRURFTkNFLkxPV0VTVCkpO1xuICAgICAgfSB3aGlsZSAodGhpcy5wZWVrKCkudHlwZSA9PT0gVG9rZW5UeXBlLkNPTU1BKTtcbiAgICB9XG5cbiAgICB0aGlzLmV4cGVjdChUb2tlblR5cGUuUkJSQUNLRVQsICddJyk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ0FycmF5TGl0ZXJhbCcsXG4gICAgICBlbGVtZW50cyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVVuYXJ5RXhwcmVzc2lvbigpOiBBU1ROb2RlIHtcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMuYWR2YW5jZSgpO1xuICAgIGNvbnN0IG9wZXJhdG9yID0gdGhpcy5nZXRPcGVyYXRvclN5bWJvbCh0b2tlbi50eXBlKTtcbiAgICBjb25zdCBvcGVyYW5kID0gdGhpcy5wYXJzZUV4cHJlc3Npb24oUFJFQ0VERU5DRS5VTkFSWSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ1VuYXJ5T3BlcmF0aW9uJyxcbiAgICAgIG9wZXJhdG9yLFxuICAgICAgb3BlcmFuZCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUJpbmFyeUV4cHJlc3Npb24obGVmdDogQVNUTm9kZSk6IEFTVE5vZGUge1xuICAgIGNvbnN0IHRva2VuID0gdGhpcy5hZHZhbmNlKCk7XG4gICAgY29uc3Qgb3BlcmF0b3IgPSB0aGlzLmdldE9wZXJhdG9yU3ltYm9sKHRva2VuLnR5cGUpO1xuICAgIGNvbnN0IHByZWNlZGVuY2UgPSB0aGlzLmdldFRva2VuUHJlY2VkZW5jZSh0b2tlbi50eXBlKTtcblxuICAgIC8vIFJpZ2h0IGFzc29jaWF0aXZpdHkgZm9yIHBvd2VyIG9wZXJhdG9yXG4gICAgY29uc3QgbmV4dFByZWNlZGVuY2UgPSB0b2tlbi50eXBlID09PSBUb2tlblR5cGUuUE9XRVIgPyBwcmVjZWRlbmNlIC0gMSA6IHByZWNlZGVuY2U7XG4gICAgY29uc3QgcmlnaHQgPSB0aGlzLnBhcnNlRXhwcmVzc2lvbihuZXh0UHJlY2VkZW5jZSk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ0JpbmFyeU9wZXJhdGlvbicsXG4gICAgICBvcGVyYXRvcixcbiAgICAgIGxlZnQsXG4gICAgICByaWdodCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZVRlcm5hcnlFeHByZXNzaW9uKGNvbmRpdGlvbjogQVNUTm9kZSk6IEFTVE5vZGUge1xuICAgIHRoaXMuYWR2YW5jZSgpOyAvLyBjb25zdW1lICc/J1xuICAgIGNvbnN0IGNvbnNlcXVlbnQgPSB0aGlzLnBhcnNlRXhwcmVzc2lvbihQUkVDRURFTkNFLkxPV0VTVCk7XG4gICAgdGhpcy5leHBlY3QoVG9rZW5UeXBlLkNPTE9OLCAnOicpO1xuICAgIGNvbnN0IGFsdGVybmF0ZSA9IHRoaXMucGFyc2VFeHByZXNzaW9uKFBSRUNFREVOQ0UuVEVSTkFSWSAtIDEpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6ICdDb25kaXRpb25hbEV4cHJlc3Npb24nLFxuICAgICAgY29uZGl0aW9uLFxuICAgICAgY29uc2VxdWVudCxcbiAgICAgIGFsdGVybmF0ZSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZU1lbWJlckFjY2VzcyhvYmplY3Q6IEFTVE5vZGUpOiBBU1ROb2RlIHtcbiAgICB0aGlzLmFkdmFuY2UoKTsgLy8gY29uc3VtZSAnLidcbiAgICBjb25zdCB0b2tlbiA9IHRoaXMucGVlaygpO1xuXG4gICAgaWYgKHRva2VuLnR5cGUgIT09IFRva2VuVHlwZS5JREVOVElGSUVSICYmIHRva2VuLnR5cGUgIT09IFRva2VuVHlwZS5WQVJJQUJMRSkge1xuICAgICAgdGhyb3cgbmV3IFVuZXhwZWN0ZWRUb2tlbkVycm9yKFxuICAgICAgICBTdHJpbmcodG9rZW4udmFsdWUpLFxuICAgICAgICBbJ2lkZW50aWZpZXInXSxcbiAgICAgICAgdG9rZW4ucG9zaXRpb25cbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5hZHZhbmNlKCk7XG4gICAgY29uc3QgcHJvcGVydHkgPSBTdHJpbmcodG9rZW4udmFsdWUpO1xuXG4gICAgY29uc3Qgbm9kZTogQVNUTm9kZSA9IHtcbiAgICAgIHR5cGU6ICdNZW1iZXJBY2Nlc3MnLFxuICAgICAgb2JqZWN0LFxuICAgICAgcHJvcGVydHksXG4gICAgfTtcblxuICAgIC8vIENoZWNrIGZvciBjaGFpbmVkIGFjY2Vzc1xuICAgIGlmICh0aGlzLnBlZWsoKS50eXBlID09PSBUb2tlblR5cGUuRE9UKSB7XG4gICAgICByZXR1cm4gdGhpcy5wYXJzZU1lbWJlckFjY2Vzcyhub2RlKTtcbiAgICB9XG4gICAgaWYgKHRoaXMucGVlaygpLnR5cGUgPT09IFRva2VuVHlwZS5MQlJBQ0tFVCkge1xuICAgICAgcmV0dXJuIHRoaXMucGFyc2VJbmRleEFjY2Vzcyhub2RlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbm9kZTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VJbmRleEFjY2VzcyhvYmplY3Q6IEFTVE5vZGUpOiBBU1ROb2RlIHtcbiAgICB0aGlzLmFkdmFuY2UoKTsgLy8gY29uc3VtZSAnWydcbiAgICBjb25zdCBpbmRleCA9IHRoaXMucGFyc2VFeHByZXNzaW9uKFBSRUNFREVOQ0UuTE9XRVNUKTtcbiAgICB0aGlzLmV4cGVjdChUb2tlblR5cGUuUkJSQUNLRVQsICddJyk7XG5cbiAgICBjb25zdCBub2RlOiBBU1ROb2RlID0ge1xuICAgICAgdHlwZTogJ0luZGV4QWNjZXNzJyxcbiAgICAgIG9iamVjdCxcbiAgICAgIGluZGV4LFxuICAgIH07XG5cbiAgICAvLyBDaGVjayBmb3IgY2hhaW5lZCBhY2Nlc3NcbiAgICBpZiAodGhpcy5wZWVrKCkudHlwZSA9PT0gVG9rZW5UeXBlLkRPVCkge1xuICAgICAgcmV0dXJuIHRoaXMucGFyc2VNZW1iZXJBY2Nlc3Mobm9kZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnBlZWsoKS50eXBlID09PSBUb2tlblR5cGUuTEJSQUNLRVQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBhcnNlSW5kZXhBY2Nlc3Mobm9kZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGU7XG4gIH1cblxuICBwcml2YXRlIGdldFByZWNlZGVuY2UoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5nZXRUb2tlblByZWNlZGVuY2UodGhpcy5wZWVrKCkudHlwZSk7XG4gIH1cblxuICBwcml2YXRlIGdldFRva2VuUHJlY2VkZW5jZSh0eXBlOiBUb2tlblR5cGUpOiBudW1iZXIge1xuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSBUb2tlblR5cGUuT1I6XG4gICAgICAgIHJldHVybiBQUkVDRURFTkNFLk9SO1xuICAgICAgY2FzZSBUb2tlblR5cGUuQU5EOlxuICAgICAgICByZXR1cm4gUFJFQ0VERU5DRS5BTkQ7XG4gICAgICBjYXNlIFRva2VuVHlwZS5FUTpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLk5FUTpcbiAgICAgICAgcmV0dXJuIFBSRUNFREVOQ0UuRVFVQUxJVFk7XG4gICAgICBjYXNlIFRva2VuVHlwZS5MVDpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkdUOlxuICAgICAgY2FzZSBUb2tlblR5cGUuTFRFOlxuICAgICAgY2FzZSBUb2tlblR5cGUuR1RFOlxuICAgICAgICByZXR1cm4gUFJFQ0VERU5DRS5DT01QQVJJU09OO1xuICAgICAgY2FzZSBUb2tlblR5cGUuUExVUzpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLk1JTlVTOlxuICAgICAgICByZXR1cm4gUFJFQ0VERU5DRS5URVJNO1xuICAgICAgY2FzZSBUb2tlblR5cGUuTVVMVElQTFk6XG4gICAgICBjYXNlIFRva2VuVHlwZS5ESVZJREU6XG4gICAgICBjYXNlIFRva2VuVHlwZS5NT0RVTE86XG4gICAgICAgIHJldHVybiBQUkVDRURFTkNFLkZBQ1RPUjtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLlBPV0VSOlxuICAgICAgICByZXR1cm4gUFJFQ0VERU5DRS5QT1dFUjtcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkRPVDpcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkxCUkFDS0VUOlxuICAgICAgICByZXR1cm4gUFJFQ0VERU5DRS5NRU1CRVI7XG4gICAgICBjYXNlIFRva2VuVHlwZS5RVUVTVElPTjpcbiAgICAgICAgcmV0dXJuIFBSRUNFREVOQ0UuVEVSTkFSWTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBQUkVDRURFTkNFLkxPV0VTVDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldE9wZXJhdG9yU3ltYm9sKHR5cGU6IFRva2VuVHlwZSk6IHN0cmluZyB7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIFRva2VuVHlwZS5QTFVTOiByZXR1cm4gJysnO1xuICAgICAgY2FzZSBUb2tlblR5cGUuTUlOVVM6IHJldHVybiAnLSc7XG4gICAgICBjYXNlIFRva2VuVHlwZS5NVUxUSVBMWTogcmV0dXJuICcqJztcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkRJVklERTogcmV0dXJuICcvJztcbiAgICAgIGNhc2UgVG9rZW5UeXBlLk1PRFVMTzogcmV0dXJuICclJztcbiAgICAgIGNhc2UgVG9rZW5UeXBlLlBPV0VSOiByZXR1cm4gJ14nO1xuICAgICAgY2FzZSBUb2tlblR5cGUuRVE6IHJldHVybiAnPT0nO1xuICAgICAgY2FzZSBUb2tlblR5cGUuTkVROiByZXR1cm4gJyE9JztcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkxUOiByZXR1cm4gJzwnO1xuICAgICAgY2FzZSBUb2tlblR5cGUuR1Q6IHJldHVybiAnPic7XG4gICAgICBjYXNlIFRva2VuVHlwZS5MVEU6IHJldHVybiAnPD0nO1xuICAgICAgY2FzZSBUb2tlblR5cGUuR1RFOiByZXR1cm4gJz49JztcbiAgICAgIGNhc2UgVG9rZW5UeXBlLkFORDogcmV0dXJuICcmJic7XG4gICAgICBjYXNlIFRva2VuVHlwZS5PUjogcmV0dXJuICd8fCc7XG4gICAgICBjYXNlIFRva2VuVHlwZS5OT1Q6IHJldHVybiAnISc7XG4gICAgICBkZWZhdWx0OiByZXR1cm4gJyc7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwZWVrKCk6IFRva2VuIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbnNbdGhpcy5jdXJyZW50XTtcbiAgfVxuXG4gIHByaXZhdGUgYWR2YW5jZSgpOiBUb2tlbiB7XG4gICAgaWYgKCF0aGlzLmlzQXRFbmQoKSkge1xuICAgICAgdGhpcy5jdXJyZW50Kys7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRva2Vuc1t0aGlzLmN1cnJlbnQgLSAxXTtcbiAgfVxuXG4gIHByaXZhdGUgaXNBdEVuZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wZWVrKCkudHlwZSA9PT0gVG9rZW5UeXBlLkVPRjtcbiAgfVxuXG4gIHByaXZhdGUgZXhwZWN0KHR5cGU6IFRva2VuVHlwZSwgZXhwZWN0ZWQ6IHN0cmluZyk6IFRva2VuIHtcbiAgICBpZiAodGhpcy5wZWVrKCkudHlwZSA9PT0gdHlwZSkge1xuICAgICAgcmV0dXJuIHRoaXMuYWR2YW5jZSgpO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgVW5leHBlY3RlZFRva2VuRXJyb3IoXG4gICAgICBTdHJpbmcodGhpcy5wZWVrKCkudmFsdWUpLFxuICAgICAgW2V4cGVjdGVkXSxcbiAgICAgIHRoaXMucGVlaygpLnBvc2l0aW9uXG4gICAgKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,228 @@
1
+ import { Decimal } from 'decimal.js';
2
+ export type ValueType = 'number' | 'decimal' | 'string' | 'boolean' | 'array' | 'object' | 'null' | 'any';
3
+ export type FormulaValue = Decimal | number | string | boolean | null | FormulaValue[] | {
4
+ [key: string]: FormulaValue;
5
+ };
6
+ export declare enum DecimalRoundingMode {
7
+ CEIL = "CEIL",
8
+ FLOOR = "FLOOR",
9
+ DOWN = "DOWN",
10
+ UP = "UP",
11
+ HALF_UP = "HALF_UP",
12
+ HALF_DOWN = "HALF_DOWN",
13
+ HALF_EVEN = "HALF_EVEN",
14
+ HALF_ODD = "HALF_ODD"
15
+ }
16
+ export interface DecimalConfig {
17
+ precision?: number;
18
+ roundingMode?: DecimalRoundingMode;
19
+ divisionScale?: number;
20
+ preserveTrailingZeros?: boolean;
21
+ autoConvertFloats?: boolean;
22
+ maxExponent?: number;
23
+ minExponent?: number;
24
+ }
25
+ export interface RoundingConfig {
26
+ mode: 'HALF_UP' | 'HALF_DOWN' | 'FLOOR' | 'CEIL' | 'NONE';
27
+ precision: number;
28
+ }
29
+ export interface ErrorBehavior {
30
+ type: 'THROW' | 'NULL' | 'ZERO' | 'DEFAULT' | 'SKIP';
31
+ defaultValue?: unknown;
32
+ }
33
+ export interface FormulaDefinition {
34
+ id: string;
35
+ expression: string;
36
+ dependencies?: string[];
37
+ onError?: ErrorBehavior;
38
+ defaultValue?: unknown;
39
+ rounding?: RoundingConfig;
40
+ metadata?: Record<string, unknown>;
41
+ }
42
+ export interface EvaluationContext {
43
+ variables: Record<string, unknown>;
44
+ collections?: Record<string, unknown[]>;
45
+ extra?: Record<string, unknown>;
46
+ }
47
+ export interface OperatorDefinition {
48
+ symbol: string;
49
+ precedence: number;
50
+ associativity: 'left' | 'right';
51
+ handler: (left: unknown, right: unknown) => unknown;
52
+ }
53
+ export interface SecurityConfig {
54
+ maxExpressionLength?: number;
55
+ maxRecursionDepth?: number;
56
+ maxIterations?: number;
57
+ maxExecutionTime?: number;
58
+ allowedFunctions?: string[];
59
+ blockedFunctions?: string[];
60
+ }
61
+ export interface FormulaEngineConfig {
62
+ enableCache?: boolean;
63
+ maxCacheSize?: number;
64
+ defaultErrorBehavior?: ErrorBehavior;
65
+ defaultRounding?: RoundingConfig;
66
+ variablePrefix?: string;
67
+ contextPrefix?: string;
68
+ strictMode?: boolean;
69
+ operators?: OperatorDefinition[];
70
+ functions?: FunctionDefinition[];
71
+ decimal?: DecimalConfig;
72
+ security?: SecurityConfig;
73
+ }
74
+ export interface DecimalLiteral {
75
+ type: 'DecimalLiteral';
76
+ value: string;
77
+ raw: string;
78
+ }
79
+ export interface NumberLiteral {
80
+ type: 'NumberLiteral';
81
+ value: number;
82
+ }
83
+ export interface StringLiteral {
84
+ type: 'StringLiteral';
85
+ value: string;
86
+ }
87
+ export interface BooleanLiteral {
88
+ type: 'BooleanLiteral';
89
+ value: boolean;
90
+ }
91
+ export interface NullLiteral {
92
+ type: 'NullLiteral';
93
+ }
94
+ export interface ArrayLiteral {
95
+ type: 'ArrayLiteral';
96
+ elements: ASTNode[];
97
+ }
98
+ export interface VariableReference {
99
+ type: 'VariableReference';
100
+ prefix: '$' | '@';
101
+ name: string;
102
+ }
103
+ export interface BinaryOperation {
104
+ type: 'BinaryOperation';
105
+ operator: string;
106
+ left: ASTNode;
107
+ right: ASTNode;
108
+ }
109
+ export interface UnaryOperation {
110
+ type: 'UnaryOperation';
111
+ operator: string;
112
+ operand: ASTNode;
113
+ }
114
+ export interface ConditionalExpression {
115
+ type: 'ConditionalExpression';
116
+ condition: ASTNode;
117
+ consequent: ASTNode;
118
+ alternate: ASTNode;
119
+ }
120
+ export interface FunctionCall {
121
+ type: 'FunctionCall';
122
+ name: string;
123
+ arguments: ASTNode[];
124
+ }
125
+ export interface MemberAccess {
126
+ type: 'MemberAccess';
127
+ object: ASTNode;
128
+ property: string;
129
+ }
130
+ export interface IndexAccess {
131
+ type: 'IndexAccess';
132
+ object: ASTNode;
133
+ index: ASTNode;
134
+ }
135
+ export type ASTNode = DecimalLiteral | NumberLiteral | StringLiteral | BooleanLiteral | NullLiteral | ArrayLiteral | VariableReference | BinaryOperation | UnaryOperation | ConditionalExpression | FunctionCall | MemberAccess | IndexAccess;
136
+ export interface ArgumentType {
137
+ name: string;
138
+ type: ValueType;
139
+ required: boolean;
140
+ default?: unknown;
141
+ }
142
+ export type FunctionImplementation = (args: unknown[], context: EvaluationContext, engine: unknown) => unknown;
143
+ export interface FunctionDefinition {
144
+ name: string;
145
+ minArgs: number;
146
+ maxArgs: number;
147
+ argTypes?: ArgumentType[];
148
+ returnType: ValueType;
149
+ implementation: FunctionImplementation;
150
+ description?: string;
151
+ }
152
+ export interface DependencyGraph {
153
+ nodes: Set<string>;
154
+ edges: Map<string, Set<string>>;
155
+ hasCycles(): boolean;
156
+ getRoots(): Set<string>;
157
+ getDependents(nodeId: string): Set<string>;
158
+ getDependencies(nodeId: string): Set<string>;
159
+ getTransitiveDependencies(nodeId: string): Set<string>;
160
+ topologicalSort(): string[];
161
+ }
162
+ export interface EvaluationResult {
163
+ value: unknown;
164
+ success: boolean;
165
+ error?: Error;
166
+ executionTimeMs: number;
167
+ accessedVariables: Set<string>;
168
+ }
169
+ export interface EvaluationResultSet {
170
+ results: Map<string, EvaluationResult>;
171
+ success: boolean;
172
+ errors: Error[];
173
+ totalExecutionTimeMs: number;
174
+ evaluationOrder: string[];
175
+ }
176
+ export interface ValidationResult {
177
+ valid: boolean;
178
+ errors: Error[];
179
+ warnings: string[];
180
+ dependencyGraph: DependencyGraph;
181
+ evaluationOrder: string[];
182
+ }
183
+ export interface CacheStats {
184
+ size: number;
185
+ hits: number;
186
+ misses: number;
187
+ hitRate: number;
188
+ }
189
+ export declare enum TokenType {
190
+ NUMBER = "NUMBER",
191
+ STRING = "STRING",
192
+ BOOLEAN = "BOOLEAN",
193
+ NULL = "NULL",
194
+ IDENTIFIER = "IDENTIFIER",
195
+ VARIABLE = "VARIABLE",
196
+ CONTEXT_VAR = "CONTEXT_VAR",
197
+ PLUS = "PLUS",
198
+ MINUS = "MINUS",
199
+ MULTIPLY = "MULTIPLY",
200
+ DIVIDE = "DIVIDE",
201
+ MODULO = "MODULO",
202
+ POWER = "POWER",
203
+ EQ = "EQ",
204
+ NEQ = "NEQ",
205
+ LT = "LT",
206
+ GT = "GT",
207
+ LTE = "LTE",
208
+ GTE = "GTE",
209
+ AND = "AND",
210
+ OR = "OR",
211
+ NOT = "NOT",
212
+ LPAREN = "LPAREN",
213
+ RPAREN = "RPAREN",
214
+ LBRACKET = "LBRACKET",
215
+ RBRACKET = "RBRACKET",
216
+ COMMA = "COMMA",
217
+ DOT = "DOT",
218
+ QUESTION = "QUESTION",
219
+ COLON = "COLON",
220
+ EOF = "EOF"
221
+ }
222
+ export interface Token {
223
+ type: TokenType;
224
+ value: string | number | boolean | null;
225
+ position: number;
226
+ line: number;
227
+ column: number;
228
+ }