@the-trybe/formula-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +6 -0
- package/PRD_FORMULA_ENGINE.md +1863 -0
- package/README.md +382 -0
- package/dist/decimal-utils.d.ts +180 -0
- package/dist/decimal-utils.js +355 -0
- package/dist/dependency-extractor.d.ts +20 -0
- package/dist/dependency-extractor.js +103 -0
- package/dist/dependency-graph.d.ts +60 -0
- package/dist/dependency-graph.js +252 -0
- package/dist/errors.d.ts +161 -0
- package/dist/errors.js +260 -0
- package/dist/evaluator.d.ts +51 -0
- package/dist/evaluator.js +494 -0
- package/dist/formula-engine.d.ts +79 -0
- package/dist/formula-engine.js +355 -0
- package/dist/functions.d.ts +3 -0
- package/dist/functions.js +720 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +61 -0
- package/dist/lexer.d.ts +25 -0
- package/dist/lexer.js +357 -0
- package/dist/parser.d.ts +32 -0
- package/dist/parser.js +372 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.js +62 -0
- package/jest.config.js +23 -0
- package/package.json +35 -0
- package/src/decimal-utils.ts +408 -0
- package/src/dependency-extractor.ts +117 -0
- package/src/dependency-graph.test.ts +238 -0
- package/src/dependency-graph.ts +288 -0
- package/src/errors.ts +296 -0
- package/src/evaluator.ts +604 -0
- package/src/formula-engine.test.ts +660 -0
- package/src/formula-engine.ts +430 -0
- package/src/functions.ts +770 -0
- package/src/index.ts +103 -0
- package/src/lexer.test.ts +288 -0
- package/src/lexer.ts +394 -0
- package/src/parser.test.ts +349 -0
- package/src/parser.ts +449 -0
- package/src/types.ts +347 -0
- package/tsconfig.json +29 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DependencyGraphBuilder = exports.DependencyGraph = void 0;
|
|
4
|
+
const dependency_extractor_1 = require("./dependency-extractor");
|
|
5
|
+
const errors_1 = require("./errors");
|
|
6
|
+
class DependencyGraph {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.nodes = new Set();
|
|
9
|
+
this.edges = new Map();
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Add a node to the graph
|
|
13
|
+
*/
|
|
14
|
+
addNode(id) {
|
|
15
|
+
this.nodes.add(id);
|
|
16
|
+
if (!this.edges.has(id)) {
|
|
17
|
+
this.edges.set(id, new Set());
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add an edge from source to target (source depends on target)
|
|
22
|
+
*/
|
|
23
|
+
addEdge(source, target) {
|
|
24
|
+
this.addNode(source);
|
|
25
|
+
this.addNode(target);
|
|
26
|
+
this.edges.get(source).add(target);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Check if the graph has any cycles
|
|
30
|
+
*/
|
|
31
|
+
hasCycles() {
|
|
32
|
+
try {
|
|
33
|
+
this.topologicalSort();
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
return error instanceof errors_1.CircularDependencyError;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get all root nodes (nodes with no dependencies)
|
|
42
|
+
*/
|
|
43
|
+
getRoots() {
|
|
44
|
+
const roots = new Set();
|
|
45
|
+
for (const node of this.nodes) {
|
|
46
|
+
const deps = this.edges.get(node) || new Set();
|
|
47
|
+
if (deps.size === 0) {
|
|
48
|
+
roots.add(node);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return roots;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get all nodes that depend on the given node
|
|
55
|
+
*/
|
|
56
|
+
getDependents(nodeId) {
|
|
57
|
+
const dependents = new Set();
|
|
58
|
+
for (const [node, deps] of this.edges) {
|
|
59
|
+
if (deps.has(nodeId)) {
|
|
60
|
+
dependents.add(node);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return dependents;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get direct dependencies of a node
|
|
67
|
+
*/
|
|
68
|
+
getDependencies(nodeId) {
|
|
69
|
+
return this.edges.get(nodeId) || new Set();
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get all transitive dependencies of a node
|
|
73
|
+
*/
|
|
74
|
+
getTransitiveDependencies(nodeId) {
|
|
75
|
+
const visited = new Set();
|
|
76
|
+
const result = new Set();
|
|
77
|
+
this.collectTransitiveDependencies(nodeId, visited, result);
|
|
78
|
+
result.delete(nodeId); // Don't include the node itself
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
collectTransitiveDependencies(nodeId, visited, result) {
|
|
82
|
+
if (visited.has(nodeId)) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
visited.add(nodeId);
|
|
86
|
+
const deps = this.edges.get(nodeId);
|
|
87
|
+
if (deps) {
|
|
88
|
+
for (const dep of deps) {
|
|
89
|
+
result.add(dep);
|
|
90
|
+
this.collectTransitiveDependencies(dep, visited, result);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Perform topological sort using Kahn's algorithm
|
|
96
|
+
* Returns nodes in evaluation order (dependencies first)
|
|
97
|
+
* Throws CircularDependencyError if a cycle is detected
|
|
98
|
+
*/
|
|
99
|
+
topologicalSort() {
|
|
100
|
+
// Calculate in-degree for each node
|
|
101
|
+
const inDegree = new Map();
|
|
102
|
+
for (const node of this.nodes) {
|
|
103
|
+
inDegree.set(node, 0);
|
|
104
|
+
}
|
|
105
|
+
// Count incoming edges for each node
|
|
106
|
+
for (const [, deps] of this.edges) {
|
|
107
|
+
for (const dep of deps) {
|
|
108
|
+
if (this.nodes.has(dep)) {
|
|
109
|
+
// We need to count how many nodes depend on this one
|
|
110
|
+
// This is actually reverse - we need dependents, not dependencies
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Actually, we need to build a reverse graph for proper topological sort
|
|
115
|
+
// edges: node -> dependencies means we need to evaluate dependencies first
|
|
116
|
+
// So the "in-degree" should count how many times a node is depended upon
|
|
117
|
+
const dependents = new Map();
|
|
118
|
+
for (const node of this.nodes) {
|
|
119
|
+
dependents.set(node, new Set());
|
|
120
|
+
}
|
|
121
|
+
for (const [node, deps] of this.edges) {
|
|
122
|
+
for (const dep of deps) {
|
|
123
|
+
if (dependents.has(dep)) {
|
|
124
|
+
dependents.get(dep).add(node);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// Calculate in-degree (number of dependencies)
|
|
129
|
+
for (const [node, deps] of this.edges) {
|
|
130
|
+
// Only count dependencies that are actual nodes in our graph
|
|
131
|
+
const validDeps = [...deps].filter(d => this.nodes.has(d));
|
|
132
|
+
inDegree.set(node, validDeps.length);
|
|
133
|
+
}
|
|
134
|
+
// Start with nodes that have no dependencies
|
|
135
|
+
const queue = [];
|
|
136
|
+
for (const [node, degree] of inDegree) {
|
|
137
|
+
if (degree === 0) {
|
|
138
|
+
queue.push(node);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const result = [];
|
|
142
|
+
const visited = new Set();
|
|
143
|
+
while (queue.length > 0) {
|
|
144
|
+
const node = queue.shift();
|
|
145
|
+
if (visited.has(node))
|
|
146
|
+
continue;
|
|
147
|
+
visited.add(node);
|
|
148
|
+
result.push(node);
|
|
149
|
+
// For each node that depends on this one, decrease its in-degree
|
|
150
|
+
const deps = dependents.get(node) || new Set();
|
|
151
|
+
for (const dependent of deps) {
|
|
152
|
+
const newDegree = (inDegree.get(dependent) || 0) - 1;
|
|
153
|
+
inDegree.set(dependent, newDegree);
|
|
154
|
+
if (newDegree === 0 && !visited.has(dependent)) {
|
|
155
|
+
queue.push(dependent);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// Check if all nodes were visited
|
|
160
|
+
if (result.length !== this.nodes.size) {
|
|
161
|
+
// There's a cycle - find it
|
|
162
|
+
const cycle = this.findCycle();
|
|
163
|
+
throw new errors_1.CircularDependencyError(cycle, [...this.nodes].filter(n => !visited.has(n)));
|
|
164
|
+
}
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Find a cycle in the graph using DFS
|
|
169
|
+
*/
|
|
170
|
+
findCycle() {
|
|
171
|
+
const visited = new Set();
|
|
172
|
+
const recursionStack = new Set();
|
|
173
|
+
const path = [];
|
|
174
|
+
const dfs = (node) => {
|
|
175
|
+
visited.add(node);
|
|
176
|
+
recursionStack.add(node);
|
|
177
|
+
path.push(node);
|
|
178
|
+
const deps = this.edges.get(node) || new Set();
|
|
179
|
+
for (const dep of deps) {
|
|
180
|
+
if (!this.nodes.has(dep))
|
|
181
|
+
continue;
|
|
182
|
+
if (!visited.has(dep)) {
|
|
183
|
+
const cycle = dfs(dep);
|
|
184
|
+
if (cycle)
|
|
185
|
+
return cycle;
|
|
186
|
+
}
|
|
187
|
+
else if (recursionStack.has(dep)) {
|
|
188
|
+
// Found a cycle - extract it from the path
|
|
189
|
+
const cycleStart = path.indexOf(dep);
|
|
190
|
+
const cycle = path.slice(cycleStart);
|
|
191
|
+
cycle.push(dep); // Close the cycle
|
|
192
|
+
return cycle;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
path.pop();
|
|
196
|
+
recursionStack.delete(node);
|
|
197
|
+
return null;
|
|
198
|
+
};
|
|
199
|
+
for (const node of this.nodes) {
|
|
200
|
+
if (!visited.has(node)) {
|
|
201
|
+
const cycle = dfs(node);
|
|
202
|
+
if (cycle)
|
|
203
|
+
return cycle;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.DependencyGraph = DependencyGraph;
|
|
210
|
+
/**
|
|
211
|
+
* Build a dependency graph from formula definitions
|
|
212
|
+
*/
|
|
213
|
+
class DependencyGraphBuilder {
|
|
214
|
+
constructor() {
|
|
215
|
+
this.extractor = new dependency_extractor_1.DependencyExtractor();
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Build a dependency graph from formula definitions
|
|
219
|
+
*/
|
|
220
|
+
build(formulas) {
|
|
221
|
+
const graph = new DependencyGraph();
|
|
222
|
+
// Create a map of formula IDs for quick lookup
|
|
223
|
+
const formulaIds = new Set(formulas.map(f => f.id));
|
|
224
|
+
// Add all formula IDs as nodes
|
|
225
|
+
for (const formula of formulas) {
|
|
226
|
+
graph.addNode(formula.id);
|
|
227
|
+
}
|
|
228
|
+
// Extract dependencies and add edges
|
|
229
|
+
for (const formula of formulas) {
|
|
230
|
+
const deps = formula.dependencies
|
|
231
|
+
? new Set(formula.dependencies)
|
|
232
|
+
: this.extractor.extract(formula.expression);
|
|
233
|
+
for (const dep of deps) {
|
|
234
|
+
// Only add edges for dependencies that are other formulas
|
|
235
|
+
// (not external variables)
|
|
236
|
+
if (formulaIds.has(dep)) {
|
|
237
|
+
graph.addEdge(formula.id, dep);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return graph;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get the evaluation order for a set of formulas
|
|
245
|
+
*/
|
|
246
|
+
getEvaluationOrder(formulas) {
|
|
247
|
+
const graph = this.build(formulas);
|
|
248
|
+
return graph.topologicalSort();
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
exports.DependencyGraphBuilder = DependencyGraphBuilder;
|
|
252
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwZW5kZW5jeS1ncmFwaC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9kZXBlbmRlbmN5LWdyYXBoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLGlFQUE2RDtBQUM3RCxxQ0FBbUQ7QUFFbkQsTUFBYSxlQUFlO0lBSTFCO1FBQ0UsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQ7O09BRUc7SUFDSCxPQUFPLENBQUMsRUFBVTtRQUNoQixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNuQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUN4QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQ2hDLENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxPQUFPLENBQUMsTUFBYyxFQUFFLE1BQWM7UUFDcEMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JCLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTO1FBQ1AsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3ZCLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixPQUFPLEtBQUssWUFBWSxnQ0FBdUIsQ0FBQztRQUNsRCxDQUFDO0lBQ0gsQ0FBQztJ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QyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVwRCwrQkFBK0I7UUFDL0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUMvQixLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBRUQscUNBQXFDO1FBQ3JDLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxFQUFFLENBQUM7WUFDL0IsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFlBQVk7Z0JBQy9CLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDO2dCQUMvQixDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBRS9DLEtBQUssTUFBTSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7Z0JBQ3ZCLDBEQUEwRDtnQkFDMUQsMkJBQTJCO2dCQUMzQixJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztvQkFDeEIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNqQyxDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILGtCQUFrQixDQUFDLFFBQTZCO1FBQzlDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkMsT0FBTyxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7SUFDakMsQ0FBQztDQUNGO0FBOUNELHdEQThDQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERlcGVuZGVuY3lHcmFwaCBhcyBJRGVwZW5kZW5jeUdyYXBoLCBGb3JtdWxhRGVmaW5pdGlvbiB9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgRGVwZW5kZW5jeUV4dHJhY3RvciB9IGZyb20gJy4vZGVwZW5kZW5jeS1leHRyYWN0b3InO1xuaW1wb3J0IHsgQ2lyY3VsYXJEZXBlbmRlbmN5RXJyb3IgfSBmcm9tICcuL2Vycm9ycyc7XG5cbmV4cG9ydCBjbGFzcyBEZXBlbmRlbmN5R3JhcGggaW1wbGVtZW50cyBJRGVwZW5kZW5jeUdyYXBoIHtcbiAgbm9kZXM6IFNldDxzdHJpbmc+O1xuICBlZGdlczogTWFwPHN0cmluZywgU2V0PHN0cmluZz4+O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubm9kZXMgPSBuZXcgU2V0KCk7XG4gICAgdGhpcy5lZGdlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBub2RlIHRvIHRoZSBncmFwaFxuICAgKi9cbiAgYWRkTm9kZShpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5ub2Rlcy5hZGQoaWQpO1xuICAgIGlmICghdGhpcy5lZGdlcy5oYXMoaWQpKSB7XG4gICAgICB0aGlzLmVkZ2VzLnNldChpZCwgbmV3IFNldCgpKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkIGFuIGVkZ2UgZnJvbSBzb3VyY2UgdG8gdGFyZ2V0IChzb3VyY2UgZGVwZW5kcyBvbiB0YXJnZXQpXG4gICAqL1xuICBhZGRFZGdlKHNvdXJjZTogc3RyaW5nLCB0YXJnZXQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuYWRkTm9kZShzb3VyY2UpO1xuICAgIHRoaXMuYWRkTm9kZSh0YXJnZXQpO1xuICAgIHRoaXMuZWRnZXMuZ2V0KHNvdXJjZSkhLmFkZCh0YXJnZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSBncmFwaCBoYXMgYW55IGN5Y2xlc1xuICAgKi9cbiAgaGFzQ3ljbGVzKCk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLnRvcG9sb2dpY2FsU29ydCgpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBDaXJjdWxhckRlcGVuZGVuY3lFcnJvcjtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFsbCByb290IG5vZGVzIChub2RlcyB3aXRoIG5vIGRlcGVuZGVuY2llcylcbiAgICovXG4gIGdldFJvb3RzKCk6IFNldDxzdHJpbmc+IHtcbiAgICBjb25zdCByb290cyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLm5vZGVzKSB7XG4gICAgICBjb25zdCBkZXBzID0gdGhpcy5lZGdlcy5nZXQobm9kZSkgfHwgbmV3IFNldCgpO1xuICAgICAgaWYgKGRlcHMuc2l6ZSA9PT0gMCkge1xuICAgICAgICByb290cy5hZGQobm9kZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByb290cztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYWxsIG5vZGVzIHRoYXQgZGVwZW5kIG9uIHRoZSBnaXZlbiBub2RlXG4gICAqL1xuICBnZXREZXBlbmRlbnRzKG5vZGVJZDogc3RyaW5nKTogU2V0PHN0cmluZz4ge1xuICAgIGNvbnN0IGRlcGVuZGVudHMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBmb3IgKGNvbnN0IFtub2RlLCBkZXBzXSBvZiB0aGlzLmVkZ2VzKSB7XG4gICAgICBpZiAoZGVwcy5oYXMobm9kZUlkKSkge1xuICAgICAgICBkZXBlbmRlbnRzLmFkZChub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRlcGVuZGVudHM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGRpcmVjdCBkZXBlbmRlbmNpZXMgb2YgYSBub2RlXG4gICAqL1xuICBnZXREZXBlbmRlbmNpZXMobm9kZUlkOiBzdHJpbmcpOiBTZXQ8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHRoaXMuZWRnZXMuZ2V0KG5vZGVJZCkgfHwgbmV3IFNldCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbGwgdHJhbnNpdGl2ZSBkZXBlbmRlbmNpZXMgb2YgYSBub2RlXG4gICAqL1xuICBnZXRUcmFuc2l0aXZlRGVwZW5kZW5jaWVzKG5vZGVJZDogc3RyaW5nKTogU2V0PHN0cmluZz4ge1xuICAgIGNvbnN0IHZpc2l0ZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICB0aGlzLmNvbGxlY3RUcmFuc2l0aXZlRGVwZW5kZW5jaWVzKG5vZGVJZCwgdmlzaXRlZCwgcmVzdWx0KTtcbiAgICByZXN1bHQuZGVsZXRlKG5vZGVJZCk7IC8vIERvbid0IGluY2x1ZGUgdGhlIG5vZGUgaXRzZWxmXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByaXZhdGUgY29sbGVjdFRyYW5zaXRpdmVEZXBlbmRlbmNpZXMoXG4gICAgbm9kZUlkOiBzdHJpbmcsXG4gICAgdmlzaXRlZDogU2V0PHN0cmluZz4sXG4gICAgcmVzdWx0OiBTZXQ8c3RyaW5nPlxuICApOiB2b2lkIHtcbiAgICBpZiAodmlzaXRlZC5oYXMobm9kZUlkKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2aXNpdGVkLmFkZChub2RlSWQpO1xuXG4gICAgY29uc3QgZGVwcyA9IHRoaXMuZWRnZXMuZ2V0KG5vZGVJZCk7XG4gICAgaWYgKGRlcHMpIHtcbiAgICAgIGZvciAoY29uc3QgZGVwIG9mIGRlcHMpIHtcbiAgICAgICAgcmVzdWx0LmFkZChkZXApO1xuICAgICAgICB0aGlzLmNvbGxlY3RUcmFuc2l0aXZlRGVwZW5kZW5jaWVzKGRlcCwgdmlzaXRlZCwgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybSB0b3BvbG9naWNhbCBzb3J0IHVzaW5nIEthaG4ncyBhbGdvcml0aG1cbiAgICogUmV0dXJucyBub2RlcyBpbiBldmFsdWF0aW9uIG9yZGVyIChkZXBlbmRlbmNpZXMgZmlyc3QpXG4gICAqIFRocm93cyBDaXJjdWxhckRlcGVuZGVuY3lFcnJvciBpZiBhIGN5Y2xlIGlzIGRldGVjdGVkXG4gICAqL1xuICB0b3BvbG9naWNhbFNvcnQoKTogc3RyaW5nW10ge1xuICAgIC8vIENhbGN1bGF0ZSBpbi1kZWdyZWUgZm9yIGVhY2ggbm9kZVxuICAgIGNvbnN0IGluRGVncmVlID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5ub2Rlcykge1xuICAgICAgaW5EZWdyZWUuc2V0KG5vZGUsIDApO1xuICAgIH1cblxuICAgIC8vIENvdW50IGluY29taW5nIGVkZ2VzIGZvciBlYWNoIG5vZGVcbiAgICBmb3IgKGNvbnN0IFssIGRlcHNdIG9mIHRoaXMuZWRnZXMpIHtcbiAgICAgIGZvciAoY29uc3QgZGVwIG9mIGRlcHMpIHtcbiAgICAgICAgaWYgKHRoaXMubm9kZXMuaGFzKGRlcCkpIHtcbiAgICAgICAgICAvLyBXZSBuZWVkIHRvIGNvdW50IGhvdyBtYW55IG5vZGVzIGRlcGVuZCBvbiB0aGlzIG9uZVxuICAgICAgICAgIC8vIFRoaXMgaXMgYWN0dWFsbHkgcmV2ZXJzZSAtIHdlIG5lZWQgZGVwZW5kZW50cywgbm90IGRlcGVuZGVuY2llc1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWN0dWFsbHksIHdlIG5lZWQgdG8gYnVpbGQgYSByZXZlcnNlIGdyYXBoIGZvciBwcm9wZXIgdG9wb2xvZ2ljYWwgc29ydFxuICAgIC8vIGVkZ2VzOiBub2RlIC0+IGRlcGVuZGVuY2llcyBtZWFucyB3ZSBuZWVkIHRvIGV2YWx1YXRlIGRlcGVuZGVuY2llcyBmaXJzdFxuICAgIC8vIFNvIHRoZSBcImluLWRlZ3JlZVwiIHNob3VsZCBjb3VudCBob3cgbWFueSB0aW1lcyBhIG5vZGUgaXMgZGVwZW5kZWQgdXBvblxuXG4gICAgY29uc3QgZGVwZW5kZW50cyA9IG5ldyBNYXA8c3RyaW5nLCBTZXQ8c3RyaW5nPj4oKTtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5ub2Rlcykge1xuICAgICAgZGVwZW5kZW50cy5zZXQobm9kZSwgbmV3IFNldCgpKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtub2RlLCBkZXBzXSBvZiB0aGlzLmVkZ2VzKSB7XG4gICAgICBmb3IgKGNvbnN0IGRlcCBvZiBkZXBzKSB7XG4gICAgICAgIGlmIChkZXBlbmRlbnRzLmhhcyhkZXApKSB7XG4gICAgICAgICAgZGVwZW5kZW50cy5nZXQoZGVwKSEuYWRkKG5vZGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2FsY3VsYXRlIGluLWRlZ3JlZSAobnVtYmVyIG9mIGRlcGVuZGVuY2llcylcbiAgICBmb3IgKGNvbnN0IFtub2RlLCBkZXBzXSBvZiB0aGlzLmVkZ2VzKSB7XG4gICAgICAvLyBPbmx5IGNvdW50IGRlcGVuZGVuY2llcyB0aGF0IGFyZSBhY3R1YWwgbm9kZXMgaW4gb3VyIGdyYXBoXG4gICAgICBjb25zdCB2YWxpZERlcHMgPSBbLi4uZGVwc10uZmlsdGVyKGQgPT4gdGhpcy5ub2Rlcy5oYXMoZCkpO1xuICAgICAgaW5EZWdyZWUuc2V0KG5vZGUsIHZhbGlkRGVwcy5sZW5ndGgpO1xuICAgIH1cblxuICAgIC8vIFN0YXJ0IHdpdGggbm9kZXMgdGhhdCBoYXZlIG5vIGRlcGVuZGVuY2llc1xuICAgIGNvbnN0IHF1ZXVlOiBzdHJpbmdbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgW25vZGUsIGRlZ3JlZV0gb2YgaW5EZWdyZWUpIHtcbiAgICAgIGlmIChkZWdyZWUgPT09IDApIHtcbiAgICAgICAgcXVldWUucHVzaChub2RlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCByZXN1bHQ6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgdmlzaXRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gICAgd2hpbGUgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IG5vZGUgPSBxdWV1ZS5zaGlmdCgpITtcbiAgICAgIGlmICh2aXNpdGVkLmhhcyhub2RlKSkgY29udGludWU7XG5cbiAgICAgIHZpc2l0ZWQuYWRkKG5vZGUpO1xuICAgICAgcmVzdWx0LnB1c2gobm9kZSk7XG5cbiAgICAgIC8vIEZvciBlYWNoIG5vZGUgdGhhdCBkZXBlbmRzIG9uIHRoaXMgb25lLCBkZWNyZWFzZSBpdHMgaW4tZGVncmVlXG4gICAgICBjb25zdCBkZXBzID0gZGVwZW5kZW50cy5nZXQobm9kZSkgfHwgbmV3IFNldCgpO1xuICAgICAgZm9yIChjb25zdCBkZXBlbmRlbnQgb2YgZGVwcykge1xuICAgICAgICBjb25zdCBuZXdEZWdyZWUgPSAoaW5EZWdyZWUuZ2V0KGRlcGVuZGVudCkgfHwgMCkgLSAxO1xuICAgICAgICBpbkRlZ3JlZS5zZXQoZGVwZW5kZW50LCBuZXdEZWdyZWUpO1xuICAgICAgICBpZiAobmV3RGVncmVlID09PSAwICYmICF2aXNpdGVkLmhhcyhkZXBlbmRlbnQpKSB7XG4gICAgICAgICAgcXVldWUucHVzaChkZXBlbmRlbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgYWxsIG5vZGVzIHdlcmUgdmlzaXRlZFxuICAgIGlmIChyZXN1bHQubGVuZ3RoICE9PSB0aGlzLm5vZGVzLnNpemUpIHtcbiAgICAgIC8vIFRoZXJlJ3MgYSBjeWNsZSAtIGZpbmQgaXRcbiAgICAgIGNvbnN0IGN5Y2xlID0gdGhpcy5maW5kQ3ljbGUoKTtcbiAgICAgIHRocm93IG5ldyBDaXJjdWxhckRlcGVuZGVuY3lFcnJvcihjeWNsZSwgWy4uLnRoaXMubm9kZXNdLmZpbHRlcihuID0+ICF2aXNpdGVkLmhhcyhuKSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogRmluZCBhIGN5Y2xlIGluIHRoZSBncmFwaCB1c2luZyBERlNcbiAgICovXG4gIHByaXZhdGUgZmluZEN5Y2xlKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB2aXNpdGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgcmVjdXJzaW9uU3RhY2sgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICBjb25zdCBwYXRoOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgY29uc3QgZGZzID0gKG5vZGU6IHN0cmluZyk6IHN0cmluZ1tdIHwgbnVsbCA9PiB7XG4gICAgICB2aXNpdGVkLmFkZChub2RlKTtcbiAgICAgIHJlY3Vyc2lvblN0YWNrLmFkZChub2RlKTtcbiAgICAgIHBhdGgucHVzaChub2RlKTtcblxuICAgICAgY29uc3QgZGVwcyA9IHRoaXMuZWRnZXMuZ2V0KG5vZGUpIHx8IG5ldyBTZXQoKTtcbiAgICAgIGZvciAoY29uc3QgZGVwIG9mIGRlcHMpIHtcbiAgICAgICAgaWYgKCF0aGlzLm5vZGVzLmhhcyhkZXApKSBjb250aW51ZTtcblxuICAgICAgICBpZiAoIXZpc2l0ZWQuaGFzKGRlcCkpIHtcbiAgICAgICAgICBjb25zdCBjeWNsZSA9IGRmcyhkZXApO1xuICAgICAgICAgIGlmIChjeWNsZSkgcmV0dXJuIGN5Y2xlO1xuICAgICAgICB9IGVsc2UgaWYgKHJlY3Vyc2lvblN0YWNrLmhhcyhkZXApKSB7XG4gICAgICAgICAgLy8gRm91bmQgYSBjeWNsZSAtIGV4dHJhY3QgaXQgZnJvbSB0aGUgcGF0aFxuICAgICAgICAgIGNvbnN0IGN5Y2xlU3RhcnQgPSBwYXRoLmluZGV4T2YoZGVwKTtcbiAgICAgICAgICBjb25zdCBjeWNsZSA9IHBhdGguc2xpY2UoY3ljbGVTdGFydCk7XG4gICAgICAgICAgY3ljbGUucHVzaChkZXApOyAvLyBDbG9zZSB0aGUgY3ljbGVcbiAgICAgICAgICByZXR1cm4gY3ljbGU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcGF0aC5wb3AoKTtcbiAgICAgIHJlY3Vyc2lvblN0YWNrLmRlbGV0ZShub2RlKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5ub2Rlcykge1xuICAgICAgaWYgKCF2aXNpdGVkLmhhcyhub2RlKSkge1xuICAgICAgICBjb25zdCBjeWNsZSA9IGRmcyhub2RlKTtcbiAgICAgICAgaWYgKGN5Y2xlKSByZXR1cm4gY3ljbGU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG59XG5cbi8qKlxuICogQnVpbGQgYSBkZXBlbmRlbmN5IGdyYXBoIGZyb20gZm9ybXVsYSBkZWZpbml0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgRGVwZW5kZW5jeUdyYXBoQnVpbGRlciB7XG4gIHByaXZhdGUgZXh0cmFjdG9yOiBEZXBlbmRlbmN5RXh0cmFjdG9yO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuZXh0cmFjdG9yID0gbmV3IERlcGVuZGVuY3lFeHRyYWN0b3IoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIGRlcGVuZGVuY3kgZ3JhcGggZnJvbSBmb3JtdWxhIGRlZmluaXRpb25zXG4gICAqL1xuICBidWlsZChmb3JtdWxhczogRm9ybXVsYURlZmluaXRpb25bXSk6IERlcGVuZGVuY3lHcmFwaCB7XG4gICAgY29uc3QgZ3JhcGggPSBuZXcgRGVwZW5kZW5jeUdyYXBoKCk7XG5cbiAgICAvLyBDcmVhdGUgYSBtYXAgb2YgZm9ybXVsYSBJRHMgZm9yIHF1aWNrIGxvb2t1cFxuICAgIGNvbnN0IGZvcm11bGFJZHMgPSBuZXcgU2V0KGZvcm11bGFzLm1hcChmID0+IGYuaWQpKTtcblxuICAgIC8vIEFkZCBhbGwgZm9ybXVsYSBJRHMgYXMgbm9kZXNcbiAgICBmb3IgKGNvbnN0IGZvcm11bGEgb2YgZm9ybXVsYXMpIHtcbiAgICAgIGdyYXBoLmFkZE5vZGUoZm9ybXVsYS5pZCk7XG4gICAgfVxuXG4gICAgLy8gRXh0cmFjdCBkZXBlbmRlbmNpZXMgYW5kIGFkZCBlZGdlc1xuICAgIGZvciAoY29uc3QgZm9ybXVsYSBvZiBmb3JtdWxhcykge1xuICAgICAgY29uc3QgZGVwcyA9IGZvcm11bGEuZGVwZW5kZW5jaWVzXG4gICAgICAgID8gbmV3IFNldChmb3JtdWxhLmRlcGVuZGVuY2llcylcbiAgICAgICAgOiB0aGlzLmV4dHJhY3Rvci5leHRyYWN0KGZvcm11bGEuZXhwcmVzc2lvbik7XG5cbiAgICAgIGZvciAoY29uc3QgZGVwIG9mIGRlcHMpIHtcbiAgICAgICAgLy8gT25seSBhZGQgZWRnZXMgZm9yIGRlcGVuZGVuY2llcyB0aGF0IGFyZSBvdGhlciBmb3JtdWxhc1xuICAgICAgICAvLyAobm90IGV4dGVybmFsIHZhcmlhYmxlcylcbiAgICAgICAgaWYgKGZvcm11bGFJZHMuaGFzKGRlcCkpIHtcbiAgICAgICAgICBncmFwaC5hZGRFZGdlKGZvcm11bGEuaWQsIGRlcCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZ3JhcGg7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBldmFsdWF0aW9uIG9yZGVyIGZvciBhIHNldCBvZiBmb3JtdWxhc1xuICAgKi9cbiAgZ2V0RXZhbHVhdGlvbk9yZGVyKGZvcm11bGFzOiBGb3JtdWxhRGVmaW5pdGlvbltdKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGdyYXBoID0gdGhpcy5idWlsZChmb3JtdWxhcyk7XG4gICAgcmV0dXJuIGdyYXBoLnRvcG9sb2dpY2FsU29ydCgpO1xuICB9XG59XG4iXX0=
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { ValueType } from './types';
|
|
2
|
+
export type ErrorCategory = 'PARSE' | 'VALIDATION' | 'EVALUATION' | 'CONFIGURATION';
|
|
3
|
+
export declare abstract class FormulaEngineError extends Error {
|
|
4
|
+
abstract readonly code: string;
|
|
5
|
+
abstract readonly category: ErrorCategory;
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
export declare class SyntaxError extends FormulaEngineError {
|
|
9
|
+
position: number;
|
|
10
|
+
line: number;
|
|
11
|
+
column: number;
|
|
12
|
+
expression: string;
|
|
13
|
+
readonly code = "PARSE_SYNTAX_ERROR";
|
|
14
|
+
readonly category: ErrorCategory;
|
|
15
|
+
constructor(message: string, position: number, line: number, column: number, expression: string);
|
|
16
|
+
}
|
|
17
|
+
export declare class UnexpectedTokenError extends FormulaEngineError {
|
|
18
|
+
token: string;
|
|
19
|
+
expected: string[];
|
|
20
|
+
position: number;
|
|
21
|
+
readonly code = "PARSE_UNEXPECTED_TOKEN";
|
|
22
|
+
readonly category: ErrorCategory;
|
|
23
|
+
constructor(token: string, expected: string[], position: number);
|
|
24
|
+
}
|
|
25
|
+
export declare class UnterminatedStringError extends FormulaEngineError {
|
|
26
|
+
readonly code = "PARSE_UNTERMINATED_STRING";
|
|
27
|
+
readonly category: ErrorCategory;
|
|
28
|
+
constructor(position: number);
|
|
29
|
+
}
|
|
30
|
+
export declare class InvalidNumberError extends FormulaEngineError {
|
|
31
|
+
readonly code = "PARSE_INVALID_NUMBER";
|
|
32
|
+
readonly category: ErrorCategory;
|
|
33
|
+
constructor(value: string, position: number);
|
|
34
|
+
}
|
|
35
|
+
export declare class CircularDependencyError extends FormulaEngineError {
|
|
36
|
+
cycle: string[];
|
|
37
|
+
involvedFormulas: string[];
|
|
38
|
+
readonly code = "VALIDATION_CIRCULAR_DEPENDENCY";
|
|
39
|
+
readonly category: ErrorCategory;
|
|
40
|
+
constructor(cycle: string[], involvedFormulas: string[]);
|
|
41
|
+
}
|
|
42
|
+
export declare class UndefinedVariableError extends FormulaEngineError {
|
|
43
|
+
variableName: string;
|
|
44
|
+
expression: string;
|
|
45
|
+
readonly code = "VALIDATION_UNDEFINED_VARIABLE";
|
|
46
|
+
readonly category: ErrorCategory;
|
|
47
|
+
constructor(variableName: string, expression: string);
|
|
48
|
+
}
|
|
49
|
+
export declare class UndefinedFunctionError extends FormulaEngineError {
|
|
50
|
+
functionName: string;
|
|
51
|
+
readonly code = "VALIDATION_UNDEFINED_FUNCTION";
|
|
52
|
+
readonly category: ErrorCategory;
|
|
53
|
+
constructor(functionName: string);
|
|
54
|
+
}
|
|
55
|
+
export declare class DuplicateFormulaError extends FormulaEngineError {
|
|
56
|
+
formulaId: string;
|
|
57
|
+
readonly code = "VALIDATION_DUPLICATE_FORMULA";
|
|
58
|
+
readonly category: ErrorCategory;
|
|
59
|
+
constructor(formulaId: string);
|
|
60
|
+
}
|
|
61
|
+
export declare class DivisionByZeroError extends FormulaEngineError {
|
|
62
|
+
readonly code = "EVAL_DIVISION_BY_ZERO";
|
|
63
|
+
readonly category: ErrorCategory;
|
|
64
|
+
constructor();
|
|
65
|
+
}
|
|
66
|
+
export declare class TypeMismatchError extends FormulaEngineError {
|
|
67
|
+
expected: ValueType | ValueType[] | string;
|
|
68
|
+
actual: ValueType | string;
|
|
69
|
+
context: string;
|
|
70
|
+
readonly code = "EVAL_TYPE_MISMATCH";
|
|
71
|
+
readonly category: ErrorCategory;
|
|
72
|
+
constructor(expected: ValueType | ValueType[] | string, actual: ValueType | string, context: string);
|
|
73
|
+
}
|
|
74
|
+
export declare class ArgumentCountError extends FormulaEngineError {
|
|
75
|
+
functionName: string;
|
|
76
|
+
expected: {
|
|
77
|
+
min: number;
|
|
78
|
+
max: number;
|
|
79
|
+
};
|
|
80
|
+
actual: number;
|
|
81
|
+
readonly code = "EVAL_ARGUMENT_COUNT";
|
|
82
|
+
readonly category: ErrorCategory;
|
|
83
|
+
constructor(functionName: string, expected: {
|
|
84
|
+
min: number;
|
|
85
|
+
max: number;
|
|
86
|
+
}, actual: number);
|
|
87
|
+
}
|
|
88
|
+
export declare class InvalidOperationError extends FormulaEngineError {
|
|
89
|
+
operator: string;
|
|
90
|
+
operandTypes: string[];
|
|
91
|
+
readonly code = "EVAL_INVALID_OPERATION";
|
|
92
|
+
readonly category: ErrorCategory;
|
|
93
|
+
constructor(operator: string, operandTypes: string[]);
|
|
94
|
+
}
|
|
95
|
+
export declare class PropertyAccessError extends FormulaEngineError {
|
|
96
|
+
property: string;
|
|
97
|
+
objectType: string;
|
|
98
|
+
readonly code = "EVAL_PROPERTY_ACCESS";
|
|
99
|
+
readonly category: ErrorCategory;
|
|
100
|
+
constructor(property: string, objectType: string);
|
|
101
|
+
}
|
|
102
|
+
export declare class IndexAccessError extends FormulaEngineError {
|
|
103
|
+
index: unknown;
|
|
104
|
+
objectType: string;
|
|
105
|
+
readonly code = "EVAL_INDEX_ACCESS";
|
|
106
|
+
readonly category: ErrorCategory;
|
|
107
|
+
constructor(index: unknown, objectType: string);
|
|
108
|
+
}
|
|
109
|
+
export declare class DecimalError extends FormulaEngineError {
|
|
110
|
+
readonly code: string;
|
|
111
|
+
readonly category: ErrorCategory;
|
|
112
|
+
constructor(message: string);
|
|
113
|
+
}
|
|
114
|
+
export declare class DecimalOverflowError extends DecimalError {
|
|
115
|
+
value: string;
|
|
116
|
+
maxExponent: number;
|
|
117
|
+
readonly code: string;
|
|
118
|
+
constructor(value: string, maxExponent: number);
|
|
119
|
+
}
|
|
120
|
+
export declare class DecimalUnderflowError extends DecimalError {
|
|
121
|
+
value: string;
|
|
122
|
+
minExponent: number;
|
|
123
|
+
readonly code: string;
|
|
124
|
+
constructor(value: string, minExponent: number);
|
|
125
|
+
}
|
|
126
|
+
export declare class DecimalDivisionByZeroError extends DecimalError {
|
|
127
|
+
readonly code: string;
|
|
128
|
+
constructor();
|
|
129
|
+
}
|
|
130
|
+
export declare class InvalidDecimalError extends DecimalError {
|
|
131
|
+
input: string;
|
|
132
|
+
readonly code: string;
|
|
133
|
+
constructor(input: string);
|
|
134
|
+
}
|
|
135
|
+
export declare class ConfigurationError extends FormulaEngineError {
|
|
136
|
+
readonly code = "CONFIGURATION_ERROR";
|
|
137
|
+
readonly category: ErrorCategory;
|
|
138
|
+
constructor(message: string);
|
|
139
|
+
}
|
|
140
|
+
export declare class SecurityError extends FormulaEngineError {
|
|
141
|
+
readonly code: string;
|
|
142
|
+
readonly category: ErrorCategory;
|
|
143
|
+
constructor(message: string);
|
|
144
|
+
}
|
|
145
|
+
export declare class MaxIterationsError extends SecurityError {
|
|
146
|
+
readonly code: string;
|
|
147
|
+
constructor(limit: number);
|
|
148
|
+
}
|
|
149
|
+
export declare class MaxRecursionError extends SecurityError {
|
|
150
|
+
readonly code: string;
|
|
151
|
+
constructor(limit: number);
|
|
152
|
+
}
|
|
153
|
+
export declare class MaxExpressionLengthError extends SecurityError {
|
|
154
|
+
readonly code: string;
|
|
155
|
+
constructor(length: number, limit: number);
|
|
156
|
+
}
|
|
157
|
+
export declare class GeneralFormulaError extends FormulaEngineError {
|
|
158
|
+
readonly code: string;
|
|
159
|
+
readonly category: ErrorCategory;
|
|
160
|
+
constructor(message: string);
|
|
161
|
+
}
|