@ricsam/formula-engine 0.0.17 → 0.0.19

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 (96) 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 +3 -5
  12. package/dist/cjs/core/autofill-utils.cjs.map +3 -3
  13. package/dist/cjs/core/commands/command-executor.cjs +140 -0
  14. package/dist/cjs/core/commands/command-executor.cjs.map +10 -0
  15. package/dist/cjs/core/commands/content-commands.cjs +574 -0
  16. package/dist/cjs/core/commands/content-commands.cjs.map +10 -0
  17. package/dist/cjs/core/commands/metadata-commands.cjs +150 -0
  18. package/dist/cjs/core/commands/metadata-commands.cjs.map +10 -0
  19. package/dist/cjs/core/commands/named-expression-commands.cjs +238 -0
  20. package/dist/cjs/core/commands/named-expression-commands.cjs.map +10 -0
  21. package/dist/cjs/core/commands/structure-commands.cjs +495 -0
  22. package/dist/cjs/core/commands/structure-commands.cjs.map +10 -0
  23. package/dist/cjs/core/commands/style-commands.cjs +219 -0
  24. package/dist/cjs/core/commands/style-commands.cjs.map +10 -0
  25. package/dist/cjs/core/commands/table-commands.cjs +226 -0
  26. package/dist/cjs/core/commands/table-commands.cjs.map +10 -0
  27. package/dist/cjs/core/commands/types.cjs +72 -0
  28. package/dist/cjs/core/commands/types.cjs.map +10 -0
  29. package/dist/cjs/core/engine.cjs +170 -297
  30. package/dist/cjs/core/engine.cjs.map +3 -3
  31. package/dist/cjs/core/managers/api-schema-manager.cjs +304 -0
  32. package/dist/cjs/core/managers/api-schema-manager.cjs.map +10 -0
  33. package/dist/cjs/core/managers/copy-manager.cjs +1 -2
  34. package/dist/cjs/core/managers/copy-manager.cjs.map +3 -3
  35. package/dist/cjs/core/types.cjs.map +2 -2
  36. package/dist/cjs/lib.cjs +13 -2
  37. package/dist/cjs/lib.cjs.map +3 -3
  38. package/dist/cjs/package.json +1 -1
  39. package/dist/mjs/core/api/api-builder.mjs +37 -0
  40. package/dist/mjs/core/api/api-builder.mjs.map +10 -0
  41. package/dist/mjs/core/api/api-helpers.mjs +161 -0
  42. package/dist/mjs/core/api/api-helpers.mjs.map +10 -0
  43. package/dist/mjs/core/api/api.mjs +35 -0
  44. package/dist/mjs/core/api/api.mjs.map +10 -0
  45. package/dist/mjs/core/api/cell-orm.mjs +49 -0
  46. package/dist/mjs/core/api/cell-orm.mjs.map +10 -0
  47. package/dist/mjs/core/api/table-orm.mjs +148 -0
  48. package/dist/mjs/core/api/table-orm.mjs.map +10 -0
  49. package/dist/mjs/core/autofill-utils.mjs +3 -5
  50. package/dist/mjs/core/autofill-utils.mjs.map +3 -3
  51. package/dist/mjs/core/commands/command-executor.mjs +109 -0
  52. package/dist/mjs/core/commands/command-executor.mjs.map +10 -0
  53. package/dist/mjs/core/commands/content-commands.mjs +544 -0
  54. package/dist/mjs/core/commands/content-commands.mjs.map +10 -0
  55. package/dist/mjs/core/commands/metadata-commands.mjs +120 -0
  56. package/dist/mjs/core/commands/metadata-commands.mjs.map +10 -0
  57. package/dist/mjs/core/commands/named-expression-commands.mjs +208 -0
  58. package/dist/mjs/core/commands/named-expression-commands.mjs.map +10 -0
  59. package/dist/mjs/core/commands/structure-commands.mjs +465 -0
  60. package/dist/mjs/core/commands/structure-commands.mjs.map +10 -0
  61. package/dist/mjs/core/commands/style-commands.mjs +189 -0
  62. package/dist/mjs/core/commands/style-commands.mjs.map +10 -0
  63. package/dist/mjs/core/commands/table-commands.mjs +196 -0
  64. package/dist/mjs/core/commands/table-commands.mjs.map +10 -0
  65. package/dist/mjs/core/commands/types.mjs +42 -0
  66. package/dist/mjs/core/commands/types.mjs.map +10 -0
  67. package/dist/mjs/core/engine.mjs +213 -297
  68. package/dist/mjs/core/engine.mjs.map +3 -3
  69. package/dist/mjs/core/managers/api-schema-manager.mjs +274 -0
  70. package/dist/mjs/core/managers/api-schema-manager.mjs.map +10 -0
  71. package/dist/mjs/core/managers/copy-manager.mjs +1 -2
  72. package/dist/mjs/core/managers/copy-manager.mjs.map +3 -3
  73. package/dist/mjs/core/types.mjs.map +2 -2
  74. package/dist/mjs/lib.mjs +13 -2
  75. package/dist/mjs/lib.mjs.map +3 -3
  76. package/dist/mjs/package.json +1 -1
  77. package/dist/types/core/api/api-builder.d.ts +16 -0
  78. package/dist/types/core/api/api-helpers.d.ts +37 -0
  79. package/dist/types/core/api/api.d.ts +83 -0
  80. package/dist/types/core/api/api.type-test.d.ts +1 -0
  81. package/dist/types/core/api/cell-orm.d.ts +29 -0
  82. package/dist/types/core/api/table-orm.d.ts +46 -0
  83. package/dist/types/core/autofill-utils.d.ts +2 -9
  84. package/dist/types/core/commands/command-executor.d.ts +83 -0
  85. package/dist/types/core/commands/content-commands.d.ts +142 -0
  86. package/dist/types/core/commands/metadata-commands.d.ts +55 -0
  87. package/dist/types/core/commands/named-expression-commands.d.ts +115 -0
  88. package/dist/types/core/commands/structure-commands.d.ts +132 -0
  89. package/dist/types/core/commands/style-commands.d.ts +76 -0
  90. package/dist/types/core/commands/table-commands.d.ts +104 -0
  91. package/dist/types/core/commands/types.d.ts +114 -0
  92. package/dist/types/core/engine.d.ts +130 -26
  93. package/dist/types/core/managers/api-schema-manager.d.ts +121 -0
  94. package/dist/types/core/types.d.ts +1 -1
  95. package/dist/types/lib.d.ts +8 -0
  96. package/package.json +1 -1
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Table Commands - Commands that modify table definitions
3
+ *
4
+ * These commands all require re-evaluation after execution.
5
+ */
6
+ import type { TableManager } from "../managers/table-manager";
7
+ import type { NamedExpressionManager } from "../managers/named-expression-manager";
8
+ import type { WorkbookManager } from "../managers/workbook-manager";
9
+ import type { ApiSchemaManager } from "../managers/api-schema-manager";
10
+ import type { CellAddress, SerializedCellValue, SpreadsheetRangeEnd, TableDefinition } from "../types";
11
+ import type { EngineCommand, EngineAction } from "./types";
12
+ /**
13
+ * Dependencies needed for table commands.
14
+ */
15
+ export interface TableCommandDeps {
16
+ tableManager: TableManager;
17
+ namedExpressionManager: NamedExpressionManager;
18
+ workbookManager: WorkbookManager;
19
+ apiSchemaManager: ApiSchemaManager;
20
+ getCellValue: (cellAddress: CellAddress) => SerializedCellValue;
21
+ renameTableInFormula: (formula: string, oldName: string, newName: string) => string;
22
+ }
23
+ /**
24
+ * Command to add a table.
25
+ */
26
+ export declare class AddTableCommand implements EngineCommand {
27
+ private deps;
28
+ private props;
29
+ readonly requiresReevaluation = true;
30
+ constructor(deps: TableCommandDeps, props: {
31
+ tableName: string;
32
+ sheetName: string;
33
+ workbookName: string;
34
+ start: string;
35
+ numRows: SpreadsheetRangeEnd;
36
+ numCols: number;
37
+ });
38
+ execute(): void;
39
+ undo(): void;
40
+ toAction(): EngineAction;
41
+ }
42
+ /**
43
+ * Command to remove a table.
44
+ */
45
+ export declare class RemoveTableCommand implements EngineCommand {
46
+ private deps;
47
+ private opts;
48
+ readonly requiresReevaluation = true;
49
+ private removedTable;
50
+ constructor(deps: TableCommandDeps, opts: {
51
+ tableName: string;
52
+ workbookName: string;
53
+ });
54
+ execute(): void;
55
+ undo(): void;
56
+ toAction(): EngineAction;
57
+ }
58
+ /**
59
+ * Command to rename a table.
60
+ */
61
+ export declare class RenameTableCommand implements EngineCommand {
62
+ private deps;
63
+ private workbookName;
64
+ private oldName;
65
+ private newName;
66
+ readonly requiresReevaluation = true;
67
+ constructor(deps: TableCommandDeps, workbookName: string, oldName: string, newName: string);
68
+ execute(): void;
69
+ undo(): void;
70
+ toAction(): EngineAction;
71
+ }
72
+ /**
73
+ * Command to update a table.
74
+ */
75
+ export declare class UpdateTableCommand implements EngineCommand {
76
+ private deps;
77
+ private opts;
78
+ readonly requiresReevaluation = true;
79
+ private previousTable;
80
+ constructor(deps: TableCommandDeps, opts: {
81
+ tableName: string;
82
+ sheetName?: string;
83
+ start?: string;
84
+ numRows?: SpreadsheetRangeEnd;
85
+ numCols?: number;
86
+ workbookName: string;
87
+ });
88
+ execute(): void;
89
+ undo(): void;
90
+ toAction(): EngineAction;
91
+ }
92
+ /**
93
+ * Command to reset all tables.
94
+ */
95
+ export declare class ResetTablesCommand implements EngineCommand {
96
+ private deps;
97
+ private newTables;
98
+ readonly requiresReevaluation = true;
99
+ private previousTables;
100
+ constructor(deps: TableCommandDeps, newTables: Map<string, Map<string, TableDefinition>>);
101
+ execute(): void;
102
+ undo(): void;
103
+ toAction(): EngineAction;
104
+ }
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Command Pattern Types for FormulaEngine
3
+ *
4
+ * Commands encapsulate all mutating operations on the engine,
5
+ * enabling undo/redo, schema validation with rollback, and action serialization.
6
+ */
7
+ import type { CellAddress } from "../types";
8
+ /**
9
+ * Serializable action representation of a command.
10
+ * Used for persistence, collaboration, and changelog functionality.
11
+ */
12
+ export interface EngineAction {
13
+ type: string;
14
+ payload: unknown;
15
+ timestamp?: number;
16
+ }
17
+ /**
18
+ * Base interface for all engine commands.
19
+ */
20
+ export interface EngineCommand {
21
+ /**
22
+ * Whether this command affects cell values/formulas and requires re-evaluation.
23
+ * Commands that only affect metadata or styles don't need re-evaluation.
24
+ */
25
+ readonly requiresReevaluation: boolean;
26
+ /**
27
+ * Execute the command (forward operation).
28
+ */
29
+ execute(): void;
30
+ /**
31
+ * Undo the command (reverse operation).
32
+ */
33
+ undo(): void;
34
+ /**
35
+ * Convert the command to a serializable action for persistence/collaboration.
36
+ */
37
+ toAction(): EngineAction;
38
+ }
39
+ /**
40
+ * Options for command execution.
41
+ */
42
+ export interface ExecuteOptions {
43
+ /**
44
+ * Whether to validate schema constraints after execution.
45
+ * Only applies to commands that require re-evaluation.
46
+ */
47
+ validate?: boolean;
48
+ /**
49
+ * Whether to skip adding to undo stack (for internal use).
50
+ */
51
+ skipUndoStack?: boolean;
52
+ /**
53
+ * Whether to skip emitting update events.
54
+ */
55
+ skipEmitUpdate?: boolean;
56
+ }
57
+ /**
58
+ * Result of schema validation.
59
+ */
60
+ export interface SchemaValidationResult {
61
+ valid: boolean;
62
+ errors: SchemaValidationErrorInfo[];
63
+ }
64
+ /**
65
+ * Information about a schema validation error.
66
+ */
67
+ export interface SchemaValidationErrorInfo {
68
+ message: string;
69
+ cellAddress?: CellAddress;
70
+ schemaNamespace?: string;
71
+ columnName?: string;
72
+ originalError?: Error;
73
+ }
74
+ /**
75
+ * Action types for all commands.
76
+ * Used for serialization and deserialization.
77
+ */
78
+ export declare const ActionTypes: {
79
+ readonly SET_CELL_CONTENT: "SET_CELL_CONTENT";
80
+ readonly SET_SHEET_CONTENT: "SET_SHEET_CONTENT";
81
+ readonly CLEAR_RANGE: "CLEAR_RANGE";
82
+ readonly PASTE_CELLS: "PASTE_CELLS";
83
+ readonly FILL_AREAS: "FILL_AREAS";
84
+ readonly MOVE_CELL: "MOVE_CELL";
85
+ readonly MOVE_RANGE: "MOVE_RANGE";
86
+ readonly AUTO_FILL: "AUTO_FILL";
87
+ readonly ADD_WORKBOOK: "ADD_WORKBOOK";
88
+ readonly REMOVE_WORKBOOK: "REMOVE_WORKBOOK";
89
+ readonly RENAME_WORKBOOK: "RENAME_WORKBOOK";
90
+ readonly CLONE_WORKBOOK: "CLONE_WORKBOOK";
91
+ readonly ADD_SHEET: "ADD_SHEET";
92
+ readonly REMOVE_SHEET: "REMOVE_SHEET";
93
+ readonly RENAME_SHEET: "RENAME_SHEET";
94
+ readonly ADD_TABLE: "ADD_TABLE";
95
+ readonly REMOVE_TABLE: "REMOVE_TABLE";
96
+ readonly RENAME_TABLE: "RENAME_TABLE";
97
+ readonly UPDATE_TABLE: "UPDATE_TABLE";
98
+ readonly RESET_TABLES: "RESET_TABLES";
99
+ readonly ADD_NAMED_EXPRESSION: "ADD_NAMED_EXPRESSION";
100
+ readonly REMOVE_NAMED_EXPRESSION: "REMOVE_NAMED_EXPRESSION";
101
+ readonly UPDATE_NAMED_EXPRESSION: "UPDATE_NAMED_EXPRESSION";
102
+ readonly RENAME_NAMED_EXPRESSION: "RENAME_NAMED_EXPRESSION";
103
+ readonly SET_NAMED_EXPRESSIONS: "SET_NAMED_EXPRESSIONS";
104
+ readonly SET_CELL_METADATA: "SET_CELL_METADATA";
105
+ readonly SET_SHEET_METADATA: "SET_SHEET_METADATA";
106
+ readonly SET_WORKBOOK_METADATA: "SET_WORKBOOK_METADATA";
107
+ readonly ADD_CONDITIONAL_STYLE: "ADD_CONDITIONAL_STYLE";
108
+ readonly REMOVE_CONDITIONAL_STYLE: "REMOVE_CONDITIONAL_STYLE";
109
+ readonly ADD_CELL_STYLE: "ADD_CELL_STYLE";
110
+ readonly REMOVE_CELL_STYLE: "REMOVE_CELL_STYLE";
111
+ readonly CLEAR_CELL_STYLES: "CLEAR_CELL_STYLES";
112
+ readonly RESET_TO_SERIALIZED: "RESET_TO_SERIALIZED";
113
+ };
114
+ export type ActionType = (typeof ActionTypes)[keyof typeof ActionTypes];
@@ -12,13 +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/types";
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
17
25
  * @template TCellMetadata - Consumer-defined type for cell metadata (rich text, links, custom data, etc.)
18
26
  * @template TSheetMetadata - Consumer-defined type for sheet metadata (text boxes, frozen panes, etc.)
19
27
  * @template TWorkbookMetadata - Consumer-defined type for workbook metadata (themes, document properties, etc.)
20
28
  */
21
- export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unknown, TWorkbookMetadata = unknown> {
29
+ export declare class FormulaEngine<TMetadata extends Metadata = Metadata, TCreateApi extends CreateApi<MetadataType<TMetadata, "cell">, Api, Declaration> | undefined = undefined> {
22
30
  private workbookManager;
23
31
  private namedExpressionManager;
24
32
  private tableManager;
@@ -29,6 +37,10 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
29
37
  private styleManager;
30
38
  private copyManager;
31
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;
32
44
  /**
33
45
  * Public access to the store manager for testing
34
46
  */
@@ -40,32 +52,32 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
40
52
  _autoFillManager: AutoFill;
41
53
  _dependencyManager: DependencyManager;
42
54
  _styleManager: StyleManager;
43
- constructor();
55
+ constructor(api?: TCreateApi);
44
56
  /**
45
57
  * Static factory method to build an empty engine
46
58
  * @template TC - Consumer-defined cell metadata type
47
59
  * @template TS - Consumer-defined sheet metadata type
48
60
  * @template TW - Consumer-defined workbook metadata type
49
61
  */
50
- static buildEmpty<TC = unknown, TS = unknown, TW = unknown>(): FormulaEngine<TC, TS, TW>;
62
+ static buildEmpty<TMetadata extends Metadata = Metadata, TApiDeclaration extends CreateApi<MetadataType<TMetadata, "cell">, any, any> | undefined = undefined>(api?: TApiDeclaration): FormulaEngine<TMetadata, TApiDeclaration>;
51
63
  getCellEvaluationResult(cellAddress: CellAddress): SingleEvaluationResult | undefined;
52
64
  getCellValue(cellAddress: CellAddress, debug?: boolean): SerializedCellValue;
53
65
  /**
54
66
  * Set metadata for a cell
55
67
  * Metadata can contain rich text, links, comments, or any consumer-defined data
56
68
  */
57
- setCellMetadata(address: CellAddress, metadata: TCellMetadata | undefined): void;
69
+ setCellMetadata(address: CellAddress, metadata: MetadataType<TMetadata, "cell"> | undefined): void;
58
70
  /**
59
71
  * Get metadata for a cell
60
72
  */
61
- getCellMetadata(address: CellAddress): TCellMetadata | undefined;
73
+ getCellMetadata(address: CellAddress): MetadataType<TMetadata, "cell"> | undefined;
62
74
  /**
63
75
  * Get all cell metadata for a sheet (serialized as Map)
64
76
  */
65
77
  getSheetMetadataSerialized(opts: {
66
78
  sheetName: string;
67
79
  workbookName: string;
68
- }): Map<string, TCellMetadata>;
80
+ }): Map<string, MetadataType<TMetadata, "sheet">>;
69
81
  /**
70
82
  * Set metadata for a sheet
71
83
  * Sheet metadata can contain text boxes, frozen panes, print settings, or any consumer-defined data
@@ -73,23 +85,23 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
73
85
  setSheetMetadata(opts: {
74
86
  workbookName: string;
75
87
  sheetName: string;
76
- }, metadata: TSheetMetadata): void;
88
+ }, metadata: MetadataType<TMetadata, "sheet">): void;
77
89
  /**
78
90
  * Get metadata for a sheet
79
91
  */
80
92
  getSheetMetadata(opts: {
81
93
  workbookName: string;
82
94
  sheetName: string;
83
- }): TSheetMetadata | undefined;
95
+ }): MetadataType<TMetadata, "sheet"> | undefined;
84
96
  /**
85
97
  * Set metadata for a workbook
86
98
  * Workbook metadata can contain themes, document properties, settings, or any consumer-defined data
87
99
  */
88
- setWorkbookMetadata(workbookName: string, metadata: TWorkbookMetadata): void;
100
+ setWorkbookMetadata(workbookName: string, metadata: MetadataType<TMetadata, "workbook">): void;
89
101
  /**
90
102
  * Get metadata for a workbook
91
103
  */
92
- getWorkbookMetadata(workbookName: string): TWorkbookMetadata | undefined;
104
+ getWorkbookMetadata(workbookName: string): MetadataType<TMetadata, "workbook"> | undefined;
93
105
  /**
94
106
  * Create a tracked reference to a range
95
107
  * Returns a stable UUID that can be used to retrieve the address later
@@ -118,29 +130,37 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
118
130
  formula: string, cellAddress: CellAddress): SerializedCellValue;
119
131
  getCellDependents(address: CellAddress | SpreadsheetRange): (SpreadsheetRange | CellAddress)[];
120
132
  getCellPrecedents(address: CellAddress | SpreadsheetRange): (SpreadsheetRange | CellAddress)[];
121
- addNamedExpression({ expression, expressionName, sheetName, workbookName, }: {
133
+ addNamedExpression(opts: {
122
134
  expression: string;
123
135
  expressionName: string;
124
136
  sheetName?: string;
125
137
  workbookName?: string;
126
138
  }): void;
127
- 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: {
128
148
  expressionName: string;
129
149
  sheetName?: string;
130
150
  workbookName?: string;
131
151
  }): boolean;
132
- updateNamedExpression({ expression, expressionName, sheetName, workbookName, }: {
152
+ updateNamedExpression(opts: {
133
153
  expression: string;
134
154
  expressionName: string;
135
155
  sheetName?: string;
136
156
  workbookName?: string;
137
157
  }): void;
138
- renameNamedExpression({ expressionName, sheetName, workbookName, newName, }: {
158
+ renameNamedExpression(opts: {
139
159
  expressionName: string;
140
160
  sheetName?: string;
141
161
  workbookName?: string;
142
162
  newName: string;
143
- }): boolean;
163
+ }): void;
144
164
  setNamedExpressions(opts: ({
145
165
  type: "global";
146
166
  } | {
@@ -160,7 +180,7 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
160
180
  start: string;
161
181
  numRows: SpreadsheetRangeEnd;
162
182
  numCols: number;
163
- }): TableDefinition;
183
+ }): void;
164
184
  renameTable(workbookName: string, names: {
165
185
  oldName: string;
166
186
  newName: string;
@@ -176,10 +196,29 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
176
196
  removeTable(opts: {
177
197
  tableName: string;
178
198
  workbookName: string;
199
+ }): void;
200
+ /**
201
+ * Check if a table exists
202
+ */
203
+ hasTable(opts: {
204
+ tableName: string;
205
+ workbookName: string;
179
206
  }): boolean;
207
+ /**
208
+ * Get a table definition by name
209
+ */
210
+ getTable(opts: {
211
+ tableName: string;
212
+ workbookName: string;
213
+ }): TableDefinition | undefined;
180
214
  resetTables(tables: Map<string, Map<string, TableDefinition>>): void;
181
215
  getTables(workbookName: string): Map<string, TableDefinition>;
182
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;
183
222
  /**
184
223
  * Add a conditional style rule
185
224
  */
@@ -187,7 +226,11 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
187
226
  /**
188
227
  * Remove a conditional style rule by index
189
228
  */
190
- 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;
191
234
  /**
192
235
  * Get all conditional styles intersecting with a range
193
236
  */
@@ -211,7 +254,11 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
211
254
  /**
212
255
  * Remove a direct cell style rule by index
213
256
  */
214
- 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;
215
262
  /**
216
263
  * Get all direct cell styles intersecting with a range
217
264
  */
@@ -337,16 +384,23 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
337
384
  addSheet(opts: {
338
385
  workbookName: string;
339
386
  sheetName: string;
340
- }): import("./types").Sheet<unknown, unknown>;
387
+ }): void;
341
388
  removeSheet(opts: {
342
389
  workbookName: string;
343
390
  sheetName: string;
344
- }): import("./types").Sheet<unknown, unknown>;
391
+ }): void;
345
392
  renameSheet(opts: {
346
393
  sheetName: string;
347
394
  newSheetName: string;
348
395
  workbookName: string;
349
- }): import("./types").Sheet<unknown, unknown>;
396
+ }): void;
397
+ /**
398
+ * Check if a sheet exists
399
+ */
400
+ hasSheet(opts: {
401
+ workbookName: string;
402
+ sheetName: string;
403
+ }): boolean;
350
404
  getSheets(workbookName: string): Map<string, import("./types").Sheet<unknown, unknown>>;
351
405
  getSheet({ workbookName, sheetName, }: {
352
406
  workbookName: string;
@@ -358,6 +412,10 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
358
412
  }): Map<string, SerializedCellValue>;
359
413
  addWorkbook(workbookName: string): void;
360
414
  removeWorkbook(workbookName: string): void;
415
+ /**
416
+ * Check if a workbook exists
417
+ */
418
+ hasWorkbook(workbookName: string): boolean;
361
419
  cloneWorkbook(fromWorkbookName: string, toWorkbookName: string): void;
362
420
  renameWorkbook(opts: {
363
421
  workbookName: string;
@@ -369,18 +427,17 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
369
427
  * @param sheetName - The name of the sheet to set the content of
370
428
  * @param content - A map of cell addresses to their serialized values
371
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
372
431
  */
373
432
  setSheetContent(opts: {
374
433
  sheetName: string;
375
434
  workbookName: string;
376
435
  }, content: Map<string, SerializedCellValue>): void;
377
- setCellContent(address: CellAddress, content: SerializedCellValue): void;
378
436
  /**
379
- * Re-evaluates all sheets to ensure all dependencies are resolved correctly
380
- *
381
- * 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
382
439
  */
383
- reevaluate(): void;
440
+ setCellContent(address: CellAddress, content: SerializedCellValue): void;
384
441
  /**
385
442
  * Auto-fills one or more ranges based on the seedRange and the direction.
386
443
  * Supports pattern detection and style copying.
@@ -420,4 +477,51 @@ export declare class FormulaEngine<TCellMetadata = unknown, TSheetMetadata = unk
420
477
  onUpdate(listener: () => void): () => void;
421
478
  serializeEngine(): string;
422
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;
423
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
+ }
@@ -363,7 +363,7 @@ export interface CopyCellsOptions {
363
363
  * - ['content', 'style', 'metadata'] - same as 'all'
364
364
  * @default 'all'
365
365
  */
366
- include?: 'all' | ('content' | 'style' | 'metadata')[];
366
+ include?: "all" | ("content" | "style" | "metadata")[];
367
367
  /**
368
368
  * The type of the content to copy
369
369
  * value: Copy the value from the source to the target,
@@ -2,3 +2,11 @@ export { FormulaEngine } from "./core/engine";
2
2
  export * from "./core/types";
3
3
  export * from "./core/utils";
4
4
  export * from "./core/utils/color-utils";
5
+ export { defineApi, createApi } from "./core/api/api";
6
+ export type { CreateApi, Declaration, Api, TableApi, CellApi } from "./core/api/api";
7
+ export { TableOrm } from "./core/api/table-orm";
8
+ export { CellOrm } from "./core/api/cell-orm";
9
+ export { SchemaValidationError } from "./core/managers/api-schema-manager";
10
+ export type { ValidationResult } from "./core/managers/api-schema-manager";
11
+ export { SchemaIntegrityError } from "./core/commands/command-executor";
12
+ export type { EngineAction, EngineCommand } from "./core/commands/types";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "module": "./dist/mjs/lib.mjs",
5
5
  "scripts": {
6
6
  "test": "bun test",