@the-trybe/formula-engine 1.0.1 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -88,6 +88,118 @@ const results = engine.evaluateAll(formulas, context);
88
88
  console.log(results.results.get('total')?.value.toString()); // "540"
89
89
  ```
90
90
 
91
+ ### Formula Definition Options
92
+
93
+ Each formula in `evaluateAll()` supports additional configuration options:
94
+
95
+ ```typescript
96
+ interface FormulaDefinition {
97
+ id: string; // Unique identifier for the formula
98
+ expression: string; // The expression to evaluate
99
+ dependencies?: string[]; // Explicit dependencies (auto-detected if omitted)
100
+ rounding?: RoundingConfig; // Rounding configuration for the result
101
+ onError?: ErrorBehavior; // How to handle evaluation errors
102
+ defaultValue?: unknown; // Default value when using onError: 'DEFAULT'
103
+ metadata?: Record<string, unknown>; // Custom metadata (not used by engine)
104
+ }
105
+ ```
106
+
107
+ #### Default Intermediate Rounding
108
+
109
+ For financial calculations, configure `defaultRounding` in the engine to automatically round all intermediate values in `evaluateAll()`:
110
+
111
+ ```typescript
112
+ const engine = new FormulaEngine({
113
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
114
+ });
115
+
116
+ const formulas = [
117
+ { id: 'subtotal', expression: '$quantity * $unitPrice' },
118
+ { id: 'tax', expression: '$subtotal * 0.0825' }, // Uses rounded subtotal
119
+ { id: 'total', expression: '$subtotal + $tax' },
120
+ ];
121
+
122
+ const results = engine.evaluateAll(formulas, {
123
+ variables: { quantity: 3, unitPrice: 10.33 }
124
+ });
125
+
126
+ // subtotal = 30.99 (auto-rounded)
127
+ // tax = 2.56 (auto-rounded, calculated from rounded subtotal)
128
+ // total = 33.55
129
+ ```
130
+
131
+ This ensures intermediate values are rounded before being used in dependent formulas, which is critical for financial/accounting calculations.
132
+
133
+ #### Disabling Intermediate Rounding
134
+
135
+ To disable the default intermediate rounding for specific batch evaluations, use the `disableIntermediateRounding` option:
136
+
137
+ ```typescript
138
+ const results = engine.evaluateAll(formulas, context, {
139
+ disableIntermediateRounding: true
140
+ });
141
+ // Raw unrounded values will propagate through dependencies
142
+ ```
143
+
144
+ #### Per-Formula Rounding Override
145
+
146
+ Individual formulas can override the default rounding with their own `rounding` configuration:
147
+
148
+ ```typescript
149
+ const engine = new FormulaEngine({
150
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
151
+ });
152
+
153
+ const formulas = [
154
+ // Override: use 4 decimal places for exchange rate
155
+ { id: 'rate', expression: '1 / 3', rounding: { mode: 'HALF_UP', precision: 4 } },
156
+ // Uses default 2 decimal rounding
157
+ { id: 'amount', expression: '1000 * $rate' },
158
+ ];
159
+
160
+ const results = engine.evaluateAll(formulas, { variables: {} });
161
+ // rate = 0.3333 (4 decimals from per-formula config)
162
+ // amount = 333.30 (2 decimals from default config)
163
+ ```
164
+
165
+ **Rounding Modes:**
166
+ - `HALF_UP` - Round towards nearest neighbor, ties round up (standard rounding)
167
+ - `HALF_DOWN` - Round towards nearest neighbor, ties round down
168
+ - `FLOOR` - Round towards negative infinity
169
+ - `CEIL` - Round towards positive infinity
170
+ - `NONE` - No rounding applied
171
+
172
+ #### Error Handling Behavior
173
+
174
+ Control how errors are handled during batch evaluation:
175
+
176
+ ```typescript
177
+ const formulas = [
178
+ {
179
+ id: 'ratio',
180
+ expression: '$a / $b',
181
+ onError: { type: 'ZERO' } // Return 0 on division by zero
182
+ },
183
+ {
184
+ id: 'result',
185
+ expression: '$ratio * 100', // Can continue with 0
186
+ },
187
+ ];
188
+
189
+ const results = engine.evaluateAll(formulas, {
190
+ variables: { a: 10, b: 0 }
191
+ });
192
+ // ratio = 0 (instead of error)
193
+ // result = 0
194
+ ```
195
+
196
+ **Error Behavior Types:**
197
+ - `THROW` - Propagate the error (default)
198
+ - `NULL` - Use `null` as the result
199
+ - `ZERO` - Use `0` as the result
200
+ - `DEFAULT` - Use `defaultValue` from the formula definition
201
+ - `SKIP` - Skip this formula (result is `undefined`)
202
+
91
203
  ### Decimal Precision
92
204
 
93
205
  JavaScript floating-point math has precision issues:
@@ -296,6 +408,14 @@ const engine = new FormulaEngine({
296
408
  divisionScale: 10, // Decimal places for division
297
409
  },
298
410
 
411
+ // Default rounding for evaluateAll() intermediate values
412
+ // When set, all formula results in batch evaluation are rounded
413
+ // before being used in dependent formulas
414
+ defaultRounding: {
415
+ mode: 'HALF_UP', // Rounding mode
416
+ precision: 2, // Decimal places (e.g., 2 for currency)
417
+ },
418
+
299
419
  // Security limits
300
420
  security: {
301
421
  maxExpressionLength: 10000,
@@ -349,8 +469,8 @@ class FormulaEngine {
349
469
  // Evaluate single expression
350
470
  evaluate(expression: string, context: EvaluationContext): EvaluationResult;
351
471
 
352
- // Evaluate all formulas in order
353
- evaluateAll(formulas: FormulaDefinition[], context: EvaluationContext): EvaluationResultSet;
472
+ // Evaluate all formulas in order (with optional rounding options)
473
+ evaluateAll(formulas: FormulaDefinition[], context: EvaluationContext, options?: EvaluateAllOptions): EvaluationResultSet;
354
474
 
355
475
  // Register custom function
356
476
  registerFunction(definition: FunctionDefinition): void;
@@ -1,4 +1,4 @@
1
- import { FormulaEngineConfig, FormulaDefinition, EvaluationContext, EvaluationResult, EvaluationResultSet, ValidationResult, FunctionDefinition, ASTNode, CacheStats, DependencyGraph as IDependencyGraph } from './types';
1
+ import { FormulaEngineConfig, FormulaDefinition, EvaluationContext, EvaluationResult, EvaluationResultSet, EvaluateAllOptions, ValidationResult, FunctionDefinition, ASTNode, CacheStats, DependencyGraph as IDependencyGraph } from './types';
2
2
  import { DecimalUtils, Decimal } from './decimal-utils';
3
3
  export declare class FormulaEngine {
4
4
  private config;
@@ -39,8 +39,12 @@ export declare class FormulaEngine {
39
39
  evaluate(expression: string, context: EvaluationContext): EvaluationResult;
40
40
  /**
41
41
  * Evaluate all formulas in dependency order
42
+ *
43
+ * @param formulas - Array of formula definitions to evaluate
44
+ * @param context - Evaluation context with variables
45
+ * @param options - Optional configuration for batch evaluation
42
46
  */
43
- evaluateAll(formulas: FormulaDefinition[], context: EvaluationContext): EvaluationResultSet;
47
+ evaluateAll(formulas: FormulaDefinition[], context: EvaluationContext, options?: EvaluateAllOptions): EvaluationResultSet;
44
48
  /**
45
49
  * Register a custom function
46
50
  */
@@ -140,8 +140,12 @@ class FormulaEngine {
140
140
  }
141
141
  /**
142
142
  * Evaluate all formulas in dependency order
143
+ *
144
+ * @param formulas - Array of formula definitions to evaluate
145
+ * @param context - Evaluation context with variables
146
+ * @param options - Optional configuration for batch evaluation
143
147
  */
144
- evaluateAll(formulas, context) {
148
+ evaluateAll(formulas, context, options) {
145
149
  const startTime = Date.now();
146
150
  const results = new Map();
147
151
  const errors = [];
@@ -164,6 +168,10 @@ class FormulaEngine {
164
168
  for (const formula of formulas) {
165
169
  formulaMap.set(formula.id, formula);
166
170
  }
171
+ // Determine if intermediate rounding should be applied
172
+ const applyIntermediateRounding = this.config.defaultRounding &&
173
+ this.config.defaultRounding.mode !== 'NONE' &&
174
+ !options?.disableIntermediateRounding;
167
175
  // Evaluate in order, merging results into context
168
176
  const workingContext = this.normalizeContext(context);
169
177
  for (const formulaId of evaluationOrder) {
@@ -172,10 +180,17 @@ class FormulaEngine {
172
180
  continue;
173
181
  try {
174
182
  const result = this.evaluator.evaluate(formula.expression, workingContext);
175
- // Apply rounding if configured
183
+ // Apply rounding: per-formula config takes precedence, then defaultRounding
176
184
  let value = result.value;
177
- if (formula.rounding && this.isDecimal(value)) {
178
- value = this.applyRounding(value, formula.rounding);
185
+ if (this.isDecimal(value)) {
186
+ if (formula.rounding) {
187
+ // Per-formula rounding always takes precedence
188
+ value = this.applyRounding(value, formula.rounding);
189
+ }
190
+ else if (applyIntermediateRounding) {
191
+ // Apply default rounding to intermediate values
192
+ value = this.applyRounding(value, this.config.defaultRounding);
193
+ }
179
194
  }
180
195
  // Handle errors based on formula config
181
196
  if (!result.success && formula.onError) {
@@ -352,4 +367,4 @@ class FormulaEngine {
352
367
  }
353
368
  }
354
369
  exports.FormulaEngine = FormulaEngine;
355
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybXVsYS1lbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZm9ybXVsYS1lbmdpbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBWUEscUNBQWtDO0FBQ2xDLDJDQUF3QztBQUN4QyxpRUFBNkQ7QUFDN0QseURBQTZFO0FBQzdFLG1EQUF3RDtBQUN4RCwyQ0FBcUQ7QUFDckQscUNBS2tCO0FBRWxCLE1BQWEsYUFBYTtJQWV4QixZQUFZLE1BQTRCO1FBTnhDLFNBQVM7UUFDRCxhQUFRLEdBQXlCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDM0Msb0JBQWUsR0FBNkIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN0RCxjQUFTLEdBQVcsQ0FBQyxDQUFDO1FBQ3RCLGdCQUFXLEdBQVcsQ0FBQyxDQUFDO1FBRzlCLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixXQUFXLEVBQUUsSUFBSTtZQUNqQixZQUFZLEVBQUUsSUFBSTtZQUNsQixVQUFVLEVBQUUsSUFBSTtZQUNoQixHQUFHLE1BQU07U0FDVixDQUFDO1FBRUYsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLDRCQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUEsa0NBQXNCLEVBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxlQUFNLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSwwQ0FBbUIsRUFBRSxDQUFDO1FBQ3JELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSx5Q0FBc0IsRUFBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxxQkFBUyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFL0UsNENB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WSxJQUFJLElBQUksQ0FBQztZQUMvRCxLQUFLLE1BQU07Z0JBQ1QsT0FBTyxTQUFTLENBQUM7WUFDbkIsS0FBSyxPQUFPLENBQUM7WUFDYjtnQkFDRSxNQUFNLE1BQU0sQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQztJQUVPLGVBQWU7UUFDckIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDO1FBQ2pELElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksT0FBTyxFQUFFLENBQUM7WUFDbEMscURBQXFEO1lBQ3JELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1lBQzFDLE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDakUsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQztnQkFDdkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBcFpELHNDQW9aQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEZvcm11bGFFbmdpbmVDb25maWcsXG4gIEZvcm11bGFEZWZpbml0aW9uLFxuICBFdmFsdWF0aW9uQ29udGV4dCxcbiAgRXZhbHVhdGlvblJlc3VsdCxcbiAgRXZhbHVhdGlvblJlc3VsdFNldCxcbiAgVmFsaWRhdGlvblJlc3VsdCxcbiAgRnVuY3Rpb25EZWZpbml0aW9uLFxuICBBU1ROb2RlLFxuICBDYWNoZVN0YXRzLFxuICBEZXBlbmRlbmN5R3JhcGggYXMgSURlcGVuZGVuY3lHcmFwaCxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBQYXJzZXIgfSBmcm9tICcuL3BhcnNlcic7XG5pbXBvcnQgeyBFdmFsdWF0b3IgfSBmcm9tICcuL2V2YWx1YXRvcic7XG5pbXBvcnQgeyBEZXBlbmRlbmN5RXh0cmFjdG9yIH0gZnJvbSAnLi9kZXBlbmRlbmN5LWV4dHJhY3Rvcic7XG5pbXBvcnQgeyBEZXBlbmRlbmN5R3JhcGgsIERlcGVuZGVuY3lHcmFwaEJ1aWxkZXIgfSBmcm9tICcuL2RlcGVuZGVuY3ktZ3JhcGgnO1xuaW1wb3J0IHsgRGVjaW1hbFV0aWxzLCBEZWNpbWFsIH0gZnJvbSAnLi9kZWNpbWFsLXV0aWxzJztcbmltcG9ydCB7IGNyZWF0ZUJ1aWx0SW5GdW5jdGlvbnMgfSBmcm9tICcuL2Z1bmN0aW9ucyc7XG5pbXBvcnQge1xuICBGb3JtdWxhRW5naW5lRXJyb3IsXG4gIEdlbmVyYWxGb3JtdWxhRXJyb3IsXG4gIER1cGxpY2F0ZUZvcm11bGFFcnJvcixcbiAgTWF4RXhwcmVzc2lvbkxlbmd0aEVycm9yLFxufSBmcm9tICcuL2Vycm9ycyc7XG5cbmV4cG9ydCBjbGFzcyBGb3JtdWxhRW5naW5lIHtcbiAgcHJpdmF0ZSBjb25maWc6IEZvcm11bGFFbmdpbmVDb25maWc7XG4gIHByaXZhdGUgcGFyc2VyOiBQYXJzZXI7XG4gIHByaXZhdGUgZXZhbHVhdG9yOiBFdmFsdWF0b3I7XG4gIHByaXZhdGUgZGVwZW5kZW5jeUV4dHJhY3RvcjogRGVwZW5kZW5jeUV4dHJhY3RvcjtcbiAgcHJpdmF0ZSBncmFwaEJ1aWxkZXI6IERlcGVuZGVuY3lHcmFwaEJ1aWxkZXI7XG4gIHByaXZhdGUgZGVjaW1hbFV0aWxzOiBEZWNpbWFsVXRpbHM7XG4gIHByaXZhdGUgZnVuY3Rpb25zOiBNYXA8c3RyaW5nLCBGdW5jdGlvbkRlZmluaXRpb24+O1xuXG4gIC8vIENhY2hlc1xuICBwcml2YXRlIGFzdENhY2hlOiBNYXA8c3RyaW5nLCBBU1ROb2RlPiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBkZXBlbmRlbmN5Q2FjaGU6IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PiA9IG5ldyBNYXAoKTtcbiAgcHJpdmF0ZSBjYWNoZUhpdHM6IG51bWJlciA9IDA7XG4gIHByaXZhdGUgY2FjaGVNaXNzZXM6IG51bWJlciA9IDA7XG5cbiAgY29uc3RydWN0b3IoY29uZmlnPzogRm9ybXVsYUVuZ2luZUNvbmZpZykge1xuICAgIHRoaXMuY29uZmlnID0ge1xuICAgICAgZW5hYmxlQ2FjaGU6IHRydWUsXG4gICAgICBtYXhDYWNoZVNpemU6IDEwMDAsXG4gICAgICBzdHJpY3RNb2RlOiB0cnVlLFxuICAgICAgLi4uY29uZmlnLFxuICAgIH07XG5cbiAgICB0aGlzLmRlY2ltYWxVdGlscyA9IG5ldyBEZWNpbWFsVXRpbHModGhpcy5jb25maWcuZGVjaW1hbCk7XG4gICAgdGhpcy5mdW5jdGlvbnMgPSBjcmVhdGVCdWlsdEluRnVuY3Rpb25zKHRoaXMuZGVjaW1hbFV0aWxzKTtcbiAgICB0aGlzLnBhcnNlciA9IG5ldyBQYXJzZXIoKTtcbiAgICB0aGlzLmRlcGVuZGVuY3lFeHRyYWN0b3IgPSBuZXcgRGVwZW5kZW5jeUV4dHJhY3RvcigpO1xuICAgIHRoaXMuZ3JhcGhCdWlsZGVyID0gbmV3IERlcGVuZGVuY3lHcmFwaEJ1aWxkZXIoKTtcbiAgICB0aGlzLmV2YWx1YXRvciA9IG5ldyBFdmFsdWF0b3IodGhpcy5kZWNpbWFsVXRpbHMsIHRoaXMuZnVuY3Rpb25zLCB0aGlzLmNvbmZpZyk7XG5cbiAgICAvLyBSZWdpc3RlciBhbnkgY3VzdG9tIGZ1bmN0aW9ucyBmcm9tIGNvbmZpZ1xuICAgIGlmICh0aGlzLmNvbmZpZy5mdW5jdGlvbnMpIHtcbiAgICAgIGZvciAoY29uc3QgZm4gb2YgdGhpcy5jb25maWcuZnVuY3Rpb25zKSB7XG4gICAgICAgIHRoaXMucmVnaXN0ZXJGdW5jdGlvbihmbik7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhcnNlIGFuIGV4cHJlc3Npb24gaW50byBhbiBBU1RcbiAgICovXG4gIHBhcnNlKGV4cHJlc3Npb246IHN0cmluZyk6IEFTVE5vZGUge1xuICAgIHRoaXMuY2hlY2tFeHByZXNzaW9uTGVuZ3RoKGV4cHJlc3Npb24pO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUNhY2hlKSB7XG4gICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmFzdENhY2hlLmdldChleHByZXNzaW9uKTtcbiAgICAgIGlmIChjYWNoZWQpIHtcbiAgICAgICAgdGhpcy5jYWNoZUhpdHMrKztcbiAgICAgICAgcmV0dXJuIGNhY2hlZDtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2FjaGVNaXNzZXMrKztcbiAgICB9XG5cbiAgICBjb25zdCBhc3QgPSB0aGlzLnBhcnNlci5wYXJzZShleHByZXNzaW9uKTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5lbmFibGVDYWNoZSkge1xuICAgICAgdGhpcy5tYXliZUV2aWN0Q2FjaGUoKTtcbiAgICAgIHRoaXMuYXN0Q2FjaGUuc2V0KGV4cHJlc3Npb24sIGFzdCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFzdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHRyYWN0IHZhcmlhYmxlIGRlcGVuZGVuY2llcyBmcm9tIGFuIGV4cHJlc3Npb25cbiAgICovXG4gIGV4dHJhY3REZXBlbmRlbmNpZXMoZXhwcmVzc2lvbjogc3RyaW5nKTogU2V0PHN0cmluZz4ge1xuICAgIGlmICh0aGlzLmNvbmZpZy5lbmFibGVDYWNoZSkge1xuICAgICAgY29uc3QgY2FjaGVkID0gdGhpcy5kZXBlbmRlbmN5Q2FjaGUuZ2V0KGV4cHJlc3Npb24pO1xuICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICByZXR1cm4gbmV3IFNldChjYWNoZWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGRlcHMgPSB0aGlzLmRlcGVuZGVuY3lFeHRyYWN0b3IuZXh0cmFjdChleHByZXNzaW9uKTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5lbmFibGVDYWNoZSkge1xuICAgICAgdGhpcy5kZXBlbmRlbmN5Q2FjaGUuc2V0KGV4cHJlc3Npb24sIG5ldyBTZXQoZGVwcykpO1xuICAgIH1cblxuICAgIHJldHVybiBkZXBzO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgZGVwZW5kZW5jeSBncmFwaCBmcm9tIGZvcm11bGEgZGVmaW5pdGlvbnNcbiAgICovXG4gIGJ1aWxkRGVwZW5kZW5jeUdyYXBoKGZvcm11bGFzOiBGb3JtdWxhRGVmaW5pdGlvbltdKTogSURlcGVuZGVuY3lHcmFwaCB7XG4gICAgcmV0dXJuIHRoaXMuZ3JhcGhCdWlsZGVyLmJ1aWxkKGZvcm11bGFzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGV2YWx1YXRpb24gb3JkZXIgZm9yIGZvcm11bGFzXG4gICAqL1xuICBnZXRFdmFsdWF0aW9uT3JkZXIoZm9ybXVsYXM6IEZvcm11bGFEZWZpbml0aW9uW10pOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuZ3JhcGhCdWlsZGVyLmdldEV2YWx1YXRpb25PcmRlcihmb3JtdWxhcyk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgZm9ybXVsYXMgd2l0aG91dCBldmFsdWF0aW5nXG4gICAqL1xuICB2YWxpZGF0ZShmb3JtdWxhczogRm9ybXVsYURlZmluaXRpb25bXSk6IFZhbGlkYXRpb25SZXN1bHQge1xuICAgIGNvbnN0IGVycm9yczogRm9ybXVsYUVuZ2luZUVycm9yW10gPSBbXTtcbiAgICBjb25zdCB3YXJuaW5nczogc3RyaW5nW10gPSBbXTtcblxuICAgIC8vIENoZWNrIGZvciBkdXBsaWNhdGUgSURzXG4gICAgY29uc3QgaWRzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgZm9yIChjb25zdCBmb3JtdWxhIG9mIGZvcm11bGFzKSB7XG4gICAgICBpZiAoaWRzLmhhcyhmb3JtdWxhLmlkKSkge1xuICAgICAgICBlcnJvcnMucHVzaChuZXcgRHVwbGljYXRlRm9ybXVsYUVycm9yKGZvcm11bGEuaWQpKTtcbiAgICAgIH1cbiAgICAgIGlkcy5hZGQoZm9ybXVsYS5pZCk7XG4gICAgfVxuXG4gICAgLy8gVHJ5IHRvIHBhcnNlIGFsbCBleHByZXNzaW9uc1xuICAgIGZvciAoY29uc3QgZm9ybXVsYSBvZiBmb3JtdWxhcykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5wYXJzZShmb3JtdWxhLmV4cHJlc3Npb24pO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRm9ybXVsYUVuZ2luZUVycm9yKSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2goZXJyb3IpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVycm9ycy5wdXNoKG5ldyBHZW5lcmFsRm9ybXVsYUVycm9yKFN0cmluZyhlcnJvcikpKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEJ1aWxkIGRlcGVuZGVuY3kgZ3JhcGggYW5kIGNoZWNrIGZvciBjeWNsZXNcbiAgICBsZXQgZGVwZW5kZW5jeUdyYXBoOiBJRGVwZW5kZW5jeUdyYXBoID0gbmV3IERlcGVuZGVuY3lHcmFwaCgpO1xuICAgIGxldCBldmFsdWF0aW9uT3JkZXI6IHN0cmluZ1tdID0gW107XG5cbiAgICB0cnkge1xuICAgICAgZGVwZW5kZW5jeUdyYXBoID0gdGhpcy5idWlsZERlcGVuZGVuY3lHcmFwaChmb3JtdWxhcyk7XG4gICAgICBldmFsdWF0aW9uT3JkZXIgPSBkZXBlbmRlbmN5R3JhcGgudG9wb2xvZ2ljYWxTb3J0KCk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEZvcm11bGFFbmdpbmVFcnJvcikge1xuICAgICAgICBlcnJvcnMucHVzaChlcnJvcik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHZhbGlkOiBlcnJvcnMubGVuZ3RoID09PSAwLFxuICAgICAgZXJyb3JzLFxuICAgICAgd2FybmluZ3MsXG4gICAgICBkZXBlbmRlbmN5R3JhcGgsXG4gICAgICBldmFsdWF0aW9uT3JkZXIsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBhIHNpbmdsZSBleHByZXNzaW9uXG4gICAqL1xuICBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIGNvbnRleHQ6IEV2YWx1YXRpb25Db250ZXh0KTogRXZhbHVhdGlvblJlc3VsdCB7XG4gICAgdGhpcy5jaGVja0V4cHJlc3Npb25MZW5ndGgoZXhwcmVzc2lvbik7XG4gICAgY29uc3Qgbm9ybWFsaXplZENvbnRleHQgPSB0aGlzLm5vcm1hbGl6ZUNvbnRleHQoY29udGV4dCk7XG4gICAgcmV0dXJuIHRoaXMuZXZhbHVhdG9yLmV2YWx1YXRlKGV4cHJlc3Npb24sIG5vcm1hbGl6ZWRDb250ZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmFsdWF0ZSBhbGwgZm9ybXVsYXMgaW4gZGVwZW5kZW5jeSBvcmRlclxuICAgKi9cbiAgZXZhbHVhdGVBbGwoXG4gICAgZm9ybXVsYXM6IEZvcm11bGFEZWZpbml0aW9uW10sXG4gICAgY29udGV4dDogRXZhbHVhdGlvbkNvbnRleHRcbiAgKTogRXZhbHVhdGlvblJlc3VsdFNldCB7XG4gICAgY29uc3Qgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICBjb25zdCByZXN1bHRzID0gbmV3IE1hcDxzdHJpbmcsIEV2YWx1YXRpb25SZXN1bHQ+KCk7XG4gICAgY29uc3QgZXJyb3JzOiBFcnJvcltdID0gW107XG5cbiAgICAvLyBHZXQgZXZhbHVhdGlvbiBvcmRlclxuICAgIGxldCBldmFsdWF0aW9uT3JkZXI6IHN0cmluZ1tdO1xuICAgIHRyeSB7XG4gICAgICBldmFsdWF0aW9uT3JkZXIgPSB0aGlzLmdldEV2YWx1YXRpb25PcmRlcihmb3JtdWxhcyk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlc3VsdHMsXG4gICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICBlcnJvcnM6IFtlcnJvciBhcyBFcnJvcl0sXG4gICAgICAgIHRvdGFsRXhlY3V0aW9uVGltZU1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgICBldmFsdWF0aW9uT3JkZXI6IFtdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBtYXAgb2YgZm9ybXVsYXMgYnkgSURcbiAgICBjb25zdCBmb3JtdWxhTWFwID0gbmV3IE1hcDxzdHJpbmcsIEZvcm11bGFEZWZpbml0aW9uPigpO1xuICAgIGZvciAoY29uc3QgZm9ybXVsYSBvZiBmb3JtdWxhcykge1xuICAgICAgZm9ybXVsYU1hcC5zZXQoZm9ybXVsYS5pZCwgZm9ybXVsYSk7XG4gICAgfVxuXG4gICAgLy8gRXZhbHVhdGUgaW4gb3JkZXIsIG1lcmdpbmcgcmVzdWx0cyBpbnRvIGNvbnRleHRcbiAgICBjb25zdCB3b3JraW5nQ29udGV4dDogRXZhbHVhdGlvbkNvbnRleHQgPSB0aGlzLm5vcm1hbGl6ZUNvbnRleHQoY29udGV4dCk7XG5cbiAgICBmb3IgKGNvbnN0IGZvcm11bGFJZCBvZiBldmFsdWF0aW9uT3JkZXIpIHtcbiAgICAgIGNvbnN0IGZvcm11bGEgPSBmb3JtdWxhTWFwLmdldChmb3JtdWxhSWQpO1xuICAgICAgaWYgKCFmb3JtdWxhKSBjb250aW51ZTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5ldmFsdWF0b3IuZXZhbHVhdGUoZm9ybXVsYS5leHByZXNzaW9uLCB3b3JraW5nQ29udGV4dCk7XG5cbiAgICAgICAgLy8gQXBwbHkgcm91bmRpbmcgaWYgY29uZmlndXJlZFxuICAgICAgICBsZXQgdmFsdWUgPSByZXN1bHQudmFsdWU7XG4gICAgICAgIGlmIChmb3JtdWxhLnJvdW5kaW5nICYmIHRoaXMuaXNEZWNpbWFsKHZhbHVlKSkge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5hcHBseVJvdW5kaW5nKHZhbHVlIGFzIERlY2ltYWwsIGZvcm11bGEucm91bmRpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIGVycm9ycyBiYXNlZCBvbiBmb3JtdWxhIGNvbmZpZ1xuICAgICAgICBpZiAoIXJlc3VsdC5zdWNjZXNzICYmIGZvcm11bGEub25FcnJvcikge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5oYW5kbGVFcnJvcihmb3JtdWxhLCByZXN1bHQuZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzdWx0cy5zZXQoZm9ybXVsYUlkLCB7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIHZhbHVlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBNZXJnZSByZXN1bHQgaW50byBjb250ZXh0IGZvciBzdWJzZXF1ZW50IGZvcm11bGFzXG4gICAgICAgIHdvcmtpbmdDb250ZXh0LnZhcmlhYmxlc1tmb3JtdWxhSWRdID0gdmFsdWU7XG5cbiAgICAgICAgaWYgKCFyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgIGVycm9ycy5wdXNoKHJlc3VsdC5lcnJvciEpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCBldmFsUmVzdWx0OiBFdmFsdWF0aW9uUmVzdWx0ID0ge1xuICAgICAgICAgIHZhbHVlOiBudWxsLFxuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGVycm9yOiBlcnJvciBhcyBFcnJvcixcbiAgICAgICAgICBleGVjdXRpb25UaW1lTXM6IDAsXG4gICAgICAgICAgYWNjZXNzZWRWYXJpYWJsZXM6IG5ldyBTZXQoKSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBIYW5kbGUgZXJyb3IgYmFzZWQgb24gZm9ybXVsYSBjb25maWdcbiAgICAgICAgaWYgKGZvcm11bGEub25FcnJvcikge1xuICAgICAgICAgIGV2YWxSZXN1bHQudmFsdWUgPSB0aGlzLmhhbmRsZUVycm9yKGZvcm11bGEsIGVycm9yIGFzIEVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdHMuc2V0KGZvcm11bGFJZCwgZXZhbFJlc3VsdCk7XG4gICAgICAgIGVycm9ycy5wdXNoKGVycm9yIGFzIEVycm9yKTtcblxuICAgICAgICAvLyBTdGlsbCBhZGQgdG8gY29udGV4dCAoYXMgbnVsbCBvciBkZWZhdWx0IHZhbHVlKSBzbyBkZXBlbmRlbnQgZm9ybXVsYXMgY2FuIHByb2NlZWRcbiAgICAgICAgd29ya2luZ0NvbnRleHQudmFyaWFibGVzW2Zvcm11bGFJZF0gPSBldmFsUmVzdWx0LnZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICByZXN1bHRzLFxuICAgICAgc3VjY2VzczogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICAgIGVycm9ycyxcbiAgICAgIHRvdGFsRXhlY3V0aW9uVGltZU1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgZXZhbHVhdGlvbk9yZGVyLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBjdXN0b20gZnVuY3Rpb25cbiAgICovXG4gIHJlZ2lzdGVyRnVuY3Rpb24oZGVmaW5pdGlvbjogRnVuY3Rpb25EZWZpbml0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IGRlZmluaXRpb24ubmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIHRoaXMuZnVuY3Rpb25zLnNldChuYW1lLCBkZWZpbml0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBtdWx0aXBsZSBjdXN0b20gZnVuY3Rpb25zXG4gICAqL1xuICByZWdpc3RlckZ1bmN0aW9ucyhkZWZpbml0aW9uczogRnVuY3Rpb25EZWZpbml0aW9uW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGRlZmluaXRpb24gb2YgZGVmaW5pdGlvbnMpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJGdW5jdGlvbihkZWZpbml0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHJlZ2lzdGVyZWQgZnVuY3Rpb24gbmFtZXNcbiAgICovXG4gIGdldFJlZ2lzdGVyZWRGdW5jdGlvbnMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMuZnVuY3Rpb25zLmtleXMoKSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgdGhlIEFTVCBjYWNoZVxuICAgKi9cbiAgY2xlYXJDYWNoZSgpOiB2b2lkIHtcbiAgICB0aGlzLmFzdENhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5kZXBlbmRlbmN5Q2FjaGUuY2xlYXIoKTtcbiAgICB0aGlzLmNhY2hlSGl0cyA9IDA7XG4gICAgdGhpcy5jYWNoZU1pc3NlcyA9IDA7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNhY2hlIHN0YXRpc3RpY3NcbiAgICovXG4gIGdldENhY2hlU3RhdHMoKTogQ2FjaGVTdGF0cyB7XG4gICAgY29uc3QgdG90YWwgPSB0aGlzLmNhY2hlSGl0cyArIHRoaXMuY2FjaGVNaXNzZXM7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNpemU6IHRoaXMuYXN0Q2FjaGUuc2l6ZSxcbiAgICAgIGhpdHM6IHRoaXMuY2FjaGVIaXRzLFxuICAgICAgbWlzc2VzOiB0aGlzLmNhY2hlTWlzc2VzLFxuICAgICAgaGl0UmF0ZTogdG90YWwgPiAwID8gdGhpcy5jYWNoZUhpdHMgLyB0b3RhbCA6IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRlY2ltYWwgdXRpbGl0aWVzIGluc3RhbmNlXG4gICAqL1xuICBnZXREZWNpbWFsVXRpbHMoKTogRGVjaW1hbFV0aWxzIHtcbiAgICByZXR1cm4gdGhpcy5kZWNpbWFsVXRpbHM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRGVjaW1hbCBmcm9tIGEgdmFsdWVcbiAgICovXG4gIGNyZWF0ZURlY2ltYWwodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IERlY2ltYWwge1xuICAgIHJldHVybiB0aGlzLmRlY2ltYWxVdGlscy5mcm9tKHZhbHVlKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUHJpdmF0ZSBtZXRob2RzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBwcml2YXRlIGNoZWNrRXhwcmVzc2lvbkxlbmd0aChleHByZXNzaW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBtYXhMZW5ndGggPSB0aGlzLmNvbmZpZy5zZWN1cml0eT8ubWF4RXhwcmVzc2lvbkxlbmd0aCA/PyAxMDAwMDtcbiAgICBpZiAoZXhwcmVzc2lvbi5sZW5ndGggPiBtYXhMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBNYXhFeHByZXNzaW9uTGVuZ3RoRXJyb3IoZXhwcmVzc2lvbi5sZW5ndGgsIG1heExlbmd0aCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBub3JtYWxpemVDb250ZXh0KGNvbnRleHQ6IEV2YWx1YXRpb25Db250ZXh0KTogRXZhbHVhdGlvbkNvbnRleHQge1xuICAgIC8vIERlZXAgY29weSBhbmQgY29udmVydCBudW1lcmljIHZhbHVlcyB0byBEZWNpbWFsIGlmIGF1dG9Db252ZXJ0RmxvYXRzIGlzIGVuYWJsZWRcbiAgICBjb25zdCBhdXRvQ29udmVydCA9IHRoaXMuY29uZmlnLmRlY2ltYWw/LmF1dG9Db252ZXJ0RmxvYXRzID8/IHRydWU7XG5cbiAgICBpZiAoIWF1dG9Db252ZXJ0KSB7XG4gICAgICByZXR1cm4geyAuLi5jb250ZXh0IH07XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZFZhcmlhYmxlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhjb250ZXh0LnZhcmlhYmxlcykpIHtcbiAgICAgIG5vcm1hbGl6ZWRWYXJpYWJsZXNba2V5XSA9IHRoaXMuY29udmVydFZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIHZhcmlhYmxlczogbm9ybWFsaXplZFZhcmlhYmxlcyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0VmFsdWUodmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhaXNOYU4odmFsdWUpICYmIGlzRmluaXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVjaW1hbFV0aWxzLmZyb20odmFsdWUpO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5tYXAodiA9PiB0aGlzLmNvbnZlcnRWYWx1ZSh2KSk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCBjb252ZXJ0ZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyh2YWx1ZSkpIHtcbiAgICAgICAgY29udmVydGVkW2tdID0gdGhpcy5jb252ZXJ0VmFsdWUodik7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29udmVydGVkO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcml2YXRlIGlzRGVjaW1hbCh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERlY2ltYWw7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5Um91bmRpbmcoXG4gICAgdmFsdWU6IERlY2ltYWwsXG4gICAgY29uZmlnOiB7IG1vZGU6IHN0cmluZzsgcHJlY2lzaW9uOiBudW1iZXIgfVxuICApOiBEZWNpbWFsIHtcbiAgICBpZiAoY29uZmlnLm1vZGUgPT09ICdOT05FJykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kZWNpbWFsVXRpbHMucm91bmQodmFsdWUsIGNvbmZpZy5wcmVjaXNpb24sIGNvbmZpZy5tb2RlIGFzIGFueSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUVycm9yKGZvcm11bGE6IEZvcm11bGFEZWZpbml0aW9uLCBfZXJyb3I/OiBFcnJvcik6IHVua25vd24ge1xuICAgIGNvbnN0IGJlaGF2aW9yID0gZm9ybXVsYS5vbkVycm9yO1xuICAgIGlmICghYmVoYXZpb3IpIHJldHVybiBudWxsO1xuXG4gICAgc3dpdGNoIChiZWhhdmlvci50eXBlKSB7XG4gICAgICBjYXNlICdOVUxMJzpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBjYXNlICdaRVJPJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVjaW1hbFV0aWxzLnplcm8oKTtcbiAgICAgIGNhc2UgJ0RFRkFVTFQnOlxuICAgICAgICByZXR1cm4gYmVoYXZpb3IuZGVmYXVsdFZhbHVlID8/IGZvcm11bGEuZGVmYXVsdFZhbHVlID8/IG51bGw7XG4gICAgICBjYXNlICdTS0lQJzpcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGNhc2UgJ1RIUk9XJzpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IF9lcnJvcjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1heWJlRXZpY3RDYWNoZSgpOiB2b2lkIHtcbiAgICBjb25zdCBtYXhTaXplID0gdGhpcy5jb25maWcubWF4Q2FjaGVTaXplID8/IDEwMDA7XG4gICAgaWYgKHRoaXMuYXN0Q2FjaGUuc2l6ZSA+PSBtYXhTaXplKSB7XG4gICAgICAvLyBTaW1wbGUgRklGTyBldmljdGlvbiAtIHJlbW92ZSBmaXJzdCAxMCUgb2YgZW50cmllc1xuICAgICAgY29uc3QgdG9SZW1vdmUgPSBNYXRoLmNlaWwobWF4U2l6ZSAqIDAuMSk7XG4gICAgICBjb25zdCBrZXlzID0gQXJyYXkuZnJvbSh0aGlzLmFzdENhY2hlLmtleXMoKSkuc2xpY2UoMCwgdG9SZW1vdmUpO1xuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgICB0aGlzLmFzdENhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgICB0aGlzLmRlcGVuZGVuY3lDYWNoZS5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
370
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybXVsYS1lbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZm9ybXVsYS1lbmdpbmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBYUEscUNBQWtDO0FBQ2xDLDJDQUF3QztBQUN4QyxpRUFBNkQ7QUFDN0QseURBQTZFO0FBQzdFLG1EQUF3RDtBQUN4RCwyQ0FBcUQ7QUFDckQscUNBS2tCO0FBRWxCLE1BQWEsYUFBYTtJQWV4QixZQUFZLE1BQTRCO1FBTnhDLFNBQVM7UUFDRCxhQUFRLEdBQXlCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDM0Msb0JBQWUsR0FBNkIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUN0RCxjQUFTLEdBQVcsQ0FBQyxDQUFDO1FBQ3RCLGdCQUFXLEdBQVcsQ0FBQyxDQUFDO1FBRzlCLElBQUksQ0FBQyxNQUFNLEdBQUc7WUFDWixXQUFXLEVBQUUsSUFBSTtZQUNqQixZQUFZLEVBQUUsSUFBSTtZQUNsQixVQUFVLEVBQUUsSUFBSTtZQUNoQixHQUFHLE1BQU07U0FDVixDQUFDO1FBRUYsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLDRCQUFZLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUEsa0NBQXNCLEVBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxlQUFNLEVBQUUsQ0FBQztRQUMzQixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSwwQ0FBbUIsRUFBRSxDQUFDO1FBQ3JELElBQUksQ0FBQyxZQUFZLEdBQUcsSUFBSSx5Q0FBc0IsRUFBRSxDQUFDO1FBQ2pELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxxQkFBUyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFFL0UsNENB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LENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBcmFELHNDQXFhQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEZvcm11bGFFbmdpbmVDb25maWcsXG4gIEZvcm11bGFEZWZpbml0aW9uLFxuICBFdmFsdWF0aW9uQ29udGV4dCxcbiAgRXZhbHVhdGlvblJlc3VsdCxcbiAgRXZhbHVhdGlvblJlc3VsdFNldCxcbiAgRXZhbHVhdGVBbGxPcHRpb25zLFxuICBWYWxpZGF0aW9uUmVzdWx0LFxuICBGdW5jdGlvbkRlZmluaXRpb24sXG4gIEFTVE5vZGUsXG4gIENhY2hlU3RhdHMsXG4gIERlcGVuZGVuY3lHcmFwaCBhcyBJRGVwZW5kZW5jeUdyYXBoLFxufSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7IFBhcnNlciB9IGZyb20gJy4vcGFyc2VyJztcbmltcG9ydCB7IEV2YWx1YXRvciB9IGZyb20gJy4vZXZhbHVhdG9yJztcbmltcG9ydCB7IERlcGVuZGVuY3lFeHRyYWN0b3IgfSBmcm9tICcuL2RlcGVuZGVuY3ktZXh0cmFjdG9yJztcbmltcG9ydCB7IERlcGVuZGVuY3lHcmFwaCwgRGVwZW5kZW5jeUdyYXBoQnVpbGRlciB9IGZyb20gJy4vZGVwZW5kZW5jeS1ncmFwaCc7XG5pbXBvcnQgeyBEZWNpbWFsVXRpbHMsIERlY2ltYWwgfSBmcm9tICcuL2RlY2ltYWwtdXRpbHMnO1xuaW1wb3J0IHsgY3JlYXRlQnVpbHRJbkZ1bmN0aW9ucyB9IGZyb20gJy4vZnVuY3Rpb25zJztcbmltcG9ydCB7XG4gIEZvcm11bGFFbmdpbmVFcnJvcixcbiAgR2VuZXJhbEZvcm11bGFFcnJvcixcbiAgRHVwbGljYXRlRm9ybXVsYUVycm9yLFxuICBNYXhFeHByZXNzaW9uTGVuZ3RoRXJyb3IsXG59IGZyb20gJy4vZXJyb3JzJztcblxuZXhwb3J0IGNsYXNzIEZvcm11bGFFbmdpbmUge1xuICBwcml2YXRlIGNvbmZpZzogRm9ybXVsYUVuZ2luZUNvbmZpZztcbiAgcHJpdmF0ZSBwYXJzZXI6IFBhcnNlcjtcbiAgcHJpdmF0ZSBldmFsdWF0b3I6IEV2YWx1YXRvcjtcbiAgcHJpdmF0ZSBkZXBlbmRlbmN5RXh0cmFjdG9yOiBEZXBlbmRlbmN5RXh0cmFjdG9yO1xuICBwcml2YXRlIGdyYXBoQnVpbGRlcjogRGVwZW5kZW5jeUdyYXBoQnVpbGRlcjtcbiAgcHJpdmF0ZSBkZWNpbWFsVXRpbHM6IERlY2ltYWxVdGlscztcbiAgcHJpdmF0ZSBmdW5jdGlvbnM6IE1hcDxzdHJpbmcsIEZ1bmN0aW9uRGVmaW5pdGlvbj47XG5cbiAgLy8gQ2FjaGVzXG4gIHByaXZhdGUgYXN0Q2FjaGU6IE1hcDxzdHJpbmcsIEFTVE5vZGU+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGRlcGVuZGVuY3lDYWNoZTogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGNhY2hlSGl0czogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBjYWNoZU1pc3NlczogbnVtYmVyID0gMDtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc/OiBGb3JtdWxhRW5naW5lQ29uZmlnKSB7XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICBlbmFibGVDYWNoZTogdHJ1ZSxcbiAgICAgIG1heENhY2hlU2l6ZTogMTAwMCxcbiAgICAgIHN0cmljdE1vZGU6IHRydWUsXG4gICAgICAuLi5jb25maWcsXG4gICAgfTtcblxuICAgIHRoaXMuZGVjaW1hbFV0aWxzID0gbmV3IERlY2ltYWxVdGlscyh0aGlzLmNvbmZpZy5kZWNpbWFsKTtcbiAgICB0aGlzLmZ1bmN0aW9ucyA9IGNyZWF0ZUJ1aWx0SW5GdW5jdGlvbnModGhpcy5kZWNpbWFsVXRpbHMpO1xuICAgIHRoaXMucGFyc2VyID0gbmV3IFBhcnNlcigpO1xuICAgIHRoaXMuZGVwZW5kZW5jeUV4dHJhY3RvciA9IG5ldyBEZXBlbmRlbmN5RXh0cmFjdG9yKCk7XG4gICAgdGhpcy5ncmFwaEJ1aWxkZXIgPSBuZXcgRGVwZW5kZW5jeUdyYXBoQnVpbGRlcigpO1xuICAgIHRoaXMuZXZhbHVhdG9yID0gbmV3IEV2YWx1YXRvcih0aGlzLmRlY2ltYWxVdGlscywgdGhpcy5mdW5jdGlvbnMsIHRoaXMuY29uZmlnKTtcblxuICAgIC8vIFJlZ2lzdGVyIGFueSBjdXN0b20gZnVuY3Rpb25zIGZyb20gY29uZmlnXG4gICAgaWYgKHRoaXMuY29uZmlnLmZ1bmN0aW9ucykge1xuICAgICAgZm9yIChjb25zdCBmbiBvZiB0aGlzLmNvbmZpZy5mdW5jdGlvbnMpIHtcbiAgICAgICAgdGhpcy5yZWdpc3RlckZ1bmN0aW9uKGZuKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGFyc2UgYW4gZXhwcmVzc2lvbiBpbnRvIGFuIEFTVFxuICAgKi9cbiAgcGFyc2UoZXhwcmVzc2lvbjogc3RyaW5nKTogQVNUTm9kZSB7XG4gICAgdGhpcy5jaGVja0V4cHJlc3Npb25MZW5ndGgoZXhwcmVzc2lvbik7XG5cbiAgICBpZiAodGhpcy5jb25maWcuZW5hYmxlQ2FjaGUpIHtcbiAgICAgIGNvbnN0IGNhY2hlZCA9IHRoaXMuYXN0Q2FjaGUuZ2V0KGV4cHJlc3Npb24pO1xuICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICB0aGlzLmNhY2hlSGl0cysrO1xuICAgICAgICByZXR1cm4gY2FjaGVkO1xuICAgICAgfVxuICAgICAgdGhpcy5jYWNoZU1pc3NlcysrO1xuICAgIH1cblxuICAgIGNvbnN0IGFzdCA9IHRoaXMucGFyc2VyLnBhcnNlKGV4cHJlc3Npb24pO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUNhY2hlKSB7XG4gICAgICB0aGlzLm1heWJlRXZpY3RDYWNoZSgpO1xuICAgICAgdGhpcy5hc3RDYWNoZS5zZXQoZXhwcmVzc2lvbiwgYXN0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXN0O1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgdmFyaWFibGUgZGVwZW5kZW5jaWVzIGZyb20gYW4gZXhwcmVzc2lvblxuICAgKi9cbiAgZXh0cmFjdERlcGVuZGVuY2llcyhleHByZXNzaW9uOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPiB7XG4gICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUNhY2hlKSB7XG4gICAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmRlcGVuZGVuY3lDYWNoZS5nZXQoZXhwcmVzc2lvbik7XG4gICAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgIHJldHVybiBuZXcgU2V0KGNhY2hlZCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZGVwcyA9IHRoaXMuZGVwZW5kZW5jeUV4dHJhY3Rvci5leHRyYWN0KGV4cHJlc3Npb24pO1xuXG4gICAgaWYgKHRoaXMuY29uZmlnLmVuYWJsZUNhY2hlKSB7XG4gICAgICB0aGlzLmRlcGVuZGVuY3lDYWNoZS5zZXQoZXhwcmVzc2lvbiwgbmV3IFNldChkZXBzKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlcHM7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSBkZXBlbmRlbmN5IGdyYXBoIGZyb20gZm9ybXVsYSBkZWZpbml0aW9uc1xuICAgKi9cbiAgYnVpbGREZXBlbmRlbmN5R3JhcGgoZm9ybXVsYXM6IEZvcm11bGFEZWZpbml0aW9uW10pOiBJRGVwZW5kZW5jeUdyYXBoIHtcbiAgICByZXR1cm4gdGhpcy5ncmFwaEJ1aWxkZXIuYnVpbGQoZm9ybXVsYXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgZXZhbHVhdGlvbiBvcmRlciBmb3IgZm9ybXVsYXNcbiAgICovXG4gIGdldEV2YWx1YXRpb25PcmRlcihmb3JtdWxhczogRm9ybXVsYURlZmluaXRpb25bXSk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5ncmFwaEJ1aWxkZXIuZ2V0RXZhbHVhdGlvbk9yZGVyKGZvcm11bGFzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBmb3JtdWxhcyB3aXRob3V0IGV2YWx1YXRpbmdcbiAgICovXG4gIHZhbGlkYXRlKGZvcm11bGFzOiBGb3JtdWxhRGVmaW5pdGlvbltdKTogVmFsaWRhdGlvblJlc3VsdCB7XG4gICAgY29uc3QgZXJyb3JzOiBGb3JtdWxhRW5naW5lRXJyb3JbXSA9IFtdO1xuICAgIGNvbnN0IHdhcm5pbmdzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgLy8gQ2hlY2sgZm9yIGR1cGxpY2F0ZSBJRHNcbiAgICBjb25zdCBpZHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IGZvcm11bGEgb2YgZm9ybXVsYXMpIHtcbiAgICAgIGlmIChpZHMuaGFzKGZvcm11bGEuaWQpKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKG5ldyBEdXBsaWNhdGVGb3JtdWxhRXJyb3IoZm9ybXVsYS5pZCkpO1xuICAgICAgfVxuICAgICAgaWRzLmFkZChmb3JtdWxhLmlkKTtcbiAgICB9XG5cbiAgICAvLyBUcnkgdG8gcGFyc2UgYWxsIGV4cHJlc3Npb25zXG4gICAgZm9yIChjb25zdCBmb3JtdWxhIG9mIGZvcm11bGFzKSB7XG4gICAgICB0cnkge1xuICAgICAgICB0aGlzLnBhcnNlKGZvcm11bGEuZXhwcmVzc2lvbik7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBGb3JtdWxhRW5naW5lRXJyb3IpIHtcbiAgICAgICAgICBlcnJvcnMucHVzaChlcnJvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZXJyb3JzLnB1c2gobmV3IEdlbmVyYWxGb3JtdWxhRXJyb3IoU3RyaW5nKGVycm9yKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQnVpbGQgZGVwZW5kZW5jeSBncmFwaCBhbmQgY2hlY2sgZm9yIGN5Y2xlc1xuICAgIGxldCBkZXBlbmRlbmN5R3JhcGg6IElEZXBlbmRlbmN5R3JhcGggPSBuZXcgRGVwZW5kZW5jeUdyYXBoKCk7XG4gICAgbGV0IGV2YWx1YXRpb25PcmRlcjogc3RyaW5nW10gPSBbXTtcblxuICAgIHRyeSB7XG4gICAgICBkZXBlbmRlbmN5R3JhcGggPSB0aGlzLmJ1aWxkRGVwZW5kZW5jeUdyYXBoKGZvcm11bGFzKTtcbiAgICAgIGV2YWx1YXRpb25PcmRlciA9IGRlcGVuZGVuY3lHcmFwaC50b3BvbG9naWNhbFNvcnQoKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRm9ybXVsYUVuZ2luZUVycm9yKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKGVycm9yKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsXG4gICAgICBlcnJvcnMsXG4gICAgICB3YXJuaW5ncyxcbiAgICAgIGRlcGVuZGVuY3lHcmFwaCxcbiAgICAgIGV2YWx1YXRpb25PcmRlcixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlIGEgc2luZ2xlIGV4cHJlc3Npb25cbiAgICovXG4gIGV2YWx1YXRlKGV4cHJlc3Npb246IHN0cmluZywgY29udGV4dDogRXZhbHVhdGlvbkNvbnRleHQpOiBFdmFsdWF0aW9uUmVzdWx0IHtcbiAgICB0aGlzLmNoZWNrRXhwcmVzc2lvbkxlbmd0aChleHByZXNzaW9uKTtcbiAgICBjb25zdCBub3JtYWxpemVkQ29udGV4dCA9IHRoaXMubm9ybWFsaXplQ29udGV4dChjb250ZXh0KTtcbiAgICByZXR1cm4gdGhpcy5ldmFsdWF0b3IuZXZhbHVhdGUoZXhwcmVzc2lvbiwgbm9ybWFsaXplZENvbnRleHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEV2YWx1YXRlIGFsbCBmb3JtdWxhcyBpbiBkZXBlbmRlbmN5IG9yZGVyXG4gICAqXG4gICAqIEBwYXJhbSBmb3JtdWxhcyAtIEFycmF5IG9mIGZvcm11bGEgZGVmaW5pdGlvbnMgdG8gZXZhbHVhdGVcbiAgICogQHBhcmFtIGNvbnRleHQgLSBFdmFsdWF0aW9uIGNvbnRleHQgd2l0aCB2YXJpYWJsZXNcbiAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25hbCBjb25maWd1cmF0aW9uIGZvciBiYXRjaCBldmFsdWF0aW9uXG4gICAqL1xuICBldmFsdWF0ZUFsbChcbiAgICBmb3JtdWxhczogRm9ybXVsYURlZmluaXRpb25bXSxcbiAgICBjb250ZXh0OiBFdmFsdWF0aW9uQ29udGV4dCxcbiAgICBvcHRpb25zPzogRXZhbHVhdGVBbGxPcHRpb25zXG4gICk6IEV2YWx1YXRpb25SZXN1bHRTZXQge1xuICAgIGNvbnN0IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgY29uc3QgcmVzdWx0cyA9IG5ldyBNYXA8c3RyaW5nLCBFdmFsdWF0aW9uUmVzdWx0PigpO1xuICAgIGNvbnN0IGVycm9yczogRXJyb3JbXSA9IFtdO1xuXG4gICAgLy8gR2V0IGV2YWx1YXRpb24gb3JkZXJcbiAgICBsZXQgZXZhbHVhdGlvbk9yZGVyOiBzdHJpbmdbXTtcbiAgICB0cnkge1xuICAgICAgZXZhbHVhdGlvbk9yZGVyID0gdGhpcy5nZXRFdmFsdWF0aW9uT3JkZXIoZm9ybXVsYXMpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICByZXN1bHRzLFxuICAgICAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICAgICAgZXJyb3JzOiBbZXJyb3IgYXMgRXJyb3JdLFxuICAgICAgICB0b3RhbEV4ZWN1dGlvblRpbWVNczogRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSxcbiAgICAgICAgZXZhbHVhdGlvbk9yZGVyOiBbXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIGEgbWFwIG9mIGZvcm11bGFzIGJ5IElEXG4gICAgY29uc3QgZm9ybXVsYU1hcCA9IG5ldyBNYXA8c3RyaW5nLCBGb3JtdWxhRGVmaW5pdGlvbj4oKTtcbiAgICBmb3IgKGNvbnN0IGZvcm11bGEgb2YgZm9ybXVsYXMpIHtcbiAgICAgIGZvcm11bGFNYXAuc2V0KGZvcm11bGEuaWQsIGZvcm11bGEpO1xuICAgIH1cblxuICAgIC8vIERldGVybWluZSBpZiBpbnRlcm1lZGlhdGUgcm91bmRpbmcgc2hvdWxkIGJlIGFwcGxpZWRcbiAgICBjb25zdCBhcHBseUludGVybWVkaWF0ZVJvdW5kaW5nID1cbiAgICAgIHRoaXMuY29uZmlnLmRlZmF1bHRSb3VuZGluZyAmJlxuICAgICAgdGhpcy5jb25maWcuZGVmYXVsdFJvdW5kaW5nLm1vZGUgIT09ICdOT05FJyAmJlxuICAgICAgIW9wdGlvbnM/LmRpc2FibGVJbnRlcm1lZGlhdGVSb3VuZGluZztcblxuICAgIC8vIEV2YWx1YXRlIGluIG9yZGVyLCBtZXJnaW5nIHJlc3VsdHMgaW50byBjb250ZXh0XG4gICAgY29uc3Qgd29ya2luZ0NvbnRleHQ6IEV2YWx1YXRpb25Db250ZXh0ID0gdGhpcy5ub3JtYWxpemVDb250ZXh0KGNvbnRleHQpO1xuXG4gICAgZm9yIChjb25zdCBmb3JtdWxhSWQgb2YgZXZhbHVhdGlvbk9yZGVyKSB7XG4gICAgICBjb25zdCBmb3JtdWxhID0gZm9ybXVsYU1hcC5nZXQoZm9ybXVsYUlkKTtcbiAgICAgIGlmICghZm9ybXVsYSkgY29udGludWU7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuZXZhbHVhdG9yLmV2YWx1YXRlKGZvcm11bGEuZXhwcmVzc2lvbiwgd29ya2luZ0NvbnRleHQpO1xuXG4gICAgICAgIC8vIEFwcGx5IHJvdW5kaW5nOiBwZXItZm9ybXVsYSBjb25maWcgdGFrZXMgcHJlY2VkZW5jZSwgdGhlbiBkZWZhdWx0Um91bmRpbmdcbiAgICAgICAgbGV0IHZhbHVlID0gcmVzdWx0LnZhbHVlO1xuICAgICAgICBpZiAodGhpcy5pc0RlY2ltYWwodmFsdWUpKSB7XG4gICAgICAgICAgaWYgKGZvcm11bGEucm91bmRpbmcpIHtcbiAgICAgICAgICAgIC8vIFBlci1mb3JtdWxhIHJvdW5kaW5nIGFsd2F5cyB0YWtlcyBwcmVjZWRlbmNlXG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMuYXBwbHlSb3VuZGluZyh2YWx1ZSBhcyBEZWNpbWFsLCBmb3JtdWxhLnJvdW5kaW5nKTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGFwcGx5SW50ZXJtZWRpYXRlUm91bmRpbmcpIHtcbiAgICAgICAgICAgIC8vIEFwcGx5IGRlZmF1bHQgcm91bmRpbmcgdG8gaW50ZXJtZWRpYXRlIHZhbHVlc1xuICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmFwcGx5Um91bmRpbmcodmFsdWUgYXMgRGVjaW1hbCwgdGhpcy5jb25maWcuZGVmYXVsdFJvdW5kaW5nISk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSGFuZGxlIGVycm9ycyBiYXNlZCBvbiBmb3JtdWxhIGNvbmZpZ1xuICAgICAgICBpZiAoIXJlc3VsdC5zdWNjZXNzICYmIGZvcm11bGEub25FcnJvcikge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5oYW5kbGVFcnJvcihmb3JtdWxhLCByZXN1bHQuZXJyb3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmVzdWx0cy5zZXQoZm9ybXVsYUlkLCB7XG4gICAgICAgICAgLi4ucmVzdWx0LFxuICAgICAgICAgIHZhbHVlLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBNZXJnZSByZXN1bHQgaW50byBjb250ZXh0IGZvciBzdWJzZXF1ZW50IGZvcm11bGFzXG4gICAgICAgIHdvcmtpbmdDb250ZXh0LnZhcmlhYmxlc1tmb3JtdWxhSWRdID0gdmFsdWU7XG5cbiAgICAgICAgaWYgKCFyZXN1bHQuc3VjY2Vzcykge1xuICAgICAgICAgIGVycm9ycy5wdXNoKHJlc3VsdC5lcnJvciEpO1xuICAgICAgICB9XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zdCBldmFsUmVzdWx0OiBFdmFsdWF0aW9uUmVzdWx0ID0ge1xuICAgICAgICAgIHZhbHVlOiBudWxsLFxuICAgICAgICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgICAgICAgIGVycm9yOiBlcnJvciBhcyBFcnJvcixcbiAgICAgICAgICBleGVjdXRpb25UaW1lTXM6IDAsXG4gICAgICAgICAgYWNjZXNzZWRWYXJpYWJsZXM6IG5ldyBTZXQoKSxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBIYW5kbGUgZXJyb3IgYmFzZWQgb24gZm9ybXVsYSBjb25maWdcbiAgICAgICAgaWYgKGZvcm11bGEub25FcnJvcikge1xuICAgICAgICAgIGV2YWxSZXN1bHQudmFsdWUgPSB0aGlzLmhhbmRsZUVycm9yKGZvcm11bGEsIGVycm9yIGFzIEVycm9yKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdHMuc2V0KGZvcm11bGFJZCwgZXZhbFJlc3VsdCk7XG4gICAgICAgIGVycm9ycy5wdXNoKGVycm9yIGFzIEVycm9yKTtcblxuICAgICAgICAvLyBTdGlsbCBhZGQgdG8gY29udGV4dCAoYXMgbnVsbCBvciBkZWZhdWx0IHZhbHVlKSBzbyBkZXBlbmRlbnQgZm9ybXVsYXMgY2FuIHByb2NlZWRcbiAgICAgICAgd29ya2luZ0NvbnRleHQudmFyaWFibGVzW2Zvcm11bGFJZF0gPSBldmFsUmVzdWx0LnZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICByZXN1bHRzLFxuICAgICAgc3VjY2VzczogZXJyb3JzLmxlbmd0aCA9PT0gMCxcbiAgICAgIGVycm9ycyxcbiAgICAgIHRvdGFsRXhlY3V0aW9uVGltZU1zOiBEYXRlLm5vdygpIC0gc3RhcnRUaW1lLFxuICAgICAgZXZhbHVhdGlvbk9yZGVyLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBjdXN0b20gZnVuY3Rpb25cbiAgICovXG4gIHJlZ2lzdGVyRnVuY3Rpb24oZGVmaW5pdGlvbjogRnVuY3Rpb25EZWZpbml0aW9uKTogdm9pZCB7XG4gICAgY29uc3QgbmFtZSA9IGRlZmluaXRpb24ubmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgIHRoaXMuZnVuY3Rpb25zLnNldChuYW1lLCBkZWZpbml0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBtdWx0aXBsZSBjdXN0b20gZnVuY3Rpb25zXG4gICAqL1xuICByZWdpc3RlckZ1bmN0aW9ucyhkZWZpbml0aW9uczogRnVuY3Rpb25EZWZpbml0aW9uW10pOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGRlZmluaXRpb24gb2YgZGVmaW5pdGlvbnMpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJGdW5jdGlvbihkZWZpbml0aW9uKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHJlZ2lzdGVyZWQgZnVuY3Rpb24gbmFtZXNcbiAgICovXG4gIGdldFJlZ2lzdGVyZWRGdW5jdGlvbnMoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMuZnVuY3Rpb25zLmtleXMoKSk7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYXIgdGhlIEFTVCBjYWNoZVxuICAgKi9cbiAgY2xlYXJDYWNoZSgpOiB2b2lkIHtcbiAgICB0aGlzLmFzdENhY2hlLmNsZWFyKCk7XG4gICAgdGhpcy5kZXBlbmRlbmN5Q2FjaGUuY2xlYXIoKTtcbiAgICB0aGlzLmNhY2hlSGl0cyA9IDA7XG4gICAgdGhpcy5jYWNoZU1pc3NlcyA9IDA7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNhY2hlIHN0YXRpc3RpY3NcbiAgICovXG4gIGdldENhY2hlU3RhdHMoKTogQ2FjaGVTdGF0cyB7XG4gICAgY29uc3QgdG90YWwgPSB0aGlzLmNhY2hlSGl0cyArIHRoaXMuY2FjaGVNaXNzZXM7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNpemU6IHRoaXMuYXN0Q2FjaGUuc2l6ZSxcbiAgICAgIGhpdHM6IHRoaXMuY2FjaGVIaXRzLFxuICAgICAgbWlzc2VzOiB0aGlzLmNhY2hlTWlzc2VzLFxuICAgICAgaGl0UmF0ZTogdG90YWwgPiAwID8gdGhpcy5jYWNoZUhpdHMgLyB0b3RhbCA6IDAsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRlY2ltYWwgdXRpbGl0aWVzIGluc3RhbmNlXG4gICAqL1xuICBnZXREZWNpbWFsVXRpbHMoKTogRGVjaW1hbFV0aWxzIHtcbiAgICByZXR1cm4gdGhpcy5kZWNpbWFsVXRpbHM7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRGVjaW1hbCBmcm9tIGEgdmFsdWVcbiAgICovXG4gIGNyZWF0ZURlY2ltYWwodmFsdWU6IHN0cmluZyB8IG51bWJlcik6IERlY2ltYWwge1xuICAgIHJldHVybiB0aGlzLmRlY2ltYWxVdGlscy5mcm9tKHZhbHVlKTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy8gUHJpdmF0ZSBtZXRob2RzXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBwcml2YXRlIGNoZWNrRXhwcmVzc2lvbkxlbmd0aChleHByZXNzaW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBtYXhMZW5ndGggPSB0aGlzLmNvbmZpZy5zZWN1cml0eT8ubWF4RXhwcmVzc2lvbkxlbmd0aCA/PyAxMDAwMDtcbiAgICBpZiAoZXhwcmVzc2lvbi5sZW5ndGggPiBtYXhMZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBNYXhFeHByZXNzaW9uTGVuZ3RoRXJyb3IoZXhwcmVzc2lvbi5sZW5ndGgsIG1heExlbmd0aCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBub3JtYWxpemVDb250ZXh0KGNvbnRleHQ6IEV2YWx1YXRpb25Db250ZXh0KTogRXZhbHVhdGlvbkNvbnRleHQge1xuICAgIC8vIERlZXAgY29weSBhbmQgY29udmVydCBudW1lcmljIHZhbHVlcyB0byBEZWNpbWFsIGlmIGF1dG9Db252ZXJ0RmxvYXRzIGlzIGVuYWJsZWRcbiAgICBjb25zdCBhdXRvQ29udmVydCA9IHRoaXMuY29uZmlnLmRlY2ltYWw/LmF1dG9Db252ZXJ0RmxvYXRzID8/IHRydWU7XG5cbiAgICBpZiAoIWF1dG9Db252ZXJ0KSB7XG4gICAgICByZXR1cm4geyAuLi5jb250ZXh0IH07XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZFZhcmlhYmxlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhjb250ZXh0LnZhcmlhYmxlcykpIHtcbiAgICAgIG5vcm1hbGl6ZWRWYXJpYWJsZXNba2V5XSA9IHRoaXMuY29udmVydFZhbHVlKHZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uY29udGV4dCxcbiAgICAgIHZhcmlhYmxlczogbm9ybWFsaXplZFZhcmlhYmxlcyxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjb252ZXJ0VmFsdWUodmFsdWU6IHVua25vd24pOiB1bmtub3duIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhaXNOYU4odmFsdWUpICYmIGlzRmluaXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZGVjaW1hbFV0aWxzLmZyb20odmFsdWUpO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5tYXAodiA9PiB0aGlzLmNvbnZlcnRWYWx1ZSh2KSk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICBjb25zdCBjb252ZXJ0ZWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0ge307XG4gICAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyh2YWx1ZSkpIHtcbiAgICAgICAgY29udmVydGVkW2tdID0gdGhpcy5jb252ZXJ0VmFsdWUodik7XG4gICAgICB9XG4gICAgICByZXR1cm4gY29udmVydGVkO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcml2YXRlIGlzRGVjaW1hbCh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERlY2ltYWw7XG4gIH1cblxuICBwcml2YXRlIGFwcGx5Um91bmRpbmcoXG4gICAgdmFsdWU6IERlY2ltYWwsXG4gICAgY29uZmlnOiB7IG1vZGU6IHN0cmluZzsgcHJlY2lzaW9uOiBudW1iZXIgfVxuICApOiBEZWNpbWFsIHtcbiAgICBpZiAoY29uZmlnLm1vZGUgPT09ICdOT05FJykge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5kZWNpbWFsVXRpbHMucm91bmQodmFsdWUsIGNvbmZpZy5wcmVjaXNpb24sIGNvbmZpZy5tb2RlIGFzIGFueSk7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZUVycm9yKGZvcm11bGE6IEZvcm11bGFEZWZpbml0aW9uLCBfZXJyb3I/OiBFcnJvcik6IHVua25vd24ge1xuICAgIGNvbnN0IGJlaGF2aW9yID0gZm9ybXVsYS5vbkVycm9yO1xuICAgIGlmICghYmVoYXZpb3IpIHJldHVybiBudWxsO1xuXG4gICAgc3dpdGNoIChiZWhhdmlvci50eXBlKSB7XG4gICAgICBjYXNlICdOVUxMJzpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICBjYXNlICdaRVJPJzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZGVjaW1hbFV0aWxzLnplcm8oKTtcbiAgICAgIGNhc2UgJ0RFRkFVTFQnOlxuICAgICAgICByZXR1cm4gYmVoYXZpb3IuZGVmYXVsdFZhbHVlID8/IGZvcm11bGEuZGVmYXVsdFZhbHVlID8/IG51bGw7XG4gICAgICBjYXNlICdTS0lQJzpcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIGNhc2UgJ1RIUk9XJzpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IF9lcnJvcjtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1heWJlRXZpY3RDYWNoZSgpOiB2b2lkIHtcbiAgICBjb25zdCBtYXhTaXplID0gdGhpcy5jb25maWcubWF4Q2FjaGVTaXplID8/IDEwMDA7XG4gICAgaWYgKHRoaXMuYXN0Q2FjaGUuc2l6ZSA+PSBtYXhTaXplKSB7XG4gICAgICAvLyBTaW1wbGUgRklGTyBldmljdGlvbiAtIHJlbW92ZSBmaXJzdCAxMCUgb2YgZW50cmllc1xuICAgICAgY29uc3QgdG9SZW1vdmUgPSBNYXRoLmNlaWwobWF4U2l6ZSAqIDAuMSk7XG4gICAgICBjb25zdCBrZXlzID0gQXJyYXkuZnJvbSh0aGlzLmFzdENhY2hlLmtleXMoKSkuc2xpY2UoMCwgdG9SZW1vdmUpO1xuICAgICAgZm9yIChjb25zdCBrZXkgb2Yga2V5cykge1xuICAgICAgICB0aGlzLmFzdENhY2hlLmRlbGV0ZShrZXkpO1xuICAgICAgICB0aGlzLmRlcGVuZGVuY3lDYWNoZS5kZWxldGUoa2V5KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { FormulaEngine } from './formula-engine';
2
- export { FormulaEngineConfig, FormulaDefinition, EvaluationContext, FunctionDefinition, ArgumentType, FunctionImplementation, DecimalConfig, DecimalRoundingMode, RoundingConfig, EvaluationResult, EvaluationResultSet, ValidationResult, CacheStats, ErrorBehavior, SecurityConfig, ASTNode, DecimalLiteral, NumberLiteral, StringLiteral, BooleanLiteral, NullLiteral, ArrayLiteral, VariableReference, BinaryOperation, UnaryOperation, ConditionalExpression, FunctionCall, MemberAccess, IndexAccess, DependencyGraph, ValueType, FormulaValue, } from './types';
2
+ export { FormulaEngineConfig, FormulaDefinition, EvaluationContext, FunctionDefinition, ArgumentType, FunctionImplementation, DecimalConfig, DecimalRoundingMode, RoundingConfig, EvaluationResult, EvaluationResultSet, EvaluateAllOptions, ValidationResult, CacheStats, ErrorBehavior, SecurityConfig, ASTNode, DecimalLiteral, NumberLiteral, StringLiteral, BooleanLiteral, NullLiteral, ArrayLiteral, VariableReference, BinaryOperation, UnaryOperation, ConditionalExpression, FunctionCall, MemberAccess, IndexAccess, DependencyGraph, ValueType, FormulaValue, } from './types';
3
3
  export { Parser } from './parser';
4
4
  export { Lexer } from './lexer';
5
5
  export { Evaluator } from './evaluator';
package/dist/index.js CHANGED
@@ -58,4 +58,4 @@ Object.defineProperty(exports, "SecurityError", { enumerable: true, get: functio
58
58
  Object.defineProperty(exports, "MaxIterationsError", { enumerable: true, get: function () { return errors_1.MaxIterationsError; } });
59
59
  Object.defineProperty(exports, "MaxRecursionError", { enumerable: true, get: function () { return errors_1.MaxRecursionError; } });
60
60
  Object.defineProperty(exports, "MaxExpressionLengthError", { enumerable: true, get: function () { return errors_1.MaxExpressionLengthError; } });
61
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZUFBZTtBQUNmLG1EQUFpRDtBQUF4QywrR0FBQSxhQUFhLE9BQUE7QUFFdEIsUUFBUTtBQUNSLGlDQThDaUI7QUFuQ2YsNEdBQUEsbUJBQW1CLE9BQUE7QUFxQ3JCLGtDQUFrQztBQUNsQyxtQ0FBa0M7QUFBekIsZ0dBQUEsTUFBTSxPQUFBO0FBQ2YsaUNBQWdDO0FBQXZCLDhGQUFBLEtBQUssT0FBQTtBQUNkLHlDQUF3QztBQUEvQixzR0FBQSxTQUFTLE9BQUE7QUFDbEIsK0RBQTZEO0FBQXBELDJIQUFBLG1CQUFtQixPQUFBO0FBQzVCLHVEQUFvRztBQUEzRix1SEFBQSxlQUFlLE9BQXVCO0FBQUUsMEhBQUEsc0JBQXNCLE9BQUE7QUFDdkUsaURBQXFFO0FBQTVELDZHQUFBLFlBQVksT0FBQTtBQUFFLHdHQUFBLE9BQU8sT0FBQTtBQUM5Qix5Q0FBcUQ7QUFBNUMsbUhBQUEsc0JBQXNCLE9BQUE7QUFFL0IsU0FBUztBQUNULG1DQXdDa0I7QUF2Q2hCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDZHQUFBLG1CQUFtQixPQUFBO0FBR25CLGVBQWU7QUFDZixxR0FBQSxXQUFXLE9BQUE7QUFDWCw4R0FBQSxvQkFBb0IsT0FBQTtBQUNwQixpSEFBQSx1QkFBdUIsT0FBQTtBQUN2Qiw0R0FBQSxrQkFBa0IsT0FBQTtBQUVsQixvQkFBb0I7QUFDcEIsaUhBQUEsdUJBQXVCLE9BQUE7QUFDdkIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIsK0dBQUEscUJBQXFCLE9BQUE7QUFFckIsb0JBQW9CO0FBQ3BCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLDBHQUFBLGdCQUFnQixPQUFBO0FBRWhCLGlCQUFpQjtBQUNqQixzR0FBQSxZQUFZLE9BQUE7QUFDWiw4R0FBQSxvQkFBb0IsT0FBQTtBQUNwQiwrR0FBQSxxQkFBcUIsT0FBQTtBQUNyQixvSEFBQSwwQkFBMEIsT0FBQTtBQUMxQiw2R0FBQSxtQkFBbUIsT0FBQTtBQUVuQix1QkFBdUI7QUFDdkIsNEdBQUEsa0JBQWtCLE9BQUE7QUFFbEIsa0JBQWtCO0FBQ2xCLHVHQUFBLGFBQWEsT0FBQTtBQUNiLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLGtIQUFBLHdCQUF3QixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWFpbiBleHBvcnRzXG5leHBvcnQgeyBGb3JtdWxhRW5naW5lIH0gZnJvbSAnLi9mb3JtdWxhLWVuZ2luZSc7XG5cbi8vIFR5cGVzXG5leHBvcnQge1xuICAvLyBDb25maWd1cmF0aW9uXG4gIEZvcm11bGFFbmdpbmVDb25maWcsXG4gIEZvcm11bGFEZWZpbml0aW9uLFxuICBFdmFsdWF0aW9uQ29udGV4dCxcbiAgRnVuY3Rpb25EZWZpbml0aW9uLFxuICBBcmd1bWVudFR5cGUsXG4gIEZ1bmN0aW9uSW1wbGVtZW50YXRpb24sXG5cbiAgLy8gRGVjaW1hbFxuICBEZWNpbWFsQ29uZmlnLFxuICBEZWNpbWFsUm91bmRpbmdNb2RlLFxuICBSb3VuZGluZ0NvbmZpZyxcblxuICAvLyBSZXN1bHRzXG4gIEV2YWx1YXRpb25SZXN1bHQsXG4gIEV2YWx1YXRpb25SZXN1bHRTZXQsXG4gIFZhbGlkYXRpb25SZXN1bHQsXG4gIENhY2hlU3RhdHMsXG5cbiAgLy8gRXJyb3IgaGFuZGxpbmdcbiAgRXJyb3JCZWhhdmlvcixcbiAgU2VjdXJpdHlDb25maWcsXG5cbiAgLy8gQVNUIG5vZGVzXG4gIEFTVE5vZGUsXG4gIERlY2ltYWxMaXRlcmFsLFxuICBOdW1iZXJMaXRlcmFsLFxuICBTdHJpbmdMaXRlcmFsLFxuICBCb29sZWFuTGl0ZXJhbCxcbiAgTnVsbExpdGVyYWwsXG4gIEFycmF5TGl0ZXJhbCxcbiAgVmFyaWFibGVSZWZlcmVuY2UsXG4gIEJpbmFyeU9wZXJhdGlvbixcbiAgVW5hcnlPcGVyYXRpb24sXG4gIENvbmRpdGlvbmFsRXhwcmVzc2lvbixcbiAgRnVuY3Rpb25DYWxsLFxuICBNZW1iZXJBY2Nlc3MsXG4gIEluZGV4QWNjZXNzLFxuXG4gIC8vIEdyYXBoXG4gIERlcGVuZGVuY3lHcmFwaCxcblxuICAvLyBWYWx1ZXNcbiAgVmFsdWVUeXBlLFxuICBGb3JtdWxhVmFsdWUsXG59IGZyb20gJy4vdHlwZXMnO1xuXG4vLyBDb21wb25lbnRzIChmb3IgYWR2YW5jZWQgdXNhZ2UpXG5leHBvcnQgeyBQYXJzZXIgfSBmcm9tICcuL3BhcnNlcic7XG5leHBvcnQgeyBMZXhlciB9IGZyb20gJy4vbGV4ZXInO1xuZXhwb3J0IHsgRXZhbHVhdG9yIH0gZnJvbSAnLi9ldmFsdWF0b3InO1xuZXhwb3J0IHsgRGVwZW5kZW5jeUV4dHJhY3RvciB9IGZyb20gJy4vZGVwZW5kZW5jeS1leHRyYWN0b3InO1xuZXhwb3J0IHsgRGVwZW5kZW5jeUdyYXBoIGFzIERlcGVuZGVuY3lHcmFwaEltcGwsIERlcGVuZGVuY3lHcmFwaEJ1aWxkZXIgfSBmcm9tICcuL2RlcGVuZGVuY3ktZ3JhcGgnO1xuZXhwb3J0IHsgRGVjaW1hbFV0aWxzLCBEZWNpbWFsLCBEZWNpbWFsTGlrZSB9IGZyb20gJy4vZGVjaW1hbC11dGlscyc7XG5leHBvcnQgeyBjcmVhdGVCdWlsdEluRnVuY3Rpb25zIH0gZnJvbSAnLi9mdW5jdGlvbnMnO1xuXG4vLyBFcnJvcnNcbmV4cG9ydCB7XG4gIEZvcm11bGFFbmdpbmVFcnJvcixcbiAgR2VuZXJhbEZvcm11bGFFcnJvcixcbiAgRXJyb3JDYXRlZ29yeSxcblxuICAvLyBQYXJzZSBlcnJvcnNcbiAgU3ludGF4RXJyb3IsXG4gIFVuZXhwZWN0ZWRUb2tlbkVycm9yLFxuICBVbnRlcm1pbmF0ZWRTdHJpbmdFcnJvcixcbiAgSW52YWxpZE51bWJlckVycm9yLFxuXG4gIC8vIFZhbGlkYXRpb24gZXJyb3JzXG4gIENpcmN1bGFyRGVwZW5kZW5jeUVycm9yLFxuICBVbmRlZmluZWRWYXJpYWJsZUVycm9yLFxuICBVbmRlZmluZWRGdW5jdGlvbkVycm9yLFxuICBEdXBsaWNhdGVGb3JtdWxhRXJyb3IsXG5cbiAgLy8gRXZhbHVhdGlvbiBlcnJvcnNcbiAgRGl2aXNpb25CeVplcm9FcnJvcixcbiAgVHlwZU1pc21hdGNoRXJyb3IsXG4gIEFyZ3VtZW50Q291bnRFcnJvcixcbiAgSW52YWxpZE9wZXJhdGlvbkVycm9yLFxuICBQcm9wZXJ0eUFjY2Vzc0Vycm9yLFxuICBJbmRleEFjY2Vzc0Vycm9yLFxuXG4gIC8vIERlY2ltYWwgZXJyb3JzXG4gIERlY2ltYWxFcnJvcixcbiAgRGVjaW1hbE92ZXJmbG93RXJyb3IsXG4gIERlY2ltYWxVbmRlcmZsb3dFcnJvcixcbiAgRGVjaW1hbERpdmlzaW9uQnlaZXJvRXJyb3IsXG4gIEludmFsaWREZWNpbWFsRXJyb3IsXG5cbiAgLy8gQ29uZmlndXJhdGlvbiBlcnJvcnNcbiAgQ29uZmlndXJhdGlvbkVycm9yLFxuXG4gIC8vIFNlY3VyaXR5IGVycm9yc1xuICBTZWN1cml0eUVycm9yLFxuICBNYXhJdGVyYXRpb25zRXJyb3IsXG4gIE1heFJlY3Vyc2lvbkVycm9yLFxuICBNYXhFeHByZXNzaW9uTGVuZ3RoRXJyb3IsXG59IGZyb20gJy4vZXJyb3JzJztcbiJdfQ==
61
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsZUFBZTtBQUNmLG1EQUFpRDtBQUF4QywrR0FBQSxhQUFhLE9BQUE7QUFFdEIsUUFBUTtBQUNSLGlDQStDaUI7QUFwQ2YsNEdBQUEsbUJBQW1CLE9BQUE7QUFzQ3JCLGtDQUFrQztBQUNsQyxtQ0FBa0M7QUFBekIsZ0dBQUEsTUFBTSxPQUFBO0FBQ2YsaUNBQWdDO0FBQXZCLDhGQUFBLEtBQUssT0FBQTtBQUNkLHlDQUF3QztBQUEvQixzR0FBQSxTQUFTLE9BQUE7QUFDbEIsK0RBQTZEO0FBQXBELDJIQUFBLG1CQUFtQixPQUFBO0FBQzVCLHVEQUFvRztBQUEzRix1SEFBQSxlQUFlLE9BQXVCO0FBQUUsMEhBQUEsc0JBQXNCLE9BQUE7QUFDdkUsaURBQXFFO0FBQTVELDZHQUFBLFlBQVksT0FBQTtBQUFFLHdHQUFBLE9BQU8sT0FBQTtBQUM5Qix5Q0FBcUQ7QUFBNUMsbUhBQUEsc0JBQXNCLE9BQUE7QUFFL0IsU0FBUztBQUNULG1DQXdDa0I7QUF2Q2hCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDZHQUFBLG1CQUFtQixPQUFBO0FBR25CLGVBQWU7QUFDZixxR0FBQSxXQUFXLE9BQUE7QUFDWCw4R0FBQSxvQkFBb0IsT0FBQTtBQUNwQixpSEFBQSx1QkFBdUIsT0FBQTtBQUN2Qiw0R0FBQSxrQkFBa0IsT0FBQTtBQUVsQixvQkFBb0I7QUFDcEIsaUhBQUEsdUJBQXVCLE9BQUE7QUFDdkIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIsZ0hBQUEsc0JBQXNCLE9BQUE7QUFDdEIsK0dBQUEscUJBQXFCLE9BQUE7QUFFckIsb0JBQW9CO0FBQ3BCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLCtHQUFBLHFCQUFxQixPQUFBO0FBQ3JCLDZHQUFBLG1CQUFtQixPQUFBO0FBQ25CLDBHQUFBLGdCQUFnQixPQUFBO0FBRWhCLGlCQUFpQjtBQUNqQixzR0FBQSxZQUFZLE9BQUE7QUFDWiw4R0FBQSxvQkFBb0IsT0FBQTtBQUNwQiwrR0FBQSxxQkFBcUIsT0FBQTtBQUNyQixvSEFBQSwwQkFBMEIsT0FBQTtBQUMxQiw2R0FBQSxtQkFBbUIsT0FBQTtBQUVuQix1QkFBdUI7QUFDdkIsNEdBQUEsa0JBQWtCLE9BQUE7QUFFbEIsa0JBQWtCO0FBQ2xCLHVHQUFBLGFBQWEsT0FBQTtBQUNiLDRHQUFBLGtCQUFrQixPQUFBO0FBQ2xCLDJHQUFBLGlCQUFpQixPQUFBO0FBQ2pCLGtIQUFBLHdCQUF3QixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gTWFpbiBleHBvcnRzXG5leHBvcnQgeyBGb3JtdWxhRW5naW5lIH0gZnJvbSAnLi9mb3JtdWxhLWVuZ2luZSc7XG5cbi8vIFR5cGVzXG5leHBvcnQge1xuICAvLyBDb25maWd1cmF0aW9uXG4gIEZvcm11bGFFbmdpbmVDb25maWcsXG4gIEZvcm11bGFEZWZpbml0aW9uLFxuICBFdmFsdWF0aW9uQ29udGV4dCxcbiAgRnVuY3Rpb25EZWZpbml0aW9uLFxuICBBcmd1bWVudFR5cGUsXG4gIEZ1bmN0aW9uSW1wbGVtZW50YXRpb24sXG5cbiAgLy8gRGVjaW1hbFxuICBEZWNpbWFsQ29uZmlnLFxuICBEZWNpbWFsUm91bmRpbmdNb2RlLFxuICBSb3VuZGluZ0NvbmZpZyxcblxuICAvLyBSZXN1bHRzXG4gIEV2YWx1YXRpb25SZXN1bHQsXG4gIEV2YWx1YXRpb25SZXN1bHRTZXQsXG4gIEV2YWx1YXRlQWxsT3B0aW9ucyxcbiAgVmFsaWRhdGlvblJlc3VsdCxcbiAgQ2FjaGVTdGF0cyxcblxuICAvLyBFcnJvciBoYW5kbGluZ1xuICBFcnJvckJlaGF2aW9yLFxuICBTZWN1cml0eUNvbmZpZyxcblxuICAvLyBBU1Qgbm9kZXNcbiAgQVNUTm9kZSxcbiAgRGVjaW1hbExpdGVyYWwsXG4gIE51bWJlckxpdGVyYWwsXG4gIFN0cmluZ0xpdGVyYWwsXG4gIEJvb2xlYW5MaXRlcmFsLFxuICBOdWxsTGl0ZXJhbCxcbiAgQXJyYXlMaXRlcmFsLFxuICBWYXJpYWJsZVJlZmVyZW5jZSxcbiAgQmluYXJ5T3BlcmF0aW9uLFxuICBVbmFyeU9wZXJhdGlvbixcbiAgQ29uZGl0aW9uYWxFeHByZXNzaW9uLFxuICBGdW5jdGlvbkNhbGwsXG4gIE1lbWJlckFjY2VzcyxcbiAgSW5kZXhBY2Nlc3MsXG5cbiAgLy8gR3JhcGhcbiAgRGVwZW5kZW5jeUdyYXBoLFxuXG4gIC8vIFZhbHVlc1xuICBWYWx1ZVR5cGUsXG4gIEZvcm11bGFWYWx1ZSxcbn0gZnJvbSAnLi90eXBlcyc7XG5cbi8vIENvbXBvbmVudHMgKGZvciBhZHZhbmNlZCB1c2FnZSlcbmV4cG9ydCB7IFBhcnNlciB9IGZyb20gJy4vcGFyc2VyJztcbmV4cG9ydCB7IExleGVyIH0gZnJvbSAnLi9sZXhlcic7XG5leHBvcnQgeyBFdmFsdWF0b3IgfSBmcm9tICcuL2V2YWx1YXRvcic7XG5leHBvcnQgeyBEZXBlbmRlbmN5RXh0cmFjdG9yIH0gZnJvbSAnLi9kZXBlbmRlbmN5LWV4dHJhY3Rvcic7XG5leHBvcnQgeyBEZXBlbmRlbmN5R3JhcGggYXMgRGVwZW5kZW5jeUdyYXBoSW1wbCwgRGVwZW5kZW5jeUdyYXBoQnVpbGRlciB9IGZyb20gJy4vZGVwZW5kZW5jeS1ncmFwaCc7XG5leHBvcnQgeyBEZWNpbWFsVXRpbHMsIERlY2ltYWwsIERlY2ltYWxMaWtlIH0gZnJvbSAnLi9kZWNpbWFsLXV0aWxzJztcbmV4cG9ydCB7IGNyZWF0ZUJ1aWx0SW5GdW5jdGlvbnMgfSBmcm9tICcuL2Z1bmN0aW9ucyc7XG5cbi8vIEVycm9yc1xuZXhwb3J0IHtcbiAgRm9ybXVsYUVuZ2luZUVycm9yLFxuICBHZW5lcmFsRm9ybXVsYUVycm9yLFxuICBFcnJvckNhdGVnb3J5LFxuXG4gIC8vIFBhcnNlIGVycm9yc1xuICBTeW50YXhFcnJvcixcbiAgVW5leHBlY3RlZFRva2VuRXJyb3IsXG4gIFVudGVybWluYXRlZFN0cmluZ0Vycm9yLFxuICBJbnZhbGlkTnVtYmVyRXJyb3IsXG5cbiAgLy8gVmFsaWRhdGlvbiBlcnJvcnNcbiAgQ2lyY3VsYXJEZXBlbmRlbmN5RXJyb3IsXG4gIFVuZGVmaW5lZFZhcmlhYmxlRXJyb3IsXG4gIFVuZGVmaW5lZEZ1bmN0aW9uRXJyb3IsXG4gIER1cGxpY2F0ZUZvcm11bGFFcnJvcixcblxuICAvLyBFdmFsdWF0aW9uIGVycm9yc1xuICBEaXZpc2lvbkJ5WmVyb0Vycm9yLFxuICBUeXBlTWlzbWF0Y2hFcnJvcixcbiAgQXJndW1lbnRDb3VudEVycm9yLFxuICBJbnZhbGlkT3BlcmF0aW9uRXJyb3IsXG4gIFByb3BlcnR5QWNjZXNzRXJyb3IsXG4gIEluZGV4QWNjZXNzRXJyb3IsXG5cbiAgLy8gRGVjaW1hbCBlcnJvcnNcbiAgRGVjaW1hbEVycm9yLFxuICBEZWNpbWFsT3ZlcmZsb3dFcnJvcixcbiAgRGVjaW1hbFVuZGVyZmxvd0Vycm9yLFxuICBEZWNpbWFsRGl2aXNpb25CeVplcm9FcnJvcixcbiAgSW52YWxpZERlY2ltYWxFcnJvcixcblxuICAvLyBDb25maWd1cmF0aW9uIGVycm9yc1xuICBDb25maWd1cmF0aW9uRXJyb3IsXG5cbiAgLy8gU2VjdXJpdHkgZXJyb3JzXG4gIFNlY3VyaXR5RXJyb3IsXG4gIE1heEl0ZXJhdGlvbnNFcnJvcixcbiAgTWF4UmVjdXJzaW9uRXJyb3IsXG4gIE1heEV4cHJlc3Npb25MZW5ndGhFcnJvcixcbn0gZnJvbSAnLi9lcnJvcnMnO1xuIl19
package/dist/types.d.ts CHANGED
@@ -173,6 +173,14 @@ export interface EvaluationResultSet {
173
173
  totalExecutionTimeMs: number;
174
174
  evaluationOrder: string[];
175
175
  }
176
+ export interface EvaluateAllOptions {
177
+ /**
178
+ * When true, disables automatic intermediate rounding even if defaultRounding
179
+ * is configured in the engine. Per-formula rounding configurations are still applied.
180
+ * @default false
181
+ */
182
+ disableIntermediateRounding?: boolean;
183
+ }
176
184
  export interface ValidationResult {
177
185
  valid: boolean;
178
186
  errors: Error[];
package/dist/types.js CHANGED
@@ -59,4 +59,4 @@ var TokenType;
59
59
  // Special
60
60
  TokenType["EOF"] = "EOF";
61
61
  })(TokenType || (exports.TokenType = TokenType = {}));
62
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBVUEsK0VBQStFO0FBQy9FLHdCQUF3QjtBQUN4QiwrRUFBK0U7QUFFL0UsSUFBWSxtQkFTWDtBQVRELFdBQVksbUJBQW1CO0lBQzdCLG9DQUFhLENBQUE7SUFDYixzQ0FBZSxDQUFBO0lBQ2Ysb0NBQWEsQ0FBQTtJQUNiLGdDQUFTLENBQUE7SUFDVCwwQ0FBbUIsQ0FBQTtJQUNuQiw4Q0FBdUIsQ0FBQTtJQUN2Qiw4Q0FBdUIsQ0FBQTtJQUN2Qiw0Q0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBVFcsbUJBQW1CLG1DQUFuQixtQkFBbUIsUUFTOUI7QUEwUUQsK0VBQStFO0FBQy9FLGNBQWM7QUFDZCwrRUFBK0U7QUFFL0UsSUFBWSxTQTZDWDtBQTdDRCxXQUFZLFNBQVM7SUFDbkIsV0FBVztJQUNYLDhCQUFpQixDQUFBO0lBQ2pCLDhCQUFpQixDQUFBO0lBQ2pCLGdDQUFtQixDQUFBO0lBQ25CLDBCQUFhLENBQUE7SUFFYiw0QkFBNEI7SUFDNUIsc0NBQXlCLENBQUE7SUFDekIsa0NBQXFCLENBQUE7SUFDckIsd0NBQTJCLENBQUE7SUFFM0IsWUFBWTtJQUNaLDBCQUFhLENBQUE7SUFDYiw0QkFBZSxDQUFBO0lBQ2Ysa0NBQXFCLENBQUE7SUFDckIsOEJBQWlCLENBQUE7SUFDakIsOEJBQWlCLENBQUE7SUFDakIsNEJBQWUsQ0FBQTtJQUVmLGFBQWE7SUFDYixzQkFBUyxDQUFBO0lBQ1Qsd0JBQVcsQ0FBQTtJQUNYLHNCQUFTLENBQUE7SUFDVCxzQkFBUyxDQUFBO0lBQ1Qsd0JBQVcsQ0FBQTtJQUNYLHdCQUFXLENBQUE7SUFFWCxVQUFVO0lBQ1Ysd0JBQVcsQ0FBQTtJQUNYLHNCQUFTLENBQUE7SUFDVCx3QkFBVyxDQUFBO0lBRVgsY0FBYztJQUNkLDhCQUFpQixDQUFBO0lBQ2pCLDhCQUFpQixDQUFBO0lBQ2pCLGtDQUFxQixDQUFBO0lBQ3JCLGtDQUFxQixDQUFBO0lBQ3JCLDRCQUFlLENBQUE7SUFDZix3QkFBVyxDQUFBO0lBQ1gsa0NBQXFCLENBQUE7SUFDckIsNEJBQWUsQ0FBQTtJQUVmLFVBQVU7SUFDVix3QkFBVyxDQUFBO0FBQ2IsQ0FBQyxFQTdDVyxTQUFTLHlCQUFULFNBQVMsUUE2Q3BCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVjaW1hbCB9IGZyb20gJ2RlY2ltYWwuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBWYWx1ZSBUeXBlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSBWYWx1ZVR5cGUgPSAnbnVtYmVyJyB8ICdkZWNpbWFsJyB8ICdzdHJpbmcnIHwgJ2Jvb2xlYW4nIHwgJ2FycmF5JyB8ICdvYmplY3QnIHwgJ251bGwnIHwgJ2FueSc7XG5cbmV4cG9ydCB0eXBlIEZvcm11bGFWYWx1ZSA9IERlY2ltYWwgfCBudW1iZXIgfCBzdHJpbmcgfCBib29sZWFuIHwgbnVsbCB8IEZvcm11bGFWYWx1ZVtdIHwgeyBba2V5OiBzdHJpbmddOiBGb3JtdWxhVmFsdWUgfTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRGVjaW1hbCBDb25maWd1cmF0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBlbnVtIERlY2ltYWxSb3VuZGluZ01vZGUge1xuICBDRUlMID0gJ0NFSUwnLFxuICBGTE9PUiA9ICdGTE9PUicsXG4gIERPV04gPSAnRE9XTicsXG4gIFVQID0gJ1VQJyxcbiAgSEFMRl9VUCA9ICdIQUxGX1VQJyxcbiAgSEFMRl9ET1dOID0gJ0hBTEZfRE9XTicsXG4gIEhBTEZfRVZFTiA9ICdIQUxGX0VWRU4nLFxuICBIQUxGX09ERCA9ICdIQUxGX09ERCcsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVjaW1hbENvbmZpZyB7XG4gIHByZWNpc2lvbj86IG51bWJlcjtcbiAgcm91bmRpbmdNb2RlPzogRGVjaW1hbFJvdW5kaW5nTW9kZTtcbiAgZGl2aXNpb25TY2FsZT86IG51bWJlcjtcbiAgcHJlc2VydmVUcmFpbGluZ1plcm9zPzogYm9vbGVhbjtcbiAgYXV0b0NvbnZlcnRGbG9hdHM/OiBib29sZWFuO1xuICBtYXhFeHBvbmVudD86IG51bWJlcjtcbiAgbWluRXhwb25lbnQ/OiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJvdW5kaW5nIENvbmZpZ3VyYXRpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBSb3VuZGluZ0NvbmZpZyB7XG4gIG1vZGU6ICdIQUxGX1VQJyB8ICdIQUxGX0RPV04nIHwgJ0ZMT09SJyB8ICdDRUlMJyB8ICdOT05FJztcbiAgcHJlY2lzaW9uOiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVycm9yIEJlaGF2aW9yXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXJyb3JCZWhhdmlvciB7XG4gIHR5cGU6ICdUSFJPVycgfCAnTlVMTCcgfCAnWkVSTycgfCAnREVGQVVMVCcgfCAnU0tJUCc7XG4gIGRlZmF1bHRWYWx1ZT86IHVua25vd247XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEZvcm11bGEgRGVmaW5pdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm11bGFEZWZpbml0aW9uIHtcbiAgaWQ6IHN0cmluZztcbiAgZXhwcmVzc2lvbjogc3RyaW5nO1xuICBkZXBlbmRlbmNpZXM/OiBzdHJpbmdbXTtcbiAgb25FcnJvcj86IEVycm9yQmVoYXZpb3I7XG4gIGRlZmF1bHRWYWx1ZT86IHVua25vd247XG4gIHJvdW5kaW5nPzogUm91bmRpbmdDb25maWc7XG4gIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEV2YWx1YXRpb24gQ29udGV4dFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEV2YWx1YXRpb25Db250ZXh0IHtcbiAgdmFyaWFibGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29sbGVjdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duW10+O1xuICBleHRyYT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbmdpbmUgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdG9yRGVmaW5pdGlvbiB7XG4gIHN5bWJvbDogc3RyaW5nO1xuICBwcmVjZWRlbmNlOiBudW1iZXI7XG4gIGFzc29jaWF0aXZpdHk6ICdsZWZ0JyB8ICdyaWdodCc7XG4gIGhhbmRsZXI6IChsZWZ0OiB1bmtub3duLCByaWdodDogdW5rbm93bikgPT4gdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWN1cml0eUNvbmZpZyB7XG4gIG1heEV4cHJlc3Npb25MZW5ndGg/OiBudW1iZXI7XG4gIG1heFJlY3Vyc2lvbkRlcHRoPzogbnVtYmVyO1xuICBtYXhJdGVyYXRpb25zPzogbnVtYmVyO1xuICBtYXhFeGVjdXRpb25UaW1lPzogbnVtYmVyO1xuICBhbGxvd2VkRnVuY3Rpb25zPzogc3RyaW5nW107XG4gIGJsb2NrZWRGdW5jdGlvbnM/OiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGb3JtdWxhRW5naW5lQ29uZmlnIHtcbiAgZW5hYmxlQ2FjaGU/OiBib29sZWFuO1xuICBtYXhDYWNoZVNpemU/OiBudW1iZXI7XG4gIGRlZmF1bHRFcnJvckJlaGF2aW9yPzogRXJyb3JCZWhhdmlvcjtcbiAgZGVmYXVsdFJvdW5kaW5nPzogUm91bmRpbmdDb25maWc7XG4gIHZhcmlhYmxlUHJlZml4Pzogc3RyaW5nO1xuICBjb250ZXh0UHJlZml4Pzogc3RyaW5nO1xuICBzdHJpY3RNb2RlPzogYm9vbGVhbjtcbiAgb3BlcmF0b3JzPzogT3BlcmF0b3JEZWZpbml0aW9uW107XG4gIGZ1bmN0aW9ucz86IEZ1bmN0aW9uRGVmaW5pdGlvbltdO1xuICBkZWNpbWFsPzogRGVjaW1hbENvbmZpZztcbiAgc2VjdXJpdHk/OiBTZWN1cml0eUNvbmZpZztcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQVNUIE5vZGUgVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBEZWNpbWFsTGl0ZXJhbCB7XG4gIHR5cGU6ICdEZWNpbWFsTGl0ZXJhbCc7XG4gIHZhbHVlOiBzdHJpbmc7XG4gIHJhdzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE51bWJlckxpdGVyYWwge1xuICB0eXBlOiAnTnVtYmVyTGl0ZXJhbCc7XG4gIHZhbHVlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RyaW5nTGl0ZXJhbCB7XG4gIHR5cGU6ICdTdHJpbmdMaXRlcmFsJztcbiAgdmFsdWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCb29sZWFuTGl0ZXJhbCB7XG4gIHR5cGU6ICdCb29sZWFuTGl0ZXJhbCc7XG4gIHZhbHVlOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE51bGxMaXRlcmFsIHtcbiAgdHlwZTogJ051bGxMaXRlcmFsJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcnJheUxpdGVyYWwge1xuICB0eXBlOiAnQXJyYXlMaXRlcmFsJztcbiAgZWxlbWVudHM6IEFTVE5vZGVbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWYXJpYWJsZVJlZmVyZW5jZSB7XG4gIHR5cGU6ICdWYXJpYWJsZVJlZmVyZW5jZSc7XG4gIHByZWZpeDogJyQnIHwgJ0AnO1xuICBuYW1lOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmluYXJ5T3BlcmF0aW9uIHtcbiAgdHlwZTogJ0JpbmFyeU9wZXJhdGlvbic7XG4gIG9wZXJhdG9yOiBzdHJpbmc7XG4gIGxlZnQ6IEFTVE5vZGU7XG4gIHJpZ2h0OiBBU1ROb2RlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVuYXJ5T3BlcmF0aW9uIHtcbiAgdHlwZTogJ1VuYXJ5T3BlcmF0aW9uJztcbiAgb3BlcmF0b3I6IHN0cmluZztcbiAgb3BlcmFuZDogQVNUTm9kZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb25kaXRpb25hbEV4cHJlc3Npb24ge1xuICB0eXBlOiAnQ29uZGl0aW9uYWxFeHByZXNzaW9uJztcbiAgY29uZGl0aW9uOiBBU1ROb2RlO1xuICBjb25zZXF1ZW50OiBBU1ROb2RlO1xuICBhbHRlcm5hdGU6IEFTVE5vZGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRnVuY3Rpb25DYWxsIHtcbiAgdHlwZTogJ0Z1bmN0aW9uQ2FsbCc7XG4gIG5hbWU6IHN0cmluZztcbiAgYXJndW1lbnRzOiBBU1ROb2RlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtYmVyQWNjZXNzIHtcbiAgdHlwZTogJ01lbWJlckFjY2Vzcyc7XG4gIG9iamVjdDogQVNUTm9kZTtcbiAgcHJvcGVydHk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmRleEFjY2VzcyB7XG4gIHR5cGU6ICdJbmRleEFjY2Vzcyc7XG4gIG9iamVjdDogQVNUTm9kZTtcbiAgaW5kZXg6IEFTVE5vZGU7XG59XG5cbmV4cG9ydCB0eXBlIEFTVE5vZGUgPVxuICB8IERlY2ltYWxMaXRlcmFsXG4gIHwgTnVtYmVyTGl0ZXJhbFxuICB8IFN0cmluZ0xpdGVyYWxcbiAgfCBCb29sZWFuTGl0ZXJhbFxuICB8IE51bGxMaXRlcmFsXG4gIHwgQXJyYXlMaXRlcmFsXG4gIHwgVmFyaWFibGVSZWZlcmVuY2VcbiAgfCBCaW5hcnlPcGVyYXRpb25cbiAgfCBVbmFyeU9wZXJhdGlvblxuICB8IENvbmRpdGlvbmFsRXhwcmVzc2lvblxuICB8IEZ1bmN0aW9uQ2FsbFxuICB8IE1lbWJlckFjY2Vzc1xuICB8IEluZGV4QWNjZXNzO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBGdW5jdGlvbiBEZWZpbml0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXJndW1lbnRUeXBlIHtcbiAgbmFtZTogc3RyaW5nO1xuICB0eXBlOiBWYWx1ZVR5cGU7XG4gIHJlcXVpcmVkOiBib29sZWFuO1xuICBkZWZhdWx0PzogdW5rbm93bjtcbn1cblxuZXhwb3J0IHR5cGUgRnVuY3Rpb25JbXBsZW1lbnRhdGlvbiA9IChcbiAgYXJnczogdW5rbm93bltdLFxuICBjb250ZXh0OiBFdmFsdWF0aW9uQ29udGV4dCxcbiAgZW5naW5lOiB1bmtub3duXG4pID0+IHVua25vd247XG5cbmV4cG9ydCBpbnRlcmZhY2UgRnVuY3Rpb25EZWZpbml0aW9uIHtcbiAgbmFtZTogc3RyaW5nO1xuICBtaW5BcmdzOiBudW1iZXI7XG4gIG1heEFyZ3M6IG51bWJlcjtcbiAgYXJnVHlwZXM/OiBBcmd1bWVudFR5cGVbXTtcbiAgcmV0dXJuVHlwZTogVmFsdWVUeXBlO1xuICBpbXBsZW1lbnRhdGlvbjogRnVuY3Rpb25JbXBsZW1lbnRhdGlvbjtcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERlcGVuZGVuY3kgR3JhcGhcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBlbmRlbmN5R3JhcGgge1xuICBub2RlczogU2V0PHN0cmluZz47XG4gIGVkZ2VzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj47XG4gIGhhc0N5Y2xlcygpOiBib29sZWFuO1xuICBnZXRSb290cygpOiBTZXQ8c3RyaW5nPjtcbiAgZ2V0RGVwZW5kZW50cyhub2RlSWQ6IHN0cmluZyk6IFNldDxzdHJpbmc+O1xuICBnZXREZXBlbmRlbmNpZXMobm9kZUlkOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPjtcbiAgZ2V0VHJhbnNpdGl2ZURlcGVuZGVuY2llcyhub2RlSWQ6IHN0cmluZyk6IFNldDxzdHJpbmc+O1xuICB0b3BvbG9naWNhbFNvcnQoKTogc3RyaW5nW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEV2YWx1YXRpb24gUmVzdWx0c1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEV2YWx1YXRpb25SZXN1bHQge1xuICB2YWx1ZTogdW5rbm93bjtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgZXJyb3I/OiBFcnJvcjtcbiAgZXhlY3V0aW9uVGltZU1zOiBudW1iZXI7XG4gIGFjY2Vzc2VkVmFyaWFibGVzOiBTZXQ8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmFsdWF0aW9uUmVzdWx0U2V0IHtcbiAgcmVzdWx0czogTWFwPHN0cmluZywgRXZhbHVhdGlvblJlc3VsdD47XG4gIHN1Y2Nlc3M6IGJvb2xlYW47XG4gIGVycm9yczogRXJyb3JbXTtcbiAgdG90YWxFeGVjdXRpb25UaW1lTXM6IG51bWJlcjtcbiAgZXZhbHVhdGlvbk9yZGVyOiBzdHJpbmdbXTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVmFsaWRhdGlvbiBSZXN1bHRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgdmFsaWQ6IGJvb2xlYW47XG4gIGVycm9yczogRXJyb3JbXTtcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICBkZXBlbmRlbmN5R3JhcGg6IERlcGVuZGVuY3lHcmFwaDtcbiAgZXZhbHVhdGlvbk9yZGVyOiBzdHJpbmdbXTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2FjaGUgU3RhdGlzdGljc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIENhY2hlU3RhdHMge1xuICBzaXplOiBudW1iZXI7XG4gIGhpdHM6IG51bWJlcjtcbiAgbWlzc2VzOiBudW1iZXI7XG4gIGhpdFJhdGU6IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVG9rZW4gVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGVudW0gVG9rZW5UeXBlIHtcbiAgLy8gTGl0ZXJhbHNcbiAgTlVNQkVSID0gJ05VTUJFUicsXG4gIFNUUklORyA9ICdTVFJJTkcnLFxuICBCT09MRUFOID0gJ0JPT0xFQU4nLFxuICBOVUxMID0gJ05VTEwnLFxuXG4gIC8vIElkZW50aWZpZXJzIGFuZCBWYXJpYWJsZXNcbiAgSURFTlRJRklFUiA9ICdJREVOVElGSUVSJyxcbiAgVkFSSUFCTEUgPSAnVkFSSUFCTEUnLFxuICBDT05URVhUX1ZBUiA9ICdDT05URVhUX1ZBUicsXG5cbiAgLy8gT3BlcmF0b3JzXG4gIFBMVVMgPSAnUExVUycsXG4gIE1JTlVTID0gJ01JTlVTJyxcbiAgTVVMVElQTFkgPSAnTVVMVElQTFknLFxuICBESVZJREUgPSAnRElWSURFJyxcbiAgTU9EVUxPID0gJ01PRFVMTycsXG4gIFBPV0VSID0gJ1BPV0VSJyxcblxuICAvLyBDb21wYXJpc29uXG4gIEVRID0gJ0VRJyxcbiAgTkVRID0gJ05FUScsXG4gIExUID0gJ0xUJyxcbiAgR1QgPSAnR1QnLFxuICBMVEUgPSAnTFRFJyxcbiAgR1RFID0gJ0dURScsXG5cbiAgLy8gTG9naWNhbFxuICBBTkQgPSAnQU5EJyxcbiAgT1IgPSAnT1InLFxuICBOT1QgPSAnTk9UJyxcblxuICAvLyBQdW5jdHVhdGlvblxuICBMUEFSRU4gPSAnTFBBUkVOJyxcbiAgUlBBUkVOID0gJ1JQQVJFTicsXG4gIExCUkFDS0VUID0gJ0xCUkFDS0VUJyxcbiAgUkJSQUNLRVQgPSAnUkJSQUNLRVQnLFxuICBDT01NQSA9ICdDT01NQScsXG4gIERPVCA9ICdET1QnLFxuICBRVUVTVElPTiA9ICdRVUVTVElPTicsXG4gIENPTE9OID0gJ0NPTE9OJyxcblxuICAvLyBTcGVjaWFsXG4gIEVPRiA9ICdFT0YnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRva2VuIHtcbiAgdHlwZTogVG9rZW5UeXBlO1xuICB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG51bGw7XG4gIHBvc2l0aW9uOiBudW1iZXI7XG4gIGxpbmU6IG51bWJlcjtcbiAgY29sdW1uOiBudW1iZXI7XG59XG4iXX0=
62
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvdHlwZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBVUEsK0VBQStFO0FBQy9FLHdCQUF3QjtBQUN4QiwrRUFBK0U7QUFFL0UsSUFBWSxtQkFTWDtBQVRELFdBQVksbUJBQW1CO0lBQzdCLG9DQUFhLENBQUE7SUFDYixzQ0FBZSxDQUFBO0lBQ2Ysb0NBQWEsQ0FBQTtJQUNiLGdDQUFTLENBQUE7SUFDVCwwQ0FBbUIsQ0FBQTtJQUNuQiw4Q0FBdUIsQ0FBQTtJQUN2Qiw4Q0FBdUIsQ0FBQTtJQUN2Qiw0Q0FBcUIsQ0FBQTtBQUN2QixDQUFDLEVBVFcsbUJBQW1CLG1DQUFuQixtQkFBbUIsUUFTOUI7QUF1UkQsK0VBQStFO0FBQy9FLGNBQWM7QUFDZCwrRUFBK0U7QUFFL0UsSUFBWSxTQTZDWDtBQTdDRCxXQUFZLFNBQVM7SUFDbkIsV0FBVztJQUNYLDhCQUFpQixDQUFBO0lBQ2pCLDhCQUFpQixDQUFBO0lBQ2pCLGdDQUFtQixDQUFBO0lBQ25CLDBCQUFhLENBQUE7SUFFYiw0QkFBNEI7SUFDNUIsc0NBQXlCLENBQUE7SUFDekIsa0NBQXFCLENBQUE7SUFDckIsd0NBQTJCLENBQUE7SUFFM0IsWUFBWTtJQUNaLDBCQUFhLENBQUE7SUFDYiw0QkFBZSxDQUFBO0lBQ2Ysa0NBQXFCLENBQUE7SUFDckIsOEJBQWlCLENBQUE7SUFDakIsOEJBQWlCLENBQUE7SUFDakIsNEJBQWUsQ0FBQTtJQUVmLGFBQWE7SUFDYixzQkFBUyxDQUFBO0lBQ1Qsd0JBQVcsQ0FBQTtJQUNYLHNCQUFTLENBQUE7SUFDVCxzQkFBUyxDQUFBO0lBQ1Qsd0JBQVcsQ0FBQTtJQUNYLHdCQUFXLENBQUE7SUFFWCxVQUFVO0lBQ1Ysd0JBQVcsQ0FBQTtJQUNYLHNCQUFTLENBQUE7SUFDVCx3QkFBVyxDQUFBO0lBRVgsY0FBYztJQUNkLDhCQUFpQixDQUFBO0lBQ2pCLDhCQUFpQixDQUFBO0lBQ2pCLGtDQUFxQixDQUFBO0lBQ3JCLGtDQUFxQixDQUFBO0lBQ3JCLDRCQUFlLENBQUE7SUFDZix3QkFBVyxDQUFBO0lBQ1gsa0NBQXFCLENBQUE7SUFDckIsNEJBQWUsQ0FBQTtJQUVmLFVBQVU7SUFDVix3QkFBVyxDQUFBO0FBQ2IsQ0FBQyxFQTdDVyxTQUFTLHlCQUFULFNBQVMsUUE2Q3BCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGVjaW1hbCB9IGZyb20gJ2RlY2ltYWwuanMnO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBWYWx1ZSBUeXBlc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgdHlwZSBWYWx1ZVR5cGUgPSAnbnVtYmVyJyB8ICdkZWNpbWFsJyB8ICdzdHJpbmcnIHwgJ2Jvb2xlYW4nIHwgJ2FycmF5JyB8ICdvYmplY3QnIHwgJ251bGwnIHwgJ2FueSc7XG5cbmV4cG9ydCB0eXBlIEZvcm11bGFWYWx1ZSA9IERlY2ltYWwgfCBudW1iZXIgfCBzdHJpbmcgfCBib29sZWFuIHwgbnVsbCB8IEZvcm11bGFWYWx1ZVtdIHwgeyBba2V5OiBzdHJpbmddOiBGb3JtdWxhVmFsdWUgfTtcblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gRGVjaW1hbCBDb25maWd1cmF0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBlbnVtIERlY2ltYWxSb3VuZGluZ01vZGUge1xuICBDRUlMID0gJ0NFSUwnLFxuICBGTE9PUiA9ICdGTE9PUicsXG4gIERPV04gPSAnRE9XTicsXG4gIFVQID0gJ1VQJyxcbiAgSEFMRl9VUCA9ICdIQUxGX1VQJyxcbiAgSEFMRl9ET1dOID0gJ0hBTEZfRE9XTicsXG4gIEhBTEZfRVZFTiA9ICdIQUxGX0VWRU4nLFxuICBIQUxGX09ERCA9ICdIQUxGX09ERCcsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVjaW1hbENvbmZpZyB7XG4gIHByZWNpc2lvbj86IG51bWJlcjtcbiAgcm91bmRpbmdNb2RlPzogRGVjaW1hbFJvdW5kaW5nTW9kZTtcbiAgZGl2aXNpb25TY2FsZT86IG51bWJlcjtcbiAgcHJlc2VydmVUcmFpbGluZ1plcm9zPzogYm9vbGVhbjtcbiAgYXV0b0NvbnZlcnRGbG9hdHM/OiBib29sZWFuO1xuICBtYXhFeHBvbmVudD86IG51bWJlcjtcbiAgbWluRXhwb25lbnQ/OiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIFJvdW5kaW5nIENvbmZpZ3VyYXRpb25cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBSb3VuZGluZ0NvbmZpZyB7XG4gIG1vZGU6ICdIQUxGX1VQJyB8ICdIQUxGX0RPV04nIHwgJ0ZMT09SJyB8ICdDRUlMJyB8ICdOT05FJztcbiAgcHJlY2lzaW9uOiBudW1iZXI7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEVycm9yIEJlaGF2aW9yXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXJyb3JCZWhhdmlvciB7XG4gIHR5cGU6ICdUSFJPVycgfCAnTlVMTCcgfCAnWkVSTycgfCAnREVGQVVMVCcgfCAnU0tJUCc7XG4gIGRlZmF1bHRWYWx1ZT86IHVua25vd247XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEZvcm11bGEgRGVmaW5pdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEZvcm11bGFEZWZpbml0aW9uIHtcbiAgaWQ6IHN0cmluZztcbiAgZXhwcmVzc2lvbjogc3RyaW5nO1xuICBkZXBlbmRlbmNpZXM/OiBzdHJpbmdbXTtcbiAgb25FcnJvcj86IEVycm9yQmVoYXZpb3I7XG4gIGRlZmF1bHRWYWx1ZT86IHVua25vd247XG4gIHJvdW5kaW5nPzogUm91bmRpbmdDb25maWc7XG4gIG1ldGFkYXRhPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEV2YWx1YXRpb24gQ29udGV4dFxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEV2YWx1YXRpb25Db250ZXh0IHtcbiAgdmFyaWFibGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29sbGVjdGlvbnM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duW10+O1xuICBleHRyYT86IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBFbmdpbmUgQ29uZmlndXJhdGlvblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdG9yRGVmaW5pdGlvbiB7XG4gIHN5bWJvbDogc3RyaW5nO1xuICBwcmVjZWRlbmNlOiBudW1iZXI7XG4gIGFzc29jaWF0aXZpdHk6ICdsZWZ0JyB8ICdyaWdodCc7XG4gIGhhbmRsZXI6IChsZWZ0OiB1bmtub3duLCByaWdodDogdW5rbm93bikgPT4gdW5rbm93bjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWN1cml0eUNvbmZpZyB7XG4gIG1heEV4cHJlc3Npb25MZW5ndGg/OiBudW1iZXI7XG4gIG1heFJlY3Vyc2lvbkRlcHRoPzogbnVtYmVyO1xuICBtYXhJdGVyYXRpb25zPzogbnVtYmVyO1xuICBtYXhFeGVjdXRpb25UaW1lPzogbnVtYmVyO1xuICBhbGxvd2VkRnVuY3Rpb25zPzogc3RyaW5nW107XG4gIGJsb2NrZWRGdW5jdGlvbnM/OiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGb3JtdWxhRW5naW5lQ29uZmlnIHtcbiAgZW5hYmxlQ2FjaGU/OiBib29sZWFuO1xuICBtYXhDYWNoZVNpemU/OiBudW1iZXI7XG4gIGRlZmF1bHRFcnJvckJlaGF2aW9yPzogRXJyb3JCZWhhdmlvcjtcbiAgZGVmYXVsdFJvdW5kaW5nPzogUm91bmRpbmdDb25maWc7XG4gIHZhcmlhYmxlUHJlZml4Pzogc3RyaW5nO1xuICBjb250ZXh0UHJlZml4Pzogc3RyaW5nO1xuICBzdHJpY3RNb2RlPzogYm9vbGVhbjtcbiAgb3BlcmF0b3JzPzogT3BlcmF0b3JEZWZpbml0aW9uW107XG4gIGZ1bmN0aW9ucz86IEZ1bmN0aW9uRGVmaW5pdGlvbltdO1xuICBkZWNpbWFsPzogRGVjaW1hbENvbmZpZztcbiAgc2VjdXJpdHk/OiBTZWN1cml0eUNvbmZpZztcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQVNUIE5vZGUgVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBEZWNpbWFsTGl0ZXJhbCB7XG4gIHR5cGU6ICdEZWNpbWFsTGl0ZXJhbCc7XG4gIHZhbHVlOiBzdHJpbmc7XG4gIHJhdzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE51bWJlckxpdGVyYWwge1xuICB0eXBlOiAnTnVtYmVyTGl0ZXJhbCc7XG4gIHZhbHVlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU3RyaW5nTGl0ZXJhbCB7XG4gIHR5cGU6ICdTdHJpbmdMaXRlcmFsJztcbiAgdmFsdWU6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCb29sZWFuTGl0ZXJhbCB7XG4gIHR5cGU6ICdCb29sZWFuTGl0ZXJhbCc7XG4gIHZhbHVlOiBib29sZWFuO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE51bGxMaXRlcmFsIHtcbiAgdHlwZTogJ051bGxMaXRlcmFsJztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcnJheUxpdGVyYWwge1xuICB0eXBlOiAnQXJyYXlMaXRlcmFsJztcbiAgZWxlbWVudHM6IEFTVE5vZGVbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBWYXJpYWJsZVJlZmVyZW5jZSB7XG4gIHR5cGU6ICdWYXJpYWJsZVJlZmVyZW5jZSc7XG4gIHByZWZpeDogJyQnIHwgJ0AnO1xuICBuYW1lOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmluYXJ5T3BlcmF0aW9uIHtcbiAgdHlwZTogJ0JpbmFyeU9wZXJhdGlvbic7XG4gIG9wZXJhdG9yOiBzdHJpbmc7XG4gIGxlZnQ6IEFTVE5vZGU7XG4gIHJpZ2h0OiBBU1ROb2RlO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFVuYXJ5T3BlcmF0aW9uIHtcbiAgdHlwZTogJ1VuYXJ5T3BlcmF0aW9uJztcbiAgb3BlcmF0b3I6IHN0cmluZztcbiAgb3BlcmFuZDogQVNUTm9kZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb25kaXRpb25hbEV4cHJlc3Npb24ge1xuICB0eXBlOiAnQ29uZGl0aW9uYWxFeHByZXNzaW9uJztcbiAgY29uZGl0aW9uOiBBU1ROb2RlO1xuICBjb25zZXF1ZW50OiBBU1ROb2RlO1xuICBhbHRlcm5hdGU6IEFTVE5vZGU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRnVuY3Rpb25DYWxsIHtcbiAgdHlwZTogJ0Z1bmN0aW9uQ2FsbCc7XG4gIG5hbWU6IHN0cmluZztcbiAgYXJndW1lbnRzOiBBU1ROb2RlW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVtYmVyQWNjZXNzIHtcbiAgdHlwZTogJ01lbWJlckFjY2Vzcyc7XG4gIG9iamVjdDogQVNUTm9kZTtcbiAgcHJvcGVydHk6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmRleEFjY2VzcyB7XG4gIHR5cGU6ICdJbmRleEFjY2Vzcyc7XG4gIG9iamVjdDogQVNUTm9kZTtcbiAgaW5kZXg6IEFTVE5vZGU7XG59XG5cbmV4cG9ydCB0eXBlIEFTVE5vZGUgPVxuICB8IERlY2ltYWxMaXRlcmFsXG4gIHwgTnVtYmVyTGl0ZXJhbFxuICB8IFN0cmluZ0xpdGVyYWxcbiAgfCBCb29sZWFuTGl0ZXJhbFxuICB8IE51bGxMaXRlcmFsXG4gIHwgQXJyYXlMaXRlcmFsXG4gIHwgVmFyaWFibGVSZWZlcmVuY2VcbiAgfCBCaW5hcnlPcGVyYXRpb25cbiAgfCBVbmFyeU9wZXJhdGlvblxuICB8IENvbmRpdGlvbmFsRXhwcmVzc2lvblxuICB8IEZ1bmN0aW9uQ2FsbFxuICB8IE1lbWJlckFjY2Vzc1xuICB8IEluZGV4QWNjZXNzO1xuXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4vLyBGdW5jdGlvbiBEZWZpbml0aW9uXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXJndW1lbnRUeXBlIHtcbiAgbmFtZTogc3RyaW5nO1xuICB0eXBlOiBWYWx1ZVR5cGU7XG4gIHJlcXVpcmVkOiBib29sZWFuO1xuICBkZWZhdWx0PzogdW5rbm93bjtcbn1cblxuZXhwb3J0IHR5cGUgRnVuY3Rpb25JbXBsZW1lbnRhdGlvbiA9IChcbiAgYXJnczogdW5rbm93bltdLFxuICBjb250ZXh0OiBFdmFsdWF0aW9uQ29udGV4dCxcbiAgZW5naW5lOiB1bmtub3duXG4pID0+IHVua25vd247XG5cbmV4cG9ydCBpbnRlcmZhY2UgRnVuY3Rpb25EZWZpbml0aW9uIHtcbiAgbmFtZTogc3RyaW5nO1xuICBtaW5BcmdzOiBudW1iZXI7XG4gIG1heEFyZ3M6IG51bWJlcjtcbiAgYXJnVHlwZXM/OiBBcmd1bWVudFR5cGVbXTtcbiAgcmV0dXJuVHlwZTogVmFsdWVUeXBlO1xuICBpbXBsZW1lbnRhdGlvbjogRnVuY3Rpb25JbXBsZW1lbnRhdGlvbjtcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIERlcGVuZGVuY3kgR3JhcGhcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBEZXBlbmRlbmN5R3JhcGgge1xuICBub2RlczogU2V0PHN0cmluZz47XG4gIGVkZ2VzOiBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj47XG4gIGhhc0N5Y2xlcygpOiBib29sZWFuO1xuICBnZXRSb290cygpOiBTZXQ8c3RyaW5nPjtcbiAgZ2V0RGVwZW5kZW50cyhub2RlSWQ6IHN0cmluZyk6IFNldDxzdHJpbmc+O1xuICBnZXREZXBlbmRlbmNpZXMobm9kZUlkOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPjtcbiAgZ2V0VHJhbnNpdGl2ZURlcGVuZGVuY2llcyhub2RlSWQ6IHN0cmluZyk6IFNldDxzdHJpbmc+O1xuICB0b3BvbG9naWNhbFNvcnQoKTogc3RyaW5nW107XG59XG5cbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbi8vIEV2YWx1YXRpb24gUmVzdWx0c1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIEV2YWx1YXRpb25SZXN1bHQge1xuICB2YWx1ZTogdW5rbm93bjtcbiAgc3VjY2VzczogYm9vbGVhbjtcbiAgZXJyb3I/OiBFcnJvcjtcbiAgZXhlY3V0aW9uVGltZU1zOiBudW1iZXI7XG4gIGFjY2Vzc2VkVmFyaWFibGVzOiBTZXQ8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFdmFsdWF0aW9uUmVzdWx0U2V0IHtcbiAgcmVzdWx0czogTWFwPHN0cmluZywgRXZhbHVhdGlvblJlc3VsdD47XG4gIHN1Y2Nlc3M6IGJvb2xlYW47XG4gIGVycm9yczogRXJyb3JbXTtcbiAgdG90YWxFeGVjdXRpb25UaW1lTXM6IG51bWJlcjtcbiAgZXZhbHVhdGlvbk9yZGVyOiBzdHJpbmdbXTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQmF0Y2ggRXZhbHVhdGlvbiBPcHRpb25zXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXZhbHVhdGVBbGxPcHRpb25zIHtcbiAgLyoqXG4gICAqIFdoZW4gdHJ1ZSwgZGlzYWJsZXMgYXV0b21hdGljIGludGVybWVkaWF0ZSByb3VuZGluZyBldmVuIGlmIGRlZmF1bHRSb3VuZGluZ1xuICAgKiBpcyBjb25maWd1cmVkIGluIHRoZSBlbmdpbmUuIFBlci1mb3JtdWxhIHJvdW5kaW5nIGNvbmZpZ3VyYXRpb25zIGFyZSBzdGlsbCBhcHBsaWVkLlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgZGlzYWJsZUludGVybWVkaWF0ZVJvdW5kaW5nPzogYm9vbGVhbjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVmFsaWRhdGlvbiBSZXN1bHRcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgdmFsaWQ6IGJvb2xlYW47XG4gIGVycm9yczogRXJyb3JbXTtcbiAgd2FybmluZ3M6IHN0cmluZ1tdO1xuICBkZXBlbmRlbmN5R3JhcGg6IERlcGVuZGVuY3lHcmFwaDtcbiAgZXZhbHVhdGlvbk9yZGVyOiBzdHJpbmdbXTtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gQ2FjaGUgU3RhdGlzdGljc1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG5leHBvcnQgaW50ZXJmYWNlIENhY2hlU3RhdHMge1xuICBzaXplOiBudW1iZXI7XG4gIGhpdHM6IG51bWJlcjtcbiAgbWlzc2VzOiBudW1iZXI7XG4gIGhpdFJhdGU6IG51bWJlcjtcbn1cblxuLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuLy8gVG9rZW4gVHlwZXNcbi8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuZXhwb3J0IGVudW0gVG9rZW5UeXBlIHtcbiAgLy8gTGl0ZXJhbHNcbiAgTlVNQkVSID0gJ05VTUJFUicsXG4gIFNUUklORyA9ICdTVFJJTkcnLFxuICBCT09MRUFOID0gJ0JPT0xFQU4nLFxuICBOVUxMID0gJ05VTEwnLFxuXG4gIC8vIElkZW50aWZpZXJzIGFuZCBWYXJpYWJsZXNcbiAgSURFTlRJRklFUiA9ICdJREVOVElGSUVSJyxcbiAgVkFSSUFCTEUgPSAnVkFSSUFCTEUnLFxuICBDT05URVhUX1ZBUiA9ICdDT05URVhUX1ZBUicsXG5cbiAgLy8gT3BlcmF0b3JzXG4gIFBMVVMgPSAnUExVUycsXG4gIE1JTlVTID0gJ01JTlVTJyxcbiAgTVVMVElQTFkgPSAnTVVMVElQTFknLFxuICBESVZJREUgPSAnRElWSURFJyxcbiAgTU9EVUxPID0gJ01PRFVMTycsXG4gIFBPV0VSID0gJ1BPV0VSJyxcblxuICAvLyBDb21wYXJpc29uXG4gIEVRID0gJ0VRJyxcbiAgTkVRID0gJ05FUScsXG4gIExUID0gJ0xUJyxcbiAgR1QgPSAnR1QnLFxuICBMVEUgPSAnTFRFJyxcbiAgR1RFID0gJ0dURScsXG5cbiAgLy8gTG9naWNhbFxuICBBTkQgPSAnQU5EJyxcbiAgT1IgPSAnT1InLFxuICBOT1QgPSAnTk9UJyxcblxuICAvLyBQdW5jdHVhdGlvblxuICBMUEFSRU4gPSAnTFBBUkVOJyxcbiAgUlBBUkVOID0gJ1JQQVJFTicsXG4gIExCUkFDS0VUID0gJ0xCUkFDS0VUJyxcbiAgUkJSQUNLRVQgPSAnUkJSQUNLRVQnLFxuICBDT01NQSA9ICdDT01NQScsXG4gIERPVCA9ICdET1QnLFxuICBRVUVTVElPTiA9ICdRVUVTVElPTicsXG4gIENPTE9OID0gJ0NPTE9OJyxcblxuICAvLyBTcGVjaWFsXG4gIEVPRiA9ICdFT0YnLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRva2VuIHtcbiAgdHlwZTogVG9rZW5UeXBlO1xuICB2YWx1ZTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IG51bGw7XG4gIHBvc2l0aW9uOiBudW1iZXI7XG4gIGxpbmU6IG51bWJlcjtcbiAgY29sdW1uOiBudW1iZXI7XG59XG4iXX0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-trybe/formula-engine",
3
- "version": "1.0.1",
3
+ "version": "1.1.1",
4
4
  "description": "Configuration-driven expression evaluation system with dependency resolution and decimal precision",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,8 @@
10
10
  "test:watch": "jest --watch",
11
11
  "test:coverage": "jest --coverage",
12
12
  "lint": "eslint src --ext .ts",
13
- "clean": "rm -rf dist"
13
+ "clean": "rm -rf dist",
14
+ "prepublishOnly": "npm run clean && npm run build && npm test"
14
15
  },
15
16
  "keywords": [
16
17
  "formula",
@@ -0,0 +1,608 @@
1
+ /**
2
+ * Tests for evaluateAll() batch evaluation rounding behavior
3
+ *
4
+ * Issue: evaluateAll() batch evaluation doesn't respect rounded intermediate values
5
+ * in dependency chains when consumers need to round intermediate values for accuracy.
6
+ *
7
+ * @see https://github.com/monaam/formula-engine/issues/XX
8
+ */
9
+
10
+ import { FormulaEngine } from './formula-engine';
11
+ import { FormulaDefinition, EvaluationContext, RoundingConfig } from './types';
12
+ import { Decimal } from './decimal-utils';
13
+
14
+ describe('evaluateAll() Intermediate Value Rounding', () => {
15
+ let engine: FormulaEngine;
16
+
17
+ beforeEach(() => {
18
+ engine = new FormulaEngine();
19
+ });
20
+
21
+ describe('Current Behavior - Unrounded Intermediate Values', () => {
22
+ it('should demonstrate the issue: unrounded values propagate through dependency chain', () => {
23
+ // This test documents the current (problematic) behavior
24
+ // In financial calculations, intermediate values should be rounded to cents
25
+
26
+ const formulas: FormulaDefinition[] = [
27
+ { id: '_discount1', expression: '127.5 * 0.15' }, // = 19.125
28
+ { id: '_discountTotal', expression: '$_discount1' }, // = 19.125 (raw)
29
+ { id: 'totalHt', expression: '127.5 - $_discountTotal' }, // = 108.375 (using raw)
30
+ ];
31
+
32
+ const results = engine.evaluateAll(formulas, { variables: {} });
33
+
34
+ expect(results.success).toBe(true);
35
+
36
+ // Current behavior: raw unrounded values propagate
37
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.125);
38
+ expect((results.results.get('_discountTotal')?.value as Decimal).toNumber()).toBe(19.125);
39
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.375);
40
+
41
+ // Expected for financial calculations:
42
+ // _discount1 = 19.125 → round to 19.13
43
+ // _discountTotal = 19.13
44
+ // totalHt = 127.5 - 19.13 = 108.37
45
+ //
46
+ // But we get 108.375 instead of 108.37
47
+ });
48
+
49
+ it('should show accumulated rounding errors in complex financial chain', () => {
50
+ // Multiple line items each with small rounding differences that accumulate
51
+ const formulas: FormulaDefinition[] = [
52
+ // Line item 1: quantity 3 at price 10.33
53
+ { id: 'line1_subtotal', expression: '3 * 10.33' }, // = 30.99
54
+ { id: 'line1_tax', expression: '$line1_subtotal * 0.0825' }, // = 2.556675 (should be 2.56)
55
+
56
+ // Line item 2: quantity 7 at price 5.67
57
+ { id: 'line2_subtotal', expression: '7 * 5.67' }, // = 39.69
58
+ { id: 'line2_tax', expression: '$line2_subtotal * 0.0825' }, // = 3.274425 (should be 3.27)
59
+
60
+ // Total tax should use rounded line item taxes
61
+ { id: 'totalTax', expression: '$line1_tax + $line2_tax' }, // = 5.8311 (should be 5.83)
62
+
63
+ // Grand total
64
+ { id: 'grandTotal', expression: '$line1_subtotal + $line2_subtotal + $totalTax' },
65
+ ];
66
+
67
+ const results = engine.evaluateAll(formulas, { variables: {} });
68
+
69
+ expect(results.success).toBe(true);
70
+
71
+ // Raw calculated values (what we currently get)
72
+ const line1Tax = (results.results.get('line1_tax')?.value as Decimal).toNumber();
73
+ const line2Tax = (results.results.get('line2_tax')?.value as Decimal).toNumber();
74
+ const totalTax = (results.results.get('totalTax')?.value as Decimal).toNumber();
75
+
76
+ // These are NOT rounded to 2 decimal places as financial calculations require
77
+ expect(line1Tax).toBeCloseTo(2.556675, 6);
78
+ expect(line2Tax).toBeCloseTo(3.274425, 6);
79
+ expect(totalTax).toBeCloseTo(5.8311, 4);
80
+
81
+ // For proper financial calculation:
82
+ // line1_tax should be 2.56 (rounded)
83
+ // line2_tax should be 3.27 (rounded)
84
+ // totalTax should be 2.56 + 3.27 = 5.83
85
+ //
86
+ // Difference of 0.0011 may seem small, but accumulates across many line items
87
+ });
88
+
89
+ it('should show discrepancy between batch and sequential evaluation with manual rounding', () => {
90
+ // When evaluating sequentially with manual rounding between steps,
91
+ // we get different results than batch evaluation
92
+
93
+ const basePrice = 127.5;
94
+ const discountRate = 0.15;
95
+
96
+ // Sequential evaluation with rounding
97
+ const discount1 = new Decimal(basePrice).times(discountRate).toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
98
+ const discountTotal = discount1; // Already rounded
99
+ const totalHtSequential = new Decimal(basePrice).minus(discountTotal).toNumber();
100
+
101
+ // Batch evaluation
102
+ const formulas: FormulaDefinition[] = [
103
+ { id: '_discount1', expression: `${basePrice} * ${discountRate}` },
104
+ { id: '_discountTotal', expression: '$_discount1' },
105
+ { id: 'totalHt', expression: `${basePrice} - $_discountTotal` },
106
+ ];
107
+
108
+ const results = engine.evaluateAll(formulas, { variables: {} });
109
+ const totalHtBatch = (results.results.get('totalHt')?.value as Decimal).toNumber();
110
+
111
+ // Sequential with rounding: 127.5 - 19.13 = 108.37
112
+ expect(totalHtSequential).toBe(108.37);
113
+
114
+ // Batch without intermediate rounding: 127.5 - 19.125 = 108.375
115
+ expect(totalHtBatch).toBe(108.375);
116
+
117
+ // They are NOT equal - this is the core issue
118
+ expect(totalHtSequential).not.toBe(totalHtBatch);
119
+ });
120
+ });
121
+
122
+ describe('Workaround - Per-Formula Rounding Configuration', () => {
123
+ it('should apply rounding when configured on individual formulas', () => {
124
+ // The existing rounding config on FormulaDefinition DOES work
125
+ // but requires specifying it on every intermediate formula
126
+
127
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
128
+
129
+ const formulas: FormulaDefinition[] = [
130
+ { id: '_discount1', expression: '127.5 * 0.15', rounding: roundConfig },
131
+ { id: '_discountTotal', expression: '$_discount1', rounding: roundConfig },
132
+ { id: 'totalHt', expression: '127.5 - $_discountTotal', rounding: roundConfig },
133
+ ];
134
+
135
+ const results = engine.evaluateAll(formulas, { variables: {} });
136
+
137
+ expect(results.success).toBe(true);
138
+
139
+ // With per-formula rounding configured, values ARE rounded
140
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.13);
141
+ expect((results.results.get('_discountTotal')?.value as Decimal).toNumber()).toBe(19.13);
142
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.37);
143
+ });
144
+
145
+ it('should propagate rounded values to dependent formulas', () => {
146
+ // Verify that rounded values (not raw) are used in subsequent calculations
147
+
148
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
149
+
150
+ const formulas: FormulaDefinition[] = [
151
+ { id: 'line1_subtotal', expression: '3 * 10.33', rounding: roundConfig },
152
+ { id: 'line1_tax', expression: '$line1_subtotal * 0.0825', rounding: roundConfig },
153
+
154
+ { id: 'line2_subtotal', expression: '7 * 5.67', rounding: roundConfig },
155
+ { id: 'line2_tax', expression: '$line2_subtotal * 0.0825', rounding: roundConfig },
156
+
157
+ { id: 'totalTax', expression: '$line1_tax + $line2_tax', rounding: roundConfig },
158
+ { id: 'grandTotal', expression: '$line1_subtotal + $line2_subtotal + $totalTax', rounding: roundConfig },
159
+ ];
160
+
161
+ const results = engine.evaluateAll(formulas, { variables: {} });
162
+
163
+ expect(results.success).toBe(true);
164
+
165
+ // All values should be properly rounded to 2 decimal places
166
+ expect((results.results.get('line1_subtotal')?.value as Decimal).toNumber()).toBe(30.99);
167
+ expect((results.results.get('line1_tax')?.value as Decimal).toNumber()).toBe(2.56);
168
+ expect((results.results.get('line2_subtotal')?.value as Decimal).toNumber()).toBe(39.69);
169
+ expect((results.results.get('line2_tax')?.value as Decimal).toNumber()).toBe(3.27);
170
+ expect((results.results.get('totalTax')?.value as Decimal).toNumber()).toBe(5.83);
171
+ expect((results.results.get('grandTotal')?.value as Decimal).toNumber()).toBe(76.51);
172
+ });
173
+
174
+ it('should be tedious to specify rounding on many formulas', () => {
175
+ // This test documents why the feature request makes sense:
176
+ // Having to specify rounding on every formula is verbose and error-prone
177
+
178
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
179
+
180
+ // In a real application, you might have 50+ formulas
181
+ // Forgetting rounding on ANY intermediate formula breaks the chain
182
+ const formulas: FormulaDefinition[] = [
183
+ { id: 'unitPrice', expression: '$basePrice / $packageQty', rounding: roundConfig },
184
+ { id: 'lineSubtotal', expression: '$unitPrice * $qty', rounding: roundConfig },
185
+ { id: 'discountAmount', expression: '$lineSubtotal * $discountPct / 100', rounding: roundConfig },
186
+ { id: 'afterDiscount', expression: '$lineSubtotal - $discountAmount', rounding: roundConfig },
187
+ { id: 'taxableAmount', expression: '$afterDiscount', rounding: roundConfig },
188
+ { id: 'stateTax', expression: '$taxableAmount * $stateTaxRate', rounding: roundConfig },
189
+ { id: 'localTax', expression: '$taxableAmount * $localTaxRate', rounding: roundConfig },
190
+ { id: 'totalTax', expression: '$stateTax + $localTax', rounding: roundConfig },
191
+ { id: 'lineTotal', expression: '$afterDiscount + $totalTax', rounding: roundConfig },
192
+ // ... many more formulas in a real system
193
+ ];
194
+
195
+ const context: EvaluationContext = {
196
+ variables: {
197
+ basePrice: 99.99,
198
+ packageQty: 3,
199
+ qty: 7,
200
+ discountPct: 10,
201
+ stateTaxRate: 0.0625,
202
+ localTaxRate: 0.02,
203
+ },
204
+ };
205
+
206
+ const results = engine.evaluateAll(formulas, context);
207
+ expect(results.success).toBe(true);
208
+
209
+ // Every formula needs rounding: { mode: 'HALF_UP', precision: 2 }
210
+ // This is repetitive and easy to forget
211
+ expect(formulas.every(f => f.rounding !== undefined)).toBe(true);
212
+ });
213
+ });
214
+
215
+ describe('Default Rounding Configuration', () => {
216
+ it('should apply defaultRounding to all intermediate values when configured', () => {
217
+ const engineWithRounding = new FormulaEngine({
218
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
219
+ });
220
+
221
+ const formulas: FormulaDefinition[] = [
222
+ { id: '_discount1', expression: '127.5 * 0.15' },
223
+ { id: '_discountTotal', expression: '$_discount1' },
224
+ { id: 'totalHt', expression: '127.5 - $_discountTotal' },
225
+ ];
226
+
227
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} });
228
+
229
+ expect(results.success).toBe(true);
230
+ // All values should be rounded to 2 decimal places
231
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.13);
232
+ expect((results.results.get('_discountTotal')?.value as Decimal).toNumber()).toBe(19.13);
233
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.37);
234
+ });
235
+
236
+ it('should apply defaultRounding to tax calculations', () => {
237
+ const engineWithRounding = new FormulaEngine({
238
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
239
+ });
240
+
241
+ const formulas: FormulaDefinition[] = [
242
+ { id: 'line1_tax', expression: '30.99 * 0.0825' },
243
+ { id: 'line2_tax', expression: '39.69 * 0.0825' },
244
+ { id: 'totalTax', expression: '$line1_tax + $line2_tax' },
245
+ ];
246
+
247
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} });
248
+
249
+ expect(results.success).toBe(true);
250
+ expect((results.results.get('line1_tax')?.value as Decimal).toNumber()).toBe(2.56);
251
+ expect((results.results.get('line2_tax')?.value as Decimal).toNumber()).toBe(3.27);
252
+ expect((results.results.get('totalTax')?.value as Decimal).toNumber()).toBe(5.83);
253
+ });
254
+
255
+ it('should allow per-formula override of defaultRounding', () => {
256
+ const engineWithRounding = new FormulaEngine({
257
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
258
+ });
259
+
260
+ // Use 1/3 which is 0.3333... to clearly show precision difference
261
+ // At 4 decimals: 0.3333, at 2 decimals: 0.33
262
+ const formulas: FormulaDefinition[] = [
263
+ { id: 'rate', expression: '1 / 3', rounding: { mode: 'HALF_UP', precision: 4 } },
264
+ { id: 'amount', expression: '1000 * $rate' }, // Uses default 2 decimal rounding
265
+ ];
266
+
267
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} });
268
+
269
+ expect(results.success).toBe(true);
270
+ // Per-formula rounding to 4 decimals: 1/3 = 0.3333
271
+ expect((results.results.get('rate')?.value as Decimal).toNumber()).toBe(0.3333);
272
+ // amount = 1000 * 0.3333 = 333.3, rounded to 2 decimals = 333.30
273
+ // If default rounding was applied to rate (0.33), amount would be 330
274
+ expect((results.results.get('amount')?.value as Decimal).toNumber()).toBe(333.3);
275
+ });
276
+
277
+ it('should disable intermediate rounding with disableIntermediateRounding option', () => {
278
+ const engineWithRounding = new FormulaEngine({
279
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
280
+ });
281
+
282
+ const formulas: FormulaDefinition[] = [
283
+ { id: '_discount1', expression: '127.5 * 0.15' },
284
+ { id: '_discountTotal', expression: '$_discount1' },
285
+ { id: 'totalHt', expression: '127.5 - $_discountTotal' },
286
+ ];
287
+
288
+ // Disable intermediate rounding
289
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} }, {
290
+ disableIntermediateRounding: true
291
+ });
292
+
293
+ expect(results.success).toBe(true);
294
+ // Raw unrounded values should propagate (like the original behavior)
295
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.125);
296
+ expect((results.results.get('_discountTotal')?.value as Decimal).toNumber()).toBe(19.125);
297
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.375);
298
+ });
299
+
300
+ it('should still apply per-formula rounding when disableIntermediateRounding is true', () => {
301
+ const engineWithRounding = new FormulaEngine({
302
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
303
+ });
304
+
305
+ const formulas: FormulaDefinition[] = [
306
+ { id: '_discount1', expression: '127.5 * 0.15', rounding: { mode: 'HALF_UP', precision: 2 } },
307
+ { id: '_discountTotal', expression: '$_discount1' }, // No per-formula rounding
308
+ { id: 'totalHt', expression: '127.5 - $_discountTotal' },
309
+ ];
310
+
311
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} }, {
312
+ disableIntermediateRounding: true
313
+ });
314
+
315
+ expect(results.success).toBe(true);
316
+ // Per-formula rounding is still applied
317
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.13);
318
+ // But default rounding is disabled, so _discountTotal uses raw value from context
319
+ // which is the rounded 19.13 from the previous formula
320
+ expect((results.results.get('_discountTotal')?.value as Decimal).toNumber()).toBe(19.13);
321
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.37);
322
+ });
323
+
324
+ it('should not apply defaultRounding when mode is NONE', () => {
325
+ const engineWithNoneRounding = new FormulaEngine({
326
+ defaultRounding: { mode: 'NONE', precision: 2 }
327
+ });
328
+
329
+ const formulas: FormulaDefinition[] = [
330
+ { id: '_discount1', expression: '127.5 * 0.15' },
331
+ { id: 'totalHt', expression: '127.5 - $_discount1' },
332
+ ];
333
+
334
+ const results = engineWithNoneRounding.evaluateAll(formulas, { variables: {} });
335
+
336
+ expect(results.success).toBe(true);
337
+ // NONE mode should not round
338
+ expect((results.results.get('_discount1')?.value as Decimal).toNumber()).toBe(19.125);
339
+ expect((results.results.get('totalHt')?.value as Decimal).toNumber()).toBe(108.375);
340
+ });
341
+
342
+ it('should match sequential evaluation when defaultRounding is configured', () => {
343
+ const engineWithRounding = new FormulaEngine({
344
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
345
+ });
346
+
347
+ const basePrice = 127.5;
348
+ const discountRate = 0.15;
349
+
350
+ // Sequential evaluation with manual rounding
351
+ const discount1 = new Decimal(basePrice).times(discountRate).toDecimalPlaces(2, Decimal.ROUND_HALF_UP);
352
+ const discountTotal = discount1;
353
+ const totalHtSequential = new Decimal(basePrice).minus(discountTotal).toDecimalPlaces(2, Decimal.ROUND_HALF_UP).toNumber();
354
+
355
+ // Batch evaluation with defaultRounding
356
+ const formulas: FormulaDefinition[] = [
357
+ { id: '_discount1', expression: `${basePrice} * ${discountRate}` },
358
+ { id: '_discountTotal', expression: '$_discount1' },
359
+ { id: 'totalHt', expression: `${basePrice} - $_discountTotal` },
360
+ ];
361
+
362
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} });
363
+ const totalHtBatch = (results.results.get('totalHt')?.value as Decimal).toNumber();
364
+
365
+ // Sequential with rounding: 127.5 - 19.13 = 108.37
366
+ expect(totalHtSequential).toBe(108.37);
367
+
368
+ // Batch with defaultRounding should now match!
369
+ expect(totalHtBatch).toBe(108.37);
370
+ expect(totalHtSequential).toBe(totalHtBatch);
371
+ });
372
+
373
+ it('should handle complex financial chain with defaultRounding', () => {
374
+ const engineWithRounding = new FormulaEngine({
375
+ defaultRounding: { mode: 'HALF_UP', precision: 2 }
376
+ });
377
+
378
+ const formulas: FormulaDefinition[] = [
379
+ // Line item 1: quantity 3 at price 10.33
380
+ { id: 'line1_subtotal', expression: '3 * 10.33' },
381
+ { id: 'line1_tax', expression: '$line1_subtotal * 0.0825' },
382
+
383
+ // Line item 2: quantity 7 at price 5.67
384
+ { id: 'line2_subtotal', expression: '7 * 5.67' },
385
+ { id: 'line2_tax', expression: '$line2_subtotal * 0.0825' },
386
+
387
+ // Total tax uses rounded line item taxes
388
+ { id: 'totalTax', expression: '$line1_tax + $line2_tax' },
389
+
390
+ // Grand total
391
+ { id: 'grandTotal', expression: '$line1_subtotal + $line2_subtotal + $totalTax' },
392
+ ];
393
+
394
+ const results = engineWithRounding.evaluateAll(formulas, { variables: {} });
395
+
396
+ expect(results.success).toBe(true);
397
+
398
+ // All values properly rounded to 2 decimal places
399
+ expect((results.results.get('line1_subtotal')?.value as Decimal).toNumber()).toBe(30.99);
400
+ expect((results.results.get('line1_tax')?.value as Decimal).toNumber()).toBe(2.56);
401
+ expect((results.results.get('line2_subtotal')?.value as Decimal).toNumber()).toBe(39.69);
402
+ expect((results.results.get('line2_tax')?.value as Decimal).toNumber()).toBe(3.27);
403
+ expect((results.results.get('totalTax')?.value as Decimal).toNumber()).toBe(5.83);
404
+ expect((results.results.get('grandTotal')?.value as Decimal).toNumber()).toBe(76.51);
405
+ });
406
+ });
407
+
408
+ describe('Edge Cases', () => {
409
+ it('should handle rounding mode NONE correctly', () => {
410
+ const formulas: FormulaDefinition[] = [
411
+ { id: 'calc', expression: '1 / 3', rounding: { mode: 'NONE', precision: 2 } },
412
+ ];
413
+
414
+ const results = engine.evaluateAll(formulas, { variables: {} });
415
+
416
+ // NONE mode should not round
417
+ const value = (results.results.get('calc')?.value as Decimal).toString();
418
+ expect(value.length).toBeGreaterThan(5); // Not truncated to 2 decimals
419
+ });
420
+
421
+ it('should handle rounding with FLOOR mode', () => {
422
+ const formulas: FormulaDefinition[] = [
423
+ { id: 'calc', expression: '19.129', rounding: { mode: 'FLOOR', precision: 2 } },
424
+ ];
425
+
426
+ const results = engine.evaluateAll(formulas, { variables: {} });
427
+ expect((results.results.get('calc')?.value as Decimal).toNumber()).toBe(19.12);
428
+ });
429
+
430
+ it('should handle rounding with CEIL mode', () => {
431
+ const formulas: FormulaDefinition[] = [
432
+ { id: 'calc', expression: '19.121', rounding: { mode: 'CEIL', precision: 2 } },
433
+ ];
434
+
435
+ const results = engine.evaluateAll(formulas, { variables: {} });
436
+ expect((results.results.get('calc')?.value as Decimal).toNumber()).toBe(19.13);
437
+ });
438
+
439
+ it('should handle mixed rounding configurations in chain', () => {
440
+ const formulas: FormulaDefinition[] = [
441
+ { id: 'a', expression: '10.555', rounding: { mode: 'HALF_UP', precision: 2 } }, // 10.56
442
+ { id: 'b', expression: '$a * 2', rounding: { mode: 'FLOOR', precision: 1 } }, // 21.1 (floor of 21.12)
443
+ { id: 'c', expression: '$b + 0.99', rounding: { mode: 'CEIL', precision: 0 } }, // 23 (ceil of 22.09)
444
+ ];
445
+
446
+ const results = engine.evaluateAll(formulas, { variables: {} });
447
+
448
+ expect((results.results.get('a')?.value as Decimal).toNumber()).toBe(10.56);
449
+ expect((results.results.get('b')?.value as Decimal).toNumber()).toBe(21.1);
450
+ expect((results.results.get('c')?.value as Decimal).toNumber()).toBe(23);
451
+ });
452
+
453
+ it('should propagate rounded value even when dependent formula has no rounding', () => {
454
+ // If formula A has rounding, formula B that depends on A should see the rounded value
455
+ const formulas: FormulaDefinition[] = [
456
+ { id: 'a', expression: '19.125', rounding: { mode: 'HALF_UP', precision: 2 } },
457
+ { id: 'b', expression: '$a * 2' }, // No rounding on b, but should use rounded a
458
+ ];
459
+
460
+ const results = engine.evaluateAll(formulas, { variables: {} });
461
+
462
+ expect((results.results.get('a')?.value as Decimal).toNumber()).toBe(19.13);
463
+ // b should be 19.13 * 2 = 38.26, NOT 19.125 * 2 = 38.25
464
+ expect((results.results.get('b')?.value as Decimal).toNumber()).toBe(38.26);
465
+ });
466
+
467
+ it('should handle non-numeric results without rounding errors', () => {
468
+ const formulas: FormulaDefinition[] = [
469
+ { id: 'amount', expression: '19.125', rounding: { mode: 'HALF_UP', precision: 2 } },
470
+ { id: 'label', expression: '"Total: " + STRING($amount)' },
471
+ { id: 'isPositive', expression: '$amount > 0' },
472
+ ];
473
+
474
+ const results = engine.evaluateAll(formulas, { variables: {} });
475
+
476
+ expect(results.success).toBe(true);
477
+ expect((results.results.get('amount')?.value as Decimal).toNumber()).toBe(19.13);
478
+ expect(results.results.get('label')?.value).toBe('Total: 19.13');
479
+ expect(results.results.get('isPositive')?.value).toBe(true);
480
+ });
481
+ });
482
+
483
+ describe('Real-World Financial Scenarios', () => {
484
+ it('should calculate invoice with proper rounding for accounting', () => {
485
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
486
+
487
+ const formulas: FormulaDefinition[] = [
488
+ // Line items
489
+ { id: 'line1', expression: '$qty1 * $price1', rounding: roundConfig },
490
+ { id: 'line2', expression: '$qty2 * $price2', rounding: roundConfig },
491
+ { id: 'line3', expression: '$qty3 * $price3', rounding: roundConfig },
492
+
493
+ // Subtotal
494
+ { id: 'subtotal', expression: '$line1 + $line2 + $line3', rounding: roundConfig },
495
+
496
+ // Discount (percentage)
497
+ { id: 'discountAmount', expression: '$subtotal * $discountPct / 100', rounding: roundConfig },
498
+ { id: 'afterDiscount', expression: '$subtotal - $discountAmount', rounding: roundConfig },
499
+
500
+ // Tax calculations (separate state and local)
501
+ { id: 'stateTax', expression: '$afterDiscount * 0.0625', rounding: roundConfig },
502
+ { id: 'localTax', expression: '$afterDiscount * 0.0225', rounding: roundConfig },
503
+ { id: 'totalTax', expression: '$stateTax + $localTax', rounding: roundConfig },
504
+
505
+ // Final total
506
+ { id: 'grandTotal', expression: '$afterDiscount + $totalTax', rounding: roundConfig },
507
+ ];
508
+
509
+ const context: EvaluationContext = {
510
+ variables: {
511
+ qty1: 3, price1: 29.99, // 89.97
512
+ qty2: 2, price2: 49.95, // 99.90
513
+ qty3: 5, price3: 9.99, // 49.95
514
+ discountPct: 15, // 15% discount
515
+ },
516
+ };
517
+
518
+ const results = engine.evaluateAll(formulas, context);
519
+
520
+ expect(results.success).toBe(true);
521
+
522
+ // Verify each step is properly rounded
523
+ expect((results.results.get('line1')?.value as Decimal).toNumber()).toBe(89.97);
524
+ expect((results.results.get('line2')?.value as Decimal).toNumber()).toBe(99.90);
525
+ expect((results.results.get('line3')?.value as Decimal).toNumber()).toBe(49.95);
526
+ expect((results.results.get('subtotal')?.value as Decimal).toNumber()).toBe(239.82);
527
+ expect((results.results.get('discountAmount')?.value as Decimal).toNumber()).toBe(35.97); // 239.82 * 0.15 = 35.973 -> 35.97
528
+ expect((results.results.get('afterDiscount')?.value as Decimal).toNumber()).toBe(203.85);
529
+ expect((results.results.get('stateTax')?.value as Decimal).toNumber()).toBe(12.74); // 203.85 * 0.0625 = 12.740625 -> 12.74
530
+ expect((results.results.get('localTax')?.value as Decimal).toNumber()).toBe(4.59); // 203.85 * 0.0225 = 4.586625 -> 4.59
531
+ expect((results.results.get('totalTax')?.value as Decimal).toNumber()).toBe(17.33);
532
+ expect((results.results.get('grandTotal')?.value as Decimal).toNumber()).toBe(221.18);
533
+ });
534
+
535
+ it('should handle currency conversion with proper intermediate rounding', () => {
536
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
537
+
538
+ const formulas: FormulaDefinition[] = [
539
+ // Amount in USD
540
+ { id: 'usdAmount', expression: '$baseAmount * $usdRate', rounding: roundConfig },
541
+
542
+ // Convert USD to EUR (intermediate conversion)
543
+ { id: 'eurAmount', expression: '$usdAmount * $eurRate', rounding: roundConfig },
544
+
545
+ // Add VAT in EUR
546
+ { id: 'vatAmount', expression: '$eurAmount * 0.20', rounding: roundConfig },
547
+ { id: 'totalEur', expression: '$eurAmount + $vatAmount', rounding: roundConfig },
548
+ ];
549
+
550
+ const context: EvaluationContext = {
551
+ variables: {
552
+ baseAmount: 1000,
553
+ usdRate: 1.0, // 1:1 for simplicity
554
+ eurRate: 0.92, // USD to EUR
555
+ },
556
+ };
557
+
558
+ const results = engine.evaluateAll(formulas, context);
559
+
560
+ expect(results.success).toBe(true);
561
+ expect((results.results.get('usdAmount')?.value as Decimal).toNumber()).toBe(1000);
562
+ expect((results.results.get('eurAmount')?.value as Decimal).toNumber()).toBe(920);
563
+ expect((results.results.get('vatAmount')?.value as Decimal).toNumber()).toBe(184);
564
+ expect((results.results.get('totalEur')?.value as Decimal).toNumber()).toBe(1104);
565
+ });
566
+
567
+ it('should handle commission calculations with tiered rates', () => {
568
+ const roundConfig: RoundingConfig = { mode: 'HALF_UP', precision: 2 };
569
+
570
+ const formulas: FormulaDefinition[] = [
571
+ // Base commission
572
+ { id: 'baseCommission', expression: '$saleAmount * 0.05', rounding: roundConfig },
573
+
574
+ // Bonus for exceeding threshold
575
+ { id: 'bonusEligible', expression: '$saleAmount > 10000 ? ($saleAmount - 10000) * 0.02 : 0', rounding: roundConfig },
576
+
577
+ // Total commission
578
+ { id: 'totalCommission', expression: '$baseCommission + $bonusEligible', rounding: roundConfig },
579
+
580
+ // Tax withholding
581
+ { id: 'taxWithholding', expression: '$totalCommission * 0.22', rounding: roundConfig },
582
+
583
+ // Net payout
584
+ { id: 'netPayout', expression: '$totalCommission - $taxWithholding', rounding: roundConfig },
585
+ ];
586
+
587
+ const context: EvaluationContext = {
588
+ variables: {
589
+ saleAmount: 15750.50,
590
+ },
591
+ };
592
+
593
+ const results = engine.evaluateAll(formulas, context);
594
+
595
+ expect(results.success).toBe(true);
596
+ // 15750.50 * 0.05 = 787.525 -> 787.53
597
+ expect((results.results.get('baseCommission')?.value as Decimal).toNumber()).toBe(787.53);
598
+ // (15750.50 - 10000) * 0.02 = 115.01
599
+ expect((results.results.get('bonusEligible')?.value as Decimal).toNumber()).toBe(115.01);
600
+ // 787.53 + 115.01 = 902.54
601
+ expect((results.results.get('totalCommission')?.value as Decimal).toNumber()).toBe(902.54);
602
+ // 902.54 * 0.22 = 198.5588 -> 198.56
603
+ expect((results.results.get('taxWithholding')?.value as Decimal).toNumber()).toBe(198.56);
604
+ // 902.54 - 198.56 = 703.98
605
+ expect((results.results.get('netPayout')?.value as Decimal).toNumber()).toBe(703.98);
606
+ });
607
+ });
608
+ });
@@ -4,6 +4,7 @@ import {
4
4
  EvaluationContext,
5
5
  EvaluationResult,
6
6
  EvaluationResultSet,
7
+ EvaluateAllOptions,
7
8
  ValidationResult,
8
9
  FunctionDefinition,
9
10
  ASTNode,
@@ -182,10 +183,15 @@ export class FormulaEngine {
182
183
 
183
184
  /**
184
185
  * Evaluate all formulas in dependency order
186
+ *
187
+ * @param formulas - Array of formula definitions to evaluate
188
+ * @param context - Evaluation context with variables
189
+ * @param options - Optional configuration for batch evaluation
185
190
  */
186
191
  evaluateAll(
187
192
  formulas: FormulaDefinition[],
188
- context: EvaluationContext
193
+ context: EvaluationContext,
194
+ options?: EvaluateAllOptions
189
195
  ): EvaluationResultSet {
190
196
  const startTime = Date.now();
191
197
  const results = new Map<string, EvaluationResult>();
@@ -211,6 +217,12 @@ export class FormulaEngine {
211
217
  formulaMap.set(formula.id, formula);
212
218
  }
213
219
 
220
+ // Determine if intermediate rounding should be applied
221
+ const applyIntermediateRounding =
222
+ this.config.defaultRounding &&
223
+ this.config.defaultRounding.mode !== 'NONE' &&
224
+ !options?.disableIntermediateRounding;
225
+
214
226
  // Evaluate in order, merging results into context
215
227
  const workingContext: EvaluationContext = this.normalizeContext(context);
216
228
 
@@ -221,10 +233,16 @@ export class FormulaEngine {
221
233
  try {
222
234
  const result = this.evaluator.evaluate(formula.expression, workingContext);
223
235
 
224
- // Apply rounding if configured
236
+ // Apply rounding: per-formula config takes precedence, then defaultRounding
225
237
  let value = result.value;
226
- if (formula.rounding && this.isDecimal(value)) {
227
- value = this.applyRounding(value as Decimal, formula.rounding);
238
+ if (this.isDecimal(value)) {
239
+ if (formula.rounding) {
240
+ // Per-formula rounding always takes precedence
241
+ value = this.applyRounding(value as Decimal, formula.rounding);
242
+ } else if (applyIntermediateRounding) {
243
+ // Apply default rounding to intermediate values
244
+ value = this.applyRounding(value as Decimal, this.config.defaultRounding!);
245
+ }
228
246
  }
229
247
 
230
248
  // Handle errors based on formula config
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export {
19
19
  // Results
20
20
  EvaluationResult,
21
21
  EvaluationResultSet,
22
+ EvaluateAllOptions,
22
23
  ValidationResult,
23
24
  CacheStats,
24
25
 
package/src/types.ts CHANGED
@@ -264,6 +264,19 @@ export interface EvaluationResultSet {
264
264
  evaluationOrder: string[];
265
265
  }
266
266
 
267
+ // ============================================================================
268
+ // Batch Evaluation Options
269
+ // ============================================================================
270
+
271
+ export interface EvaluateAllOptions {
272
+ /**
273
+ * When true, disables automatic intermediate rounding even if defaultRounding
274
+ * is configured in the engine. Per-formula rounding configurations are still applied.
275
+ * @default false
276
+ */
277
+ disableIntermediateRounding?: boolean;
278
+ }
279
+
267
280
  // ============================================================================
268
281
  // Validation Result
269
282
  // ============================================================================