@worksheet-js/formula 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/LICENSE +44 -0
- package/README.md +87 -0
- package/dist/index.d.mts +320 -0
- package/dist/index.d.ts +320 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/package.json +36 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file types.ts
|
|
3
|
+
* @description Core type definitions and interfaces for the @worksheet-js/formula engine.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Interface provided to formula function implementations during evaluation.
|
|
7
|
+
* Allows functions to safely access spreadsheet data and metadata.
|
|
8
|
+
*/
|
|
9
|
+
interface EvalContext {
|
|
10
|
+
/**
|
|
11
|
+
* Retrieves the computed value of a cell.
|
|
12
|
+
* If the cell contains a formula, it will be evaluated recursively ($x,y$).
|
|
13
|
+
*/
|
|
14
|
+
getCell(x: number, y: number): unknown;
|
|
15
|
+
/**
|
|
16
|
+
* Optional method to fetch the value of a range cell without triggering a full evaluation loop.
|
|
17
|
+
* Useful for high-performance lookup and indexing operations.
|
|
18
|
+
*/
|
|
19
|
+
getRange?(x: number, y: number): unknown;
|
|
20
|
+
/** Zero-based column index of the cell currently being evaluated. */
|
|
21
|
+
currentX?: number;
|
|
22
|
+
/** Zero-based row index of the cell currently being evaluated. */
|
|
23
|
+
currentY?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Executes a formula function by its canonical uppercase name.
|
|
26
|
+
* Used primarily by lambda-style functions (e.g., MAP, REDUCE).
|
|
27
|
+
*/
|
|
28
|
+
call?(name: string, args: unknown[]): unknown;
|
|
29
|
+
/**
|
|
30
|
+
* Parses and evaluates a standalone formula fragment.
|
|
31
|
+
*/
|
|
32
|
+
evaluate?(formula: string): unknown;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Represents a reference to a single cell coordinate.
|
|
36
|
+
*/
|
|
37
|
+
interface CellRef {
|
|
38
|
+
type: 'cell';
|
|
39
|
+
/** Zero-based column index. */
|
|
40
|
+
x: number;
|
|
41
|
+
/** Zero-based row index. */
|
|
42
|
+
y: number;
|
|
43
|
+
/** Original address string as found in the formula (e.g., "$A$1"). */
|
|
44
|
+
addr: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Represents a reference to a rectangular range of cells.
|
|
48
|
+
*/
|
|
49
|
+
interface RangeRef {
|
|
50
|
+
type: 'range';
|
|
51
|
+
/** Top-left column index. */
|
|
52
|
+
x1: number;
|
|
53
|
+
/** Top-left row index. */
|
|
54
|
+
y1: number;
|
|
55
|
+
/** Bottom-right column index. */
|
|
56
|
+
x2: number;
|
|
57
|
+
/** Bottom-right row index. */
|
|
58
|
+
y2: number;
|
|
59
|
+
/** Original range address string (e.g., "A1:B3"). */
|
|
60
|
+
addr: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Union type covering all possible cell and range reference structures.
|
|
64
|
+
*/
|
|
65
|
+
type Ref = CellRef | RangeRef;
|
|
66
|
+
/**
|
|
67
|
+
* Interface provided to the formula engine by the host application.
|
|
68
|
+
*/
|
|
69
|
+
interface CellDataProvider {
|
|
70
|
+
/**
|
|
71
|
+
* Retrieves the raw string input of a cell.
|
|
72
|
+
* @param x - Zero-based column index.
|
|
73
|
+
* @param y - Zero-based row index.
|
|
74
|
+
*/
|
|
75
|
+
getRawValue(x: number, y: number): string;
|
|
76
|
+
/**
|
|
77
|
+
* Optional callback triggered when a cell's computed value changes.
|
|
78
|
+
* @param x - Zero-based column index.
|
|
79
|
+
* @param y - Zero-based row index.
|
|
80
|
+
* @param value - The new computed result.
|
|
81
|
+
*/
|
|
82
|
+
onComputed?(x: number, y: number, value: unknown): void;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Represents a spreadsheet formula error (e.g., #DIV/0!, #N/A).
|
|
86
|
+
*/
|
|
87
|
+
declare class FormulaError {
|
|
88
|
+
code: string;
|
|
89
|
+
constructor(code: string);
|
|
90
|
+
toString(): string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Type definition for a function implementation.
|
|
94
|
+
*/
|
|
95
|
+
type FunctionImpl = (args: unknown[], ctx: EvalContext) => unknown;
|
|
96
|
+
/**
|
|
97
|
+
* Supported function categories, aligned with Google Sheets and Excel standards.
|
|
98
|
+
*/
|
|
99
|
+
type FunctionCategory = 'Math' | 'Text' | 'Logical' | 'Lookup' | 'Date' | 'Info' | 'Statistical' | 'Engineering' | 'Financial' | 'Database' | 'Web' | 'Operator' | 'Array' | 'Google';
|
|
100
|
+
/**
|
|
101
|
+
* Metadata structure for a single spreadsheet function.
|
|
102
|
+
*/
|
|
103
|
+
interface FunctionMeta {
|
|
104
|
+
name: string;
|
|
105
|
+
category: FunctionCategory;
|
|
106
|
+
summary: string;
|
|
107
|
+
syntax: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* @file FormulaEngine.ts
|
|
112
|
+
* @description The core calculation engine for @worksheet-js/formula.
|
|
113
|
+
*
|
|
114
|
+
* Responsibilities:
|
|
115
|
+
* 1. AST Lifecycle: Parses formula strings into Abstract Syntax Trees (AST).
|
|
116
|
+
* 2. Evaluation: Recursively evaluates the AST against live spreadsheet data.
|
|
117
|
+
* 3. Reactive Dependency Tracking: Maintains a directed acyclic graph (DAG) of cell relationships.
|
|
118
|
+
* 4. Cache Management: Optimizes performance via result and AST memoization.
|
|
119
|
+
* 5. Re-calculation: Cascades invalidations through the dependency graph when cell data changes.
|
|
120
|
+
* 6. Error Handling: Detects circular references and parsing failures.
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The FormulaEngine orchestrates the parsing and evaluation of spreadsheet formulas.
|
|
125
|
+
*
|
|
126
|
+
* It manages an internal cache of computed results and parsed Abstract Syntax Trees (ASTs),
|
|
127
|
+
* as well as a dependency graph to enable efficient re-calculation when data changes.
|
|
128
|
+
*
|
|
129
|
+
* Supports standard arithmetic, ranges, and a comprehensive library of built-in functions.
|
|
130
|
+
*/
|
|
131
|
+
declare class FormulaEngine {
|
|
132
|
+
private provider;
|
|
133
|
+
/** Cache of computed results indexed by cell key. */
|
|
134
|
+
private cache;
|
|
135
|
+
/** Cache of parsed ASTs indexed by the raw formula string. */
|
|
136
|
+
private astCache;
|
|
137
|
+
/**
|
|
138
|
+
* Outbound dependencies: maps a cell key to a set of cells that depend on it.
|
|
139
|
+
* Example: if C1 has "=A1+B1", then dependents["A1"] contains "C1".
|
|
140
|
+
*/
|
|
141
|
+
private dependents;
|
|
142
|
+
/**
|
|
143
|
+
* Inbound dependencies: maps a cell key to a set of cells it references.
|
|
144
|
+
* Example: if C1 has "=A1+B1", then dependsOn["C1"] contains {"A1", "B1"}.
|
|
145
|
+
*/
|
|
146
|
+
private dependsOn;
|
|
147
|
+
/** Tracks cells currently in the evaluation stack to detect circular references. */
|
|
148
|
+
private evaluating;
|
|
149
|
+
/**
|
|
150
|
+
* Creates a new instance of the FormulaEngine.
|
|
151
|
+
* @param provider - An implementation of CellDataProvider.
|
|
152
|
+
*/
|
|
153
|
+
constructor(provider: CellDataProvider);
|
|
154
|
+
/**
|
|
155
|
+
* Computes the final value of a specific cell coordinate.
|
|
156
|
+
*
|
|
157
|
+
* If the cell contains a formula (starts with '='), it is parsed into an AST and evaluated.
|
|
158
|
+
* Results are cached until explicitly invalidated via the `invalidate` method.
|
|
159
|
+
* Any cell references within the formula will register a dependency relationship.
|
|
160
|
+
*
|
|
161
|
+
* @param x - Zero-based column index.
|
|
162
|
+
* @param y - Zero-based row index.
|
|
163
|
+
* @returns The evaluated result (number, string, boolean, or FormulaError).
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const val = engine.evaluate(0, 0); // Evaluates A1
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
evaluate(x: number, y: number): unknown;
|
|
171
|
+
/**
|
|
172
|
+
* Signals that a cell's raw input has changed.
|
|
173
|
+
* This invalidates the cell's cache and triggers a recursive invalidation of all dependents.
|
|
174
|
+
*
|
|
175
|
+
* @param x - Column index.
|
|
176
|
+
* @param y - Row index.
|
|
177
|
+
*
|
|
178
|
+
* @note Call this BEFORE updating the provider's raw value for the cell,
|
|
179
|
+
* or alternatively use `invalidateBatch` for bulk operations. The current
|
|
180
|
+
* raw value is read to locate and remove the old cached AST. After invalidation
|
|
181
|
+
* the engine will re-parse on next evaluate() call.
|
|
182
|
+
*/
|
|
183
|
+
invalidate(x: number, y: number): void;
|
|
184
|
+
/**
|
|
185
|
+
* Performs bulk invalidation for multiple cells.
|
|
186
|
+
* Prevents redundant re-calculations by processing the cascade in a single pass.
|
|
187
|
+
*
|
|
188
|
+
* @param coords - Array of cell coordinates.
|
|
189
|
+
*/
|
|
190
|
+
invalidateBatch(coords: Array<{
|
|
191
|
+
x: number;
|
|
192
|
+
y: number;
|
|
193
|
+
}>): void;
|
|
194
|
+
/**
|
|
195
|
+
* Clears all internal caches and dependency tracking.
|
|
196
|
+
* Use this for full sheet resets or large data imports.
|
|
197
|
+
*
|
|
198
|
+
* After calling this, all cells will be re-evaluated lazily on next access.
|
|
199
|
+
* Any previously registered dependency relationships are fully discarded.
|
|
200
|
+
*/
|
|
201
|
+
invalidateAll(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Returns a list of cell coordinates that depend on the value of the specified cell.
|
|
204
|
+
*/
|
|
205
|
+
getDependents(x: number, y: number): Array<[number, number]>;
|
|
206
|
+
/**
|
|
207
|
+
* Removes all trace of a cell from the engine (cache, AST, and dependencies).
|
|
208
|
+
*/
|
|
209
|
+
remove(x: number, y: number): void;
|
|
210
|
+
/** Registers a new dependency between two cells. */
|
|
211
|
+
private _addDep;
|
|
212
|
+
/** Clears all stored dependencies for a specific cell. */
|
|
213
|
+
private _clearDepsFor;
|
|
214
|
+
/**
|
|
215
|
+
* Cascades invalidation through the dependency graph using a Breadth-First Search (BFS).
|
|
216
|
+
* Re-evaluates all affected cells and notifies the host provider.
|
|
217
|
+
*/
|
|
218
|
+
private _invalidateCascade;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @file index.ts
|
|
223
|
+
* @description Central registry for all formula functions in Worksheet Systems.
|
|
224
|
+
*
|
|
225
|
+
* This module aggregates functions from all specialized modules (math, text, logic, etc.),
|
|
226
|
+
* defines their categories, and provides metadata required for the function
|
|
227
|
+
* insertion UI and documentation tooltips.
|
|
228
|
+
*/
|
|
229
|
+
|
|
230
|
+
/** Complete function registry keyed by uppercase name */
|
|
231
|
+
declare const FUNCTIONS: Record<string, FunctionImpl>;
|
|
232
|
+
/** Sorted list of all function names */
|
|
233
|
+
declare const FUNCTION_NAMES: string[];
|
|
234
|
+
/** All functions with category and description */
|
|
235
|
+
declare const FUNCTION_REGISTRY: FunctionMeta[];
|
|
236
|
+
/** Get functions by category */
|
|
237
|
+
declare function getFunctionsByCategory(category: FunctionCategory | 'All'): FunctionMeta[];
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Formulas available to 'starter' plan users.
|
|
241
|
+
* 'pro' and 'enterprise' plans have full access.
|
|
242
|
+
*/
|
|
243
|
+
declare const BASIC_FORMULAS: Set<string>;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* @file parser.ts
|
|
247
|
+
* @description A high-performance recursive descent parser for spreadsheet formulas.
|
|
248
|
+
*
|
|
249
|
+
* Employs a Pratt-style parsing strategy to handle operator precedence and associativity
|
|
250
|
+
* across complex mathematical and logical expressions.
|
|
251
|
+
*
|
|
252
|
+
* Grammar Overview:
|
|
253
|
+
* expr ::= comparison
|
|
254
|
+
* comparison ::= concat ( ('='|'<>'|'<'|'>'|'<='|'>=') concat )*
|
|
255
|
+
* concat ::= additive ( '&' additive )*
|
|
256
|
+
* additive ::= multiplicative ( ('+' | '-') multiplicative )*
|
|
257
|
+
* multiplicative ::= power ( ('*' | '/') power )*
|
|
258
|
+
* power ::= unary ( '^' unary )*
|
|
259
|
+
* unary ::= ('-' | '+') unary | primary '%' | primary
|
|
260
|
+
* primary ::= number | string | bool | error | ref | func | '(' expr ')' | '{' array '}'
|
|
261
|
+
*/
|
|
262
|
+
/**
|
|
263
|
+
* Represents a node in the Abstract Syntax Tree (AST).
|
|
264
|
+
*/
|
|
265
|
+
type AstNode = {
|
|
266
|
+
type: 'number';
|
|
267
|
+
value: number;
|
|
268
|
+
} | {
|
|
269
|
+
type: 'string';
|
|
270
|
+
value: string;
|
|
271
|
+
} | {
|
|
272
|
+
type: 'boolean';
|
|
273
|
+
value: boolean;
|
|
274
|
+
} | {
|
|
275
|
+
type: 'error';
|
|
276
|
+
code: string;
|
|
277
|
+
} | {
|
|
278
|
+
type: 'cell';
|
|
279
|
+
addr: string;
|
|
280
|
+
x: number;
|
|
281
|
+
y: number;
|
|
282
|
+
} | {
|
|
283
|
+
type: 'range';
|
|
284
|
+
addr: string;
|
|
285
|
+
x1: number;
|
|
286
|
+
y1: number;
|
|
287
|
+
x2: number;
|
|
288
|
+
y2: number;
|
|
289
|
+
} | {
|
|
290
|
+
type: 'unary';
|
|
291
|
+
op: string;
|
|
292
|
+
operand: AstNode;
|
|
293
|
+
} | {
|
|
294
|
+
type: 'binary';
|
|
295
|
+
op: string;
|
|
296
|
+
left: AstNode;
|
|
297
|
+
right: AstNode;
|
|
298
|
+
} | {
|
|
299
|
+
type: 'call';
|
|
300
|
+
name: string;
|
|
301
|
+
args: AstNode[];
|
|
302
|
+
} | {
|
|
303
|
+
type: 'array';
|
|
304
|
+
values: AstNode[][];
|
|
305
|
+
} | {
|
|
306
|
+
type: 'percent';
|
|
307
|
+
operand: AstNode;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Parses a spreadsheet formula string into an Abstract Syntax Tree (AST).
|
|
311
|
+
*
|
|
312
|
+
* Handles literal values, cell/range references, binary operators, and
|
|
313
|
+
* built-in function calls. Automatically strips the leading '=' if present.
|
|
314
|
+
*
|
|
315
|
+
* @param formula - The raw formula string.
|
|
316
|
+
* @returns The root node of the parsed AST.
|
|
317
|
+
*/
|
|
318
|
+
declare function parse(formula: string): AstNode;
|
|
319
|
+
|
|
320
|
+
export { type AstNode, BASIC_FORMULAS, type CellDataProvider, type CellRef, type EvalContext, FUNCTIONS, FUNCTION_NAMES, FUNCTION_REGISTRY, FormulaEngine, FormulaError, type FunctionCategory, type FunctionImpl, type FunctionMeta, type RangeRef, type Ref, getFunctionsByCategory, parse };
|