@ricsam/formula-engine 0.2.8 → 0.2.10

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 (130) hide show
  1. package/README.md +41 -3
  2. package/dist/cjs/core/engine.cjs +551 -166
  3. package/dist/cjs/core/engine.cjs.map +3 -3
  4. package/dist/cjs/core/managers/dependency-manager.cjs +151 -67
  5. package/dist/cjs/core/managers/dependency-manager.cjs.map +3 -3
  6. package/dist/cjs/core/managers/evaluation-manager.cjs.map +1 -1
  7. package/dist/cjs/core/managers/workbook-manager.cjs +197 -1
  8. package/dist/cjs/core/managers/workbook-manager.cjs.map +3 -3
  9. package/dist/cjs/core/mutation-invalidation.cjs +241 -0
  10. package/dist/cjs/core/mutation-invalidation.cjs.map +10 -0
  11. package/dist/cjs/core/types.cjs.map +2 -2
  12. package/dist/cjs/core/workbook-renamer.cjs.map +1 -1
  13. package/dist/cjs/evaluator/formula-evaluator.cjs +22 -48
  14. package/dist/cjs/evaluator/formula-evaluator.cjs.map +3 -3
  15. package/dist/cjs/functions/math/sum/summation-utils.cjs +2 -2
  16. package/dist/cjs/functions/math/sum/summation-utils.cjs.map +2 -2
  17. package/dist/cjs/lib.cjs +2 -13
  18. package/dist/cjs/lib.cjs.map +3 -3
  19. package/dist/cjs/package.json +1 -1
  20. package/dist/cjs/parser/formatter.cjs +3 -4
  21. package/dist/cjs/parser/formatter.cjs.map +3 -3
  22. package/dist/cjs/parser/parser.cjs +24 -216
  23. package/dist/cjs/parser/parser.cjs.map +3 -3
  24. package/dist/mjs/core/engine.mjs +565 -207
  25. package/dist/mjs/core/engine.mjs.map +3 -3
  26. package/dist/mjs/core/managers/dependency-manager.mjs +151 -67
  27. package/dist/mjs/core/managers/dependency-manager.mjs.map +3 -3
  28. package/dist/mjs/core/managers/evaluation-manager.mjs.map +1 -1
  29. package/dist/mjs/core/managers/workbook-manager.mjs +197 -1
  30. package/dist/mjs/core/managers/workbook-manager.mjs.map +3 -3
  31. package/dist/mjs/core/mutation-invalidation.mjs +201 -0
  32. package/dist/mjs/core/mutation-invalidation.mjs.map +10 -0
  33. package/dist/mjs/core/types.mjs.map +2 -2
  34. package/dist/mjs/core/workbook-renamer.mjs.map +1 -1
  35. package/dist/mjs/evaluator/formula-evaluator.mjs +22 -48
  36. package/dist/mjs/evaluator/formula-evaluator.mjs.map +3 -3
  37. package/dist/mjs/functions/math/sum/summation-utils.mjs +2 -2
  38. package/dist/mjs/functions/math/sum/summation-utils.mjs.map +2 -2
  39. package/dist/mjs/lib.mjs +2 -13
  40. package/dist/mjs/lib.mjs.map +3 -3
  41. package/dist/mjs/package.json +1 -1
  42. package/dist/mjs/parser/formatter.mjs +3 -4
  43. package/dist/mjs/parser/formatter.mjs.map +3 -3
  44. package/dist/mjs/parser/parser.mjs +24 -216
  45. package/dist/mjs/parser/parser.mjs.map +3 -3
  46. package/dist/types/core/engine.d.ts +31 -135
  47. package/dist/types/core/managers/dependency-manager.d.ts +5 -1
  48. package/dist/types/core/managers/evaluation-manager.d.ts +1 -1
  49. package/dist/types/core/managers/workbook-manager.d.ts +23 -1
  50. package/dist/types/core/mutation-invalidation.d.ts +46 -0
  51. package/dist/types/core/types.d.ts +35 -0
  52. package/dist/types/lib.d.ts +0 -8
  53. package/dist/types/parser/parser.d.ts +4 -6
  54. package/package.json +1 -1
  55. package/dist/cjs/core/commands/command-executor.cjs +0 -149
  56. package/dist/cjs/core/commands/command-executor.cjs.map +0 -10
  57. package/dist/cjs/core/commands/content-commands.cjs +0 -857
  58. package/dist/cjs/core/commands/content-commands.cjs.map +0 -10
  59. package/dist/cjs/core/commands/metadata-commands.cjs +0 -160
  60. package/dist/cjs/core/commands/metadata-commands.cjs.map +0 -10
  61. package/dist/cjs/core/commands/named-expression-commands.cjs +0 -363
  62. package/dist/cjs/core/commands/named-expression-commands.cjs.map +0 -10
  63. package/dist/cjs/core/commands/structure-commands.cjs +0 -696
  64. package/dist/cjs/core/commands/structure-commands.cjs.map +0 -10
  65. package/dist/cjs/core/commands/style-commands.cjs +0 -229
  66. package/dist/cjs/core/commands/style-commands.cjs.map +0 -10
  67. package/dist/cjs/core/commands/table-commands.cjs +0 -495
  68. package/dist/cjs/core/commands/table-commands.cjs.map +0 -10
  69. package/dist/cjs/core/commands/types.cjs +0 -99
  70. package/dist/cjs/core/commands/types.cjs.map +0 -10
  71. package/dist/cjs/core/managers/schema-manager.cjs +0 -374
  72. package/dist/cjs/core/managers/schema-manager.cjs.map +0 -10
  73. package/dist/cjs/core/schema/cell-orm.cjs +0 -76
  74. package/dist/cjs/core/schema/cell-orm.cjs.map +0 -10
  75. package/dist/cjs/core/schema/grid-orm.cjs +0 -125
  76. package/dist/cjs/core/schema/grid-orm.cjs.map +0 -10
  77. package/dist/cjs/core/schema/schema-builder.cjs +0 -74
  78. package/dist/cjs/core/schema/schema-builder.cjs.map +0 -10
  79. package/dist/cjs/core/schema/schema-helpers.cjs +0 -200
  80. package/dist/cjs/core/schema/schema-helpers.cjs.map +0 -10
  81. package/dist/cjs/core/schema/schema.cjs +0 -91
  82. package/dist/cjs/core/schema/schema.cjs.map +0 -10
  83. package/dist/cjs/core/schema/table-orm.cjs +0 -189
  84. package/dist/cjs/core/schema/table-orm.cjs.map +0 -10
  85. package/dist/mjs/core/commands/command-executor.mjs +0 -109
  86. package/dist/mjs/core/commands/command-executor.mjs.map +0 -10
  87. package/dist/mjs/core/commands/content-commands.mjs +0 -821
  88. package/dist/mjs/core/commands/content-commands.mjs.map +0 -10
  89. package/dist/mjs/core/commands/metadata-commands.mjs +0 -120
  90. package/dist/mjs/core/commands/metadata-commands.mjs.map +0 -10
  91. package/dist/mjs/core/commands/named-expression-commands.mjs +0 -323
  92. package/dist/mjs/core/commands/named-expression-commands.mjs.map +0 -10
  93. package/dist/mjs/core/commands/structure-commands.mjs +0 -661
  94. package/dist/mjs/core/commands/structure-commands.mjs.map +0 -10
  95. package/dist/mjs/core/commands/style-commands.mjs +0 -189
  96. package/dist/mjs/core/commands/style-commands.mjs.map +0 -10
  97. package/dist/mjs/core/commands/table-commands.mjs +0 -459
  98. package/dist/mjs/core/commands/table-commands.mjs.map +0 -10
  99. package/dist/mjs/core/commands/types.mjs +0 -59
  100. package/dist/mjs/core/commands/types.mjs.map +0 -10
  101. package/dist/mjs/core/managers/schema-manager.mjs +0 -334
  102. package/dist/mjs/core/managers/schema-manager.mjs.map +0 -10
  103. package/dist/mjs/core/schema/cell-orm.mjs +0 -35
  104. package/dist/mjs/core/schema/cell-orm.mjs.map +0 -10
  105. package/dist/mjs/core/schema/grid-orm.mjs +0 -84
  106. package/dist/mjs/core/schema/grid-orm.mjs.map +0 -10
  107. package/dist/mjs/core/schema/schema-builder.mjs +0 -34
  108. package/dist/mjs/core/schema/schema-builder.mjs.map +0 -10
  109. package/dist/mjs/core/schema/schema-helpers.mjs +0 -160
  110. package/dist/mjs/core/schema/schema-helpers.mjs.map +0 -10
  111. package/dist/mjs/core/schema/schema.mjs +0 -51
  112. package/dist/mjs/core/schema/schema.mjs.map +0 -10
  113. package/dist/mjs/core/schema/table-orm.mjs +0 -156
  114. package/dist/mjs/core/schema/table-orm.mjs.map +0 -10
  115. package/dist/types/core/commands/command-executor.d.ts +0 -81
  116. package/dist/types/core/commands/content-commands.d.ts +0 -172
  117. package/dist/types/core/commands/metadata-commands.d.ts +0 -55
  118. package/dist/types/core/commands/named-expression-commands.d.ts +0 -130
  119. package/dist/types/core/commands/structure-commands.d.ts +0 -155
  120. package/dist/types/core/commands/style-commands.d.ts +0 -76
  121. package/dist/types/core/commands/table-commands.d.ts +0 -119
  122. package/dist/types/core/commands/types.d.ts +0 -143
  123. package/dist/types/core/managers/schema-manager.d.ts +0 -142
  124. package/dist/types/core/schema/cell-orm.d.ts +0 -33
  125. package/dist/types/core/schema/grid-orm.d.ts +0 -63
  126. package/dist/types/core/schema/schema-builder.d.ts +0 -16
  127. package/dist/types/core/schema/schema-helpers.d.ts +0 -49
  128. package/dist/types/core/schema/schema.d.ts +0 -167
  129. package/dist/types/core/schema/schema.type-test.d.ts +0 -1
  130. package/dist/types/core/schema/table-orm.d.ts +0 -46
@@ -16,64 +16,27 @@ import { DependencyManager } from "./managers/dependency-manager.mjs";
16
16
  import { StyleManager } from "./managers/style-manager.mjs";
17
17
  import { CopyManager } from "./managers/copy-manager.mjs";
18
18
  import { ReferenceManager } from "./managers/reference-manager.mjs";
19
- import {
20
- SchemaManager
21
- } from "./managers/schema-manager.mjs";
22
- import { buildSchemaFromDeclaration } from "./schema/schema-builder.mjs";
23
- import { TableOrm } from "./schema/table-orm.mjs";
24
- import { CellOrm } from "./schema/cell-orm.mjs";
25
- import { GridOrm } from "./schema/grid-orm.mjs";
26
19
  import {
27
20
  ENGINE_SNAPSHOT_VERSION
28
21
  } from "./engine-snapshot.mjs";
29
22
  import {
30
- CommandExecutor
31
- } from "./commands/command-executor.mjs";
32
- import {
33
- SetCellContentCommand,
34
- SetSheetContentCommand,
35
- ClearRangeCommand,
36
- PasteCellsCommand,
37
- FillAreasCommand,
38
- MoveCellCommand,
39
- MoveRangeCommand,
40
- AutoFillCommand
41
- } from "./commands/content-commands.mjs";
42
- import {
43
- AddWorkbookCommand,
44
- RemoveWorkbookCommand,
45
- RenameWorkbookCommand,
46
- CloneWorkbookCommand,
47
- AddSheetCommand,
48
- RemoveSheetCommand,
49
- RenameSheetCommand
50
- } from "./commands/structure-commands.mjs";
51
- import {
52
- AddTableCommand,
53
- RemoveTableCommand,
54
- RenameTableCommand,
55
- UpdateTableCommand,
56
- ResetTablesCommand
57
- } from "./commands/table-commands.mjs";
58
- import {
59
- AddNamedExpressionCommand,
60
- RemoveNamedExpressionCommand,
61
- UpdateNamedExpressionCommand,
62
- RenameNamedExpressionCommand,
63
- SetNamedExpressionsCommand
64
- } from "./commands/named-expression-commands.mjs";
23
+ buildFormulaTouchedCells,
24
+ buildSheetContentTouchedCells,
25
+ buildTableContextChangedCells,
26
+ buildTableTouchedCells,
27
+ buildTouchedCells,
28
+ captureCellContents,
29
+ getFiniteRangeAddresses,
30
+ getMutationAddressKey,
31
+ getNamedExpressionScopeResourceKeys,
32
+ mergeTouchedCells
33
+ } from "./mutation-invalidation.mjs";
65
34
  import {
66
- SetCellMetadataCommand,
67
- SetSheetMetadataCommand,
68
- SetWorkbookMetadataCommand
69
- } from "./commands/metadata-commands.mjs";
70
- import {
71
- AddConditionalStyleCommand,
72
- RemoveConditionalStyleCommand,
73
- AddCellStyleCommand,
74
- RemoveCellStyleCommand,
75
- ClearCellStylesCommand
76
- } from "./commands/style-commands.mjs";
35
+ getNamedExpressionResourceKey,
36
+ getSheetResourceKey,
37
+ getTableResourceKey,
38
+ getWorkbookResourceKey
39
+ } from "./resource-keys.mjs";
77
40
 
78
41
  class FormulaEngine {
79
42
  workbookManager;
@@ -86,10 +49,6 @@ class FormulaEngine {
86
49
  styleManager;
87
50
  copyManager;
88
51
  referenceManager;
89
- schemaManager;
90
- commandExecutor;
91
- schema;
92
- schemaDeclaration;
93
52
  _workbookManager;
94
53
  _namedExpressionManager;
95
54
  _tableManager;
@@ -98,8 +57,7 @@ class FormulaEngine {
98
57
  _autoFillManager;
99
58
  _dependencyManager;
100
59
  _styleManager;
101
- constructor(schema) {
102
- this.schemaDeclaration = schema?.declaration;
60
+ constructor() {
103
61
  this.eventManager = new EventManager;
104
62
  this.workbookManager = new WorkbookManager;
105
63
  this.namedExpressionManager = new NamedExpressionManager;
@@ -112,13 +70,6 @@ class FormulaEngine {
112
70
  this.copyManager = new CopyManager(this.workbookManager, this.evaluationManager, this.styleManager);
113
71
  this.autoFillManager = new AutoFill(this.workbookManager, this.styleManager);
114
72
  this.referenceManager = new ReferenceManager;
115
- this.schemaManager = new SchemaManager(this.tableManager);
116
- this.commandExecutor = new CommandExecutor(this.evaluationManager, this.eventManager, () => this.schemaManager.validateAllSchemaConstraints((cell) => this.getCellValue(cell), (cell) => this.getCellMetadata(cell), (table) => this.getTableDataCells(table)));
117
- if (this.schemaDeclaration) {
118
- this.schema = buildSchemaFromDeclaration(this, this.schemaDeclaration, this.schemaManager);
119
- } else {
120
- this.schema = {};
121
- }
122
73
  this._workbookManager = this.workbookManager;
123
74
  this._namedExpressionManager = this.namedExpressionManager;
124
75
  this._tableManager = this.tableManager;
@@ -128,46 +79,63 @@ class FormulaEngine {
128
79
  this._dependencyManager = this.dependencyManager;
129
80
  this._styleManager = this.styleManager;
130
81
  }
131
- static buildEmpty(schema) {
132
- return new FormulaEngine(schema);
133
- }
134
- addTableSchema(namespace, address, headers) {
135
- this.schemaManager.registerTableSchema(namespace, address.workbookName, address.tableName, headers);
136
- const orm = new TableOrm(this, address.workbookName, address.tableName, headers, namespace);
137
- this.schema[namespace] = orm;
138
- return orm;
82
+ static buildEmpty() {
83
+ return new FormulaEngine;
139
84
  }
140
- addCellSchema(namespace, cellAddress, parse, write = (value) => ({ value })) {
141
- this.schemaManager.registerCellSchema(namespace, cellAddress, parse);
142
- const orm = new CellOrm(this, cellAddress, parse, write, namespace);
143
- this.schema[namespace] = orm;
144
- return orm;
145
- }
146
- addGridSchema(namespace, address, range, parse, write = (value) => ({ value })) {
147
- this.schemaManager.registerGridSchema(namespace, address.workbookName, address.sheetName, range, parse);
148
- const orm = new GridOrm(this, address.workbookName, address.sheetName, range, parse, write, namespace);
149
- this.schema[namespace] = orm;
150
- return orm;
151
- }
152
- removeTableSchema(namespace) {
153
- return this.removeSchemaOfType(namespace, "table");
85
+ emitMutation(footprint) {
86
+ this.evaluationManager.invalidateFromMutation(footprint);
87
+ this.eventManager.emitUpdate();
154
88
  }
155
- removeCellSchema(namespace) {
156
- return this.removeSchemaOfType(namespace, "cell");
89
+ emitUpdate() {
90
+ this.eventManager.emitUpdate();
157
91
  }
158
- removeGridSchema(namespace) {
159
- return this.removeSchemaOfType(namespace, "grid");
92
+ getExistingSheetContent(opts) {
93
+ const sheet = this.workbookManager.getSheet(opts);
94
+ return sheet ? new Map(sheet.content) : undefined;
160
95
  }
161
- removeSchemaOfType(namespace, type) {
162
- const schema = this.schemaManager.getSchema(namespace);
163
- if (!schema || schema.type !== type) {
164
- return false;
96
+ getWorkbookResourceKeys(workbookName) {
97
+ const resourceKeys = new Set([getWorkbookResourceKey(workbookName)]);
98
+ for (const sheetName of this.workbookManager.getWorkbooks().get(workbookName)?.sheets.keys() ?? []) {
99
+ resourceKeys.add(getSheetResourceKey({ workbookName, sheetName }));
165
100
  }
166
- const removed = this.schemaManager.removeSchema(namespace);
167
- if (removed) {
168
- delete this.schema[namespace];
101
+ for (const tableName of this.tableManager.getTables(workbookName).keys()) {
102
+ resourceKeys.add(getTableResourceKey({ workbookName, tableName }));
103
+ }
104
+ const namedExpressions = this.namedExpressionManager.getNamedExpressions();
105
+ for (const name of namedExpressions.workbookExpressions.get(workbookName)?.keys() ?? []) {
106
+ resourceKeys.add(getNamedExpressionResourceKey({ expressionName: name, workbookName }));
107
+ }
108
+ for (const [sheetName, expressions] of namedExpressions.sheetExpressions.get(workbookName) ?? []) {
109
+ resourceKeys.add(getSheetResourceKey({ workbookName, sheetName }));
110
+ for (const name of expressions.keys()) {
111
+ resourceKeys.add(getNamedExpressionResourceKey({
112
+ expressionName: name,
113
+ workbookName,
114
+ sheetName
115
+ }));
116
+ }
169
117
  }
170
- return removed;
118
+ return Array.from(resourceKeys);
119
+ }
120
+ getSheetResourceKeys(opts) {
121
+ const resourceKeys = new Set([
122
+ getWorkbookResourceKey(opts.workbookName),
123
+ getSheetResourceKey(opts)
124
+ ]);
125
+ for (const [tableName, table] of this.tableManager.getTables(opts.workbookName)) {
126
+ if (table.sheetName === opts.sheetName) {
127
+ resourceKeys.add(getTableResourceKey({ workbookName: opts.workbookName, tableName }));
128
+ }
129
+ }
130
+ const sheetExpressions = this.namedExpressionManager.getNamedExpressions().sheetExpressions.get(opts.workbookName)?.get(opts.sheetName);
131
+ for (const name of sheetExpressions?.keys() ?? []) {
132
+ resourceKeys.add(getNamedExpressionResourceKey({
133
+ expressionName: name,
134
+ workbookName: opts.workbookName,
135
+ sheetName: opts.sheetName
136
+ }));
137
+ }
138
+ return Array.from(resourceKeys);
171
139
  }
172
140
  getCellEvaluationResult(cellAddress) {
173
141
  return this.evaluationManager.getCellEvaluationResult(cellAddress);
@@ -180,7 +148,8 @@ class FormulaEngine {
180
148
  return this.evaluationManager.evaluationResultToSerializedValue(result, cellAddress, debug);
181
149
  }
182
150
  setCellMetadata(address, metadata) {
183
- this.commandExecutor.execute(new SetCellMetadataCommand(this.workbookManager, address, metadata));
151
+ this.workbookManager.setCellMetadata(address, metadata);
152
+ this.emitUpdate();
184
153
  }
185
154
  getCellMetadata(address) {
186
155
  const metadata = this.workbookManager.getCellMetadata(address);
@@ -190,13 +159,15 @@ class FormulaEngine {
190
159
  return this.workbookManager.getSheetMetadataSerialized(opts);
191
160
  }
192
161
  setSheetMetadata(opts, metadata) {
193
- this.commandExecutor.execute(new SetSheetMetadataCommand(this.workbookManager, opts, metadata));
162
+ this.workbookManager.setSheetMetadata(opts, metadata);
163
+ this.emitUpdate();
194
164
  }
195
165
  getSheetMetadata(opts) {
196
166
  return this.workbookManager.getSheetMetadata(opts);
197
167
  }
198
168
  setWorkbookMetadata(workbookName, metadata) {
199
- this.commandExecutor.execute(new SetWorkbookMetadataCommand(this.workbookManager, workbookName, metadata));
169
+ this.workbookManager.setWorkbookMetadata(workbookName, metadata);
170
+ this.emitUpdate();
200
171
  }
201
172
  getWorkbookMetadata(workbookName) {
202
173
  return this.workbookManager.getWorkbookMetadata(workbookName);
@@ -223,10 +194,20 @@ class FormulaEngine {
223
194
  throw new Error("Not implemented");
224
195
  }
225
196
  addNamedExpression(opts) {
226
- this.commandExecutor.execute(new AddNamedExpressionCommand(this.getNamedExpressionCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
197
+ this.namedExpressionManager.addNamedExpression(opts);
198
+ this.emitMutation({
199
+ touchedCells: [],
200
+ resourceKeys: [getNamedExpressionResourceKey(opts)]
201
+ });
227
202
  }
228
203
  removeNamedExpression(opts) {
229
- this.commandExecutor.execute(new RemoveNamedExpressionCommand(this.getNamedExpressionCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
204
+ const removed = this.namedExpressionManager.removeNamedExpression(opts);
205
+ if (removed) {
206
+ this.emitMutation({
207
+ touchedCells: [],
208
+ resourceKeys: [getNamedExpressionResourceKey(opts)]
209
+ });
210
+ }
230
211
  }
231
212
  hasNamedExpression(opts) {
232
213
  const scope = opts.sheetName && opts.workbookName ? {
@@ -240,25 +221,154 @@ class FormulaEngine {
240
221
  });
241
222
  }
242
223
  updateNamedExpression(opts) {
243
- this.commandExecutor.execute(new UpdateNamedExpressionCommand(this.getNamedExpressionCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
224
+ this.namedExpressionManager.updateNamedExpression(opts);
225
+ this.emitMutation({
226
+ touchedCells: [],
227
+ resourceKeys: [getNamedExpressionResourceKey(opts)]
228
+ });
244
229
  }
245
230
  renameNamedExpression(opts) {
246
- this.commandExecutor.execute(new RenameNamedExpressionCommand(this.getNamedExpressionCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
231
+ this.namedExpressionManager.renameNamedExpression(opts);
232
+ const changedCells = this.workbookManager.updateAllFormulas((formula) => renameNamedExpressionInFormula(formula, opts.expressionName, opts.newName));
233
+ const changedNamedExpressions = this.namedExpressionManager.updateAllNamedExpressions((formula) => renameNamedExpressionInFormula(formula, opts.expressionName, opts.newName));
234
+ this.emitMutation({
235
+ touchedCells: buildFormulaTouchedCells(changedCells),
236
+ resourceKeys: [
237
+ getNamedExpressionResourceKey({
238
+ expressionName: opts.expressionName,
239
+ workbookName: opts.workbookName,
240
+ sheetName: opts.sheetName
241
+ }),
242
+ getNamedExpressionResourceKey({
243
+ expressionName: opts.newName,
244
+ workbookName: opts.workbookName,
245
+ sheetName: opts.sheetName
246
+ }),
247
+ ...changedNamedExpressions
248
+ ]
249
+ });
247
250
  }
248
251
  setNamedExpressions(opts) {
249
- this.commandExecutor.execute(new SetNamedExpressionsCommand(this.getNamedExpressionCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
252
+ const allExpressions = this.namedExpressionManager.getNamedExpressions();
253
+ let previousExpressions;
254
+ if (opts.type === "global") {
255
+ previousExpressions = new Map(allExpressions.globalExpressions);
256
+ } else if (opts.type === "workbook") {
257
+ previousExpressions = new Map(allExpressions.workbookExpressions.get(opts.workbookName) || []);
258
+ } else {
259
+ const sheetExpressions = allExpressions.sheetExpressions.get(opts.workbookName)?.get(opts.sheetName);
260
+ previousExpressions = new Map(sheetExpressions || []);
261
+ }
262
+ this.namedExpressionManager.setNamedExpressions(opts);
263
+ const scope = opts.type === "global" ? {} : opts.type === "workbook" ? { workbookName: opts.workbookName } : {
264
+ workbookName: opts.workbookName,
265
+ sheetName: opts.sheetName
266
+ };
267
+ this.emitMutation({
268
+ touchedCells: [],
269
+ resourceKeys: [
270
+ ...getNamedExpressionScopeResourceKeys(previousExpressions.keys(), scope),
271
+ ...getNamedExpressionScopeResourceKeys(opts.expressions.keys(), scope)
272
+ ]
273
+ });
250
274
  }
251
275
  addTable(props) {
252
- this.commandExecutor.execute(new AddTableCommand(this.getTableCommandDeps(), props), { validate: this.schemaManager.hasSchemas() });
276
+ const table = this.tableManager.addTable({
277
+ ...props,
278
+ getCellValue: (cellAddress) => this.getCellValue(cellAddress)
279
+ });
280
+ this.emitMutation({
281
+ touchedCells: buildTableTouchedCells(this.workbookManager, [table]),
282
+ tableContextChangedCells: buildTableContextChangedCells(this.workbookManager, [table]),
283
+ resourceKeys: [
284
+ getTableResourceKey({
285
+ workbookName: props.workbookName,
286
+ tableName: props.tableName
287
+ })
288
+ ]
289
+ });
253
290
  }
254
291
  renameTable(workbookName, names) {
255
- this.commandExecutor.execute(new RenameTableCommand(this.getTableCommandDeps(), workbookName, names.oldName, names.newName), { validate: this.schemaManager.hasSchemas() });
292
+ const oldTable = this.tableManager.getTable({
293
+ workbookName,
294
+ name: names.oldName
295
+ });
296
+ const oldTableSnapshot = oldTable ? { ...oldTable, headers: new Map(oldTable.headers) } : undefined;
297
+ this.tableManager.renameTable(workbookName, names);
298
+ const changedCells = this.workbookManager.updateAllFormulas((formula) => renameTableInFormula(formula, names.oldName, names.newName));
299
+ const changedNamedExpressions = this.namedExpressionManager.updateAllNamedExpressions((formula) => renameTableInFormula(formula, names.oldName, names.newName));
300
+ const newTable = this.tableManager.getTable({
301
+ workbookName,
302
+ name: names.newName
303
+ });
304
+ this.emitMutation({
305
+ touchedCells: mergeTouchedCells(buildTableTouchedCells(this.workbookManager, [oldTableSnapshot]), buildTableTouchedCells(this.workbookManager, [newTable]), buildFormulaTouchedCells(changedCells)),
306
+ tableContextChangedCells: buildTableContextChangedCells(this.workbookManager, [oldTableSnapshot, newTable]),
307
+ resourceKeys: [
308
+ getTableResourceKey({
309
+ workbookName,
310
+ tableName: names.oldName
311
+ }),
312
+ getTableResourceKey({
313
+ workbookName,
314
+ tableName: names.newName
315
+ }),
316
+ ...changedNamedExpressions
317
+ ]
318
+ });
256
319
  }
257
320
  updateTable(opts) {
258
- this.commandExecutor.execute(new UpdateTableCommand(this.getTableCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
321
+ const oldTable = this.tableManager.getTable({
322
+ workbookName: opts.workbookName,
323
+ name: opts.tableName
324
+ });
325
+ const oldTableSnapshot = oldTable ? { ...oldTable, headers: new Map(oldTable.headers) } : undefined;
326
+ this.tableManager.updateTable({
327
+ ...opts,
328
+ getCellValue: (cellAddress) => this.getCellValue(cellAddress)
329
+ });
330
+ const newTable = this.tableManager.getTable({
331
+ workbookName: opts.workbookName,
332
+ name: opts.tableName
333
+ });
334
+ this.emitMutation({
335
+ touchedCells: mergeTouchedCells(buildTableTouchedCells(this.workbookManager, [oldTableSnapshot]), buildTableTouchedCells(this.workbookManager, [newTable])),
336
+ tableContextChangedCells: buildTableContextChangedCells(this.workbookManager, [oldTableSnapshot, newTable]),
337
+ resourceKeys: [
338
+ getTableResourceKey({
339
+ workbookName: opts.workbookName,
340
+ tableName: opts.tableName
341
+ })
342
+ ]
343
+ });
259
344
  }
260
345
  removeTable(opts) {
261
- this.commandExecutor.execute(new RemoveTableCommand(this.getTableCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
346
+ const oldTable = this.tableManager.getTable({
347
+ workbookName: opts.workbookName,
348
+ name: opts.tableName
349
+ });
350
+ const oldTableSnapshot = oldTable ? { ...oldTable, headers: new Map(oldTable.headers) } : undefined;
351
+ const found = this.tableManager.removeTable(opts);
352
+ if (found) {
353
+ this.emitMutation({
354
+ touchedCells: buildTableTouchedCells(this.workbookManager, [
355
+ oldTableSnapshot
356
+ ]),
357
+ tableContextChangedCells: buildTableContextChangedCells(this.workbookManager, [oldTableSnapshot]),
358
+ resourceKeys: [
359
+ getTableResourceKey({
360
+ workbookName: opts.workbookName,
361
+ tableName: opts.tableName
362
+ })
363
+ ]
364
+ });
365
+ }
366
+ }
367
+ getAllTables() {
368
+ return Array.from(this.tableManager.tables.values()).flatMap((tables) => Array.from(tables.values()).map((table) => ({
369
+ ...table,
370
+ headers: new Map(table.headers)
371
+ })));
262
372
  }
263
373
  hasTable(opts) {
264
374
  return !!this.tableManager.getTable({
@@ -273,7 +383,21 @@ class FormulaEngine {
273
383
  });
274
384
  }
275
385
  resetTables(tables) {
276
- this.commandExecutor.execute(new ResetTablesCommand(this.getTableCommandDeps(), tables), { validate: this.schemaManager.hasSchemas() });
386
+ const oldTables = this.getAllTables();
387
+ const newTables = Array.from(tables.values()).flatMap((workbookTables) => Array.from(workbookTables.values()));
388
+ const resourceKeys = new Set;
389
+ for (const table of [...oldTables, ...newTables]) {
390
+ resourceKeys.add(getTableResourceKey({
391
+ workbookName: table.workbookName,
392
+ tableName: table.name
393
+ }));
394
+ }
395
+ this.tableManager.resetTables(tables);
396
+ this.emitMutation({
397
+ touchedCells: mergeTouchedCells(buildTableTouchedCells(this.workbookManager, oldTables), buildTableTouchedCells(this.workbookManager, newTables)),
398
+ tableContextChangedCells: buildTableContextChangedCells(this.workbookManager, [...oldTables, ...newTables]),
399
+ resourceKeys: Array.from(resourceKeys)
400
+ });
277
401
  }
278
402
  getTables(workbookName) {
279
403
  return this.tableManager.getTables(workbookName);
@@ -281,28 +405,15 @@ class FormulaEngine {
281
405
  isCellInTable(cellAddress) {
282
406
  return this.tableManager.isCellInTable(cellAddress);
283
407
  }
284
- getTableDataCells(table) {
285
- const { start, endRow, headers } = table;
286
- const dataStartRow = start.rowIndex + 1;
287
- const endColIndex = start.colIndex + headers.size - 1;
288
- const rangeAddress = {
289
- workbookName: table.workbookName,
290
- sheetName: table.sheetName,
291
- range: {
292
- start: { col: start.colIndex, row: dataStartRow },
293
- end: {
294
- col: { type: "number", value: endColIndex },
295
- row: endRow
296
- }
297
- }
298
- };
299
- return this.workbookManager.getCellsInRange(rangeAddress);
300
- }
301
408
  addConditionalStyle(style) {
302
- this.commandExecutor.execute(new AddConditionalStyleCommand(this.styleManager, style));
409
+ this.styleManager.addConditionalStyle(style);
410
+ this.emitUpdate();
303
411
  }
304
412
  removeConditionalStyle(workbookName, index) {
305
- this.commandExecutor.execute(new RemoveConditionalStyleCommand(this.styleManager, workbookName, index));
413
+ const removed = this.styleManager.removeConditionalStyle(workbookName, index);
414
+ if (removed) {
415
+ this.emitUpdate();
416
+ }
306
417
  }
307
418
  getConditionalStyleCount(workbookName) {
308
419
  const allStyles = this.styleManager.getAllConditionalStyles();
@@ -321,10 +432,14 @@ class FormulaEngine {
321
432
  return this.styleManager.getAllConditionalStyles();
322
433
  }
323
434
  addCellStyle(style) {
324
- this.commandExecutor.execute(new AddCellStyleCommand(this.styleManager, style));
435
+ this.styleManager.addCellStyle(style);
436
+ this.emitUpdate();
325
437
  }
326
438
  removeCellStyle(workbookName, index) {
327
- this.commandExecutor.execute(new RemoveCellStyleCommand(this.styleManager, workbookName, index));
439
+ const removed = this.styleManager.removeCellStyle(workbookName, index);
440
+ if (removed) {
441
+ this.emitUpdate();
442
+ }
328
443
  }
329
444
  getCellStyleCount(workbookName) {
330
445
  const allStyles = this.styleManager.getAllCellStyles();
@@ -337,13 +452,69 @@ class FormulaEngine {
337
452
  return this.styleManager.getStyleForRange(range);
338
453
  }
339
454
  clearCellStyles(range) {
340
- this.commandExecutor.execute(new ClearCellStylesCommand(this.styleManager, range));
455
+ this.styleManager.clearCellStyles(range);
456
+ this.emitUpdate();
457
+ }
458
+ getTopLeftCell(cells) {
459
+ let topLeft = cells[0];
460
+ for (const cell of cells) {
461
+ if (cell.rowIndex < topLeft.rowIndex || cell.rowIndex === topLeft.rowIndex && cell.colIndex < topLeft.colIndex) {
462
+ topLeft = cell;
463
+ }
464
+ }
465
+ return topLeft;
466
+ }
467
+ dedupeAddresses(addresses) {
468
+ return Array.from(new Map(addresses.map((address) => [getMutationAddressKey(address), address])).values());
469
+ }
470
+ getPasteTouchedAddresses(source, target, options) {
471
+ if (source.length === 0) {
472
+ return [];
473
+ }
474
+ const topLeft = this.getTopLeftCell(source);
475
+ const colOffset = target.colIndex - topLeft.colIndex;
476
+ const rowOffset = target.rowIndex - topLeft.rowIndex;
477
+ const targetCells = source.map((sourceCell) => ({
478
+ workbookName: target.workbookName,
479
+ sheetName: target.sheetName,
480
+ colIndex: sourceCell.colIndex + colOffset,
481
+ rowIndex: sourceCell.rowIndex + rowOffset
482
+ }));
483
+ return this.dedupeAddresses(options.cut ? [...source, ...targetCells] : targetCells);
341
484
  }
342
485
  pasteCells(source, target, options) {
343
- this.commandExecutor.execute(new PasteCellsCommand(this.workbookManager, this.copyManager, source, target, options), { validate: this.schemaManager.hasSchemas() });
486
+ if (source.length === 0) {
487
+ return;
488
+ }
489
+ const touchedAddresses = this.getPasteTouchedAddresses(source, target, options);
490
+ const before = captureCellContents(this.workbookManager, touchedAddresses);
491
+ this.copyManager.pasteCells(source, target, options);
492
+ const after = captureCellContents(this.workbookManager, touchedAddresses);
493
+ this.emitMutation({
494
+ touchedCells: buildTouchedCells(touchedAddresses.map((address) => ({
495
+ address,
496
+ before: before.get(getMutationAddressKey(address)),
497
+ after: after.get(getMutationAddressKey(address))
498
+ }))),
499
+ resourceKeys: []
500
+ });
344
501
  }
345
502
  fillAreas(seedRange, targetRanges, options) {
346
- this.commandExecutor.execute(new FillAreasCommand(this.workbookManager, this.copyManager, seedRange, targetRanges, options), { validate: this.schemaManager.hasSchemas() });
503
+ const touchedAddresses = this.dedupeAddresses([
504
+ ...targetRanges.flatMap((targetRange) => getFiniteRangeAddresses(targetRange)),
505
+ ...options.cut ? getFiniteRangeAddresses(seedRange) : []
506
+ ]);
507
+ const before = captureCellContents(this.workbookManager, touchedAddresses);
508
+ this.copyManager.fillAreas(seedRange, targetRanges, options);
509
+ const after = captureCellContents(this.workbookManager, touchedAddresses);
510
+ this.emitMutation({
511
+ touchedCells: buildTouchedCells(touchedAddresses.map((address) => ({
512
+ address,
513
+ before: before.get(getMutationAddressKey(address)),
514
+ after: after.get(getMutationAddressKey(address))
515
+ }))),
516
+ resourceKeys: []
517
+ });
347
518
  }
348
519
  smartPaste(sourceCells, pasteSelection, options) {
349
520
  if (sourceCells.length === 0) {
@@ -424,17 +595,27 @@ class FormulaEngine {
424
595
  return { minCol, minRow, maxCol, maxRow };
425
596
  }
426
597
  moveCell(source, target) {
427
- this.commandExecutor.execute(new MoveCellCommand(this.workbookManager, this.copyManager, source, target), { validate: this.schemaManager.hasSchemas() });
598
+ this.pasteCells([source], target, {
599
+ cut: true,
600
+ type: "formula",
601
+ include: "all"
602
+ });
428
603
  }
429
604
  moveRange(sourceRange, target) {
430
- this.commandExecutor.execute(new MoveRangeCommand(this.workbookManager, this.copyManager, sourceRange, target), { validate: this.schemaManager.hasSchemas() });
605
+ const cells = this.copyManager.expandRangeToCells(sourceRange);
606
+ this.pasteCells(cells, target, {
607
+ cut: true,
608
+ type: "formula",
609
+ include: "all"
610
+ });
431
611
  }
432
612
  addSheet(opts) {
433
- this.commandExecutor.execute(new AddSheetCommand(this.getStructureCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
434
- const sheet = this.workbookManager.getSheet(opts);
435
- if (!sheet) {
436
- throw new Error(`Failed to create sheet '${opts.sheetName}'`);
437
- }
613
+ const sheet = this.workbookManager.addSheet(opts);
614
+ this.namedExpressionManager.addSheet(opts);
615
+ this.emitMutation({
616
+ touchedCells: [],
617
+ resourceKeys: [getSheetResourceKey(opts)]
618
+ });
438
619
  return sheet;
439
620
  }
440
621
  createSheet(opts) {
@@ -445,10 +626,40 @@ class FormulaEngine {
445
626
  });
446
627
  }
447
628
  removeSheet(opts) {
448
- this.commandExecutor.execute(new RemoveSheetCommand(this.getStructureCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
629
+ const resourceKeys = this.getSheetResourceKeys(opts);
630
+ this.workbookManager.removeSheet(opts);
631
+ this.namedExpressionManager.removeSheet(opts);
632
+ this.tableManager.removeSheet(opts);
633
+ this.styleManager.removeSheetStyles(opts.workbookName, opts.sheetName);
634
+ this.referenceManager.invalidateSheet(opts.workbookName, opts.sheetName);
635
+ this.emitMutation({
636
+ touchedCells: [],
637
+ resourceKeys,
638
+ removedScopes: [{ type: "sheet", ...opts }]
639
+ });
449
640
  }
450
641
  renameSheet(opts) {
451
- this.commandExecutor.execute(new RenameSheetCommand(this.getStructureCommandDeps(), opts), { validate: this.schemaManager.hasSchemas() });
642
+ const oldResourceKeys = this.getSheetResourceKeys(opts);
643
+ this.workbookManager.renameSheet(opts);
644
+ this.namedExpressionManager.renameSheet(opts);
645
+ this.tableManager.updateTablesForSheetRename(opts);
646
+ this.styleManager.updateSheetName(opts.workbookName, opts.sheetName, opts.newSheetName);
647
+ const changedCells = this.workbookManager.updateAllFormulas((formula) => renameSheetInFormula({
648
+ formula,
649
+ oldSheetName: opts.sheetName,
650
+ newSheetName: opts.newSheetName
651
+ }));
652
+ this.referenceManager.updateSheetName(opts.workbookName, opts.sheetName, opts.newSheetName);
653
+ this.emitMutation({
654
+ touchedCells: buildFormulaTouchedCells(changedCells),
655
+ resourceKeys: Array.from(new Set([
656
+ ...oldResourceKeys,
657
+ ...this.getSheetResourceKeys({
658
+ workbookName: opts.workbookName,
659
+ sheetName: opts.newSheetName
660
+ })
661
+ ]))
662
+ });
452
663
  }
453
664
  hasSheet(opts) {
454
665
  return !!this.workbookManager.getSheet(opts);
@@ -474,35 +685,234 @@ class FormulaEngine {
474
685
  getSheetSerialized(opts) {
475
686
  return this.workbookManager.getSheetSerialized(opts);
476
687
  }
688
+ search(query, options) {
689
+ return this.workbookManager.search(query, options);
690
+ }
691
+ replace(query, replacement, target, options) {
692
+ const prepared = this.workbookManager.prepareReplace(query, replacement, target, options);
693
+ this.workbookManager.setCellContent(prepared.address, prepared.afterContent);
694
+ this.emitMutation({
695
+ touchedCells: buildTouchedCells([
696
+ {
697
+ address: prepared.address,
698
+ before: prepared.beforeContent,
699
+ after: prepared.afterContent
700
+ }
701
+ ]),
702
+ resourceKeys: []
703
+ });
704
+ return prepared.change;
705
+ }
706
+ replaceAll(query, replacement, options) {
707
+ const preparedReplacements = this.workbookManager.prepareReplaceAll(query, replacement, options);
708
+ if (preparedReplacements.length === 0) {
709
+ return [];
710
+ }
711
+ for (const prepared of preparedReplacements) {
712
+ this.workbookManager.setCellContent(prepared.address, prepared.afterContent);
713
+ }
714
+ this.emitMutation({
715
+ touchedCells: buildTouchedCells(preparedReplacements.map((prepared) => ({
716
+ address: prepared.address,
717
+ before: prepared.beforeContent,
718
+ after: prepared.afterContent
719
+ }))),
720
+ resourceKeys: []
721
+ });
722
+ return preparedReplacements.flatMap((prepared) => prepared.changes);
723
+ }
477
724
  addWorkbook(workbookName) {
478
- this.commandExecutor.execute(new AddWorkbookCommand(this.getStructureCommandDeps(), workbookName), { validate: this.schemaManager.hasSchemas() });
725
+ this.workbookManager.addWorkbook(workbookName);
726
+ this.namedExpressionManager.addWorkbook(workbookName);
727
+ this.tableManager.addWorkbook(workbookName);
728
+ this.emitMutation({
729
+ touchedCells: [],
730
+ resourceKeys: [getWorkbookResourceKey(workbookName)]
731
+ });
479
732
  }
480
733
  removeWorkbook(workbookName) {
481
- this.commandExecutor.execute(new RemoveWorkbookCommand(this.getStructureCommandDeps(), workbookName), { validate: this.schemaManager.hasSchemas() });
734
+ const resourceKeys = this.getWorkbookResourceKeys(workbookName);
735
+ this.workbookManager.removeWorkbook(workbookName);
736
+ this.namedExpressionManager.removeWorkbook(workbookName);
737
+ this.tableManager.removeWorkbook(workbookName);
738
+ this.styleManager.removeWorkbookStyles(workbookName);
739
+ this.referenceManager.invalidateWorkbook(workbookName);
740
+ this.emitMutation({
741
+ touchedCells: [],
742
+ resourceKeys,
743
+ removedScopes: [{ type: "workbook", workbookName }]
744
+ });
482
745
  }
483
746
  hasWorkbook(workbookName) {
484
747
  return this.workbookManager.getWorkbooks().has(workbookName);
485
748
  }
486
749
  cloneWorkbook(fromWorkbookName, toWorkbookName) {
487
- this.commandExecutor.execute(new CloneWorkbookCommand(this.getStructureCommandDeps(), fromWorkbookName, toWorkbookName), { validate: this.schemaManager.hasSchemas() });
750
+ const sourceWorkbook = this.workbookManager.getWorkbooks().get(fromWorkbookName);
751
+ if (!sourceWorkbook) {
752
+ throw new Error(`Source workbook "${fromWorkbookName}" not found`);
753
+ }
754
+ if (this.workbookManager.getWorkbooks().has(toWorkbookName)) {
755
+ throw new Error(`Target workbook "${toWorkbookName}" already exists`);
756
+ }
757
+ this.workbookManager.addWorkbook(toWorkbookName);
758
+ this.namedExpressionManager.addWorkbook(toWorkbookName);
759
+ this.tableManager.addWorkbook(toWorkbookName);
760
+ for (const [sheetName, sheet] of sourceWorkbook.sheets) {
761
+ this.workbookManager.addSheet({
762
+ workbookName: toWorkbookName,
763
+ sheetName
764
+ });
765
+ this.namedExpressionManager.addSheet({
766
+ workbookName: toWorkbookName,
767
+ sheetName
768
+ });
769
+ this.workbookManager.setSheetContent({ workbookName: toWorkbookName, sheetName }, new Map(sheet.content));
770
+ const targetSheet = this.workbookManager.getSheet({
771
+ workbookName: toWorkbookName,
772
+ sheetName
773
+ });
774
+ if (targetSheet) {
775
+ targetSheet.metadata = new Map(sheet.metadata);
776
+ if (sheet.sheetMetadata !== undefined) {
777
+ targetSheet.sheetMetadata = structuredClone(sheet.sheetMetadata);
778
+ }
779
+ }
780
+ }
781
+ const targetWorkbook = this.workbookManager.getWorkbooks().get(toWorkbookName);
782
+ if (targetWorkbook && sourceWorkbook.workbookMetadata !== undefined) {
783
+ targetWorkbook.workbookMetadata = structuredClone(sourceWorkbook.workbookMetadata);
784
+ }
785
+ const namedExpressions = this.namedExpressionManager.getNamedExpressions();
786
+ const sourceWorkbookExpressions = namedExpressions.workbookExpressions.get(fromWorkbookName);
787
+ if (sourceWorkbookExpressions) {
788
+ for (const [expressionName, expression] of sourceWorkbookExpressions) {
789
+ this.namedExpressionManager.addNamedExpression({
790
+ expressionName,
791
+ expression: expression.expression,
792
+ workbookName: toWorkbookName
793
+ });
794
+ }
795
+ }
796
+ const sourceSheetExpressions = namedExpressions.sheetExpressions.get(fromWorkbookName);
797
+ if (sourceSheetExpressions) {
798
+ for (const [sheetName, expressions] of sourceSheetExpressions) {
799
+ for (const [expressionName, expression] of expressions) {
800
+ this.namedExpressionManager.addNamedExpression({
801
+ expressionName,
802
+ expression: expression.expression,
803
+ workbookName: toWorkbookName,
804
+ sheetName
805
+ });
806
+ }
807
+ }
808
+ }
809
+ const sourceTables = this.tableManager.tables.get(fromWorkbookName);
810
+ if (sourceTables) {
811
+ for (const [tableName] of sourceTables) {
812
+ this.tableManager.copyTable({ workbookName: fromWorkbookName, tableName }, { workbookName: toWorkbookName, tableName });
813
+ }
814
+ }
815
+ for (const style of this.styleManager.getAllConditionalStyles()) {
816
+ if (style.areas.some((area) => area.workbookName === fromWorkbookName)) {
817
+ this.styleManager.addConditionalStyle({
818
+ ...style,
819
+ areas: style.areas.map((area) => area.workbookName === fromWorkbookName ? { ...area, workbookName: toWorkbookName } : area)
820
+ });
821
+ }
822
+ }
823
+ for (const style of this.styleManager.getAllCellStyles()) {
824
+ if (style.areas.some((area) => area.workbookName === fromWorkbookName)) {
825
+ this.styleManager.addCellStyle({
826
+ ...style,
827
+ areas: style.areas.map((area) => area.workbookName === fromWorkbookName ? { ...area, workbookName: toWorkbookName } : area)
828
+ });
829
+ }
830
+ }
831
+ this.workbookManager.updateFormulasForWorkbook(toWorkbookName, (formula) => renameWorkbookInFormula({
832
+ formula,
833
+ oldWorkbookName: fromWorkbookName,
834
+ newWorkbookName: toWorkbookName
835
+ }));
836
+ this.emitMutation({
837
+ touchedCells: [],
838
+ resourceKeys: [getWorkbookResourceKey(toWorkbookName)]
839
+ });
488
840
  }
489
841
  renameWorkbook(opts) {
490
- this.commandExecutor.execute(new RenameWorkbookCommand(this.getStructureCommandDeps(), opts.workbookName, opts.newWorkbookName), { validate: this.schemaManager.hasSchemas() });
842
+ const oldResourceKeys = this.getWorkbookResourceKeys(opts.workbookName);
843
+ this.workbookManager.renameWorkbook(opts);
844
+ this.namedExpressionManager.renameWorkbook(opts);
845
+ this.tableManager.updateTablesForWorkbookRename(opts);
846
+ this.styleManager.updateWorkbookName(opts.workbookName, opts.newWorkbookName);
847
+ const changedCells = this.workbookManager.updateAllFormulas((formula) => renameWorkbookInFormula({
848
+ formula,
849
+ oldWorkbookName: opts.workbookName,
850
+ newWorkbookName: opts.newWorkbookName
851
+ }));
852
+ this.referenceManager.updateWorkbookName(opts.workbookName, opts.newWorkbookName);
853
+ this.emitMutation({
854
+ touchedCells: buildFormulaTouchedCells(changedCells),
855
+ resourceKeys: Array.from(new Set([
856
+ ...oldResourceKeys,
857
+ ...this.getWorkbookResourceKeys(opts.newWorkbookName)
858
+ ]))
859
+ });
491
860
  }
492
861
  getWorkbooks() {
493
862
  return this.workbookManager.getWorkbooks();
494
863
  }
495
864
  setSheetContent(opts, content) {
496
- this.commandExecutor.execute(new SetSheetContentCommand(this.workbookManager, opts, content), { validate: this.schemaManager.hasSchemas() });
865
+ const previousContent = this.getExistingSheetContent(opts);
866
+ this.workbookManager.setSheetContent(opts, content);
867
+ this.emitMutation({
868
+ touchedCells: buildSheetContentTouchedCells(opts, previousContent, content),
869
+ resourceKeys: []
870
+ });
497
871
  }
498
872
  setCellContent(address, content) {
499
- this.commandExecutor.execute(new SetCellContentCommand(this.workbookManager, address, content), { validate: this.schemaManager.hasSchemas() });
873
+ const previousValue = this.workbookManager.getCellContent(address);
874
+ this.workbookManager.setCellContent(address, content);
875
+ this.emitMutation({
876
+ touchedCells: buildTouchedCells([
877
+ {
878
+ address,
879
+ before: previousValue,
880
+ after: content
881
+ }
882
+ ]),
883
+ resourceKeys: []
884
+ });
500
885
  }
501
886
  autoFill(opts, seedRange, fillRanges, direction) {
502
- this.commandExecutor.execute(new AutoFillCommand(this.workbookManager, this.styleManager, this.autoFillManager, opts, seedRange, fillRanges, direction), { validate: this.schemaManager.hasSchemas() });
887
+ const touchedAddresses = this.dedupeAddresses(fillRanges.flatMap((range) => getFiniteRangeAddresses({
888
+ workbookName: opts.workbookName,
889
+ sheetName: opts.sheetName,
890
+ range
891
+ })));
892
+ const before = captureCellContents(this.workbookManager, touchedAddresses);
893
+ this.autoFillManager.fill(opts, seedRange, fillRanges, direction);
894
+ const after = captureCellContents(this.workbookManager, touchedAddresses);
895
+ this.emitMutation({
896
+ touchedCells: buildTouchedCells(touchedAddresses.map((address) => ({
897
+ address,
898
+ before: before.get(getMutationAddressKey(address)),
899
+ after: after.get(getMutationAddressKey(address))
900
+ }))),
901
+ resourceKeys: []
902
+ });
503
903
  }
504
904
  clearSpreadsheetRange(address) {
505
- this.commandExecutor.execute(new ClearRangeCommand(this.workbookManager, address), { validate: this.schemaManager.hasSchemas() });
905
+ const clearedCells = Array.from(this.workbookManager.iterateCellsInRange(address));
906
+ const before = captureCellContents(this.workbookManager, clearedCells);
907
+ this.workbookManager.clearSpreadsheetRange(address);
908
+ this.emitMutation({
909
+ touchedCells: buildTouchedCells(clearedCells.map((cellAddress) => ({
910
+ address: cellAddress,
911
+ before: before.get(getMutationAddressKey(cellAddress)),
912
+ after: undefined
913
+ }))),
914
+ resourceKeys: []
915
+ });
506
916
  }
507
917
  getState() {
508
918
  return {
@@ -558,63 +968,11 @@ class FormulaEngine {
558
968
  dependency: deserialized.managers.dependency,
559
969
  cache: deserialized.managers.cache
560
970
  }, this.evaluationManager);
561
- this.commandExecutor.clearHistory();
562
- this.commandExecutor.clearActionLog();
563
971
  this.eventManager.emitUpdate();
564
972
  }
565
- undo() {
566
- return this.commandExecutor.undo();
567
- }
568
- redo() {
569
- return this.commandExecutor.redo();
570
- }
571
- canUndo() {
572
- return this.commandExecutor.canUndo();
573
- }
574
- canRedo() {
575
- return this.commandExecutor.canRedo();
576
- }
577
- getActionLog() {
578
- return this.commandExecutor.getActionLog();
579
- }
580
- clearActionLog() {
581
- this.commandExecutor.clearActionLog();
582
- }
583
- clearHistory() {
584
- this.commandExecutor.clearHistory();
585
- }
586
- getStructureCommandDeps() {
587
- return {
588
- workbookManager: this.workbookManager,
589
- namedExpressionManager: this.namedExpressionManager,
590
- tableManager: this.tableManager,
591
- styleManager: this.styleManager,
592
- referenceManager: this.referenceManager,
593
- apiSchemaManager: this.schemaManager,
594
- renameSheetInFormula,
595
- renameWorkbookInFormula
596
- };
597
- }
598
- getTableCommandDeps() {
599
- return {
600
- tableManager: this.tableManager,
601
- namedExpressionManager: this.namedExpressionManager,
602
- workbookManager: this.workbookManager,
603
- apiSchemaManager: this.schemaManager,
604
- getCellValue: (cell) => this.getCellValue(cell),
605
- renameTableInFormula
606
- };
607
- }
608
- getNamedExpressionCommandDeps() {
609
- return {
610
- namedExpressionManager: this.namedExpressionManager,
611
- workbookManager: this.workbookManager,
612
- renameNamedExpressionInFormula
613
- };
614
- }
615
973
  }
616
974
  export {
617
975
  FormulaEngine
618
976
  };
619
977
 
620
- //# debugId=613601FAC854C5A464756E2164756E21
978
+ //# debugId=E7431D6779F19EBD64756E2164756E21