@ricsam/formula-engine 0.0.16 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/cjs/core/api/api-builder.cjs +67 -0
  2. package/dist/cjs/core/api/api-builder.cjs.map +10 -0
  3. package/dist/cjs/core/api/api-helpers.cjs +191 -0
  4. package/dist/cjs/core/api/api-helpers.cjs.map +10 -0
  5. package/dist/cjs/core/api/api.cjs +65 -0
  6. package/dist/cjs/core/api/api.cjs.map +10 -0
  7. package/dist/cjs/core/api/cell-orm.cjs +80 -0
  8. package/dist/cjs/core/api/cell-orm.cjs.map +10 -0
  9. package/dist/cjs/core/api/table-orm.cjs +171 -0
  10. package/dist/cjs/core/api/table-orm.cjs.map +10 -0
  11. package/dist/cjs/core/autofill-utils.cjs +75 -39
  12. package/dist/cjs/core/autofill-utils.cjs.map +3 -3
  13. package/dist/cjs/core/cell-mover.cjs +178 -0
  14. package/dist/cjs/core/cell-mover.cjs.map +10 -0
  15. package/dist/cjs/core/commands/command-executor.cjs +140 -0
  16. package/dist/cjs/core/commands/command-executor.cjs.map +10 -0
  17. package/dist/cjs/core/commands/content-commands.cjs +574 -0
  18. package/dist/cjs/core/commands/content-commands.cjs.map +10 -0
  19. package/dist/cjs/core/commands/index.cjs +95 -0
  20. package/dist/cjs/core/commands/index.cjs.map +10 -0
  21. package/dist/cjs/core/commands/metadata-commands.cjs +150 -0
  22. package/dist/cjs/core/commands/metadata-commands.cjs.map +10 -0
  23. package/dist/cjs/core/commands/named-expression-commands.cjs +238 -0
  24. package/dist/cjs/core/commands/named-expression-commands.cjs.map +10 -0
  25. package/dist/cjs/core/commands/structure-commands.cjs +495 -0
  26. package/dist/cjs/core/commands/structure-commands.cjs.map +10 -0
  27. package/dist/cjs/core/commands/style-commands.cjs +219 -0
  28. package/dist/cjs/core/commands/style-commands.cjs.map +10 -0
  29. package/dist/cjs/core/commands/table-commands.cjs +226 -0
  30. package/dist/cjs/core/commands/table-commands.cjs.map +10 -0
  31. package/dist/cjs/core/commands/types.cjs +72 -0
  32. package/dist/cjs/core/commands/types.cjs.map +10 -0
  33. package/dist/cjs/core/engine.cjs +218 -263
  34. package/dist/cjs/core/engine.cjs.map +3 -3
  35. package/dist/cjs/core/managers/api-schema-manager.cjs +304 -0
  36. package/dist/cjs/core/managers/api-schema-manager.cjs.map +10 -0
  37. package/dist/cjs/core/managers/copy-manager.cjs +336 -82
  38. package/dist/cjs/core/managers/copy-manager.cjs.map +3 -3
  39. package/dist/cjs/core/managers/reference-manager.cjs +124 -0
  40. package/dist/cjs/core/managers/reference-manager.cjs.map +10 -0
  41. package/dist/cjs/core/managers/style-manager.cjs +115 -147
  42. package/dist/cjs/core/managers/style-manager.cjs.map +3 -3
  43. package/dist/cjs/core/managers/workbook-manager.cjs +87 -3
  44. package/dist/cjs/core/managers/workbook-manager.cjs.map +3 -3
  45. package/dist/cjs/core/types.cjs.map +1 -1
  46. package/dist/cjs/lib.cjs +13 -2
  47. package/dist/cjs/lib.cjs.map +3 -3
  48. package/dist/cjs/package.json +1 -1
  49. package/dist/mjs/core/api/api-builder.mjs +37 -0
  50. package/dist/mjs/core/api/api-builder.mjs.map +10 -0
  51. package/dist/mjs/core/api/api-helpers.mjs +161 -0
  52. package/dist/mjs/core/api/api-helpers.mjs.map +10 -0
  53. package/dist/mjs/core/api/api.mjs +35 -0
  54. package/dist/mjs/core/api/api.mjs.map +10 -0
  55. package/dist/mjs/core/api/cell-orm.mjs +49 -0
  56. package/dist/mjs/core/api/cell-orm.mjs.map +10 -0
  57. package/dist/mjs/core/api/table-orm.mjs +148 -0
  58. package/dist/mjs/core/api/table-orm.mjs.map +10 -0
  59. package/dist/mjs/core/autofill-utils.mjs +75 -39
  60. package/dist/mjs/core/autofill-utils.mjs.map +3 -3
  61. package/dist/mjs/core/cell-mover.mjs +148 -0
  62. package/dist/mjs/core/cell-mover.mjs.map +10 -0
  63. package/dist/mjs/core/commands/command-executor.mjs +109 -0
  64. package/dist/mjs/core/commands/command-executor.mjs.map +10 -0
  65. package/dist/mjs/core/commands/content-commands.mjs +544 -0
  66. package/dist/mjs/core/commands/content-commands.mjs.map +10 -0
  67. package/dist/mjs/core/commands/index.mjs +87 -0
  68. package/dist/mjs/core/commands/index.mjs.map +10 -0
  69. package/dist/mjs/core/commands/metadata-commands.mjs +120 -0
  70. package/dist/mjs/core/commands/metadata-commands.mjs.map +10 -0
  71. package/dist/mjs/core/commands/named-expression-commands.mjs +208 -0
  72. package/dist/mjs/core/commands/named-expression-commands.mjs.map +10 -0
  73. package/dist/mjs/core/commands/structure-commands.mjs +465 -0
  74. package/dist/mjs/core/commands/structure-commands.mjs.map +10 -0
  75. package/dist/mjs/core/commands/style-commands.mjs +189 -0
  76. package/dist/mjs/core/commands/style-commands.mjs.map +10 -0
  77. package/dist/mjs/core/commands/table-commands.mjs +196 -0
  78. package/dist/mjs/core/commands/table-commands.mjs.map +10 -0
  79. package/dist/mjs/core/commands/types.mjs +42 -0
  80. package/dist/mjs/core/commands/types.mjs.map +10 -0
  81. package/dist/mjs/core/engine.mjs +253 -263
  82. package/dist/mjs/core/engine.mjs.map +3 -3
  83. package/dist/mjs/core/managers/api-schema-manager.mjs +274 -0
  84. package/dist/mjs/core/managers/api-schema-manager.mjs.map +10 -0
  85. package/dist/mjs/core/managers/copy-manager.mjs +338 -82
  86. package/dist/mjs/core/managers/copy-manager.mjs.map +3 -3
  87. package/dist/mjs/core/managers/reference-manager.mjs +93 -0
  88. package/dist/mjs/core/managers/reference-manager.mjs.map +10 -0
  89. package/dist/mjs/core/managers/style-manager.mjs +115 -147
  90. package/dist/mjs/core/managers/style-manager.mjs.map +3 -3
  91. package/dist/mjs/core/managers/workbook-manager.mjs +87 -3
  92. package/dist/mjs/core/managers/workbook-manager.mjs.map +3 -3
  93. package/dist/mjs/core/types.mjs.map +1 -1
  94. package/dist/mjs/lib.mjs +13 -2
  95. package/dist/mjs/lib.mjs.map +3 -3
  96. package/dist/mjs/package.json +1 -1
  97. package/dist/types/core/api/api-builder.d.ts +16 -0
  98. package/dist/types/core/api/api-helpers.d.ts +37 -0
  99. package/dist/types/core/api/api.d.ts +83 -0
  100. package/dist/types/core/api/api.type-test.d.ts +1 -0
  101. package/dist/types/core/api/cell-orm.d.ts +29 -0
  102. package/dist/types/core/api/table-orm.d.ts +46 -0
  103. package/dist/types/core/autofill-utils.d.ts +6 -9
  104. package/dist/types/core/cell-mover.d.ts +63 -0
  105. package/dist/types/core/commands/command-executor.d.ts +83 -0
  106. package/dist/types/core/commands/content-commands.d.ts +142 -0
  107. package/dist/types/core/commands/index.d.ts +16 -0
  108. package/dist/types/core/commands/metadata-commands.d.ts +55 -0
  109. package/dist/types/core/commands/named-expression-commands.d.ts +115 -0
  110. package/dist/types/core/commands/structure-commands.d.ts +132 -0
  111. package/dist/types/core/commands/style-commands.d.ts +76 -0
  112. package/dist/types/core/commands/table-commands.d.ts +104 -0
  113. package/dist/types/core/commands/types.d.ts +114 -0
  114. package/dist/types/core/engine.d.ts +241 -23
  115. package/dist/types/core/managers/api-schema-manager.d.ts +121 -0
  116. package/dist/types/core/managers/copy-manager.d.ts +47 -2
  117. package/dist/types/core/managers/reference-manager.d.ts +54 -0
  118. package/dist/types/core/managers/style-manager.d.ts +6 -6
  119. package/dist/types/core/managers/workbook-manager.d.ts +39 -1
  120. package/dist/types/core/types.d.ts +52 -11
  121. package/dist/types/lib.d.ts +8 -0
  122. package/package.json +1 -1
@@ -12,10 +12,21 @@ import { EventManager } from "./managers/event-manager";
12
12
  import { EvaluationManager } from "./managers/evaluation-manager";
13
13
  import { DependencyManager } from "./managers/dependency-manager";
14
14
  import { StyleManager } from "./managers/style-manager";
15
+ import type { Api, CreateApi, Declaration } from "./api/api";
16
+ import { type EngineAction } from "./commands";
17
+ type Metadata = {
18
+ cell?: unknown;
19
+ sheet?: unknown;
20
+ workbook?: unknown;
21
+ };
22
+ type MetadataType<TMetadata extends Metadata, TKey extends keyof Metadata> = TMetadata[TKey];
15
23
  /**
16
24
  * Main FormulaEngine class
25
+ * @template TCellMetadata - Consumer-defined type for cell metadata (rich text, links, custom data, etc.)
26
+ * @template TSheetMetadata - Consumer-defined type for sheet metadata (text boxes, frozen panes, etc.)
27
+ * @template TWorkbookMetadata - Consumer-defined type for workbook metadata (themes, document properties, etc.)
17
28
  */
18
- export declare class FormulaEngine {
29
+ export declare class FormulaEngine<TMetadata extends Metadata = Metadata, TCreateApi extends CreateApi<MetadataType<TMetadata, "cell">, Api, Declaration> | undefined = undefined> {
19
30
  private workbookManager;
20
31
  private namedExpressionManager;
21
32
  private tableManager;
@@ -25,6 +36,11 @@ export declare class FormulaEngine {
25
36
  private dependencyManager;
26
37
  private styleManager;
27
38
  private copyManager;
39
+ private referenceManager;
40
+ private apiSchemaManager;
41
+ private commandExecutor;
42
+ api: TCreateApi extends CreateApi<MetadataType<TMetadata, "cell">, Api, Declaration> ? TCreateApi["api"] : undefined;
43
+ private apiDeclaration;
28
44
  /**
29
45
  * Public access to the store manager for testing
30
46
  */
@@ -36,13 +52,77 @@ export declare class FormulaEngine {
36
52
  _autoFillManager: AutoFill;
37
53
  _dependencyManager: DependencyManager;
38
54
  _styleManager: StyleManager;
39
- constructor();
55
+ constructor(api?: TCreateApi);
40
56
  /**
41
57
  * Static factory method to build an empty engine
58
+ * @template TC - Consumer-defined cell metadata type
59
+ * @template TS - Consumer-defined sheet metadata type
60
+ * @template TW - Consumer-defined workbook metadata type
42
61
  */
43
- static buildEmpty(): FormulaEngine;
62
+ static buildEmpty<TMetadata extends Metadata = Metadata, TApiDeclaration extends CreateApi<MetadataType<TMetadata, "cell">, any, any> | undefined = undefined>(api?: TApiDeclaration): FormulaEngine<TMetadata, TApiDeclaration>;
44
63
  getCellEvaluationResult(cellAddress: CellAddress): SingleEvaluationResult | undefined;
45
64
  getCellValue(cellAddress: CellAddress, debug?: boolean): SerializedCellValue;
65
+ /**
66
+ * Set metadata for a cell
67
+ * Metadata can contain rich text, links, comments, or any consumer-defined data
68
+ */
69
+ setCellMetadata(address: CellAddress, metadata: MetadataType<TMetadata, "cell"> | undefined): void;
70
+ /**
71
+ * Get metadata for a cell
72
+ */
73
+ getCellMetadata(address: CellAddress): MetadataType<TMetadata, "cell"> | undefined;
74
+ /**
75
+ * Get all cell metadata for a sheet (serialized as Map)
76
+ */
77
+ getSheetMetadataSerialized(opts: {
78
+ sheetName: string;
79
+ workbookName: string;
80
+ }): Map<string, MetadataType<TMetadata, "sheet">>;
81
+ /**
82
+ * Set metadata for a sheet
83
+ * Sheet metadata can contain text boxes, frozen panes, print settings, or any consumer-defined data
84
+ */
85
+ setSheetMetadata(opts: {
86
+ workbookName: string;
87
+ sheetName: string;
88
+ }, metadata: MetadataType<TMetadata, "sheet">): void;
89
+ /**
90
+ * Get metadata for a sheet
91
+ */
92
+ getSheetMetadata(opts: {
93
+ workbookName: string;
94
+ sheetName: string;
95
+ }): MetadataType<TMetadata, "sheet"> | undefined;
96
+ /**
97
+ * Set metadata for a workbook
98
+ * Workbook metadata can contain themes, document properties, settings, or any consumer-defined data
99
+ */
100
+ setWorkbookMetadata(workbookName: string, metadata: MetadataType<TMetadata, "workbook">): void;
101
+ /**
102
+ * Get metadata for a workbook
103
+ */
104
+ getWorkbookMetadata(workbookName: string): MetadataType<TMetadata, "workbook"> | undefined;
105
+ /**
106
+ * Create a tracked reference to a range
107
+ * Returns a stable UUID that can be used to retrieve the address later
108
+ * The reference automatically updates when sheets/workbooks are renamed
109
+ */
110
+ createRef(address: RangeAddress): string;
111
+ /**
112
+ * Get the current address for a tracked reference
113
+ * Returns undefined if reference doesn't exist or has been invalidated
114
+ */
115
+ getRefAddress(refId: string): RangeAddress | undefined;
116
+ /**
117
+ * Delete a tracked reference
118
+ * Returns true if the reference was deleted, false if it didn't exist
119
+ */
120
+ deleteRef(refId: string): boolean;
121
+ /**
122
+ * Get all invalid reference IDs
123
+ * Useful for cleanup after sheet/workbook deletions
124
+ */
125
+ getInvalidRefs(): string[];
46
126
  evaluateFormula(
47
127
  /**
48
128
  * formula without the leading = sign
@@ -50,29 +130,37 @@ export declare class FormulaEngine {
50
130
  formula: string, cellAddress: CellAddress): SerializedCellValue;
51
131
  getCellDependents(address: CellAddress | SpreadsheetRange): (SpreadsheetRange | CellAddress)[];
52
132
  getCellPrecedents(address: CellAddress | SpreadsheetRange): (SpreadsheetRange | CellAddress)[];
53
- addNamedExpression({ expression, expressionName, sheetName, workbookName, }: {
133
+ addNamedExpression(opts: {
54
134
  expression: string;
55
135
  expressionName: string;
56
136
  sheetName?: string;
57
137
  workbookName?: string;
58
138
  }): void;
59
- removeNamedExpression({ expressionName, sheetName, workbookName, }: {
139
+ removeNamedExpression(opts: {
140
+ expressionName: string;
141
+ sheetName?: string;
142
+ workbookName?: string;
143
+ }): void;
144
+ /**
145
+ * Check if a named expression exists
146
+ */
147
+ hasNamedExpression(opts: {
60
148
  expressionName: string;
61
149
  sheetName?: string;
62
150
  workbookName?: string;
63
151
  }): boolean;
64
- updateNamedExpression({ expression, expressionName, sheetName, workbookName, }: {
152
+ updateNamedExpression(opts: {
65
153
  expression: string;
66
154
  expressionName: string;
67
155
  sheetName?: string;
68
156
  workbookName?: string;
69
157
  }): void;
70
- renameNamedExpression({ expressionName, sheetName, workbookName, newName, }: {
158
+ renameNamedExpression(opts: {
71
159
  expressionName: string;
72
160
  sheetName?: string;
73
161
  workbookName?: string;
74
162
  newName: string;
75
- }): boolean;
163
+ }): void;
76
164
  setNamedExpressions(opts: ({
77
165
  type: "global";
78
166
  } | {
@@ -92,7 +180,7 @@ export declare class FormulaEngine {
92
180
  start: string;
93
181
  numRows: SpreadsheetRangeEnd;
94
182
  numCols: number;
95
- }): TableDefinition;
183
+ }): void;
96
184
  renameTable(workbookName: string, names: {
97
185
  oldName: string;
98
186
  newName: string;
@@ -108,10 +196,29 @@ export declare class FormulaEngine {
108
196
  removeTable(opts: {
109
197
  tableName: string;
110
198
  workbookName: string;
199
+ }): void;
200
+ /**
201
+ * Check if a table exists
202
+ */
203
+ hasTable(opts: {
204
+ tableName: string;
205
+ workbookName: string;
111
206
  }): boolean;
207
+ /**
208
+ * Get a table definition by name
209
+ */
210
+ getTable(opts: {
211
+ tableName: string;
212
+ workbookName: string;
213
+ }): TableDefinition | undefined;
112
214
  resetTables(tables: Map<string, Map<string, TableDefinition>>): void;
113
215
  getTables(workbookName: string): Map<string, TableDefinition>;
114
216
  isCellInTable(cellAddress: CellAddress): TableDefinition | undefined;
217
+ /**
218
+ * Get all data cells in a table (excluding header row).
219
+ * Uses workbook indexes to efficiently handle infinite tables.
220
+ */
221
+ private getTableDataCells;
115
222
  /**
116
223
  * Add a conditional style rule
117
224
  */
@@ -119,7 +226,11 @@ export declare class FormulaEngine {
119
226
  /**
120
227
  * Remove a conditional style rule by index
121
228
  */
122
- removeConditionalStyle(workbookName: string, index: number): boolean;
229
+ removeConditionalStyle(workbookName: string, index: number): void;
230
+ /**
231
+ * Get the count of conditional styles for a workbook
232
+ */
233
+ getConditionalStyleCount(workbookName: string): number;
123
234
  /**
124
235
  * Get all conditional styles intersecting with a range
125
236
  */
@@ -128,6 +239,14 @@ export declare class FormulaEngine {
128
239
  * Get the computed style for a specific cell
129
240
  */
130
241
  getCellStyle(cellAddress: CellAddress): CellStyle | undefined;
242
+ /**
243
+ * Get all cell styles (for testing and serialization)
244
+ */
245
+ getAllCellStyles(): DirectCellStyle[];
246
+ /**
247
+ * Get all conditional styles (for testing and serialization)
248
+ */
249
+ getAllConditionalStyles(): ConditionalStyle[];
131
250
  /**
132
251
  * Add a direct cell style rule
133
252
  */
@@ -135,7 +254,11 @@ export declare class FormulaEngine {
135
254
  /**
136
255
  * Remove a direct cell style rule by index
137
256
  */
138
- removeCellStyle(workbookName: string, index: number): boolean;
257
+ removeCellStyle(workbookName: string, index: number): void;
258
+ /**
259
+ * Get the count of direct cell styles for a workbook
260
+ */
261
+ getCellStyleCount(workbookName: string): number;
139
262
  /**
140
263
  * Get all direct cell styles intersecting with a range
141
264
  */
@@ -221,53 +344,100 @@ export declare class FormulaEngine {
221
344
  * Get bounds (min/max row/col) from an array of cell addresses
222
345
  */
223
346
  private getBoundsFromCells;
347
+ /**
348
+ * Move a single cell to a new location
349
+ * Updates all formula references that point to the moved cell
350
+ *
351
+ * @param source - The cell to move
352
+ * @param target - The destination cell address
353
+ *
354
+ * @example
355
+ * // Move A1 to D5. If B1 contains =A1, it will be updated to =D5
356
+ * engine.moveCell(
357
+ * { workbookName, sheetName, colIndex: 0, rowIndex: 0 },
358
+ * { workbookName, sheetName, colIndex: 3, rowIndex: 4 }
359
+ * );
360
+ */
361
+ moveCell(source: CellAddress, target: CellAddress): void;
362
+ /**
363
+ * Move a range of cells to a new location
364
+ * Updates all formula references that point to the moved cells
365
+ *
366
+ * @param sourceRange - The range to move
367
+ * @param target - The top-left destination cell address
368
+ *
369
+ * @example
370
+ * // Move A1:D5 to F10. If E1 contains =SUM(A1:D5), it will be updated to =SUM(F10:I14)
371
+ * engine.moveRange(
372
+ * {
373
+ * workbookName,
374
+ * sheetName,
375
+ * range: {
376
+ * start: { col: 0, row: 0 },
377
+ * end: { col: { type: "number", value: 3 }, row: { type: "number", value: 4 } }
378
+ * }
379
+ * },
380
+ * { workbookName, sheetName, colIndex: 5, rowIndex: 9 }
381
+ * );
382
+ */
383
+ moveRange(sourceRange: RangeAddress, target: CellAddress): void;
224
384
  addSheet(opts: {
225
385
  workbookName: string;
226
386
  sheetName: string;
227
- }): import("./types").Sheet;
387
+ }): void;
228
388
  removeSheet(opts: {
229
389
  workbookName: string;
230
390
  sheetName: string;
231
- }): import("./types").Sheet;
391
+ }): void;
232
392
  renameSheet(opts: {
233
393
  sheetName: string;
234
394
  newSheetName: string;
235
395
  workbookName: string;
236
- }): import("./types").Sheet;
237
- getSheets(workbookName: string): Map<string, import("./types").Sheet>;
396
+ }): void;
397
+ /**
398
+ * Check if a sheet exists
399
+ */
400
+ hasSheet(opts: {
401
+ workbookName: string;
402
+ sheetName: string;
403
+ }): boolean;
404
+ getSheets(workbookName: string): Map<string, import("./types").Sheet<unknown, unknown>>;
238
405
  getSheet({ workbookName, sheetName, }: {
239
406
  workbookName: string;
240
407
  sheetName: string;
241
- }): import("./types").Sheet | undefined;
408
+ }): import("./types").Sheet<unknown, unknown> | undefined;
242
409
  getSheetSerialized(opts: {
243
410
  sheetName: string;
244
411
  workbookName: string;
245
412
  }): Map<string, SerializedCellValue>;
246
413
  addWorkbook(workbookName: string): void;
247
414
  removeWorkbook(workbookName: string): void;
415
+ /**
416
+ * Check if a workbook exists
417
+ */
418
+ hasWorkbook(workbookName: string): boolean;
248
419
  cloneWorkbook(fromWorkbookName: string, toWorkbookName: string): void;
249
420
  renameWorkbook(opts: {
250
421
  workbookName: string;
251
422
  newWorkbookName: string;
252
423
  }): void;
253
- getWorkbooks(): Map<string, import("./types").Workbook>;
424
+ getWorkbooks(): Map<string, import("./types").Workbook<unknown, unknown, unknown>>;
254
425
  /**
255
426
  * Overrides the content of a sheet.
256
427
  * @param sheetName - The name of the sheet to set the content of
257
428
  * @param content - A map of cell addresses to their serialized values
258
429
  * @remarks This method is used to set the content of a sheet. It will re-evaluate all sheets to ensure all dependencies are resolved correctly.
430
+ * @throws SchemaIntegrityError if any evaluated cell value violates a schema constraint
259
431
  */
260
432
  setSheetContent(opts: {
261
433
  sheetName: string;
262
434
  workbookName: string;
263
435
  }, content: Map<string, SerializedCellValue>): void;
264
- setCellContent(address: CellAddress, content: SerializedCellValue): void;
265
436
  /**
266
- * Re-evaluates all sheets to ensure all dependencies are resolved correctly
267
- *
268
- * but just clears the evaluation cache
437
+ * Set the content of a single cell.
438
+ * @throws SchemaIntegrityError if the evaluated value violates a schema constraint
269
439
  */
270
- reevaluate(): void;
440
+ setCellContent(address: CellAddress, content: SerializedCellValue): void;
271
441
  /**
272
442
  * Auto-fills one or more ranges based on the seedRange and the direction.
273
443
  * Supports pattern detection and style copying.
@@ -293,7 +463,7 @@ export declare class FormulaEngine {
293
463
  */
294
464
  clearSpreadsheetRange(address: RangeAddress): void;
295
465
  getState(): {
296
- workbooks: Map<string, import("./types").Workbook>;
466
+ workbooks: Map<string, import("./types").Workbook<unknown, unknown, unknown>>;
297
467
  namedExpressions: {
298
468
  sheetExpressions: Map<string, Map<string, Map<string, NamedExpression>>>;
299
469
  workbookExpressions: Map<string, Map<string, NamedExpression>>;
@@ -302,8 +472,56 @@ export declare class FormulaEngine {
302
472
  tables: Map<string, Map<string, TableDefinition>>;
303
473
  conditionalStyles: ConditionalStyle[];
304
474
  cellStyles: DirectCellStyle[];
475
+ references: Map<string, import("./types").TrackedReference>;
305
476
  };
306
477
  onUpdate(listener: () => void): () => void;
307
478
  serializeEngine(): string;
308
479
  resetToSerializedEngine(data: string): void;
480
+ /**
481
+ * Undo the last command.
482
+ * @returns true if undo was performed, false if nothing to undo
483
+ */
484
+ undo(): boolean;
485
+ /**
486
+ * Redo the last undone command.
487
+ * @returns true if redo was performed, false if nothing to redo
488
+ */
489
+ redo(): boolean;
490
+ /**
491
+ * Check if undo is available.
492
+ */
493
+ canUndo(): boolean;
494
+ /**
495
+ * Check if redo is available.
496
+ */
497
+ canRedo(): boolean;
498
+ /**
499
+ * Get the action log for persistence/collaboration.
500
+ * Actions can be serialized and replayed to reconstruct state.
501
+ */
502
+ getActionLog(): EngineAction[];
503
+ /**
504
+ * Clear the action log.
505
+ */
506
+ clearActionLog(): void;
507
+ /**
508
+ * Clear undo/redo history.
509
+ */
510
+ clearHistory(): void;
511
+ /**
512
+ * Get dependencies for structure commands.
513
+ * @internal
514
+ */
515
+ private getStructureCommandDeps;
516
+ /**
517
+ * Get dependencies for table commands.
518
+ * @internal
519
+ */
520
+ private getTableCommandDeps;
521
+ /**
522
+ * Get dependencies for named expression commands.
523
+ * @internal
524
+ */
525
+ private getNamedExpressionCommandDeps;
309
526
  }
527
+ export {};
@@ -0,0 +1,121 @@
1
+ /**
2
+ * ApiSchemaManager - Manages API schema definitions and validation
3
+ *
4
+ * Tracks registered schemas and provides validation for cell writes,
5
+ * spill operations, and copy/paste operations.
6
+ */
7
+ import type { CellAddress, SerializedCellValue, SpreadsheetRange, TableDefinition } from "../types";
8
+ import type { TableManager } from "./table-manager";
9
+ export type ParseFunction<TCellMetadata = unknown> = (value: unknown, metadata: TCellMetadata) => unknown;
10
+ export type TableSchemaHeaders<TCellMetadata = unknown> = Record<string, {
11
+ parse: ParseFunction<TCellMetadata>;
12
+ index: number;
13
+ }>;
14
+ export interface RegisteredTableSchema {
15
+ type: "table";
16
+ namespace: string;
17
+ workbookName: string;
18
+ tableName: string;
19
+ headers: TableSchemaHeaders;
20
+ }
21
+ export interface RegisteredCellSchema {
22
+ type: "cell";
23
+ namespace: string;
24
+ cellAddress: CellAddress;
25
+ parse: ParseFunction;
26
+ }
27
+ export type RegisteredSchema = RegisteredTableSchema | RegisteredCellSchema;
28
+ export interface ValidationResult {
29
+ valid: boolean;
30
+ error?: string;
31
+ originalError?: Error;
32
+ }
33
+ export declare class SchemaValidationError extends Error {
34
+ cellAddress?: CellAddress | undefined;
35
+ originalError?: Error | undefined;
36
+ constructor(message: string, cellAddress?: CellAddress | undefined, originalError?: Error | undefined);
37
+ }
38
+ export declare class ApiSchemaManager {
39
+ private tableManager;
40
+ private schemas;
41
+ constructor(tableManager: TableManager);
42
+ /**
43
+ * Register a table schema
44
+ */
45
+ registerTableSchema(namespace: string, workbookName: string, tableName: string, headers: TableSchemaHeaders): void;
46
+ /**
47
+ * Register a cell schema
48
+ */
49
+ registerCellSchema(namespace: string, cellAddress: CellAddress, parse: ParseFunction): void;
50
+ /**
51
+ * Get a schema by namespace
52
+ */
53
+ getSchema(namespace: string): RegisteredSchema | undefined;
54
+ /**
55
+ * Remove a schema
56
+ */
57
+ removeSchema(namespace: string): boolean;
58
+ /**
59
+ * Check if a cell is protected by a schema
60
+ * Returns the schema info if protected, null otherwise
61
+ */
62
+ isCellProtected(cell: CellAddress): {
63
+ schema: RegisteredSchema;
64
+ columnName?: string;
65
+ } | null;
66
+ /**
67
+ * Check if a cell is within a table's data range (excluding header row)
68
+ */
69
+ private isCellInTableDataRange;
70
+ /**
71
+ * Get column name by index from headers
72
+ */
73
+ private getColumnNameByIndex;
74
+ /**
75
+ * Validate a cell write against schemas
76
+ */
77
+ validateCellWrite(cell: CellAddress, value: SerializedCellValue, metadata?: unknown): ValidationResult;
78
+ /**
79
+ * Validate a spill area against schemas
80
+ * Returns validation result - if invalid, spill should produce #SPILL! error
81
+ */
82
+ validateSpillArea(origin: CellAddress, spillArea: SpreadsheetRange, getSpillValue: (row: number, col: number) => SerializedCellValue, getMetadata?: (cell: CellAddress) => unknown): ValidationResult;
83
+ /**
84
+ * Update schemas when a table is renamed
85
+ */
86
+ updateForTableRename(workbookName: string, oldTableName: string, newTableName: string): void;
87
+ /**
88
+ * Update schemas when a sheet is renamed
89
+ */
90
+ updateForSheetRename(workbookName: string, oldSheetName: string, newSheetName: string): void;
91
+ /**
92
+ * Update schemas when a workbook is renamed
93
+ */
94
+ updateForWorkbookRename(oldWorkbookName: string, newWorkbookName: string): void;
95
+ /**
96
+ * Get all schemas (for debugging/testing)
97
+ */
98
+ getAllSchemas(): Map<string, RegisteredSchema>;
99
+ /**
100
+ * Validate all schema constraints using evaluated cell values.
101
+ *
102
+ * This is the key method for schema validation with rollback:
103
+ * - It validates EVALUATED values, not raw content
104
+ * - A cell with "=123+123" validates as number (246), not string
105
+ * - Called after re-evaluation to check all schema-constrained cells
106
+ *
107
+ * @param getCellValue - Function to get the evaluated value of a cell
108
+ * @param getCellMetadata - Optional function to get cell metadata
109
+ * @returns Validation result with all errors found
110
+ */
111
+ validateAllSchemaConstraints(getCellValue: (cell: CellAddress) => SerializedCellValue, getCellMetadata?: (cell: CellAddress) => unknown, getTableDataCells?: (table: TableDefinition) => CellAddress[]): {
112
+ valid: boolean;
113
+ errors: Array<{
114
+ message: string;
115
+ cellAddress?: CellAddress;
116
+ schemaNamespace?: string;
117
+ columnName?: string;
118
+ originalError?: Error;
119
+ }>;
120
+ };
121
+ }
@@ -10,14 +10,59 @@ export declare class CopyManager {
10
10
  private evaluationManager;
11
11
  private styleManager;
12
12
  constructor(workbookManager: WorkbookManager, evaluationManager: EvaluationManager, styleManager: StyleManager);
13
+ /**
14
+ * Normalize the include option to an array of parts to copy
15
+ */
16
+ private normalizeInclude;
17
+ /**
18
+ * Check if a specific part should be included in the copy operation
19
+ */
20
+ private shouldInclude;
13
21
  /**
14
22
  * Paste cells from source to target
23
+ * Delegates to cutCells for move operations or copyOnlyCells for copy operations
15
24
  */
16
- copyCells(source: CellAddress[], target: CellAddress, options: CopyCellsOptions): void;
25
+ pasteCells(source: CellAddress[], target: CellAddress, options: CopyCellsOptions): void;
26
+ /**
27
+ * Cut cells: Proper snapshot flow for move operations
28
+ * 1. Snapshot source cells (with styles)
29
+ * 2. Remove source cells and punch holes in style areas
30
+ * 3. Update references in OTHER cells (not in moved set)
31
+ * 4. Update formulas in snapshot and apply to target
32
+ */
33
+ private cutCells;
34
+ /**
35
+ * Copy cells: Standard copy operation (not cut/move)
36
+ * Snapshot → Copy with adjustment → Copy formatting
37
+ */
38
+ private copyOnlyCells;
17
39
  /**
18
40
  * Find the top-left cell (minimum row/col indices)
19
41
  */
20
42
  private findTopLeft;
43
+ /**
44
+ * Create a snapshot of cells' content and metadata
45
+ * This prevents issues with overlapping ranges where source and target overlap
46
+ * Used for copy operations (not cut)
47
+ */
48
+ private snapshotCells;
49
+ /**
50
+ * Create a snapshot of cells with content, metadata, AND styles
51
+ * Used for cut operations to preserve all cell information
52
+ */
53
+ private snapshotCellsWithStyles;
54
+ /**
55
+ * Apply styles from a snapshot to a target cell
56
+ * Creates new style areas at the target location
57
+ */
58
+ private applyStylesFromSnapshot;
59
+ /**
60
+ * Copy content from a cell snapshot to a target cell
61
+ */
62
+ private copyCellContentFromSnapshot;
63
+ /**
64
+ * Update all formula references when cells are cut (moved)
65
+ */
21
66
  /**
22
67
  * Copy content from one cell to another
23
68
  */
@@ -69,7 +114,7 @@ export declare class CopyManager {
69
114
  * Expand a RangeAddress into an array of CellAddress
70
115
  * Handles finite ranges, row-bounded, and column-bounded ranges
71
116
  */
72
- private expandRangeToCells;
117
+ expandRangeToCells(rangeAddress: RangeAddress): CellAddress[];
73
118
  /**
74
119
  * Copy cell content with explicit row/column offset for fill operations
75
120
  */
@@ -0,0 +1,54 @@
1
+ /**
2
+ * ReferenceManager - Manages tracked references for external elements
3
+ *
4
+ * Allows consumers to create stable references to ranges that automatically
5
+ * update when sheets/workbooks are renamed and become invalid when deleted.
6
+ */
7
+ import type { RangeAddress, TrackedReference } from "../types";
8
+ export declare class ReferenceManager {
9
+ private references;
10
+ constructor();
11
+ /**
12
+ * Create a new tracked reference
13
+ * Returns UUID for the reference
14
+ */
15
+ createRef(address: RangeAddress): string;
16
+ /**
17
+ * Get the current address for a reference
18
+ * Returns undefined if reference doesn't exist or is invalid
19
+ */
20
+ getRefAddress(refId: string): RangeAddress | undefined;
21
+ /**
22
+ * Delete a reference
23
+ * Returns true if reference was deleted, false if it didn't exist
24
+ */
25
+ deleteRef(refId: string): boolean;
26
+ /**
27
+ * Get all invalid reference IDs
28
+ */
29
+ getInvalidRefs(): string[];
30
+ /**
31
+ * Update references when sheet is renamed
32
+ */
33
+ updateSheetName(workbookName: string, oldSheetName: string, newSheetName: string): void;
34
+ /**
35
+ * Update references when workbook is renamed
36
+ */
37
+ updateWorkbookName(oldWorkbookName: string, newWorkbookName: string): void;
38
+ /**
39
+ * Mark references as invalid when sheet is removed
40
+ */
41
+ invalidateSheet(workbookName: string, sheetName: string): void;
42
+ /**
43
+ * Mark references as invalid when workbook is removed
44
+ */
45
+ invalidateWorkbook(workbookName: string): void;
46
+ /**
47
+ * Get all references for serialization
48
+ */
49
+ getAllReferences(): Map<string, TrackedReference>;
50
+ /**
51
+ * Restore references from serialization
52
+ */
53
+ resetReferences(refs: Map<string, TrackedReference>): void;
54
+ }
@@ -34,7 +34,7 @@ export declare class StyleManager {
34
34
  getStylesIntersectingWithRange(range: RangeAddress): DirectCellStyle[];
35
35
  /**
36
36
  * Get the style for a range if all cells in the range have the same style
37
- * Returns the DirectCellStyle if the range is completely contained within a single style's area
37
+ * Returns the DirectCellStyle if the range is completely contained within a single style's areas
38
38
  * Returns undefined if multiple styles, partial coverage, or no styles apply
39
39
  */
40
40
  getStyleForRange(range: RangeAddress): DirectCellStyle | undefined;
@@ -100,12 +100,12 @@ export declare class StyleManager {
100
100
  clearCellStyles(range: RangeAddress): void;
101
101
  /**
102
102
  * Clear cell styles in a range using subtraction
103
- * For each intersecting style, subtract the cleared range:
104
- * - If style is completely contained: remove entire style
105
- * - If style partially overlaps: split into remaining rectangles
106
- * - If no intersection: keep unchanged
103
+ * For each intersecting style, subtract the cleared range from its areas:
104
+ * - If an area is completely contained: remove that area
105
+ * - If an area partially overlaps: split into remaining rectangles (hole punching)
106
+ * - If no intersection: keep area unchanged
107
107
  *
108
- * This matches Excel's behavior where pasting replaces formatting
108
+ * This matches Excel's behavior where cutting/pasting creates multi-area styles
109
109
  */
110
110
  clearCellStylesInRange(range: RangeAddress): void;
111
111
  }