@actual-app/api 26.2.0-nightly.20260113 → 26.2.0-nightly.20260115

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.
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
10
10
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
11
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
12
  };
13
- var _g, _Stack_constructing, _LRUCache_instances, _LRUCache_max, _LRUCache_maxSize, _LRUCache_dispose, _LRUCache_onInsert, _LRUCache_disposeAfter, _LRUCache_fetchMethod, _LRUCache_memoMethod, _LRUCache_perf, _LRUCache_size, _LRUCache_calculatedSize, _LRUCache_keyMap, _LRUCache_keyList, _LRUCache_valList, _LRUCache_next, _LRUCache_prev, _LRUCache_head, _LRUCache_tail, _LRUCache_free, _LRUCache_disposed, _LRUCache_sizes, _LRUCache_starts, _LRUCache_ttls, _LRUCache_hasDispose, _LRUCache_hasFetchMethod, _LRUCache_hasDisposeAfter, _LRUCache_hasOnInsert, _LRUCache_initializeTTLTracking, _LRUCache_updateItemAge, _LRUCache_statusTTL, _LRUCache_setItemTTL, _LRUCache_isStale, _LRUCache_initializeSizeTracking, _LRUCache_removeItemSize, _LRUCache_addItemSize, _LRUCache_requireSize, _LRUCache_indexes, _LRUCache_rindexes, _LRUCache_isValidIndex, _LRUCache_evict, _LRUCache_backgroundFetch, _LRUCache_isBackgroundFetch, _LRUCache_connect, _LRUCache_moveToTail, _LRUCache_delete, _LRUCache_clear, _h;
13
+ var _g, _Stack_constructing, _LRUCache_instances, _LRUCache_max, _LRUCache_maxSize, _LRUCache_dispose, _LRUCache_onInsert, _LRUCache_disposeAfter, _LRUCache_fetchMethod, _LRUCache_memoMethod, _LRUCache_perf, _LRUCache_size, _LRUCache_calculatedSize, _LRUCache_keyMap, _LRUCache_keyList, _LRUCache_valList, _LRUCache_next, _LRUCache_prev, _LRUCache_head, _LRUCache_tail, _LRUCache_free, _LRUCache_disposed, _LRUCache_sizes, _LRUCache_starts, _LRUCache_ttls, _LRUCache_autopurgeTimers, _LRUCache_hasDispose, _LRUCache_hasFetchMethod, _LRUCache_hasDisposeAfter, _LRUCache_hasOnInsert, _LRUCache_initializeTTLTracking, _LRUCache_updateItemAge, _LRUCache_statusTTL, _LRUCache_setItemTTL, _LRUCache_isStale, _LRUCache_initializeSizeTracking, _LRUCache_removeItemSize, _LRUCache_addItemSize, _LRUCache_requireSize, _LRUCache_indexes, _LRUCache_rindexes, _LRUCache_isValidIndex, _LRUCache_evict, _LRUCache_backgroundFetch, _LRUCache_isBackgroundFetch, _LRUCache_connect, _LRUCache_moveToTail, _LRUCache_delete, _LRUCache_clear, _h;
14
14
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
15
15
  const fs$1 = require("fs");
16
16
  const path = require("path");
@@ -4272,6 +4272,7 @@ class LRUCache {
4272
4272
  // properties
4273
4273
  starts: __classPrivateFieldGet(c, _LRUCache_starts, "f"),
4274
4274
  ttls: __classPrivateFieldGet(c, _LRUCache_ttls, "f"),
4275
+ autopurgeTimers: __classPrivateFieldGet(c, _LRUCache_autopurgeTimers, "f"),
4275
4276
  sizes: __classPrivateFieldGet(c, _LRUCache_sizes, "f"),
4276
4277
  keyMap: __classPrivateFieldGet(c, _LRUCache_keyMap, "f"),
4277
4278
  keyList: __classPrivateFieldGet(c, _LRUCache_keyList, "f"),
@@ -4372,6 +4373,7 @@ class LRUCache {
4372
4373
  _LRUCache_sizes.set(this, void 0);
4373
4374
  _LRUCache_starts.set(this, void 0);
4374
4375
  _LRUCache_ttls.set(this, void 0);
4376
+ _LRUCache_autopurgeTimers.set(this, void 0);
4375
4377
  _LRUCache_hasDispose.set(this, void 0);
4376
4378
  _LRUCache_hasFetchMethod.set(this, void 0);
4377
4379
  _LRUCache_hasDisposeAfter.set(this, void 0);
@@ -4592,15 +4594,21 @@ class LRUCache {
4592
4594
  * Iterating over the cache itself yields the same results as
4593
4595
  * {@link LRUCache.entries}
4594
4596
  */
4595
- [(_LRUCache_max = new WeakMap(), _LRUCache_maxSize = new WeakMap(), _LRUCache_dispose = new WeakMap(), _LRUCache_onInsert = new WeakMap(), _LRUCache_disposeAfter = new WeakMap(), _LRUCache_fetchMethod = new WeakMap(), _LRUCache_memoMethod = new WeakMap(), _LRUCache_perf = new WeakMap(), _LRUCache_size = new WeakMap(), _LRUCache_calculatedSize = new WeakMap(), _LRUCache_keyMap = new WeakMap(), _LRUCache_keyList = new WeakMap(), _LRUCache_valList = new WeakMap(), _LRUCache_next = new WeakMap(), _LRUCache_prev = new WeakMap(), _LRUCache_head = new WeakMap(), _LRUCache_tail = new WeakMap(), _LRUCache_free = new WeakMap(), _LRUCache_disposed = new WeakMap(), _LRUCache_sizes = new WeakMap(), _LRUCache_starts = new WeakMap(), _LRUCache_ttls = new WeakMap(), _LRUCache_hasDispose = new WeakMap(), _LRUCache_hasFetchMethod = new WeakMap(), _LRUCache_hasDisposeAfter = new WeakMap(), _LRUCache_hasOnInsert = new WeakMap(), _LRUCache_updateItemAge = new WeakMap(), _LRUCache_statusTTL = new WeakMap(), _LRUCache_setItemTTL = new WeakMap(), _LRUCache_isStale = new WeakMap(), _LRUCache_removeItemSize = new WeakMap(), _LRUCache_addItemSize = new WeakMap(), _LRUCache_requireSize = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_initializeTTLTracking = function _LRUCache_initializeTTLTracking() {
4597
+ [(_LRUCache_max = new WeakMap(), _LRUCache_maxSize = new WeakMap(), _LRUCache_dispose = new WeakMap(), _LRUCache_onInsert = new WeakMap(), _LRUCache_disposeAfter = new WeakMap(), _LRUCache_fetchMethod = new WeakMap(), _LRUCache_memoMethod = new WeakMap(), _LRUCache_perf = new WeakMap(), _LRUCache_size = new WeakMap(), _LRUCache_calculatedSize = new WeakMap(), _LRUCache_keyMap = new WeakMap(), _LRUCache_keyList = new WeakMap(), _LRUCache_valList = new WeakMap(), _LRUCache_next = new WeakMap(), _LRUCache_prev = new WeakMap(), _LRUCache_head = new WeakMap(), _LRUCache_tail = new WeakMap(), _LRUCache_free = new WeakMap(), _LRUCache_disposed = new WeakMap(), _LRUCache_sizes = new WeakMap(), _LRUCache_starts = new WeakMap(), _LRUCache_ttls = new WeakMap(), _LRUCache_autopurgeTimers = new WeakMap(), _LRUCache_hasDispose = new WeakMap(), _LRUCache_hasFetchMethod = new WeakMap(), _LRUCache_hasDisposeAfter = new WeakMap(), _LRUCache_hasOnInsert = new WeakMap(), _LRUCache_updateItemAge = new WeakMap(), _LRUCache_statusTTL = new WeakMap(), _LRUCache_setItemTTL = new WeakMap(), _LRUCache_isStale = new WeakMap(), _LRUCache_removeItemSize = new WeakMap(), _LRUCache_addItemSize = new WeakMap(), _LRUCache_requireSize = new WeakMap(), _LRUCache_instances = new WeakSet(), _LRUCache_initializeTTLTracking = function _LRUCache_initializeTTLTracking() {
4596
4598
  const ttls = new ZeroArray(__classPrivateFieldGet(this, _LRUCache_max, "f"));
4597
4599
  const starts = new ZeroArray(__classPrivateFieldGet(this, _LRUCache_max, "f"));
4598
4600
  __classPrivateFieldSet(this, _LRUCache_ttls, ttls, "f");
4599
4601
  __classPrivateFieldSet(this, _LRUCache_starts, starts, "f");
4602
+ const purgeTimers = this.ttlAutopurge ? new Array(__classPrivateFieldGet(this, _LRUCache_max, "f")) : void 0;
4603
+ __classPrivateFieldSet(this, _LRUCache_autopurgeTimers, purgeTimers, "f");
4600
4604
  __classPrivateFieldSet(this, _LRUCache_setItemTTL, (index, ttl, start = __classPrivateFieldGet(this, _LRUCache_perf, "f").now()) => {
4601
4605
  starts[index] = ttl !== 0 ? start : 0;
4602
4606
  ttls[index] = ttl;
4603
- if (ttl !== 0 && this.ttlAutopurge) {
4607
+ if (purgeTimers?.[index]) {
4608
+ clearTimeout(purgeTimers[index]);
4609
+ purgeTimers[index] = void 0;
4610
+ }
4611
+ if (ttl !== 0 && purgeTimers) {
4604
4612
  const t2 = setTimeout(() => {
4605
4613
  if (__classPrivateFieldGet(this, _LRUCache_isStale, "f").call(this, index)) {
4606
4614
  __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_delete).call(this, __classPrivateFieldGet(this, _LRUCache_keyList, "f")[index], "expire");
@@ -4609,6 +4617,7 @@ class LRUCache {
4609
4617
  if (t2.unref) {
4610
4618
  t2.unref();
4611
4619
  }
4620
+ purgeTimers[index] = t2;
4612
4621
  }
4613
4622
  }, "f");
4614
4623
  __classPrivateFieldSet(this, _LRUCache_updateItemAge, (index) => {
@@ -5280,6 +5289,10 @@ _h = Symbol.toStringTag, _LRUCache_evict = function _LRUCache_evict(free) {
5280
5289
  }
5281
5290
  }
5282
5291
  __classPrivateFieldGet(this, _LRUCache_removeItemSize, "f").call(this, head);
5292
+ if (__classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")?.[head]) {
5293
+ clearTimeout(__classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")[head]);
5294
+ __classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")[head] = void 0;
5295
+ }
5283
5296
  if (free) {
5284
5297
  __classPrivateFieldGet(this, _LRUCache_keyList, "f")[head] = void 0;
5285
5298
  __classPrivateFieldGet(this, _LRUCache_valList, "f")[head] = void 0;
@@ -5433,6 +5446,10 @@ _h = Symbol.toStringTag, _LRUCache_evict = function _LRUCache_evict(free) {
5433
5446
  if (__classPrivateFieldGet(this, _LRUCache_size, "f") !== 0) {
5434
5447
  const index = __classPrivateFieldGet(this, _LRUCache_keyMap, "f").get(k);
5435
5448
  if (index !== void 0) {
5449
+ if (__classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")?.[index]) {
5450
+ clearTimeout(__classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")?.[index]);
5451
+ __classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")[index] = void 0;
5452
+ }
5436
5453
  deleted = true;
5437
5454
  if (__classPrivateFieldGet(this, _LRUCache_size, "f") === 1) {
5438
5455
  __classPrivateFieldGet(this, _LRUCache_instances, "m", _LRUCache_clear).call(this, reason);
@@ -5501,6 +5518,11 @@ _h = Symbol.toStringTag, _LRUCache_evict = function _LRUCache_evict(free) {
5501
5518
  if (__classPrivateFieldGet(this, _LRUCache_ttls, "f") && __classPrivateFieldGet(this, _LRUCache_starts, "f")) {
5502
5519
  __classPrivateFieldGet(this, _LRUCache_ttls, "f").fill(0);
5503
5520
  __classPrivateFieldGet(this, _LRUCache_starts, "f").fill(0);
5521
+ for (const t2 of __classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f") ?? []) {
5522
+ if (t2 !== void 0)
5523
+ clearTimeout(t2);
5524
+ }
5525
+ __classPrivateFieldGet(this, _LRUCache_autopurgeTimers, "f")?.fill(void 0);
5504
5526
  }
5505
5527
  if (__classPrivateFieldGet(this, _LRUCache_sizes, "f")) {
5506
5528
  __classPrivateFieldGet(this, _LRUCache_sizes, "f").fill(0);
@@ -5725,7 +5747,7 @@ const millisecondsInDay = 864e5;
5725
5747
  const millisecondsInMinute = 6e4;
5726
5748
  const millisecondsInHour = 36e5;
5727
5749
  const millisecondsInSecond = 1e3;
5728
- const constructFromSymbol = Symbol.for("constructDateFrom");
5750
+ const constructFromSymbol = /* @__PURE__ */ Symbol.for("constructDateFrom");
5729
5751
  function constructFrom(date, value) {
5730
5752
  if (typeof date === "function")
5731
5753
  return date(value);
@@ -9879,7 +9901,7 @@ var postProcessor = {
9879
9901
  return value;
9880
9902
  }
9881
9903
  };
9882
- const PATH_KEY = Symbol("i18next/PATH_KEY");
9904
+ const PATH_KEY = /* @__PURE__ */ Symbol("i18next/PATH_KEY");
9883
9905
  function createProxy() {
9884
9906
  const state = [];
9885
9907
  const handler = /* @__PURE__ */ Object.create(null);
@@ -10520,9 +10542,6 @@ class PluralResolver {
10520
10542
  this.logger = baseLogger.create("pluralResolver");
10521
10543
  this.pluralRulesCache = {};
10522
10544
  }
10523
- addRule(lng, obj) {
10524
- this.rules[lng] = obj;
10525
- }
10526
10545
  clearCache() {
10527
10546
  this.pluralRulesCache = {};
10528
10547
  }
@@ -11302,6 +11321,9 @@ class I18n extends EventEmitter {
11302
11321
  if (options.nsSeparator !== void 0) {
11303
11322
  this.options.userDefinedNsSeparator = options.nsSeparator;
11304
11323
  }
11324
+ if (typeof this.options.overloadTranslationOptionHandler !== "function") {
11325
+ this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
11326
+ }
11305
11327
  const createClassOnDemand = (ClassOrObject) => {
11306
11328
  if (!ClassOrObject)
11307
11329
  return null;
@@ -11780,6 +11802,19 @@ class I18n extends EventEmitter {
11780
11802
  clone.store = new ResourceStore(clonedData, mergedOptions);
11781
11803
  clone.services.resourceStore = clone.store;
11782
11804
  }
11805
+ if (options.interpolation) {
11806
+ const defOpts = get$4();
11807
+ const mergedInterpolation = {
11808
+ ...defOpts.interpolation,
11809
+ ...this.options.interpolation,
11810
+ ...options.interpolation
11811
+ };
11812
+ const mergedForInterpolator = {
11813
+ ...mergedOptions,
11814
+ interpolation: mergedInterpolation
11815
+ };
11816
+ clone.services.interpolator = new Interpolator(mergedForInterpolator);
11817
+ }
11783
11818
  clone.translator = new Translator(clone.services, mergedOptions);
11784
11819
  clone.translator.on("*", (event, ...args) => {
11785
11820
  clone.emit(event, ...args);
@@ -14365,8 +14400,14 @@ const schema = {
14365
14400
  goal: f("integer"),
14366
14401
  long_goal: f("integer")
14367
14402
  },
14403
+ dashboard_pages: {
14404
+ id: f("id"),
14405
+ name: f("string"),
14406
+ tombstone: f("boolean")
14407
+ },
14368
14408
  dashboard: {
14369
14409
  id: f("id"),
14410
+ dashboard_page_id: f("id", { ref: "dashboard_pages" }),
14370
14411
  type: f("string", { required: true }),
14371
14412
  width: f("integer", { required: true }),
14372
14413
  height: f("integer", { required: true }),
@@ -59696,33 +59737,6 @@ async function listRemoteFiles() {
59696
59737
  hasKey: hasKey(file.encryptKeyId)
59697
59738
  })).filter(Boolean);
59698
59739
  }
59699
- async function getRemoteFile(fileId) {
59700
- const userToken = await getItem("user-token");
59701
- if (!userToken) {
59702
- return null;
59703
- }
59704
- let res;
59705
- try {
59706
- res = await fetchJSON(getServer().SYNC_SERVER + "/get-user-file-info", {
59707
- headers: {
59708
- "X-ACTUAL-TOKEN": userToken,
59709
- "X-ACTUAL-FILE-ID": fileId
59710
- }
59711
- });
59712
- }
59713
- catch (e) {
59714
- logger.log("Unexpected error fetching file from server", e);
59715
- return null;
59716
- }
59717
- if (res.status === "error") {
59718
- logger.log("Error fetching file from server", res);
59719
- return null;
59720
- }
59721
- return {
59722
- ...res.data,
59723
- hasKey: hasKey(res.data.encryptKeyId)
59724
- };
59725
- }
59726
59740
  async function download(cloudFileId) {
59727
59741
  const userToken = await getItem("user-token");
59728
59742
  const syncServer = getServer().SYNC_SERVER;
@@ -66159,7 +66173,7 @@ class CellAddress {
66159
66173
  return new CellAddress(this.col, this.row, this.type, sheet);
66160
66174
  }
66161
66175
  isInvalid(baseAddress) {
66162
- return invalidSimpleCellAddress(this.toSimpleCellAddress(baseAddress));
66176
+ return isColOrRowInvalid(this.toSimpleCellAddress(baseAddress));
66163
66177
  }
66164
66178
  shiftRelativeDimensions(toRight, toBottom) {
66165
66179
  const col = this.isColumnAbsolute() ? this.col : this.col + toRight;
@@ -66190,7 +66204,7 @@ class CellAddress {
66190
66204
  }
66191
66205
  unparse(baseAddress) {
66192
66206
  const simpleAddress = this.toSimpleCellAddress(baseAddress);
66193
- if (invalidSimpleCellAddress(simpleAddress)) {
66207
+ if (isColOrRowInvalid(simpleAddress)) {
66194
66208
  return void 0;
66195
66209
  }
66196
66210
  const column = columnIndexToLabel(simpleAddress.col);
@@ -66223,17 +66237,18 @@ const addressRegex = new RegExp(`^(${SHEET_NAME_PATTERN})?(\\${ABSOLUTE_OPERATOR
66223
66237
  const columnRegex = new RegExp(`^(${SHEET_NAME_PATTERN})?(\\${ABSOLUTE_OPERATOR}?)([A-Za-z]+)$`);
66224
66238
  const rowRegex = new RegExp(`^(${SHEET_NAME_PATTERN})?(\\${ABSOLUTE_OPERATOR}?)([0-9]+)$`);
66225
66239
  const simpleSheetNameRegex = new RegExp(`^${UNQUOTED_SHEET_NAME_PATTERN}$`);
66226
- const cellAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66240
+ const cellAddressFromString = (stringAddress, baseAddress, resolveSheetReference) => {
66227
66241
  const result = addressRegex.exec(stringAddress);
66228
- const col = columnLabelToIndex(result[6]);
66229
- let sheet = extractSheetNumber(result, sheetMapping);
66230
- if (sheet === void 0) {
66242
+ if (!result) {
66231
66243
  return void 0;
66232
66244
  }
66245
+ const col = columnLabelToIndex(result[6]);
66246
+ const row = Number(result[8]) - 1;
66247
+ const sheetName = extractSheetName(result);
66248
+ const sheet = sheetNameToId(sheetName, resolveSheetReference);
66233
66249
  if (sheet === null) {
66234
- sheet = void 0;
66250
+ return void 0;
66235
66251
  }
66236
- const row = Number(result[8]) - 1;
66237
66252
  if (result[5] === ABSOLUTE_OPERATOR && result[7] === ABSOLUTE_OPERATOR) {
66238
66253
  return CellAddress.absolute(col, row, sheet);
66239
66254
  }
@@ -66247,16 +66262,17 @@ const cellAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66247
66262
  return CellAddress.relative(col - baseAddress.col, row - baseAddress.row, sheet);
66248
66263
  }
66249
66264
  };
66250
- const columnAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66265
+ const columnAddressFromString = (stringAddress, baseAddress, resolveSheetReference) => {
66251
66266
  const result = columnRegex.exec(stringAddress);
66252
- let sheet = extractSheetNumber(result, sheetMapping);
66253
- if (sheet === void 0) {
66267
+ if (!result) {
66254
66268
  return void 0;
66255
66269
  }
66270
+ const col = columnLabelToIndex(result[6]);
66271
+ const sheetName = extractSheetName(result);
66272
+ const sheet = sheetNameToId(sheetName, resolveSheetReference);
66256
66273
  if (sheet === null) {
66257
- sheet = void 0;
66274
+ return void 0;
66258
66275
  }
66259
- const col = columnLabelToIndex(result[6]);
66260
66276
  if (result[5] === ABSOLUTE_OPERATOR) {
66261
66277
  return ColumnAddress.absolute(col, sheet);
66262
66278
  }
@@ -66264,16 +66280,17 @@ const columnAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66264
66280
  return ColumnAddress.relative(col - baseAddress.col, sheet);
66265
66281
  }
66266
66282
  };
66267
- const rowAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66283
+ const rowAddressFromString = (stringAddress, baseAddress, resolveSheetReference) => {
66268
66284
  const result = rowRegex.exec(stringAddress);
66269
- let sheet = extractSheetNumber(result, sheetMapping);
66270
- if (sheet === void 0) {
66285
+ if (!result) {
66271
66286
  return void 0;
66272
66287
  }
66288
+ const row = Number(result[6]) - 1;
66289
+ const sheetName = extractSheetName(result);
66290
+ const sheet = sheetNameToId(sheetName, resolveSheetReference);
66273
66291
  if (sheet === null) {
66274
- sheet = void 0;
66292
+ return void 0;
66275
66293
  }
66276
- const row = Number(result[6]) - 1;
66277
66294
  if (result[5] === ABSOLUTE_OPERATOR) {
66278
66295
  return RowAddress.absolute(row, sheet);
66279
66296
  }
@@ -66281,33 +66298,32 @@ const rowAddressFromString = (sheetMapping, stringAddress, baseAddress) => {
66281
66298
  return RowAddress.relative(row - baseAddress.row, sheet);
66282
66299
  }
66283
66300
  };
66284
- const simpleCellAddressFromString = (sheetMapping, stringAddress, contextSheetId) => {
66301
+ const simpleCellAddressFromString = (resolveSheetReference, stringAddress, contextSheetId) => {
66285
66302
  const regExpExecArray = addressRegex.exec(stringAddress);
66286
66303
  if (!regExpExecArray) {
66287
66304
  return void 0;
66288
66305
  }
66289
66306
  const col = columnLabelToIndex(regExpExecArray[6]);
66290
- let sheet = extractSheetNumber(regExpExecArray, sheetMapping);
66291
- if (sheet === void 0) {
66292
- return void 0;
66293
- }
66307
+ const row = Number(regExpExecArray[8]) - 1;
66308
+ const sheetName = extractSheetName(regExpExecArray);
66309
+ const sheet = sheetNameToId(sheetName, resolveSheetReference);
66294
66310
  if (sheet === null) {
66295
- sheet = contextSheetId;
66311
+ return void 0;
66296
66312
  }
66297
- const row = Number(regExpExecArray[8]) - 1;
66298
- return simpleCellAddress(sheet, col, row);
66313
+ const effectiveSheet = sheet === void 0 ? contextSheetId : sheet;
66314
+ return simpleCellAddress(effectiveSheet, col, row);
66299
66315
  };
66300
- const simpleCellRangeFromString = (sheetMapping, stringAddress, contextSheetId) => {
66316
+ const simpleCellRangeFromString = (resolveSheetReference, stringAddress, contextSheetId) => {
66301
66317
  const split2 = stringAddress.split(RANGE_OPERATOR);
66302
66318
  if (split2.length !== 2) {
66303
66319
  return void 0;
66304
66320
  }
66305
66321
  const [startString, endString] = split2;
66306
- const start = simpleCellAddressFromString(sheetMapping, startString, contextSheetId);
66322
+ const start = simpleCellAddressFromString(resolveSheetReference, startString, contextSheetId);
66307
66323
  if (start === void 0) {
66308
66324
  return void 0;
66309
66325
  }
66310
- const end = simpleCellAddressFromString(sheetMapping, endString, start.sheet);
66326
+ const end = simpleCellAddressFromString(resolveSheetReference, endString, start.sheet);
66311
66327
  if (end === void 0) {
66312
66328
  return void 0;
66313
66329
  }
@@ -66370,16 +66386,17 @@ function sheetIndexToString(sheetId, sheetMappingFn) {
66370
66386
  return `'${sheetName}'`;
66371
66387
  }
66372
66388
  }
66373
- function extractSheetNumber(regexResult, sheetMapping) {
66389
+ function extractSheetName(regexResult) {
66374
66390
  var _a;
66375
- let maybeSheetName = (_a = regexResult[3]) !== null && _a !== void 0 ? _a : regexResult[2];
66376
- if (maybeSheetName) {
66377
- maybeSheetName = maybeSheetName.replace(/''/g, "'");
66378
- return sheetMapping(maybeSheetName);
66379
- }
66380
- else {
66381
- return null;
66391
+ const maybeSheetName = (_a = regexResult[3]) !== null && _a !== void 0 ? _a : regexResult[2];
66392
+ return maybeSheetName ? maybeSheetName.replace(/''/g, "'") : null;
66393
+ }
66394
+ function sheetNameToId(sheetName, resolveSheetReference) {
66395
+ if (!sheetName) {
66396
+ return void 0;
66382
66397
  }
66398
+ const sheetId = resolveSheetReference(sheetName);
66399
+ return sheetId === void 0 ? null : sheetId;
66383
66400
  }
66384
66401
  function isEmpty(arr) {
66385
66402
  return arr && arr.length === 0;
@@ -74868,11 +74885,12 @@ const buildLexerConfig = (config2) => {
74868
74885
  };
74869
74886
  };
74870
74887
  class FormulaParser extends EmbeddedActionsParser {
74871
- constructor(lexerConfig, sheetMapping) {
74888
+ constructor(lexerConfig, resolveSheetReference) {
74872
74889
  super(lexerConfig.allTokens, {
74873
74890
  outputCst: false,
74874
74891
  maxLookahead: 7
74875
74892
  });
74893
+ this.resolveSheetReference = resolveSheetReference;
74876
74894
  this.booleanExpressionOrEmpty = this.RULE("booleanExpressionOrEmpty", () => {
74877
74895
  return this.OR([{
74878
74896
  ALT: () => this.SUBRULE(this.booleanExpression)
@@ -74923,8 +74941,8 @@ class FormulaParser extends EmbeddedActionsParser {
74923
74941
  this.columnRangeExpression = this.RULE("columnRangeExpression", () => {
74924
74942
  const range2 = this.CONSUME(ColumnRange);
74925
74943
  const [startImage, endImage] = range2.image.split(":");
74926
- const firstAddress = this.ACTION(() => columnAddressFromString(this.sheetMapping, startImage, this.formulaAddress));
74927
- const secondAddress = this.ACTION(() => columnAddressFromString(this.sheetMapping, endImage, this.formulaAddress));
74944
+ const firstAddress = this.ACTION(() => columnAddressFromString(startImage, this.formulaAddress, this.resolveSheetReference));
74945
+ const secondAddress = this.ACTION(() => columnAddressFromString(endImage, this.formulaAddress, this.resolveSheetReference));
74928
74946
  if (firstAddress === void 0 || secondAddress === void 0) {
74929
74947
  return buildCellErrorAst(new CellError(ErrorType.REF));
74930
74948
  }
@@ -74940,8 +74958,8 @@ class FormulaParser extends EmbeddedActionsParser {
74940
74958
  this.rowRangeExpression = this.RULE("rowRangeExpression", () => {
74941
74959
  const range2 = this.CONSUME(RowRange);
74942
74960
  const [startImage, endImage] = range2.image.split(":");
74943
- const firstAddress = this.ACTION(() => rowAddressFromString(this.sheetMapping, startImage, this.formulaAddress));
74944
- const secondAddress = this.ACTION(() => rowAddressFromString(this.sheetMapping, endImage, this.formulaAddress));
74961
+ const firstAddress = this.ACTION(() => rowAddressFromString(startImage, this.formulaAddress, this.resolveSheetReference));
74962
+ const secondAddress = this.ACTION(() => rowAddressFromString(endImage, this.formulaAddress, this.resolveSheetReference));
74945
74963
  if (firstAddress === void 0 || secondAddress === void 0) {
74946
74964
  return buildCellErrorAst(new CellError(ErrorType.REF));
74947
74965
  }
@@ -74957,7 +74975,7 @@ class FormulaParser extends EmbeddedActionsParser {
74957
74975
  this.cellReference = this.RULE("cellReference", () => {
74958
74976
  const cell = this.CONSUME(CellReference);
74959
74977
  const address = this.ACTION(() => {
74960
- return cellAddressFromString(this.sheetMapping, cell.image, this.formulaAddress);
74978
+ return cellAddressFromString(cell.image, this.formulaAddress, this.resolveSheetReference);
74961
74979
  });
74962
74980
  if (address === void 0) {
74963
74981
  return buildErrorWithRawInputAst(cell.image, new CellError(ErrorType.REF), cell.leadingWhitespace);
@@ -74973,10 +74991,10 @@ class FormulaParser extends EmbeddedActionsParser {
74973
74991
  var _a;
74974
74992
  const end = this.CONSUME(CellReference);
74975
74993
  const startAddress = this.ACTION(() => {
74976
- return cellAddressFromString(this.sheetMapping, start.image, this.formulaAddress);
74994
+ return cellAddressFromString(start.image, this.formulaAddress, this.resolveSheetReference);
74977
74995
  });
74978
74996
  const endAddress = this.ACTION(() => {
74979
- return cellAddressFromString(this.sheetMapping, end.image, this.formulaAddress);
74997
+ return cellAddressFromString(end.image, this.formulaAddress, this.resolveSheetReference);
74980
74998
  });
74981
74999
  if (startAddress === void 0 || endAddress === void 0) {
74982
75000
  return this.ACTION(() => {
@@ -75002,7 +75020,7 @@ class FormulaParser extends EmbeddedActionsParser {
75002
75020
  var _a;
75003
75021
  const offsetProcedure = this.SUBRULE(this.offsetProcedureExpression);
75004
75022
  const startAddress = this.ACTION(() => {
75005
- return cellAddressFromString(this.sheetMapping, start.image, this.formulaAddress);
75023
+ return cellAddressFromString(start.image, this.formulaAddress, this.resolveSheetReference);
75006
75024
  });
75007
75025
  if (startAddress === void 0) {
75008
75026
  return buildCellErrorAst(new CellError(ErrorType.REF));
@@ -75026,7 +75044,7 @@ class FormulaParser extends EmbeddedActionsParser {
75026
75044
  this.endRangeWithOffsetStartReference = this.RULE("endRangeWithOffsetStartReference", (start) => {
75027
75045
  const end = this.CONSUME(CellReference);
75028
75046
  const endAddress = this.ACTION(() => {
75029
- return cellAddressFromString(this.sheetMapping, end.image, this.formulaAddress);
75047
+ return cellAddressFromString(end.image, this.formulaAddress, this.resolveSheetReference);
75030
75048
  });
75031
75049
  if (endAddress === void 0) {
75032
75050
  return this.ACTION(() => {
@@ -75285,7 +75303,6 @@ class FormulaParser extends EmbeddedActionsParser {
75285
75303
  return this.SUBRULE(this.booleanExpression);
75286
75304
  });
75287
75305
  this.lexerConfig = lexerConfig;
75288
- this.sheetMapping = sheetMapping;
75289
75306
  this.formulaAddress = simpleCellAddress(0, 0, 0);
75290
75307
  this.performSelfAnalysis();
75291
75308
  }
@@ -75507,10 +75524,9 @@ class FormulaLexer {
75507
75524
  }
75508
75525
  }
75509
75526
  class Unparser {
75510
- constructor(config2, lexerConfig, sheetMappingFn, namedExpressions) {
75527
+ constructor(config2, sheetMapping, namedExpressions) {
75511
75528
  this.config = config2;
75512
- this.lexerConfig = lexerConfig;
75513
- this.sheetMappingFn = sheetMappingFn;
75529
+ this.sheetMapping = sheetMapping;
75514
75530
  this.namedExpressions = namedExpressions;
75515
75531
  }
75516
75532
  unparse(ast, address) {
@@ -75588,8 +75604,15 @@ class Unparser {
75588
75604
  }
75589
75605
  }
75590
75606
  }
75607
+ /**
75608
+ * Unparses a sheet name.
75609
+ * @param {number} sheetId - the ID of the sheet
75610
+ * @returns {string} the unparsed sheet name
75611
+ */
75591
75612
  unparseSheetName(sheetId) {
75592
- const sheetName = sheetIndexToString(sheetId, this.sheetMappingFn);
75613
+ const sheetName = sheetIndexToString(sheetId, (id2) => this.sheetMapping.getSheetNameOrThrowError(id2, {
75614
+ includePlaceholders: true
75615
+ }));
75593
75616
  if (sheetName === void 0) {
75594
75617
  throw new NoSheetWithIdError(sheetId);
75595
75618
  }
@@ -75617,14 +75640,14 @@ function formatNumber(number2, decimalSeparator) {
75617
75640
  return numericString.replace(".", decimalSeparator);
75618
75641
  }
75619
75642
  class ParserWithCaching {
75620
- constructor(config2, functionRegistry, sheetMapping) {
75643
+ constructor(config2, functionRegistry, resolveSheetReference) {
75621
75644
  this.config = config2;
75622
75645
  this.functionRegistry = functionRegistry;
75623
- this.sheetMapping = sheetMapping;
75646
+ this.resolveSheetReference = resolveSheetReference;
75624
75647
  this.statsCacheUsed = 0;
75625
75648
  this.lexerConfig = buildLexerConfig(config2);
75626
75649
  this.lexer = new FormulaLexer(this.lexerConfig);
75627
- this.formulaParser = new FormulaParser(this.lexerConfig, this.sheetMapping);
75650
+ this.formulaParser = new FormulaParser(this.lexerConfig, this.resolveSheetReference);
75628
75651
  this.cache = new Cache(this.functionRegistry);
75629
75652
  }
75630
75653
  /**
@@ -75820,7 +75843,7 @@ class ParserWithCaching {
75820
75843
  while (idx < tokens.length) {
75821
75844
  const token = tokens[idx];
75822
75845
  if (tokenMatcher(token, CellReference)) {
75823
- const cellAddress = cellAddressFromString(this.sheetMapping, token.image, baseAddress);
75846
+ const cellAddress = cellAddressFromString(token.image, baseAddress, this.resolveSheetReference);
75824
75847
  if (cellAddress === void 0) {
75825
75848
  hash = hash.concat(token.image);
75826
75849
  }
@@ -75835,8 +75858,8 @@ class ParserWithCaching {
75835
75858
  }
75836
75859
  else if (tokenMatcher(token, ColumnRange)) {
75837
75860
  const [start, end] = token.image.split(":");
75838
- const startAddress = columnAddressFromString(this.sheetMapping, start, baseAddress);
75839
- const endAddress = columnAddressFromString(this.sheetMapping, end, baseAddress);
75861
+ const startAddress = columnAddressFromString(start, baseAddress, this.resolveSheetReference);
75862
+ const endAddress = columnAddressFromString(end, baseAddress, this.resolveSheetReference);
75840
75863
  if (startAddress === void 0 || endAddress === void 0) {
75841
75864
  hash = hash.concat("!REF");
75842
75865
  }
@@ -75846,8 +75869,8 @@ class ParserWithCaching {
75846
75869
  }
75847
75870
  else if (tokenMatcher(token, RowRange)) {
75848
75871
  const [start, end] = token.image.split(":");
75849
- const startAddress = rowAddressFromString(this.sheetMapping, start, baseAddress);
75850
- const endAddress = rowAddressFromString(this.sheetMapping, end, baseAddress);
75872
+ const startAddress = rowAddressFromString(start, baseAddress, this.resolveSheetReference);
75873
+ const endAddress = rowAddressFromString(end, baseAddress, this.resolveSheetReference);
75851
75874
  if (startAddress === void 0 || endAddress === void 0) {
75852
75875
  hash = hash.concat("!REF");
75853
75876
  }
@@ -76080,14 +76103,14 @@ const filterDependenciesOutOfScope = (deps) => {
76080
76103
  return true;
76081
76104
  }
76082
76105
  if (dep instanceof AbsoluteCellRange) {
76083
- return !(invalidSimpleCellAddress(dep.start) || invalidSimpleCellAddress(dep.end));
76106
+ return !(isColOrRowInvalid(dep.start) || isColOrRowInvalid(dep.end));
76084
76107
  }
76085
76108
  else {
76086
- return !invalidSimpleCellAddress(dep);
76109
+ return !isColOrRowInvalid(dep);
76087
76110
  }
76088
76111
  });
76089
76112
  };
76090
- const EmptyValue = Symbol("Empty value");
76113
+ const EmptyValue = /* @__PURE__ */ Symbol("Empty value");
76091
76114
  function getRawValue(num2) {
76092
76115
  if (num2 instanceof RichNumber) {
76093
76116
  return num2.val;
@@ -76414,6 +76437,299 @@ class ContentChanges {
76414
76437
  });
76415
76438
  }
76416
76439
  }
76440
+ class InternalNamedExpression {
76441
+ constructor(displayName, address, added, options) {
76442
+ this.displayName = displayName;
76443
+ this.address = address;
76444
+ this.added = added;
76445
+ this.options = options;
76446
+ }
76447
+ normalizeExpressionName() {
76448
+ return this.displayName.toLowerCase();
76449
+ }
76450
+ copy() {
76451
+ return new InternalNamedExpression(this.displayName, this.address, this.added, this.options);
76452
+ }
76453
+ }
76454
+ class WorkbookStore {
76455
+ constructor() {
76456
+ this.mapping = /* @__PURE__ */ new Map();
76457
+ }
76458
+ has(expressionName) {
76459
+ return this.mapping.has(this.normalizeExpressionName(expressionName));
76460
+ }
76461
+ isNameAvailable(expressionName) {
76462
+ const normalizedExpressionName = this.normalizeExpressionName(expressionName);
76463
+ const namedExpression = this.mapping.get(normalizedExpressionName);
76464
+ return !(namedExpression && namedExpression.added);
76465
+ }
76466
+ add(namedExpression) {
76467
+ this.mapping.set(namedExpression.normalizeExpressionName(), namedExpression);
76468
+ }
76469
+ get(expressionName) {
76470
+ return this.mapping.get(this.normalizeExpressionName(expressionName));
76471
+ }
76472
+ getExisting(expressionName) {
76473
+ const namedExpression = this.mapping.get(this.normalizeExpressionName(expressionName));
76474
+ if (namedExpression && namedExpression.added) {
76475
+ return namedExpression;
76476
+ }
76477
+ else {
76478
+ return void 0;
76479
+ }
76480
+ }
76481
+ remove(expressionName) {
76482
+ const normalizedExpressionName = this.normalizeExpressionName(expressionName);
76483
+ const namedExpression = this.mapping.get(normalizedExpressionName);
76484
+ if (namedExpression) {
76485
+ namedExpression.added = false;
76486
+ }
76487
+ }
76488
+ getAllNamedExpressions() {
76489
+ return Array.from(this.mapping.values()).filter((ne) => ne.added);
76490
+ }
76491
+ normalizeExpressionName(expressionName) {
76492
+ return expressionName.toLowerCase();
76493
+ }
76494
+ }
76495
+ class WorksheetStore {
76496
+ constructor() {
76497
+ this.mapping = /* @__PURE__ */ new Map();
76498
+ }
76499
+ add(namedExpression) {
76500
+ this.mapping.set(this.normalizeExpressionName(namedExpression.displayName), namedExpression);
76501
+ }
76502
+ get(expressionName) {
76503
+ return this.mapping.get(this.normalizeExpressionName(expressionName));
76504
+ }
76505
+ has(expressionName) {
76506
+ return this.mapping.has(this.normalizeExpressionName(expressionName));
76507
+ }
76508
+ getAllNamedExpressions() {
76509
+ return Array.from(this.mapping.values()).filter((ne) => ne.added);
76510
+ }
76511
+ isNameAvailable(expressionName) {
76512
+ const normalizedExpressionName = this.normalizeExpressionName(expressionName);
76513
+ return !this.mapping.has(normalizedExpressionName);
76514
+ }
76515
+ remove(expressionName) {
76516
+ const normalizedExpressionName = this.normalizeExpressionName(expressionName);
76517
+ const namedExpression = this.mapping.get(normalizedExpressionName);
76518
+ if (namedExpression) {
76519
+ this.mapping.delete(normalizedExpressionName);
76520
+ }
76521
+ }
76522
+ normalizeExpressionName(expressionName) {
76523
+ return expressionName.toLowerCase();
76524
+ }
76525
+ }
76526
+ class NamedExpressions {
76527
+ constructor() {
76528
+ this.nextNamedExpressionRow = 0;
76529
+ this.workbookStore = new WorkbookStore();
76530
+ this.worksheetStores = /* @__PURE__ */ new Map();
76531
+ this.addressCache = /* @__PURE__ */ new Map();
76532
+ }
76533
+ isNameAvailable(expressionName, sheetId) {
76534
+ var _a, _b;
76535
+ if (sheetId === void 0) {
76536
+ return this.workbookStore.isNameAvailable(expressionName);
76537
+ }
76538
+ else {
76539
+ return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.isNameAvailable(expressionName)) !== null && _b !== void 0 ? _b : true;
76540
+ }
76541
+ }
76542
+ namedExpressionInAddress(row) {
76543
+ const namedExpression = this.addressCache.get(row);
76544
+ if (namedExpression && namedExpression.added) {
76545
+ return namedExpression;
76546
+ }
76547
+ else {
76548
+ return void 0;
76549
+ }
76550
+ }
76551
+ namedExpressionForScope(expressionName, sheetId) {
76552
+ var _a;
76553
+ if (sheetId === void 0) {
76554
+ return this.workbookStore.getExisting(expressionName);
76555
+ }
76556
+ else {
76557
+ return (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.get(expressionName);
76558
+ }
76559
+ }
76560
+ nearestNamedExpression(expressionName, sheetId) {
76561
+ var _a, _b;
76562
+ return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.get(expressionName)) !== null && _b !== void 0 ? _b : this.workbookStore.getExisting(expressionName);
76563
+ }
76564
+ isExpressionInScope(expressionName, sheetId) {
76565
+ var _a, _b;
76566
+ return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.has(expressionName)) !== null && _b !== void 0 ? _b : false;
76567
+ }
76568
+ /**
76569
+ * Checks the validity of a named-expression's name.
76570
+ *
76571
+ * The name:
76572
+ * - Must start with a Unicode letter or with an underscore (`_`).
76573
+ * - Can contain only Unicode letters, numbers, underscores, and periods (`.`).
76574
+ * - Can't be the same as any possible reference in the A1 notation (`[A-Za-z]+[0-9]+`).
76575
+ * - Can't be the same as any possible reference in the R1C1 notation (`[rR][0-9]*[cC][0-9]*`).
76576
+ *
76577
+ * The naming rules follow the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#__RefHeading__1017964_715980110) standard.
76578
+ */
76579
+ isNameValid(expressionName) {
76580
+ const a1CellRefRegexp = new RegExp(`^${CELL_REFERENCE_PATTERN}$`);
76581
+ const r1c1CellRefRegexp = new RegExp(`^${R1C1_CELL_REFERENCE_PATTERN}$`);
76582
+ const namedExpRegexp = new RegExp(`^${NAMED_EXPRESSION_PATTERN}$`);
76583
+ if (a1CellRefRegexp.test(expressionName) || r1c1CellRefRegexp.test(expressionName)) {
76584
+ return false;
76585
+ }
76586
+ return namedExpRegexp.test(expressionName);
76587
+ }
76588
+ addNamedExpression(expressionName, sheetId, options) {
76589
+ const store2 = sheetId === void 0 ? this.workbookStore : this.worksheetStoreOrCreate(sheetId);
76590
+ let namedExpression = store2.get(expressionName);
76591
+ if (namedExpression !== void 0) {
76592
+ namedExpression.added = true;
76593
+ namedExpression.displayName = expressionName;
76594
+ namedExpression.options = options;
76595
+ }
76596
+ else {
76597
+ namedExpression = new InternalNamedExpression(expressionName, this.nextAddress(), true, options);
76598
+ store2.add(namedExpression);
76599
+ }
76600
+ this.addressCache.set(namedExpression.address.row, namedExpression);
76601
+ return namedExpression;
76602
+ }
76603
+ restoreNamedExpression(namedExpression, sheetId) {
76604
+ const store2 = sheetId === void 0 ? this.workbookStore : this.worksheetStoreOrCreate(sheetId);
76605
+ namedExpression.added = true;
76606
+ store2.add(namedExpression);
76607
+ this.addressCache.set(namedExpression.address.row, namedExpression);
76608
+ return namedExpression;
76609
+ }
76610
+ namedExpressionOrPlaceholder(expressionName, sheetId) {
76611
+ var _a;
76612
+ return (_a = this.worksheetStoreOrCreate(sheetId).get(expressionName)) !== null && _a !== void 0 ? _a : this.workbookNamedExpressionOrPlaceholder(expressionName);
76613
+ }
76614
+ workbookNamedExpressionOrPlaceholder(expressionName) {
76615
+ let namedExpression = this.workbookStore.get(expressionName);
76616
+ if (namedExpression === void 0) {
76617
+ namedExpression = new InternalNamedExpression(expressionName, this.nextAddress(), false);
76618
+ this.workbookStore.add(namedExpression);
76619
+ }
76620
+ return namedExpression;
76621
+ }
76622
+ remove(expressionName, sheetId) {
76623
+ let store2;
76624
+ if (sheetId === void 0) {
76625
+ store2 = this.workbookStore;
76626
+ }
76627
+ else {
76628
+ store2 = this.worksheetStore(sheetId);
76629
+ }
76630
+ const namedExpression = store2 === null || store2 === void 0 ? void 0 : store2.get(expressionName);
76631
+ if (store2 === void 0 || namedExpression === void 0 || !namedExpression.added) {
76632
+ throw Error("Named expression does not exist");
76633
+ }
76634
+ store2.remove(expressionName);
76635
+ if (store2 instanceof WorksheetStore && store2.mapping.size === 0) {
76636
+ this.worksheetStores.delete(sheetId);
76637
+ }
76638
+ this.addressCache.delete(namedExpression.address.row);
76639
+ }
76640
+ getAllNamedExpressionsNamesInScope(sheetId) {
76641
+ return this.getAllNamedExpressions().filter(({ scope }) => scope === sheetId).map((ne) => ne.expression.displayName);
76642
+ }
76643
+ getAllNamedExpressionsNames() {
76644
+ return this.getAllNamedExpressions().map((ne) => ne.expression.displayName);
76645
+ }
76646
+ getAllNamedExpressions() {
76647
+ const storedNamedExpressions = [];
76648
+ this.workbookStore.getAllNamedExpressions().forEach((expr) => {
76649
+ storedNamedExpressions.push({
76650
+ expression: expr,
76651
+ scope: void 0
76652
+ });
76653
+ });
76654
+ this.worksheetStores.forEach((store2, sheetNum) => {
76655
+ store2.getAllNamedExpressions().forEach((expr) => {
76656
+ storedNamedExpressions.push({
76657
+ expression: expr,
76658
+ scope: sheetNum
76659
+ });
76660
+ });
76661
+ });
76662
+ return storedNamedExpressions;
76663
+ }
76664
+ getAllNamedExpressionsForScope(scope) {
76665
+ var _a, _b;
76666
+ if (scope === void 0) {
76667
+ return this.workbookStore.getAllNamedExpressions();
76668
+ }
76669
+ else {
76670
+ return (_b = (_a = this.worksheetStores.get(scope)) === null || _a === void 0 ? void 0 : _a.getAllNamedExpressions()) !== null && _b !== void 0 ? _b : [];
76671
+ }
76672
+ }
76673
+ worksheetStoreOrCreate(sheetId) {
76674
+ let store2 = this.worksheetStores.get(sheetId);
76675
+ if (!store2) {
76676
+ store2 = new WorksheetStore();
76677
+ this.worksheetStores.set(sheetId, store2);
76678
+ }
76679
+ return store2;
76680
+ }
76681
+ worksheetStore(sheetId) {
76682
+ return this.worksheetStores.get(sheetId);
76683
+ }
76684
+ nextAddress() {
76685
+ return simpleCellAddress(NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS, 0, this.nextNamedExpressionRow++);
76686
+ }
76687
+ }
76688
+ NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS = -1;
76689
+ const doesContainRelativeReferences = (ast) => {
76690
+ switch (ast.type) {
76691
+ case AstNodeType.EMPTY:
76692
+ case AstNodeType.NUMBER:
76693
+ case AstNodeType.STRING:
76694
+ case AstNodeType.ERROR:
76695
+ case AstNodeType.ERROR_WITH_RAW_INPUT:
76696
+ return false;
76697
+ case AstNodeType.CELL_REFERENCE:
76698
+ return !ast.reference.isAbsolute();
76699
+ case AstNodeType.CELL_RANGE:
76700
+ case AstNodeType.COLUMN_RANGE:
76701
+ case AstNodeType.ROW_RANGE:
76702
+ return !ast.start.isAbsolute();
76703
+ case AstNodeType.NAMED_EXPRESSION:
76704
+ return false;
76705
+ case AstNodeType.PERCENT_OP:
76706
+ case AstNodeType.PLUS_UNARY_OP:
76707
+ case AstNodeType.MINUS_UNARY_OP: {
76708
+ return doesContainRelativeReferences(ast.value);
76709
+ }
76710
+ case AstNodeType.CONCATENATE_OP:
76711
+ case AstNodeType.EQUALS_OP:
76712
+ case AstNodeType.NOT_EQUAL_OP:
76713
+ case AstNodeType.LESS_THAN_OP:
76714
+ case AstNodeType.GREATER_THAN_OP:
76715
+ case AstNodeType.LESS_THAN_OR_EQUAL_OP:
76716
+ case AstNodeType.GREATER_THAN_OR_EQUAL_OP:
76717
+ case AstNodeType.MINUS_OP:
76718
+ case AstNodeType.PLUS_OP:
76719
+ case AstNodeType.TIMES_OP:
76720
+ case AstNodeType.DIV_OP:
76721
+ case AstNodeType.POWER_OP:
76722
+ return doesContainRelativeReferences(ast.left) || doesContainRelativeReferences(ast.right);
76723
+ case AstNodeType.PARENTHESIS:
76724
+ return doesContainRelativeReferences(ast.expression);
76725
+ case AstNodeType.FUNCTION_CALL: {
76726
+ return ast.args.some((arg) => doesContainRelativeReferences(arg));
76727
+ }
76728
+ case AstNodeType.ARRAY: {
76729
+ return ast.args.some((row) => row.some((arg) => doesContainRelativeReferences(arg)));
76730
+ }
76731
+ }
76732
+ };
76417
76733
  class RowsSpan {
76418
76734
  constructor(sheet, rowStart, rowEnd) {
76419
76735
  this.sheet = sheet;
@@ -76805,68 +77121,164 @@ class AddressMapping {
76805
77121
  this.policy = policy;
76806
77122
  this.mapping = /* @__PURE__ */ new Map();
76807
77123
  }
76808
- /** @inheritDoc */
76809
- getCell(address) {
77124
+ /**
77125
+ * Gets the cell vertex at the specified address.
77126
+ */
77127
+ getCell(address, options = {}) {
76810
77128
  const sheetMapping = this.mapping.get(address.sheet);
76811
- if (sheetMapping === void 0) {
76812
- throw new NoSheetWithIdError(address.sheet);
77129
+ if (!sheetMapping) {
77130
+ if (options.throwIfSheetNotExists) {
77131
+ throw new NoSheetWithIdError(address.sheet);
77132
+ }
77133
+ return void 0;
77134
+ }
77135
+ const cell = sheetMapping.getCell(address);
77136
+ if (!cell && options.throwIfCellNotExists) {
77137
+ throw Error("Vertex for address missing in AddressMapping");
76813
77138
  }
76814
- return sheetMapping.getCell(address);
77139
+ return cell;
76815
77140
  }
76816
- fetchCell(address) {
77141
+ /**
77142
+ * Gets the cell vertex at the specified address or throws if it doesn't exist.
77143
+ * @throws {NoSheetWithIdError} if sheet doesn't exist
77144
+ * @throws {Error} if cell doesn't exist
77145
+ */
77146
+ getCellOrThrow(address) {
76817
77147
  const sheetMapping = this.mapping.get(address.sheet);
76818
- if (sheetMapping === void 0) {
77148
+ if (!sheetMapping) {
76819
77149
  throw new NoSheetWithIdError(address.sheet);
76820
77150
  }
76821
- const vertex = sheetMapping.getCell(address);
76822
- if (!vertex) {
77151
+ const cell = sheetMapping.getCell(address);
77152
+ if (!cell) {
76823
77153
  throw Error("Vertex for address missing in AddressMapping");
76824
77154
  }
76825
- return vertex;
77155
+ return cell;
76826
77156
  }
76827
- strategyFor(sheetId) {
77157
+ /**
77158
+ * Gets the address mapping strategy for the specified sheet.
77159
+ * @throws {NoSheetWithIdError} if sheet doesn't exist
77160
+ */
77161
+ getStrategyForSheetOrThrow(sheetId) {
76828
77162
  const strategy = this.mapping.get(sheetId);
76829
77163
  if (strategy === void 0) {
76830
77164
  throw new NoSheetWithIdError(sheetId);
76831
77165
  }
76832
77166
  return strategy;
76833
77167
  }
76834
- addSheet(sheetId, strategy) {
76835
- if (this.mapping.has(sheetId)) {
76836
- throw Error("Sheet already added");
77168
+ /**
77169
+ * Adds a new sheet with the specified strategy.
77170
+ * @throws {Error} if sheet is already added and throwIfSheetAlreadyExists is true
77171
+ */
77172
+ addSheetWithStrategy(sheetId, strategy, options = {
77173
+ throwIfSheetAlreadyExists: true
77174
+ }) {
77175
+ const strategyFound = this.mapping.get(sheetId);
77176
+ if (strategyFound) {
77177
+ if (options.throwIfSheetAlreadyExists) {
77178
+ throw Error("Sheet already added");
77179
+ }
77180
+ return strategyFound;
76837
77181
  }
76838
77182
  this.mapping.set(sheetId, strategy);
77183
+ return strategy;
76839
77184
  }
76840
- autoAddSheet(sheetId, sheetBoundaries) {
77185
+ /**
77186
+ * Adds a sheet or changes the strategy for an existing sheet.
77187
+ * Designed for the purpose of exchanging the placeholder strategy for a real strategy.
77188
+ */
77189
+ addSheetOrChangeStrategy(sheetId, sheetBoundaries) {
77190
+ const newStrategy = this.createStrategyBasedOnBoundaries(sheetBoundaries);
77191
+ const strategyPlaceholder = this.mapping.get(sheetId);
77192
+ if (!strategyPlaceholder) {
77193
+ this.mapping.set(sheetId, newStrategy);
77194
+ return newStrategy;
77195
+ }
77196
+ if (newStrategy instanceof DenseStrategy) {
77197
+ return strategyPlaceholder;
77198
+ }
77199
+ this.moveStrategyContent(strategyPlaceholder, newStrategy, sheetId);
77200
+ this.mapping.set(sheetId, newStrategy);
77201
+ return newStrategy;
77202
+ }
77203
+ /**
77204
+ * Moves the content of the source strategy to the target strategy.
77205
+ */
77206
+ moveStrategyContent(sourceStrategy, targetStrategy, sheetContext) {
77207
+ const sourceVertices = sourceStrategy.getEntries(sheetContext);
77208
+ for (const [address, vertex] of sourceVertices) {
77209
+ targetStrategy.setCell(address, vertex);
77210
+ }
77211
+ }
77212
+ /**
77213
+ * Adds a sheet and sets the strategy based on the sheet boundaries.
77214
+ * @throws {Error} if sheet already exists and throwIfSheetAlreadyExists is true
77215
+ */
77216
+ addSheetAndSetStrategyBasedOnBoundaries(sheetId, sheetBoundaries, options = {
77217
+ throwIfSheetAlreadyExists: true
77218
+ }) {
77219
+ this.addSheetWithStrategy(sheetId, this.createStrategyBasedOnBoundaries(sheetBoundaries), options);
77220
+ }
77221
+ /**
77222
+ * Creates a strategy based on the sheet boundaries.
77223
+ */
77224
+ createStrategyBasedOnBoundaries(sheetBoundaries) {
76841
77225
  const { height, width, fill } = sheetBoundaries;
76842
77226
  const strategyConstructor = this.policy.call(fill);
76843
- this.addSheet(sheetId, new strategyConstructor(width, height));
77227
+ return new strategyConstructor(width, height);
77228
+ }
77229
+ /**
77230
+ * Adds a placeholder strategy (DenseStrategy) for a sheet. If the sheet already exists, does nothing.
77231
+ */
77232
+ addSheetStrategyPlaceholderIfNotExists(sheetId) {
77233
+ if (this.mapping.has(sheetId)) {
77234
+ return;
77235
+ }
77236
+ this.mapping.set(sheetId, new DenseStrategy(0, 0));
77237
+ }
77238
+ /**
77239
+ * Removes a sheet from the address mapping.
77240
+ * If sheet does not exist, does nothing.
77241
+ * @returns {boolean} true if sheet was removed, false if it did not exist.
77242
+ */
77243
+ removeSheetIfExists(sheetId) {
77244
+ return this.mapping.delete(sheetId);
76844
77245
  }
77246
+ /**
77247
+ * Gets the interpreter value of a cell at the specified address.
77248
+ * @returns {InterpreterValue} The interpreter value (returns EmptyValue if cell doesn't exist)
77249
+ */
76845
77250
  getCellValue(address) {
76846
77251
  const vertex = this.getCell(address);
76847
77252
  if (vertex === void 0) {
76848
77253
  return EmptyValue;
76849
77254
  }
76850
- else if (vertex instanceof ArrayVertex) {
77255
+ else if (vertex instanceof ArrayFormulaVertex) {
76851
77256
  return vertex.getArrayCellValue(address);
76852
77257
  }
76853
77258
  else {
76854
77259
  return vertex.getCellValue();
76855
77260
  }
76856
77261
  }
77262
+ /**
77263
+ * Gets the raw cell content at the specified address.
77264
+ * @returns {RawCellContent} The raw cell content or null if cell doesn't exist or is not a value cell
77265
+ */
76857
77266
  getRawValue(address) {
76858
77267
  const vertex = this.getCell(address);
76859
77268
  if (vertex instanceof ValueCellVertex) {
76860
77269
  return vertex.getValues().rawValue;
76861
77270
  }
76862
- else if (vertex instanceof ArrayVertex) {
77271
+ else if (vertex instanceof ArrayFormulaVertex) {
76863
77272
  return vertex.getArrayCellRawValue(address);
76864
77273
  }
76865
77274
  else {
76866
77275
  return null;
76867
77276
  }
76868
77277
  }
76869
- /** @inheritDoc */
77278
+ /**
77279
+ * Sets a cell vertex at the specified address.
77280
+ * @throws {Error} if sheet not initialized
77281
+ */
76870
77282
  setCell(address, newVertex) {
76871
77283
  const sheetMapping = this.mapping.get(address.sheet);
76872
77284
  if (!sheetMapping) {
@@ -76874,15 +77286,19 @@ class AddressMapping {
76874
77286
  }
76875
77287
  sheetMapping.setCell(address, newVertex);
76876
77288
  }
77289
+ /**
77290
+ * Moves a cell from source address to destination address.
77291
+ * Supports cross-sheet moves (used for placeholder sheet merging).
77292
+ * @throws {Error} if source sheet not initialized
77293
+ * @throws {Error} if destination occupied
77294
+ * @throws {Error} if source cell doesn't exist
77295
+ */
76877
77296
  moveCell(source, destination) {
76878
77297
  const sheetMapping = this.mapping.get(source.sheet);
76879
77298
  if (!sheetMapping) {
76880
77299
  throw Error("Sheet not initialized.");
76881
77300
  }
76882
- if (source.sheet !== destination.sheet) {
76883
- throw Error("Cannot move cells between sheets.");
76884
- }
76885
- if (sheetMapping.has(destination)) {
77301
+ if (this.has(destination)) {
76886
77302
  throw new Error("Cannot move cell. Destination already occupied.");
76887
77303
  }
76888
77304
  const vertex = sheetMapping.getCell(source);
@@ -76892,6 +77308,10 @@ class AddressMapping {
76892
77308
  this.setCell(destination, vertex);
76893
77309
  this.removeCell(source);
76894
77310
  }
77311
+ /**
77312
+ * Removes a cell at the specified address.
77313
+ * @throws Error if sheet not initialized
77314
+ */
76895
77315
  removeCell(address) {
76896
77316
  const sheetMapping = this.mapping.get(address.sheet);
76897
77317
  if (!sheetMapping) {
@@ -76899,7 +77319,9 @@ class AddressMapping {
76899
77319
  }
76900
77320
  sheetMapping.removeCell(address);
76901
77321
  }
76902
- /** @inheritDoc */
77322
+ /**
77323
+ * Checks if a cell exists at the specified address.
77324
+ */
76903
77325
  has(address) {
76904
77326
  const sheetMapping = this.mapping.get(address.sheet);
76905
77327
  if (sheetMapping === void 0) {
@@ -76907,78 +77329,99 @@ class AddressMapping {
76907
77329
  }
76908
77330
  return sheetMapping.has(address);
76909
77331
  }
76910
- /** @inheritDoc */
76911
- getHeight(sheetId) {
76912
- const sheetMapping = this.mapping.get(sheetId);
76913
- if (sheetMapping === void 0) {
76914
- throw new NoSheetWithIdError(sheetId);
76915
- }
77332
+ /**
77333
+ * Gets the height of the specified sheet.
77334
+ */
77335
+ getSheetHeight(sheetId) {
77336
+ const sheetMapping = this.getStrategyForSheetOrThrow(sheetId);
76916
77337
  return sheetMapping.getHeight();
76917
77338
  }
76918
- /** @inheritDoc */
76919
- getWidth(sheetId) {
76920
- const sheetMapping = this.mapping.get(sheetId);
76921
- if (!sheetMapping) {
76922
- throw new NoSheetWithIdError(sheetId);
76923
- }
77339
+ /**
77340
+ * Gets the width of the specified sheet.
77341
+ */
77342
+ getSheetWidth(sheetId) {
77343
+ const sheetMapping = this.getStrategyForSheetOrThrow(sheetId);
76924
77344
  return sheetMapping.getWidth();
76925
77345
  }
76926
- addRows(sheet, row, numberOfRows) {
76927
- const sheetMapping = this.mapping.get(sheet);
76928
- if (sheetMapping === void 0) {
76929
- throw new NoSheetWithIdError(sheet);
76930
- }
77346
+ /**
77347
+ * Adds rows to a sheet.
77348
+ */
77349
+ addRows(sheetId, row, numberOfRows) {
77350
+ const sheetMapping = this.getStrategyForSheetOrThrow(sheetId);
76931
77351
  sheetMapping.addRows(row, numberOfRows);
76932
77352
  }
77353
+ /**
77354
+ * Removes rows from a sheet.
77355
+ */
76933
77356
  removeRows(removedRows) {
76934
- const sheetMapping = this.mapping.get(removedRows.sheet);
76935
- if (sheetMapping === void 0) {
76936
- throw new NoSheetWithIdError(removedRows.sheet);
76937
- }
77357
+ const sheetMapping = this.getStrategyForSheetOrThrow(removedRows.sheet);
76938
77358
  sheetMapping.removeRows(removedRows);
76939
77359
  }
76940
- removeSheet(sheetId) {
76941
- this.mapping.delete(sheetId);
76942
- }
76943
- addColumns(sheet, column, numberOfColumns) {
76944
- const sheetMapping = this.mapping.get(sheet);
76945
- if (sheetMapping === void 0) {
76946
- throw new NoSheetWithIdError(sheet);
76947
- }
77360
+ /**
77361
+ * Adds columns to a sheet starting at the specified column index.
77362
+ */
77363
+ addColumns(sheetId, column, numberOfColumns) {
77364
+ const sheetMapping = this.getStrategyForSheetOrThrow(sheetId);
76948
77365
  sheetMapping.addColumns(column, numberOfColumns);
76949
77366
  }
77367
+ /**
77368
+ * Removes columns from a sheet.
77369
+ */
76950
77370
  removeColumns(removedColumns) {
76951
- const sheetMapping = this.mapping.get(removedColumns.sheet);
76952
- if (sheetMapping === void 0) {
76953
- throw new NoSheetWithIdError(removedColumns.sheet);
76954
- }
77371
+ const sheetMapping = this.getStrategyForSheetOrThrow(removedColumns.sheet);
76955
77372
  sheetMapping.removeColumns(removedColumns);
76956
77373
  }
77374
+ /**
77375
+ * Returns an iterator of cell vertices within the specified rows span.
77376
+ */
76957
77377
  *verticesFromRowsSpan(rowsSpan) {
76958
77378
  yield* this.mapping.get(rowsSpan.sheet).verticesFromRowsSpan(rowsSpan);
76959
77379
  }
77380
+ /**
77381
+ * Returns an iterator of cell vertices within the specified columns span.
77382
+ */
76960
77383
  *verticesFromColumnsSpan(columnsSpan) {
76961
77384
  yield* this.mapping.get(columnsSpan.sheet).verticesFromColumnsSpan(columnsSpan);
76962
77385
  }
77386
+ /**
77387
+ * Returns an iterator of address-vertex pairs within the specified rows span.
77388
+ */
76963
77389
  *entriesFromRowsSpan(rowsSpan) {
76964
- yield* this.mapping.get(rowsSpan.sheet).entriesFromRowsSpan(rowsSpan);
77390
+ const sheetMapping = this.getStrategyForSheetOrThrow(rowsSpan.sheet);
77391
+ yield* sheetMapping.entriesFromRowsSpan(rowsSpan);
76965
77392
  }
77393
+ /**
77394
+ * Returns an iterator of address-vertex pairs within the specified columns span.
77395
+ */
76966
77396
  *entriesFromColumnsSpan(columnsSpan) {
76967
- yield* this.mapping.get(columnsSpan.sheet).entriesFromColumnsSpan(columnsSpan);
77397
+ const sheetMapping = this.getStrategyForSheetOrThrow(columnsSpan.sheet);
77398
+ yield* sheetMapping.entriesFromColumnsSpan(columnsSpan);
76968
77399
  }
77400
+ /**
77401
+ * Returns an iterator of all address-vertex pairs across all sheets.
77402
+ * @returns {IterableIterator<[SimpleCellAddress, Maybe<CellVertex>]>} Iterator of [address, vertex] tuples
77403
+ */
76969
77404
  *entries() {
76970
77405
  for (const [sheet, mapping] of this.mapping.entries()) {
76971
77406
  yield* mapping.getEntries(sheet);
76972
77407
  }
76973
77408
  }
76974
- *sheetEntries(sheet) {
76975
- const sheetMapping = this.mapping.get(sheet);
76976
- if (sheetMapping !== void 0) {
76977
- yield* sheetMapping.getEntries(sheet);
76978
- }
76979
- else {
76980
- throw new NoSheetWithIdError(sheet);
76981
- }
77409
+ /**
77410
+ * Returns an iterator of address-vertex pairs for a specific sheet.
77411
+ * @returns {IterableIterator<[SimpleCellAddress, CellVertex]>} Iterator of [address, vertex] tuples
77412
+ * @throws {NoSheetWithIdError} if sheet doesn't exist
77413
+ */
77414
+ *sheetEntries(sheetId) {
77415
+ const sheetMapping = this.getStrategyForSheetOrThrow(sheetId);
77416
+ yield* sheetMapping.getEntries(sheetId);
77417
+ }
77418
+ /**
77419
+ * Checks if a sheet has any entries.
77420
+ * @throws {NoSheetWithIdError} if sheet doesn't exist
77421
+ */
77422
+ hasAnyEntries(sheetId) {
77423
+ const iterator = this.sheetEntries(sheetId);
77424
+ return !iterator.next().done;
76982
77425
  }
76983
77426
  }
76984
77427
  class ArrayMapping {
@@ -77246,10 +77689,10 @@ class FormulaVertex {
77246
77689
  }
77247
77690
  static fromAst(formula, address, size2, version) {
77248
77691
  if (size2.isScalar()) {
77249
- return new FormulaCellVertex(formula, address, version);
77692
+ return new ScalarFormulaVertex(formula, address, version);
77250
77693
  }
77251
77694
  else {
77252
- return new ArrayVertex(formula, address, size2, version);
77695
+ return new ArrayFormulaVertex(formula, address, size2, version);
77253
77696
  }
77254
77697
  }
77255
77698
  /**
@@ -77275,7 +77718,7 @@ class FormulaVertex {
77275
77718
  return this.cellAddress;
77276
77719
  }
77277
77720
  }
77278
- class ArrayVertex extends FormulaVertex {
77721
+ class ArrayFormulaVertex extends FormulaVertex {
77279
77722
  constructor(formula, cellAddress, size2, version = 0) {
77280
77723
  super(formula, cellAddress, version);
77281
77724
  if (size2.isRef) {
@@ -77388,7 +77831,7 @@ class ArrayVertex extends FormulaVertex {
77388
77831
  this.array = new ErroredArray(error, this.array.size);
77389
77832
  }
77390
77833
  }
77391
- class FormulaCellVertex extends FormulaVertex {
77834
+ class ScalarFormulaVertex extends FormulaVertex {
77392
77835
  constructor(formula, address, version) {
77393
77836
  super(formula, address, version);
77394
77837
  }
@@ -77493,18 +77936,6 @@ class RangeVertex {
77493
77936
  this.dependentCacheRanges.forEach((range2) => range2.criterionFunctionCache.clear());
77494
77937
  this.dependentCacheRanges.clear();
77495
77938
  }
77496
- /**
77497
- * Returns start of the range (it's top-left corner)
77498
- */
77499
- getStart() {
77500
- return this.start;
77501
- }
77502
- /**
77503
- * Returns end of the range (it's bottom-right corner)
77504
- */
77505
- getEnd() {
77506
- return this.end;
77507
- }
77508
77939
  }
77509
77940
  const collectAddressesDependentToRange = (functionRegistry, vertex, range2, lazilyTransformingAstService, dependencyGraph) => {
77510
77941
  if (vertex instanceof RangeVertex) {
@@ -77985,38 +78416,42 @@ class Graph {
77985
78416
  * Returns error for missing node.
77986
78417
  */
77987
78418
  missingNodeError(node2) {
77988
- return new Error(`Unknown node ${node2}`);
78419
+ return new Error(`Unknown node ${JSON.stringify(node2)}`);
77989
78420
  }
77990
78421
  }
77991
78422
  class RangeMapping {
77992
78423
  constructor() {
77993
78424
  this.rangeMapping = /* @__PURE__ */ new Map();
77994
78425
  }
77995
- getMappingSize(sheet) {
78426
+ /**
78427
+ * Returns number of ranges in the sheet or 0 if the sheet does not exist
78428
+ */
78429
+ getNumberOfRangesInSheet(sheet) {
77996
78430
  var _a, _b;
77997
78431
  return (_b = (_a = this.rangeMapping.get(sheet)) === null || _a === void 0 ? void 0 : _a.size) !== null && _b !== void 0 ? _b : 0;
77998
78432
  }
77999
78433
  /**
78000
- * Saves range vertex
78001
- *
78002
- * @param vertex - vertex to save
78434
+ * Adds or updates vertex in the mapping
78003
78435
  */
78004
- setRange(vertex) {
78005
- let sheetMap = this.rangeMapping.get(vertex.getStart().sheet);
78436
+ addOrUpdateVertex(vertex) {
78437
+ let sheetMap = this.rangeMapping.get(vertex.sheet);
78006
78438
  if (sheetMap === void 0) {
78007
78439
  sheetMap = /* @__PURE__ */ new Map();
78008
- this.rangeMapping.set(vertex.getStart().sheet, sheetMap);
78440
+ this.rangeMapping.set(vertex.sheet, sheetMap);
78009
78441
  }
78010
- const key = keyFromAddresses(vertex.getStart(), vertex.getEnd());
78442
+ const key = RangeMapping.calculateRangeKey(vertex.start, vertex.end);
78011
78443
  sheetMap.set(key, vertex);
78012
78444
  }
78013
- removeRange(vertex) {
78014
- const sheet = vertex.getStart().sheet;
78445
+ /**
78446
+ * Removes vertex from the mapping if it exists
78447
+ */
78448
+ removeVertexIfExists(vertex) {
78449
+ const sheet = vertex.sheet;
78015
78450
  const sheetMap = this.rangeMapping.get(sheet);
78016
78451
  if (sheetMap === void 0) {
78017
78452
  return;
78018
78453
  }
78019
- const key = keyFromAddresses(vertex.getStart(), vertex.getEnd());
78454
+ const key = RangeMapping.calculateRangeKey(vertex.start, vertex.end);
78020
78455
  sheetMap.delete(key);
78021
78456
  if (sheetMap.size === 0) {
78022
78457
  this.rangeMapping.delete(sheet);
@@ -78024,17 +78459,17 @@ class RangeMapping {
78024
78459
  }
78025
78460
  /**
78026
78461
  * Returns associated vertex for given range
78027
- *
78028
- * @param start - top-left corner of the range
78029
- * @param end - bottom-right corner of the range
78030
78462
  */
78031
- getRange(start, end) {
78463
+ getRangeVertex(start, end) {
78032
78464
  const sheetMap = this.rangeMapping.get(start.sheet);
78033
- const key = keyFromAddresses(start, end);
78465
+ const key = RangeMapping.calculateRangeKey(start, end);
78034
78466
  return sheetMap === null || sheetMap === void 0 ? void 0 : sheetMap.get(key);
78035
78467
  }
78036
- fetchRange(start, end) {
78037
- const maybeRange = this.getRange(start, end);
78468
+ /**
78469
+ * Returns associated vertex for given range or throws an error if not found
78470
+ */
78471
+ getVertexOrThrow(start, end) {
78472
+ const maybeRange = this.getRangeVertex(start, end);
78038
78473
  if (!maybeRange) {
78039
78474
  throw Error("Range does not exist");
78040
78475
  }
@@ -78060,9 +78495,9 @@ class RangeMapping {
78060
78495
  }
78061
78496
  }
78062
78497
  const verticesToMerge = [];
78063
- updated.sort((left, right) => compareBy(left[1], right[1], coordinate));
78498
+ updated.sort((left, right) => RangeMapping.compareBy(left[1], right[1], coordinate));
78064
78499
  for (const [oldKey, vertex] of updated) {
78065
- const newKey = keyFromRange(vertex.range);
78500
+ const newKey = RangeMapping.calculateRangeKey(vertex.range.start, vertex.range.end);
78066
78501
  if (newKey === oldKey) {
78067
78502
  continue;
78068
78503
  }
@@ -78072,7 +78507,7 @@ class RangeMapping {
78072
78507
  verticesToMerge.push([existingVertex, vertex]);
78073
78508
  }
78074
78509
  else {
78075
- this.setRange(vertex);
78510
+ this.addOrUpdateVertex(vertex);
78076
78511
  }
78077
78512
  }
78078
78513
  return {
@@ -78081,7 +78516,7 @@ class RangeMapping {
78081
78516
  verticesWithChangedSize
78082
78517
  };
78083
78518
  }
78084
- moveAllRangesInSheetAfterRowByRows(sheet, row, numberOfRows) {
78519
+ moveAllRangesInSheetAfterAddingRows(sheet, row, numberOfRows) {
78085
78520
  return this.updateVerticesFromSheet(sheet, (key, vertex) => {
78086
78521
  if (row <= vertex.start.row) {
78087
78522
  vertex.range.shiftByRows(numberOfRows);
@@ -78102,7 +78537,7 @@ class RangeMapping {
78102
78537
  }
78103
78538
  });
78104
78539
  }
78105
- moveAllRangesInSheetAfterColumnByColumns(sheet, column, numberOfColumns) {
78540
+ moveAllRangesInSheetAfterAddingColumns(sheet, column, numberOfColumns) {
78106
78541
  return this.updateVerticesFromSheet(sheet, (key, vertex) => {
78107
78542
  if (column <= vertex.start.col) {
78108
78543
  vertex.range.shiftByColumns(numberOfColumns);
@@ -78139,14 +78574,6 @@ class RangeMapping {
78139
78574
  }
78140
78575
  });
78141
78576
  }
78142
- removeRangesInSheet(sheet) {
78143
- if (this.rangeMapping.has(sheet)) {
78144
- const ranges = this.rangeMapping.get(sheet).values();
78145
- this.rangeMapping.delete(sheet);
78146
- return ranges;
78147
- }
78148
- return [][Symbol.iterator]();
78149
- }
78150
78577
  *rangesInSheet(sheet) {
78151
78578
  const sheetMap = this.rangeMapping.get(sheet);
78152
78579
  if (!sheetMap) {
@@ -78162,14 +78589,12 @@ class RangeMapping {
78162
78589
  }
78163
78590
  }
78164
78591
  /**
78165
- * Finds smaller range does have own vertex.
78166
- *
78167
- * @param range
78592
+ * Finds smaller range if exists.
78168
78593
  */
78169
78594
  findSmallerRange(range2) {
78170
78595
  if (range2.height() > 1 && Number.isFinite(range2.height())) {
78171
78596
  const valuesRangeEndRowLess = simpleCellAddress(range2.end.sheet, range2.end.col, range2.end.row - 1);
78172
- const rowLessVertex = this.getRange(range2.start, valuesRangeEndRowLess);
78597
+ const rowLessVertex = this.getRangeVertex(range2.start, valuesRangeEndRowLess);
78173
78598
  if (rowLessVertex !== void 0) {
78174
78599
  const restRange = AbsoluteCellRange.fromSimpleCellAddresses(simpleCellAddress(range2.start.sheet, range2.start.col, range2.end.row), range2.end);
78175
78600
  return {
@@ -78182,6 +78607,27 @@ class RangeMapping {
78182
78607
  restRange: range2
78183
78608
  };
78184
78609
  }
78610
+ /**
78611
+ * Calculates a string key from start and end addresses
78612
+ */
78613
+ static calculateRangeKey(start, end) {
78614
+ return `${start.col},${start.row},${end.col},${end.row}`;
78615
+ }
78616
+ /**
78617
+ * Compares two range vertices by their start and end addresses using the provided coordinate function
78618
+ */
78619
+ static compareBy(left, right, coordinate) {
78620
+ const leftStart = coordinate(left.range.start);
78621
+ const rightStart = coordinate(right.range.start);
78622
+ if (leftStart === rightStart) {
78623
+ const leftEnd = coordinate(left.range.end);
78624
+ const rightEnd = coordinate(right.range.end);
78625
+ return leftEnd - rightEnd;
78626
+ }
78627
+ else {
78628
+ return leftStart - rightStart;
78629
+ }
78630
+ }
78185
78631
  *entriesFromSheet(sheet) {
78186
78632
  const sheetMap = this.rangeMapping.get(sheet);
78187
78633
  if (!sheetMap) {
@@ -78190,7 +78636,11 @@ class RangeMapping {
78190
78636
  yield* sheetMap.entries();
78191
78637
  }
78192
78638
  removeByKey(sheet, key) {
78193
- this.rangeMapping.get(sheet).delete(key);
78639
+ const sheetMap = this.rangeMapping.get(sheet);
78640
+ if (!sheetMap) {
78641
+ throw new Error(`Sheet ${sheet} not found`);
78642
+ }
78643
+ sheetMap.delete(key);
78194
78644
  }
78195
78645
  getByKey(sheet, key) {
78196
78646
  var _a;
@@ -78206,31 +78656,13 @@ class RangeMapping {
78206
78656
  }
78207
78657
  }
78208
78658
  updated.forEach((entry) => {
78209
- this.setRange(entry.vertex);
78659
+ this.addOrUpdateVertex(entry.vertex);
78210
78660
  });
78211
78661
  return {
78212
78662
  verticesWithChangedSize: updated.filter((entry) => entry.changedSize).map((entry) => entry.vertex)
78213
78663
  };
78214
78664
  }
78215
78665
  }
78216
- function keyFromAddresses(start, end) {
78217
- return `${start.col},${start.row},${end.col},${end.row}`;
78218
- }
78219
- function keyFromRange(range2) {
78220
- return keyFromAddresses(range2.start, range2.end);
78221
- }
78222
- const compareBy = (left, right, coordinate) => {
78223
- const leftStart = coordinate(left.range.start);
78224
- const rightStart = coordinate(left.range.start);
78225
- if (leftStart === rightStart) {
78226
- const leftEnd = coordinate(left.range.end);
78227
- const rightEnd = coordinate(right.range.end);
78228
- return leftEnd - rightEnd;
78229
- }
78230
- else {
78231
- return leftStart - rightStart;
78232
- }
78233
- };
78234
78666
  class TranslationPackage {
78235
78667
  constructor(functions, errors2, ui) {
78236
78668
  this.functions = functions;
@@ -78335,107 +78767,361 @@ var UIElement;
78335
78767
  (function (UIElement2) {
78336
78768
  UIElement2["NEW_SHEET_PREFIX"] = "NEW_SHEET_PREFIX";
78337
78769
  })(UIElement || (UIElement = {}));
78338
- function canonicalize(sheetDisplayName) {
78339
- return sheetDisplayName.toLowerCase();
78340
- }
78341
78770
  class Sheet {
78342
- constructor(id2, displayName) {
78771
+ constructor(id2, displayName, isPlaceholder = false) {
78343
78772
  this.id = id2;
78344
78773
  this.displayName = displayName;
78774
+ this.isPlaceholder = isPlaceholder;
78345
78775
  }
78776
+ /**
78777
+ * Returns the canonical (normalized) name of the sheet.
78778
+ */
78346
78779
  get canonicalName() {
78347
- return canonicalize(this.displayName);
78780
+ return SheetMapping.canonicalizeSheetName(this.displayName);
78348
78781
  }
78349
78782
  }
78350
78783
  class SheetMapping {
78351
78784
  constructor(languages) {
78352
- this.languages = languages;
78353
- this.mappingFromCanonicalName = /* @__PURE__ */ new Map();
78354
- this.mappingFromId = /* @__PURE__ */ new Map();
78355
78785
  this.lastSheetId = -1;
78356
- this.fetch = (sheetName) => {
78357
- const sheet = this.mappingFromCanonicalName.get(canonicalize(sheetName));
78358
- if (sheet === void 0) {
78359
- throw new NoSheetWithNameError(sheetName);
78360
- }
78361
- return sheet.id;
78362
- };
78363
- this.get = (sheetName) => {
78364
- var _a;
78365
- return (_a = this.mappingFromCanonicalName.get(canonicalize(sheetName))) === null || _a === void 0 ? void 0 : _a.id;
78366
- };
78367
- this.fetchDisplayName = (sheetId) => {
78368
- return this.fetchSheetById(sheetId).displayName;
78369
- };
78786
+ this.mappingFromCanonicalNameToId = /* @__PURE__ */ new Map();
78787
+ this.allSheets = /* @__PURE__ */ new Map();
78370
78788
  this.sheetNamePrefix = languages.getUITranslation(UIElement.NEW_SHEET_PREFIX);
78371
78789
  }
78790
+ /**
78791
+ * Converts sheet name to canonical/normalized form.
78792
+ * @static
78793
+ */
78794
+ static canonicalizeSheetName(sheetDisplayName) {
78795
+ return sheetDisplayName.toLowerCase();
78796
+ }
78797
+ /**
78798
+ * Returns sheet ID for the given name. By default excludes placeholders.
78799
+ */
78800
+ getSheetId(sheetName, options = {}) {
78801
+ var _a;
78802
+ return (_a = this._getSheetByName(sheetName, options)) === null || _a === void 0 ? void 0 : _a.id;
78803
+ }
78804
+ /**
78805
+ * Returns sheet ID for the given name. Excludes placeholders.
78806
+ *
78807
+ * @throws {NoSheetWithNameError} if the sheet with the given name does not exist.
78808
+ */
78809
+ getSheetIdOrThrowError(sheetName) {
78810
+ const sheet = this._getSheetByName(sheetName, {});
78811
+ if (sheet === void 0) {
78812
+ throw new NoSheetWithNameError(sheetName);
78813
+ }
78814
+ return sheet.id;
78815
+ }
78816
+ /**
78817
+ * Returns display name for the given sheet ID. Excludes placeholders.
78818
+ *
78819
+ * @returns {Maybe<string>} the display name, or undefined if the sheet with the given ID does not exist.
78820
+ */
78821
+ getSheetName(sheetId) {
78822
+ var _a;
78823
+ return (_a = this._getSheet(sheetId, {})) === null || _a === void 0 ? void 0 : _a.displayName;
78824
+ }
78825
+ /**
78826
+ * Returns display name for the given sheet ID. Excludes placeholders.
78827
+ *
78828
+ * @throws {NoSheetWithIdError} if the sheet with the given ID does not exist.
78829
+ */
78830
+ getSheetNameOrThrowError(sheetId, options = {}) {
78831
+ return this._getSheetOrThrowError(sheetId, options).displayName;
78832
+ }
78833
+ /**
78834
+ * Iterates over all sheet display names. By default excludes placeholders.
78835
+ */
78836
+ *iterateSheetNames(options = {}) {
78837
+ for (const sheet of this.allSheets.values()) {
78838
+ if (options.includePlaceholders || !sheet.isPlaceholder) {
78839
+ yield sheet.displayName;
78840
+ }
78841
+ }
78842
+ }
78843
+ /**
78844
+ * Returns array of all sheet display names. By default excludes placeholders.
78845
+ */
78846
+ getSheetNames(options = {}) {
78847
+ return Array.from(this.iterateSheetNames(options));
78848
+ }
78849
+ /**
78850
+ * Returns total count of sheets. By default excludes placeholders.
78851
+ */
78852
+ numberOfSheets(options = {}) {
78853
+ return this.getSheetNames(options).length;
78854
+ }
78855
+ /**
78856
+ * Checks if sheet with given ID exists. By default excludes placeholders.
78857
+ */
78858
+ hasSheetWithId(sheetId, options = {}) {
78859
+ return this._getSheet(sheetId, options) !== void 0;
78860
+ }
78861
+ /**
78862
+ * Checks if sheet with given name exists (case-insensitive). Excludes placeholders.
78863
+ */
78864
+ hasSheetWithName(sheetName) {
78865
+ return this._getSheetByName(sheetName, {}) !== void 0;
78866
+ }
78867
+ /**
78868
+ * Adds new sheet with optional name and returns its ID.
78869
+ * If called with a name of an existing placeholder sheet, converts the placeholder sheet to a real sheet.
78870
+ *
78871
+ * @throws {SheetNameAlreadyTakenError} if the sheet with the given name already exists.
78872
+ */
78372
78873
  addSheet(newSheetDisplayName = `${this.sheetNamePrefix}${this.lastSheetId + 2}`) {
78373
- const newSheetCanonicalName = canonicalize(newSheetDisplayName);
78374
- if (this.mappingFromCanonicalName.has(newSheetCanonicalName)) {
78375
- throw new SheetNameAlreadyTakenError(newSheetDisplayName);
78874
+ const sheetWithConflictingName = this._getSheetByName(newSheetDisplayName, {
78875
+ includePlaceholders: true
78876
+ });
78877
+ if (sheetWithConflictingName) {
78878
+ if (!sheetWithConflictingName.isPlaceholder) {
78879
+ throw new SheetNameAlreadyTakenError(newSheetDisplayName);
78880
+ }
78881
+ sheetWithConflictingName.isPlaceholder = false;
78882
+ return sheetWithConflictingName.id;
78376
78883
  }
78377
78884
  this.lastSheetId++;
78378
78885
  const sheet = new Sheet(this.lastSheetId, newSheetDisplayName);
78379
- this.store(sheet);
78886
+ this._storeSheetInMappings(sheet);
78380
78887
  return sheet.id;
78381
78888
  }
78382
- removeSheet(sheetId) {
78383
- const sheet = this.fetchSheetById(sheetId);
78384
- if (sheetId == this.lastSheetId) {
78385
- --this.lastSheetId;
78889
+ /**
78890
+ * Adds a sheet with a specific ID and name. Used for redo operations.
78891
+ * If called with a name of an existing placeholder sheet, converts the placeholder sheet to a real sheet.
78892
+ *
78893
+ * @throws {SheetNameAlreadyTakenError} if the sheet with the given name already exists.
78894
+ */
78895
+ addSheetWithId(sheetId, sheetDisplayName) {
78896
+ const sheetWithConflictingName = this._getSheetByName(sheetDisplayName, {
78897
+ includePlaceholders: true
78898
+ });
78899
+ if (sheetWithConflictingName) {
78900
+ if (sheetWithConflictingName.id !== sheetId) {
78901
+ throw new SheetNameAlreadyTakenError(sheetDisplayName);
78902
+ }
78903
+ if (!sheetWithConflictingName.isPlaceholder) {
78904
+ throw new SheetNameAlreadyTakenError(sheetDisplayName);
78905
+ }
78906
+ sheetWithConflictingName.isPlaceholder = false;
78907
+ return;
78386
78908
  }
78387
- this.mappingFromCanonicalName.delete(sheet.canonicalName);
78388
- this.mappingFromId.delete(sheet.id);
78389
- }
78390
- getDisplayName(sheetId) {
78391
- var _a;
78392
- return (_a = this.mappingFromId.get(sheetId)) === null || _a === void 0 ? void 0 : _a.displayName;
78909
+ if (sheetId > this.lastSheetId) {
78910
+ this.lastSheetId = sheetId;
78911
+ }
78912
+ const sheet = new Sheet(sheetId, sheetDisplayName);
78913
+ this._storeSheetInMappings(sheet);
78393
78914
  }
78394
- *displayNames() {
78395
- for (const sheet of this.mappingFromCanonicalName.values()) {
78396
- yield sheet.displayName;
78915
+ /**
78916
+ * Adds a placeholder sheet with the given name if it does not exist yet
78917
+ */
78918
+ addPlaceholderIfNotExists(sheetName) {
78919
+ const sheetWithConflictingName = this._getSheetByName(sheetName, {
78920
+ includePlaceholders: true
78921
+ });
78922
+ if (sheetWithConflictingName) {
78923
+ return sheetWithConflictingName.id;
78397
78924
  }
78925
+ this.lastSheetId++;
78926
+ const sheet = new Sheet(this.lastSheetId, sheetName, true);
78927
+ this._storeSheetInMappings(sheet);
78928
+ return sheet.id;
78398
78929
  }
78399
- numberOfSheets() {
78400
- return this.mappingFromCanonicalName.size;
78930
+ /**
78931
+ * Adds a placeholder sheet with a specific ID and name.
78932
+ * Used for undo operations to restore previously merged placeholder sheets.
78933
+ *
78934
+ * @throws {SheetNameAlreadyTakenError} if the sheet with the given name already exists.
78935
+ */
78936
+ addPlaceholderWithId(sheetId, sheetDisplayName) {
78937
+ const sheetWithConflictingName = this._getSheetByName(sheetDisplayName, {
78938
+ includePlaceholders: true
78939
+ });
78940
+ if (sheetWithConflictingName) {
78941
+ throw new SheetNameAlreadyTakenError(sheetDisplayName);
78942
+ }
78943
+ if (this.hasSheetWithId(sheetId, {
78944
+ includePlaceholders: true
78945
+ })) {
78946
+ throw new Error(`Sheet with id ${sheetId} already exists`);
78947
+ }
78948
+ if (sheetId > this.lastSheetId) {
78949
+ this.lastSheetId = sheetId;
78950
+ }
78951
+ const sheet = new Sheet(sheetId, sheetDisplayName, true);
78952
+ this._storeSheetInMappings(sheet);
78401
78953
  }
78402
- hasSheetWithId(sheetId) {
78403
- return this.mappingFromId.has(sheetId);
78954
+ /**
78955
+ *
78956
+ * Removes sheet with given ID.
78957
+ * If sheet does not exist, does nothing.
78958
+ * @returns {boolean} true if sheet was removed, false if it did not exist.
78959
+ */
78960
+ removeSheetIfExists(sheetId, options = {}) {
78961
+ const sheet = this._getSheet(sheetId, options);
78962
+ if (!sheet) {
78963
+ return false;
78964
+ }
78965
+ this.allSheets.delete(sheetId);
78966
+ this.mappingFromCanonicalNameToId.delete(sheet.canonicalName);
78967
+ if (sheetId === this.lastSheetId) {
78968
+ this.lastSheetId--;
78969
+ }
78970
+ return true;
78404
78971
  }
78405
- hasSheetWithName(sheetName) {
78406
- return this.mappingFromCanonicalName.has(canonicalize(sheetName));
78972
+ /**
78973
+ * Marks sheet with given ID as a placeholder.
78974
+ * @throws {NoSheetWithIdError} if the sheet with the given ID does not exist
78975
+ */
78976
+ markSheetAsPlaceholder(sheetId) {
78977
+ const sheet = this._getSheetOrThrowError(sheetId, {});
78978
+ sheet.isPlaceholder = true;
78407
78979
  }
78980
+ /**
78981
+ * Renames sheet.
78982
+ * - If called with sheetId of a placeholder sheet, throws {NoSheetWithIdError}.
78983
+ * - If newDisplayName is conflicting with an existing sheet, throws {SheetNameAlreadyTakenError}.
78984
+ * - If newDisplayName is conflicting with a placeholder sheet name, deletes the placeholder sheet and returns its id as mergedWithPlaceholderSheet.
78985
+ *
78986
+ * @throws {SheetNameAlreadyTakenError} if the sheet with the given name already exists.
78987
+ * @throws {NoSheetWithIdError} if the sheet with the given ID does not exist.
78988
+ */
78408
78989
  renameSheet(sheetId, newDisplayName) {
78409
- const sheet = this.fetchSheetById(sheetId);
78990
+ const sheet = this._getSheetOrThrowError(sheetId, {});
78410
78991
  const currentDisplayName = sheet.displayName;
78411
78992
  if (currentDisplayName === newDisplayName) {
78412
- return void 0;
78993
+ return {
78994
+ previousDisplayName: void 0
78995
+ };
78413
78996
  }
78414
- const sheetWithThisCanonicalName = this.mappingFromCanonicalName.get(canonicalize(newDisplayName));
78415
- if (sheetWithThisCanonicalName !== void 0 && sheetWithThisCanonicalName.id !== sheet.id) {
78416
- throw new SheetNameAlreadyTakenError(newDisplayName);
78997
+ const sheetWithConflictingName = this._getSheetByName(newDisplayName, {
78998
+ includePlaceholders: true
78999
+ });
79000
+ let mergedWithPlaceholderSheet = void 0;
79001
+ if (sheetWithConflictingName !== void 0 && sheetWithConflictingName.id !== sheet.id) {
79002
+ if (!sheetWithConflictingName.isPlaceholder) {
79003
+ throw new SheetNameAlreadyTakenError(newDisplayName);
79004
+ }
79005
+ else {
79006
+ this.mappingFromCanonicalNameToId.delete(sheetWithConflictingName.canonicalName);
79007
+ this.allSheets.delete(sheetWithConflictingName.id);
79008
+ if (sheetWithConflictingName.id === this.lastSheetId) {
79009
+ this.lastSheetId--;
79010
+ }
79011
+ mergedWithPlaceholderSheet = sheetWithConflictingName.id;
79012
+ }
78417
79013
  }
78418
79014
  const currentCanonicalName = sheet.canonicalName;
78419
- this.mappingFromCanonicalName.delete(currentCanonicalName);
79015
+ this.mappingFromCanonicalNameToId.delete(currentCanonicalName);
78420
79016
  sheet.displayName = newDisplayName;
78421
- this.store(sheet);
78422
- return currentDisplayName;
79017
+ this._storeSheetInMappings(sheet);
79018
+ return {
79019
+ previousDisplayName: currentDisplayName,
79020
+ mergedWithPlaceholderSheet
79021
+ };
79022
+ }
79023
+ /**
79024
+ * Stores sheet in both internal mappings.
79025
+ * - If ID exists, it is updated. If not, it is added.
79026
+ * - If canonical name exists, it is updated. If not, it is added.
79027
+ *
79028
+ * @internal
79029
+ */
79030
+ _storeSheetInMappings(sheet) {
79031
+ this.allSheets.set(sheet.id, sheet);
79032
+ this.mappingFromCanonicalNameToId.set(sheet.canonicalName, sheet.id);
78423
79033
  }
78424
- sheetNames() {
78425
- return Array.from(this.mappingFromId.values()).map((s) => s.displayName);
79034
+ /**
79035
+ * Returns sheet by ID
79036
+ *
79037
+ * @returns {Maybe<Sheet>} the sheet, or undefined if not found.
79038
+ * @internal
79039
+ */
79040
+ _getSheet(sheetId, options) {
79041
+ const retrievedSheet = this.allSheets.get(sheetId);
79042
+ if (retrievedSheet === void 0) {
79043
+ return void 0;
79044
+ }
79045
+ return options.includePlaceholders || !retrievedSheet.isPlaceholder ? retrievedSheet : void 0;
78426
79046
  }
78427
- store(sheet) {
78428
- this.mappingFromId.set(sheet.id, sheet);
78429
- this.mappingFromCanonicalName.set(sheet.canonicalName, sheet);
79047
+ /**
79048
+ * Returns sheet by name
79049
+ *
79050
+ * @returns {Maybe<Sheet>} the sheet, or undefined if not found.
79051
+ * @internal
79052
+ */
79053
+ _getSheetByName(sheetName, options) {
79054
+ const sheetId = this.mappingFromCanonicalNameToId.get(SheetMapping.canonicalizeSheetName(sheetName));
79055
+ if (sheetId === void 0) {
79056
+ return void 0;
79057
+ }
79058
+ return this._getSheet(sheetId, options);
78430
79059
  }
78431
- fetchSheetById(sheetId) {
78432
- const sheet = this.mappingFromId.get(sheetId);
79060
+ /**
79061
+ * Returns sheet by ID
79062
+ *
79063
+ * @throws {NoSheetWithIdError} if the sheet with the given ID does not exist.
79064
+ * @internal
79065
+ */
79066
+ _getSheetOrThrowError(sheetId, options) {
79067
+ const sheet = this._getSheet(sheetId, options);
78433
79068
  if (sheet === void 0) {
78434
79069
  throw new NoSheetWithIdError(sheetId);
78435
79070
  }
78436
79071
  return sheet;
78437
79072
  }
78438
79073
  }
79074
+ class SheetReferenceRegistrar {
79075
+ constructor(sheetMapping, addressMapping) {
79076
+ this.sheetMapping = sheetMapping;
79077
+ this.addressMapping = addressMapping;
79078
+ }
79079
+ /**
79080
+ * Adds placeholder sheet if it doesn't exist and adds placeholder strategy to address mapping.
79081
+ * @returns {number} sheet id
79082
+ */
79083
+ ensureSheetRegistered(sheetName) {
79084
+ const sheetId = this.sheetMapping.addPlaceholderIfNotExists(sheetName);
79085
+ this.addressMapping.addSheetStrategyPlaceholderIfNotExists(sheetId);
79086
+ return sheetId;
79087
+ }
79088
+ }
79089
+ function validateAsSheet(sheet) {
79090
+ if (!Array.isArray(sheet)) {
79091
+ throw new InvalidArgumentsError("an array of arrays.");
79092
+ }
79093
+ for (let i = 0; i < sheet.length; i++) {
79094
+ if (!Array.isArray(sheet[i])) {
79095
+ throw new InvalidArgumentsError("an array of arrays.");
79096
+ }
79097
+ }
79098
+ }
79099
+ function findBoundaries(sheet) {
79100
+ let width = 0;
79101
+ let height = 0;
79102
+ let cellsCount = 0;
79103
+ for (let currentRow = 0; currentRow < sheet.length; currentRow++) {
79104
+ let currentRowWidth = 0;
79105
+ for (let currentCol = 0; currentCol < sheet[currentRow].length; currentCol++) {
79106
+ const currentValue = sheet[currentRow][currentCol];
79107
+ if (currentValue === void 0 || currentValue === null) {
79108
+ continue;
79109
+ }
79110
+ currentRowWidth = currentCol + 1;
79111
+ ++cellsCount;
79112
+ }
79113
+ width = Math.max(width, currentRowWidth);
79114
+ if (currentRowWidth > 0) {
79115
+ height = currentRow + 1;
79116
+ }
79117
+ }
79118
+ const sheetSize = width * height;
79119
+ return {
79120
+ height,
79121
+ width,
79122
+ fill: sheetSize === 0 ? 0 : cellsCount / sheetSize
79123
+ };
79124
+ }
78439
79125
  class DependencyGraph {
78440
79126
  constructor(addressMapping, rangeMapping, sheetMapping, arrayMapping, stats, lazilyTransformingAstService, functionRegistry, namedExpressions) {
78441
79127
  this.addressMapping = addressMapping;
@@ -78482,14 +79168,14 @@ class DependencyGraph {
78482
79168
  const [address, dependencies] = dependenciesResult;
78483
79169
  return dependencies.map((dependency) => {
78484
79170
  if (dependency instanceof AbsoluteCellRange) {
78485
- return [dependency.start, this.rangeMapping.fetchRange(dependency.start, dependency.end)];
79171
+ return [dependency.start, this.rangeMapping.getVertexOrThrow(dependency.start, dependency.end)];
78486
79172
  }
78487
79173
  else if (dependency instanceof NamedExpressionDependency) {
78488
79174
  const namedExpression = this.namedExpressions.namedExpressionOrPlaceholder(dependency.name, address.sheet);
78489
- return [namedExpression.address, this.addressMapping.fetchCell(namedExpression.address)];
79175
+ return [namedExpression.address, this.addressMapping.getCellOrThrow(namedExpression.address)];
78490
79176
  }
78491
79177
  else {
78492
- return [dependency, this.addressMapping.fetchCell(dependency)];
79178
+ return [dependency, this.addressMapping.getCellOrThrow(dependency)];
78493
79179
  }
78494
79180
  });
78495
79181
  }
@@ -78531,6 +79217,7 @@ class DependencyGraph {
78531
79217
  return [address, absolutizeDependencies(deps, address)];
78532
79218
  };
78533
79219
  this.graph = new Graph(this.dependencyQueryVertices);
79220
+ this.sheetReferenceRegistrar = new SheetReferenceRegistrar(sheetMapping, addressMapping);
78534
79221
  }
78535
79222
  /**
78536
79223
  * Invariants:
@@ -78563,7 +79250,7 @@ class DependencyGraph {
78563
79250
  }
78564
79251
  setValueToCell(address, value) {
78565
79252
  const vertex = this.shrinkPossibleArrayAndGetCell(address);
78566
- if (vertex instanceof ArrayVertex) {
79253
+ if (vertex instanceof ArrayFormulaVertex) {
78567
79254
  this.arrayMapping.removeArray(vertex.getRange());
78568
79255
  }
78569
79256
  if (vertex instanceof ValueCellVertex) {
@@ -78582,6 +79269,11 @@ class DependencyGraph {
78582
79269
  this.correctInfiniteRangesDependency(address);
78583
79270
  return this.getAndClearContentChanges();
78584
79271
  }
79272
+ /**
79273
+ * Sets a cell empty.
79274
+ * - if vertex has no dependents, removes it from graph, address mapping and range mapping and cleans up its dependencies
79275
+ * - if vertex has dependents, exchanges it for an EmptyCellVertex and marks it as dirty
79276
+ */
78585
79277
  setCellEmpty(address) {
78586
79278
  const vertex = this.shrinkPossibleArrayAndGetCell(address);
78587
79279
  if (vertex === void 0) {
@@ -78613,16 +79305,22 @@ class DependencyGraph {
78613
79305
  }
78614
79306
  processCellDependencies(cellDependencies, endVertex) {
78615
79307
  const endVertexId = this.graph.getNodeId(endVertex);
79308
+ if (endVertexId === void 0) {
79309
+ throw new Error("End vertex not found");
79310
+ }
78616
79311
  cellDependencies.forEach((dep) => {
78617
79312
  if (dep instanceof AbsoluteCellRange) {
78618
79313
  const range2 = dep;
78619
79314
  let rangeVertex = this.getRange(range2.start, range2.end);
78620
79315
  if (rangeVertex === void 0) {
78621
79316
  rangeVertex = new RangeVertex(range2);
78622
- this.rangeMapping.setRange(rangeVertex);
79317
+ this.rangeMapping.addOrUpdateVertex(rangeVertex);
78623
79318
  }
78624
79319
  this.graph.addNodeAndReturnId(rangeVertex);
78625
79320
  const rangeVertexId = this.graph.getNodeId(rangeVertex);
79321
+ if (rangeVertexId === void 0) {
79322
+ throw new Error("Range vertex not found");
79323
+ }
78626
79324
  if (!range2.isFinite()) {
78627
79325
  this.graph.markNodeAsInfiniteRange(rangeVertexId);
78628
79326
  }
@@ -78697,7 +79395,7 @@ class DependencyGraph {
78697
79395
  for (const adjacentNode of this.graph.adjacentNodes(vertex)) {
78698
79396
  this.graph.markNodeAsDirty(adjacentNode);
78699
79397
  }
78700
- if (vertex instanceof ArrayVertex) {
79398
+ if (vertex instanceof ArrayFormulaVertex) {
78701
79399
  if (vertex.isLeftCorner(address)) {
78702
79400
  this.shrinkArrayToCorner(vertex);
78703
79401
  this.arrayMapping.removeArray(vertex.getRange());
@@ -78725,29 +79423,64 @@ class DependencyGraph {
78725
79423
  contentChanges: this.getAndClearContentChanges()
78726
79424
  };
78727
79425
  }
78728
- removeSheet(removedSheetId) {
78729
- this.clearSheet(removedSheetId);
78730
- for (const [adr, vertex] of this.addressMapping.sheetEntries(removedSheetId)) {
78731
- for (const adjacentNode of this.graph.adjacentNodes(vertex)) {
78732
- this.graph.markNodeAsDirty(adjacentNode);
78733
- }
78734
- this.removeVertex(vertex);
78735
- this.addressMapping.removeCell(adr);
78736
- }
79426
+ /**
79427
+ * Adds a new sheet to the graph.
79428
+ * If the sheetId was a placeholder sheet, marks its vertices as dirty.
79429
+ */
79430
+ addSheet(sheetId) {
79431
+ this.addressMapping.addSheetOrChangeStrategy(sheetId, findBoundaries([]));
79432
+ this.stats.measure(StatType.ADJUSTING_ADDRESS_MAPPING, () => {
79433
+ this.markAllCellsAsDirtyInSheet(sheetId);
79434
+ });
78737
79435
  this.stats.measure(StatType.ADJUSTING_RANGES, () => {
78738
- const rangesToRemove = this.rangeMapping.removeRangesInSheet(removedSheetId);
78739
- for (const range2 of rangesToRemove) {
78740
- this.removeVertex(range2);
78741
- }
78742
- this.stats.measure(StatType.ADJUSTING_ADDRESS_MAPPING, () => {
78743
- this.addressMapping.removeSheet(removedSheetId);
78744
- });
79436
+ this.markAllRangesAsDirtyInSheet(sheetId);
78745
79437
  });
78746
79438
  }
79439
+ /**
79440
+ * Removes all vertices without dependents in other sheets from address mapping, range mapping and array mapping.
79441
+ * - If nothing is left, removes the sheet from sheet mapping and address mapping.
79442
+ * - Otherwise, marks it as placeholder.
79443
+ */
79444
+ removeSheet(sheetId) {
79445
+ this.clearSheet(sheetId);
79446
+ const addressMappingCleared = !this.addressMapping.hasAnyEntries(sheetId);
79447
+ const rangeMappingCleared = this.rangeMapping.getNumberOfRangesInSheet(sheetId) === 0;
79448
+ if (addressMappingCleared && rangeMappingCleared) {
79449
+ this.sheetMapping.removeSheetIfExists(sheetId);
79450
+ this.addressMapping.removeSheetIfExists(sheetId);
79451
+ }
79452
+ else {
79453
+ this.sheetMapping.markSheetAsPlaceholder(sheetId);
79454
+ }
79455
+ }
79456
+ /**
79457
+ * Removes placeholderSheetToDelete and reroutes edges to the corresponding vertices in sheetToKeep
79458
+ *
79459
+ * Assumptions about placeholderSheetToDelete:
79460
+ * - is empty (contains only empty cell vertices and range vertices),
79461
+ * - empty cell vertices have no dependencies,
79462
+ * - range vertices have dependencies only in placeholderSheetToDelete,
79463
+ * - vertices may have dependents in placeholderSheetToDelete and other sheets,
79464
+ */
79465
+ mergeSheets(sheetToKeep, placeholderSheetToDelete) {
79466
+ if (!this.isPlaceholder(placeholderSheetToDelete)) {
79467
+ throw new Error(`Cannot merge sheets: sheet ${placeholderSheetToDelete} is not a placeholder`);
79468
+ }
79469
+ this.mergeRangeVertices(sheetToKeep, placeholderSheetToDelete);
79470
+ this.mergeCellVertices(sheetToKeep, placeholderSheetToDelete);
79471
+ this.addressMapping.removeSheetIfExists(placeholderSheetToDelete);
79472
+ this.addStructuralNodesToChangeSet();
79473
+ }
79474
+ /**
79475
+ * Clears the sheet content.
79476
+ * - removes all cell vertices without dependents
79477
+ * - removes all array vertices
79478
+ * - for vertices with dependents, exchanges them for EmptyCellVertex and marks them as dirty
79479
+ */
78747
79480
  clearSheet(sheetId) {
78748
79481
  const arrays = /* @__PURE__ */ new Set();
78749
79482
  for (const [address, vertex] of this.addressMapping.sheetEntries(sheetId)) {
78750
- if (vertex instanceof ArrayVertex) {
79483
+ if (vertex instanceof ArrayFormulaVertex) {
78751
79484
  arrays.add(vertex);
78752
79485
  }
78753
79486
  else {
@@ -78765,7 +79498,7 @@ class DependencyGraph {
78765
79498
  for (const adjacentNode of this.graph.adjacentNodes(vertex)) {
78766
79499
  this.graph.markNodeAsDirty(adjacentNode);
78767
79500
  }
78768
- if (vertex instanceof ArrayVertex) {
79501
+ if (vertex instanceof ArrayFormulaVertex) {
78769
79502
  if (vertex.isLeftCorner(address)) {
78770
79503
  this.shrinkArrayToCorner(vertex);
78771
79504
  this.arrayMapping.removeArray(vertex.getRange());
@@ -78798,7 +79531,7 @@ class DependencyGraph {
78798
79531
  this.addressMapping.addRows(addedRows.sheet, addedRows.rowStart, addedRows.numberOfRows);
78799
79532
  });
78800
79533
  const affectedArrays = this.stats.measure(StatType.ADJUSTING_RANGES, () => {
78801
- const result = this.rangeMapping.moveAllRangesInSheetAfterRowByRows(addedRows.sheet, addedRows.rowStart, addedRows.numberOfRows);
79534
+ const result = this.rangeMapping.moveAllRangesInSheetAfterAddingRows(addedRows.sheet, addedRows.rowStart, addedRows.numberOfRows);
78802
79535
  this.fixRangesWhenAddingRows(addedRows.sheet, addedRows.rowStart, addedRows.numberOfRows);
78803
79536
  return this.getArrayVerticesRelatedToRanges(result.verticesWithChangedSize);
78804
79537
  });
@@ -78818,7 +79551,7 @@ class DependencyGraph {
78818
79551
  this.addressMapping.addColumns(addedColumns.sheet, addedColumns.columnStart, addedColumns.numberOfColumns);
78819
79552
  });
78820
79553
  const affectedArrays = this.stats.measure(StatType.ADJUSTING_RANGES, () => {
78821
- const result = this.rangeMapping.moveAllRangesInSheetAfterColumnByColumns(addedColumns.sheet, addedColumns.columnStart, addedColumns.numberOfColumns);
79554
+ const result = this.rangeMapping.moveAllRangesInSheetAfterAddingColumns(addedColumns.sheet, addedColumns.columnStart, addedColumns.numberOfColumns);
78822
79555
  this.fixRangesWhenAddingColumns(addedColumns.sheet, addedColumns.columnStart, addedColumns.numberOfColumns);
78823
79556
  return this.getArrayVerticesRelatedToRanges(result.verticesWithChangedSize);
78824
79557
  });
@@ -78896,13 +79629,20 @@ class DependencyGraph {
78896
79629
  }
78897
79630
  this.rangeMapping.moveRangesInsideSourceRange(sourceRange, toRight, toBottom, toSheet);
78898
79631
  }
79632
+ /**
79633
+ * Sets an array empty.
79634
+ * - removes all corresponding entries from address mapping
79635
+ * - reroutes the edges
79636
+ * - removes vertex from graph and cleans up its dependencies
79637
+ * - removes vertex from range mapping and array mapping
79638
+ */
78899
79639
  setArrayEmpty(arrayVertex) {
78900
79640
  const arrayRange = AbsoluteCellRange.spanFrom(arrayVertex.getAddress(this.lazilyTransformingAstService), arrayVertex.width, arrayVertex.height);
78901
- const adjacentNodes = this.graph.adjacentNodes(arrayVertex);
79641
+ const dependentVertices = this.graph.adjacentNodes(arrayVertex);
78902
79642
  for (const address of arrayRange.addresses(this)) {
78903
79643
  this.addressMapping.removeCell(address);
78904
79644
  }
78905
- for (const adjacentNode of adjacentNodes.values()) {
79645
+ for (const adjacentNode of dependentVertices.values()) {
78906
79646
  const nodeDependencies = collectAddressesDependentToRange(this.functionRegistry, adjacentNode, arrayVertex.getRange(), this.lazilyTransformingAstService, this);
78907
79647
  for (const address of nodeDependencies) {
78908
79648
  const { vertex, id: id2 } = this.fetchCellOrCreateEmpty(address);
@@ -78923,9 +79663,12 @@ class DependencyGraph {
78923
79663
  this.graph.addNodeAndReturnId(vertex);
78924
79664
  this.setAddressMappingForArrayVertex(vertex, address);
78925
79665
  }
79666
+ /**
79667
+ * Iterator over all array formula nodes in the graph.
79668
+ */
78926
79669
  *arrayFormulaNodes() {
78927
79670
  for (const vertex of this.graph.getNodes()) {
78928
- if (vertex instanceof ArrayVertex) {
79671
+ if (vertex instanceof ArrayFormulaVertex) {
78929
79672
  yield vertex;
78930
79673
  }
78931
79674
  }
@@ -78937,18 +79680,33 @@ class DependencyGraph {
78937
79680
  yield* this.addressMapping.entriesFromColumnsSpan(columnsSpan);
78938
79681
  }
78939
79682
  fetchCell(address) {
78940
- return this.addressMapping.fetchCell(address);
79683
+ return this.addressMapping.getCellOrThrow(address);
78941
79684
  }
79685
+ /**
79686
+ * Gets the cell vertex at the specified address.
79687
+ * @throws {NoSheetWithIdError} if sheet doesn't exist
79688
+ */
78942
79689
  getCell(address) {
78943
- return this.addressMapping.getCell(address);
79690
+ return this.addressMapping.getCell(address, {
79691
+ throwIfSheetNotExists: true
79692
+ });
78944
79693
  }
78945
79694
  getCellValue(address) {
79695
+ if (this.isPlaceholder(address.sheet)) {
79696
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
79697
+ }
78946
79698
  return this.addressMapping.getCellValue(address);
78947
79699
  }
78948
79700
  getRawValue(address) {
79701
+ if (this.isPlaceholder(address.sheet)) {
79702
+ return null;
79703
+ }
78949
79704
  return this.addressMapping.getRawValue(address);
78950
79705
  }
78951
79706
  getScalarValue(address) {
79707
+ if (this.isPlaceholder(address.sheet)) {
79708
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
79709
+ }
78952
79710
  const value = this.addressMapping.getCellValue(address);
78953
79711
  if (value instanceof SimpleRangeValue) {
78954
79712
  return new CellError(ErrorType.VALUE, ErrorMessage.ScalarExpected);
@@ -78959,19 +79717,19 @@ class DependencyGraph {
78959
79717
  return this.graph.existsEdge(fromNode, toNode);
78960
79718
  }
78961
79719
  getSheetId(sheetName) {
78962
- return this.sheetMapping.fetch(sheetName);
79720
+ return this.sheetMapping.getSheetIdOrThrowError(sheetName);
78963
79721
  }
78964
79722
  getSheetHeight(sheet) {
78965
- return this.addressMapping.getHeight(sheet);
79723
+ return this.addressMapping.getSheetHeight(sheet);
78966
79724
  }
78967
79725
  getSheetWidth(sheet) {
78968
- return this.addressMapping.getWidth(sheet);
79726
+ return this.addressMapping.getSheetWidth(sheet);
78969
79727
  }
78970
79728
  getArray(range2) {
78971
79729
  return this.arrayMapping.getArray(range2);
78972
79730
  }
78973
79731
  getRange(start, end) {
78974
- return this.rangeMapping.getRange(start, end);
79732
+ return this.rangeMapping.getRangeVertex(start, end);
78975
79733
  }
78976
79734
  topSortWithScc() {
78977
79735
  return this.graph.topSortWithScc();
@@ -78984,7 +79742,7 @@ class DependencyGraph {
78984
79742
  }
78985
79743
  forceApplyPostponedTransformations() {
78986
79744
  for (const vertex of this.graph.getNodes()) {
78987
- if (vertex instanceof FormulaCellVertex) {
79745
+ if (vertex instanceof ScalarFormulaVertex) {
78988
79746
  vertex.ensureRecentData(this.lazilyTransformingAstService);
78989
79747
  }
78990
79748
  }
@@ -79031,7 +79789,7 @@ class DependencyGraph {
79031
79789
  }
79032
79790
  isArrayInternalCell(address) {
79033
79791
  const vertex = this.getCell(address);
79034
- return vertex instanceof ArrayVertex && !vertex.isLeftCorner(address);
79792
+ return vertex instanceof ArrayFormulaVertex && !vertex.isLeftCorner(address);
79035
79793
  }
79036
79794
  getAndClearContentChanges() {
79037
79795
  const changes = this.changes;
@@ -79042,16 +79800,98 @@ class DependencyGraph {
79042
79800
  const deps = this.graph.adjacentNodes(inputVertex);
79043
79801
  const ret = [];
79044
79802
  deps.forEach((vertex) => {
79045
- const castVertex = vertex;
79046
- if (castVertex instanceof RangeVertex) {
79047
- ret.push(simpleCellRange(castVertex.start, castVertex.end));
79803
+ if (vertex instanceof RangeVertex) {
79804
+ ret.push(simpleCellRange(vertex.start, vertex.end));
79048
79805
  }
79049
- else {
79050
- ret.push(castVertex.getAddress(this.lazilyTransformingAstService));
79806
+ else if (vertex instanceof FormulaVertex) {
79807
+ ret.push(vertex.getAddress(this.lazilyTransformingAstService));
79051
79808
  }
79052
79809
  });
79053
79810
  return ret;
79054
79811
  }
79812
+ /**
79813
+ * Marks all cell vertices in the sheet as dirty.
79814
+ */
79815
+ markAllCellsAsDirtyInSheet(sheetId) {
79816
+ const sheetCells = this.addressMapping.sheetEntries(sheetId);
79817
+ for (const [, vertex] of sheetCells) {
79818
+ this.graph.markNodeAsDirty(vertex);
79819
+ }
79820
+ }
79821
+ /**
79822
+ * Marks all range vertices in the sheet as dirty.
79823
+ */
79824
+ markAllRangesAsDirtyInSheet(sheetId) {
79825
+ const sheetRanges = this.rangeMapping.rangesInSheet(sheetId);
79826
+ for (const vertex of sheetRanges) {
79827
+ this.graph.markNodeAsDirty(vertex);
79828
+ }
79829
+ }
79830
+ /**
79831
+ * For each range vertex in placeholderSheetToDelete:
79832
+ * - reroutes dependencies and dependents of range vertex to the corresponding vertex in sheetToKeep
79833
+ * - removes range vertex from graph and range mapping
79834
+ * - cleans up dependencies of the removed vertex
79835
+ */
79836
+ mergeRangeVertices(sheetToKeep, placeholderSheetToDelete) {
79837
+ const rangeVertices = Array.from(this.rangeMapping.rangesInSheet(placeholderSheetToDelete));
79838
+ for (const vertexToDelete of rangeVertices) {
79839
+ if (!this.graph.hasNode(vertexToDelete)) {
79840
+ continue;
79841
+ }
79842
+ const start = vertexToDelete.start;
79843
+ const end = vertexToDelete.end;
79844
+ if (start.sheet !== placeholderSheetToDelete && end.sheet !== placeholderSheetToDelete) {
79845
+ continue;
79846
+ }
79847
+ const targetStart = simpleCellAddress(sheetToKeep, start.col, start.row);
79848
+ const targetEnd = simpleCellAddress(sheetToKeep, end.col, end.row);
79849
+ const vertexToKeep = this.rangeMapping.getRangeVertex(targetStart, targetEnd);
79850
+ if (vertexToKeep) {
79851
+ this.rerouteDependents(vertexToDelete, vertexToKeep);
79852
+ this.removeVertexAndRerouteDependencies(vertexToDelete, vertexToKeep);
79853
+ this.rangeMapping.removeVertexIfExists(vertexToDelete);
79854
+ this.graph.markNodeAsDirty(vertexToKeep);
79855
+ }
79856
+ else {
79857
+ this.rangeMapping.removeVertexIfExists(vertexToDelete);
79858
+ vertexToDelete.range.moveToSheet(sheetToKeep);
79859
+ this.rangeMapping.addOrUpdateVertex(vertexToDelete);
79860
+ this.graph.markNodeAsDirty(vertexToDelete);
79861
+ }
79862
+ }
79863
+ }
79864
+ /**
79865
+ * For each cell vertex in placeholderSheetToDelete:
79866
+ * - reroutes dependents of cell vertex to the corresponding vertex in sheetToKeep
79867
+ * - removes cell vertex from graph and address mapping
79868
+ * - cleans up dependencies of the removed vertex
79869
+ */
79870
+ mergeCellVertices(sheetToKeep, placeholderSheetToDelete) {
79871
+ const cellVertices = Array.from(this.addressMapping.sheetEntries(placeholderSheetToDelete));
79872
+ for (const [addressToDelete, vertexToDelete] of cellVertices) {
79873
+ const addressToKeep = simpleCellAddress(sheetToKeep, addressToDelete.col, addressToDelete.row);
79874
+ const vertexToKeep = this.getCell(addressToKeep);
79875
+ if (vertexToKeep) {
79876
+ this.rerouteDependents(vertexToDelete, vertexToKeep);
79877
+ this.removeVertexAndCleanupDependencies(vertexToDelete);
79878
+ this.addressMapping.removeCell(addressToDelete);
79879
+ this.graph.markNodeAsDirty(vertexToKeep);
79880
+ }
79881
+ else {
79882
+ this.addressMapping.moveCell(addressToDelete, addressToKeep);
79883
+ this.graph.markNodeAsDirty(vertexToDelete);
79884
+ }
79885
+ }
79886
+ }
79887
+ /**
79888
+ * Checks if the given sheet ID refers to a placeholder sheet (doesn't exist but is referenced by other sheets)
79889
+ */
79890
+ isPlaceholder(sheetId) {
79891
+ return sheetId !== NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS && !this.sheetMapping.hasSheetWithId(sheetId, {
79892
+ includePlaceholders: false
79893
+ });
79894
+ }
79055
79895
  exchangeGraphNode(oldNode, newNode) {
79056
79896
  this.graph.addNodeAndReturnId(newNode);
79057
79897
  const adjNodesStored = this.graph.adjacentNodes(oldNode);
@@ -79072,6 +79912,9 @@ class DependencyGraph {
79072
79912
  }
79073
79913
  const { vertex, id: maybeVertexId } = this.fetchCellOrCreateEmpty(address);
79074
79914
  const vertexId = maybeVertexId !== null && maybeVertexId !== void 0 ? maybeVertexId : this.graph.getNodeId(vertex);
79915
+ if (vertexId === void 0) {
79916
+ throw new Error("Vertex not found");
79917
+ }
79075
79918
  relevantInfiniteRanges.forEach(({ id: id2 }) => {
79076
79919
  this.graph.addEdge(vertexId, id2);
79077
79920
  });
@@ -79091,7 +79934,7 @@ class DependencyGraph {
79091
79934
  return;
79092
79935
  }
79093
79936
  this.graph.adjacentNodes(range2).forEach((adjacentVertex) => {
79094
- if (adjacentVertex instanceof ArrayVertex) {
79937
+ if (adjacentVertex instanceof ArrayFormulaVertex) {
79095
79938
  arrayVertices.add(adjacentVertex);
79096
79939
  }
79097
79940
  });
@@ -79183,7 +80026,7 @@ class DependencyGraph {
79183
80026
  }
79184
80027
  while (find2.smallerRangeVertex === void 0) {
79185
80028
  const newRangeVertex = new RangeVertex(AbsoluteCellRange.spanFrom(currentRangeVertex.range.start, currentRangeVertex.range.width(), currentRangeVertex.range.height() - 1));
79186
- this.rangeMapping.setRange(newRangeVertex);
80029
+ this.rangeMapping.addOrUpdateVertex(newRangeVertex);
79187
80030
  this.graph.addNodeAndReturnId(newRangeVertex);
79188
80031
  const restRange = new AbsoluteCellRange(simpleCellAddress(currentRangeVertex.range.start.sheet, currentRangeVertex.range.start.col, currentRangeVertex.range.end.row), currentRangeVertex.range.end);
79189
80032
  this.addAllFromRange(restRange, currentRangeVertex);
@@ -79225,12 +80068,12 @@ class DependencyGraph {
79225
80068
  const address = vertex.getAddress(this.lazilyTransformingAstService);
79226
80069
  const range2 = AbsoluteCellRange.spanFrom(address, vertex.width, vertex.height);
79227
80070
  const oldNode = this.shrinkPossibleArrayAndGetCell(address);
79228
- if (vertex instanceof ArrayVertex) {
80071
+ if (vertex instanceof ArrayFormulaVertex) {
79229
80072
  this.setArray(range2, vertex);
79230
80073
  }
79231
80074
  this.exchangeOrAddGraphNode(oldNode, vertex);
79232
80075
  this.addressMapping.setCell(address, vertex);
79233
- if (vertex instanceof ArrayVertex) {
80076
+ if (vertex instanceof ArrayFormulaVertex) {
79234
80077
  if (!this.isThereSpaceForArray(vertex)) {
79235
80078
  return;
79236
80079
  }
@@ -79248,7 +80091,7 @@ class DependencyGraph {
79248
80091
  }
79249
80092
  setAddressMappingForArrayVertex(vertex, formulaAddress) {
79250
80093
  this.addressMapping.setCell(formulaAddress, vertex);
79251
- if (!(vertex instanceof ArrayVertex)) {
80094
+ if (!(vertex instanceof ArrayFormulaVertex)) {
79252
80095
  return;
79253
80096
  }
79254
80097
  const range2 = AbsoluteCellRange.spanFromOrUndef(formulaAddress, vertex.width, vertex.height);
@@ -79266,7 +80109,8 @@ class DependencyGraph {
79266
80109
  truncateRanges(span, coordinate) {
79267
80110
  const { verticesToRemove, verticesToMerge, verticesWithChangedSize } = this.rangeMapping.truncateRanges(span, coordinate);
79268
80111
  for (const [existingVertex, mergedVertex] of verticesToMerge) {
79269
- this.mergeRangeVertices(existingVertex, mergedVertex);
80112
+ this.rerouteDependents(mergedVertex, existingVertex);
80113
+ this.removeVertexAndCleanupDependencies(mergedVertex);
79270
80114
  }
79271
80115
  for (const rangeVertex of verticesToRemove) {
79272
80116
  this.removeVertexAndCleanupDependencies(rangeVertex);
@@ -79343,36 +80187,59 @@ class DependencyGraph {
79343
80187
  }
79344
80188
  shrinkPossibleArrayAndGetCell(address) {
79345
80189
  const vertex = this.getCell(address);
79346
- if (!(vertex instanceof ArrayVertex)) {
80190
+ if (!(vertex instanceof ArrayFormulaVertex)) {
79347
80191
  return vertex;
79348
80192
  }
79349
80193
  this.setNoSpaceIfArray(vertex);
79350
80194
  return this.getCell(address);
79351
80195
  }
79352
80196
  setNoSpaceIfArray(vertex) {
79353
- if (vertex instanceof ArrayVertex) {
80197
+ if (vertex instanceof ArrayFormulaVertex) {
79354
80198
  this.shrinkArrayToCorner(vertex);
79355
80199
  vertex.setNoSpace();
79356
80200
  }
79357
80201
  }
80202
+ /**
80203
+ * Removes a vertex from the graph and range mapping and cleans up its dependencies.
80204
+ */
79358
80205
  removeVertex(vertex) {
79359
80206
  this.removeVertexAndCleanupDependencies(vertex);
79360
80207
  if (vertex instanceof RangeVertex) {
79361
- this.rangeMapping.removeRange(vertex);
80208
+ this.rangeMapping.removeVertexIfExists(vertex);
79362
80209
  }
79363
80210
  }
79364
- mergeRangeVertices(existingVertex, newVertex) {
79365
- const adjNodesStored = this.graph.adjacentNodes(newVertex);
79366
- this.removeVertexAndCleanupDependencies(newVertex);
79367
- this.graph.removeEdgeIfExists(existingVertex, newVertex);
79368
- adjNodesStored.forEach((adjacentNode) => {
80211
+ /**
80212
+ * Reroutes dependent vertices of source to target. Also removes the edge target -> source if it exists.
80213
+ */
80214
+ rerouteDependents(source, target) {
80215
+ const dependents = this.graph.adjacentNodes(source);
80216
+ this.graph.removeEdgeIfExists(target, source);
80217
+ dependents.forEach((adjacentNode) => {
79369
80218
  if (this.graph.hasNode(adjacentNode)) {
79370
- this.graph.addEdge(existingVertex, adjacentNode);
80219
+ this.graph.addEdge(target, adjacentNode);
80220
+ }
80221
+ });
80222
+ }
80223
+ /**
80224
+ * Removes a vertex from graph and reroutes its dependencies to other vertex. Also removes the edge vertexToKeep -> vertexToDelete if it exists.
80225
+ */
80226
+ removeVertexAndRerouteDependencies(vertexToDelete, vertexToKeep) {
80227
+ const dependencies = this.graph.removeNode(vertexToDelete);
80228
+ this.graph.removeEdgeIfExists(vertexToKeep, vertexToDelete);
80229
+ dependencies.forEach(([_, dependency]) => {
80230
+ if (this.graph.hasNode(dependency)) {
80231
+ this.graph.addEdge(dependency, vertexToKeep);
79371
80232
  }
79372
80233
  });
79373
80234
  }
80235
+ /**
80236
+ * Removes a vertex from graph and cleans up its dependencies.
80237
+ * Dependency clean up = remove all RangeVertex and EmptyCellVertex dependencies if no other vertex depends on them.
80238
+ * Also cleans up placeholder sheets that have no remaining vertices (not needed anymore)
80239
+ */
79374
80240
  removeVertexAndCleanupDependencies(inputVertex) {
79375
80241
  const dependencies = new Set(this.graph.removeNode(inputVertex));
80242
+ const affectedSheets = /* @__PURE__ */ new Set();
79376
80243
  while (dependencies.size > 0) {
79377
80244
  const dependency = dependencies.values().next().value;
79378
80245
  dependencies.delete(dependency);
@@ -79382,13 +80249,29 @@ class DependencyGraph {
79382
80249
  this.graph.removeNode(vertex).forEach((candidate) => dependencies.add(candidate));
79383
80250
  }
79384
80251
  if (vertex instanceof RangeVertex) {
79385
- this.rangeMapping.removeRange(vertex);
80252
+ this.rangeMapping.removeVertexIfExists(vertex);
80253
+ affectedSheets.add(vertex.sheet);
79386
80254
  }
79387
- else if (vertex instanceof EmptyCellVertex) {
80255
+ else if (vertex instanceof EmptyCellVertex && isSimpleCellAddress(address)) {
79388
80256
  this.addressMapping.removeCell(address);
80257
+ affectedSheets.add(address.sheet);
79389
80258
  }
79390
80259
  }
79391
80260
  }
80261
+ this.cleanupPlaceholderSheets(affectedSheets);
80262
+ }
80263
+ /**
80264
+ * Removes placeholder sheets that have no remaining vertices.
80265
+ */
80266
+ cleanupPlaceholderSheets(sheetIds) {
80267
+ for (const sheetId of sheetIds) {
80268
+ if (this.isPlaceholder(sheetId) && !this.addressMapping.hasAnyEntries(sheetId) && this.rangeMapping.getNumberOfRangesInSheet(sheetId) === 0) {
80269
+ this.sheetMapping.removeSheetIfExists(sheetId, {
80270
+ includePlaceholders: true
80271
+ });
80272
+ this.addressMapping.removeSheetIfExists(sheetId);
80273
+ }
80274
+ }
79392
80275
  }
79393
80276
  }
79394
80277
  class EmptyCellVertex {
@@ -79807,7 +80690,7 @@ var CellType;
79807
80690
  CellType2["ARRAYFORMULA"] = "ARRAYFORMULA";
79808
80691
  })(CellType || (CellType = {}));
79809
80692
  const getCellType = (vertex, address) => {
79810
- if (vertex instanceof ArrayVertex) {
80693
+ if (vertex instanceof ArrayFormulaVertex) {
79811
80694
  if (vertex.isLeftCorner(address)) {
79812
80695
  return CellType.ARRAYFORMULA;
79813
80696
  }
@@ -79815,7 +80698,7 @@ const getCellType = (vertex, address) => {
79815
80698
  return CellType.ARRAY;
79816
80699
  }
79817
80700
  }
79818
- if (vertex instanceof FormulaCellVertex || vertex instanceof ParsingErrorVertex) {
80701
+ if (vertex instanceof ScalarFormulaVertex || vertex instanceof ParsingErrorVertex) {
79819
80702
  return CellType.FORMULA;
79820
80703
  }
79821
80704
  if (vertex instanceof ValueCellVertex) {
@@ -79923,7 +80806,7 @@ const simpleCellAddress = (sheet, col, row) => ({
79923
80806
  col,
79924
80807
  row
79925
80808
  });
79926
- const invalidSimpleCellAddress = (address) => address.col < 0 || address.row < 0;
80809
+ const isColOrRowInvalid = (address) => address.col < 0 || address.row < 0;
79927
80810
  const movedSimpleCellAddress = (address, toSheet, toRight, toBottom) => {
79928
80811
  return simpleCellAddress(toSheet, address.col + toRight, address.row + toBottom);
79929
80812
  };
@@ -82459,7 +83342,7 @@ function checkLicenseKeyValidity(licenseKey) {
82459
83342
  messageDescriptor.template = "valid";
82460
83343
  }
82461
83344
  else if (typeof licenseKey === "string" && checkKeySchema(licenseKey)) {
82462
- const [day, month, year] = "14/10/2025".split("/");
83345
+ const [day, month, year] = "18/12/2025".split("/");
82463
83346
  const releaseDays = Math.floor(( /* @__PURE__ */new Date(`${month}/${day}/${year}`)).getTime() / 864e5);
82464
83347
  const keyValidityDays = extractTime(licenseKey);
82465
83348
  messageDescriptor.vars.keyValidityDate = formatDate(new Date((keyValidityDays + 1) * 864e5));
@@ -82717,7 +83600,7 @@ class ClipboardOperations {
82717
83600
  if (this.clipboard === void 0) {
82718
83601
  return;
82719
83602
  }
82720
- if (invalidSimpleCellAddress(destinationLeftCorner) || !this.dependencyGraph.sheetMapping.hasSheetWithId(destinationLeftCorner.sheet)) {
83603
+ if (isColOrRowInvalid(destinationLeftCorner) || !this.dependencyGraph.sheetMapping.hasSheetWithId(destinationLeftCorner.sheet)) {
82721
83604
  throw new InvalidArgumentsError("a valid target address.");
82722
83605
  }
82723
83606
  const targetRange = AbsoluteCellRange.spanFrom(destinationLeftCorner, this.clipboard.width, this.clipboard.height);
@@ -82735,299 +83618,6 @@ class ClipboardOperations {
82735
83618
  return this.clipboard !== void 0 && this.clipboard.type === ClipboardOperationType.COPY;
82736
83619
  }
82737
83620
  }
82738
- class InternalNamedExpression {
82739
- constructor(displayName, address, added, options) {
82740
- this.displayName = displayName;
82741
- this.address = address;
82742
- this.added = added;
82743
- this.options = options;
82744
- }
82745
- normalizeExpressionName() {
82746
- return this.displayName.toLowerCase();
82747
- }
82748
- copy() {
82749
- return new InternalNamedExpression(this.displayName, this.address, this.added, this.options);
82750
- }
82751
- }
82752
- class WorkbookStore {
82753
- constructor() {
82754
- this.mapping = /* @__PURE__ */ new Map();
82755
- }
82756
- has(expressionName) {
82757
- return this.mapping.has(this.normalizeExpressionName(expressionName));
82758
- }
82759
- isNameAvailable(expressionName) {
82760
- const normalizedExpressionName = this.normalizeExpressionName(expressionName);
82761
- const namedExpression = this.mapping.get(normalizedExpressionName);
82762
- return !(namedExpression && namedExpression.added);
82763
- }
82764
- add(namedExpression) {
82765
- this.mapping.set(namedExpression.normalizeExpressionName(), namedExpression);
82766
- }
82767
- get(expressionName) {
82768
- return this.mapping.get(this.normalizeExpressionName(expressionName));
82769
- }
82770
- getExisting(expressionName) {
82771
- const namedExpression = this.mapping.get(this.normalizeExpressionName(expressionName));
82772
- if (namedExpression && namedExpression.added) {
82773
- return namedExpression;
82774
- }
82775
- else {
82776
- return void 0;
82777
- }
82778
- }
82779
- remove(expressionName) {
82780
- const normalizedExpressionName = this.normalizeExpressionName(expressionName);
82781
- const namedExpression = this.mapping.get(normalizedExpressionName);
82782
- if (namedExpression) {
82783
- namedExpression.added = false;
82784
- }
82785
- }
82786
- getAllNamedExpressions() {
82787
- return Array.from(this.mapping.values()).filter((ne) => ne.added);
82788
- }
82789
- normalizeExpressionName(expressionName) {
82790
- return expressionName.toLowerCase();
82791
- }
82792
- }
82793
- class WorksheetStore {
82794
- constructor() {
82795
- this.mapping = /* @__PURE__ */ new Map();
82796
- }
82797
- add(namedExpression) {
82798
- this.mapping.set(this.normalizeExpressionName(namedExpression.displayName), namedExpression);
82799
- }
82800
- get(expressionName) {
82801
- return this.mapping.get(this.normalizeExpressionName(expressionName));
82802
- }
82803
- has(expressionName) {
82804
- return this.mapping.has(this.normalizeExpressionName(expressionName));
82805
- }
82806
- getAllNamedExpressions() {
82807
- return Array.from(this.mapping.values()).filter((ne) => ne.added);
82808
- }
82809
- isNameAvailable(expressionName) {
82810
- const normalizedExpressionName = this.normalizeExpressionName(expressionName);
82811
- return !this.mapping.has(normalizedExpressionName);
82812
- }
82813
- remove(expressionName) {
82814
- const normalizedExpressionName = this.normalizeExpressionName(expressionName);
82815
- const namedExpression = this.mapping.get(normalizedExpressionName);
82816
- if (namedExpression) {
82817
- this.mapping.delete(normalizedExpressionName);
82818
- }
82819
- }
82820
- normalizeExpressionName(expressionName) {
82821
- return expressionName.toLowerCase();
82822
- }
82823
- }
82824
- class NamedExpressions {
82825
- constructor() {
82826
- this.nextNamedExpressionRow = 0;
82827
- this.workbookStore = new WorkbookStore();
82828
- this.worksheetStores = /* @__PURE__ */ new Map();
82829
- this.addressCache = /* @__PURE__ */ new Map();
82830
- }
82831
- isNameAvailable(expressionName, sheetId) {
82832
- var _a, _b;
82833
- if (sheetId === void 0) {
82834
- return this.workbookStore.isNameAvailable(expressionName);
82835
- }
82836
- else {
82837
- return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.isNameAvailable(expressionName)) !== null && _b !== void 0 ? _b : true;
82838
- }
82839
- }
82840
- namedExpressionInAddress(row) {
82841
- const namedExpression = this.addressCache.get(row);
82842
- if (namedExpression && namedExpression.added) {
82843
- return namedExpression;
82844
- }
82845
- else {
82846
- return void 0;
82847
- }
82848
- }
82849
- namedExpressionForScope(expressionName, sheetId) {
82850
- var _a;
82851
- if (sheetId === void 0) {
82852
- return this.workbookStore.getExisting(expressionName);
82853
- }
82854
- else {
82855
- return (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.get(expressionName);
82856
- }
82857
- }
82858
- nearestNamedExpression(expressionName, sheetId) {
82859
- var _a, _b;
82860
- return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.get(expressionName)) !== null && _b !== void 0 ? _b : this.workbookStore.getExisting(expressionName);
82861
- }
82862
- isExpressionInScope(expressionName, sheetId) {
82863
- var _a, _b;
82864
- return (_b = (_a = this.worksheetStore(sheetId)) === null || _a === void 0 ? void 0 : _a.has(expressionName)) !== null && _b !== void 0 ? _b : false;
82865
- }
82866
- /**
82867
- * Checks the validity of a named-expression's name.
82868
- *
82869
- * The name:
82870
- * - Must start with a Unicode letter or with an underscore (`_`).
82871
- * - Can contain only Unicode letters, numbers, underscores, and periods (`.`).
82872
- * - Can't be the same as any possible reference in the A1 notation (`[A-Za-z]+[0-9]+`).
82873
- * - Can't be the same as any possible reference in the R1C1 notation (`[rR][0-9]*[cC][0-9]*`).
82874
- *
82875
- * The naming rules follow the [OpenDocument](https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#__RefHeading__1017964_715980110) standard.
82876
- */
82877
- isNameValid(expressionName) {
82878
- const a1CellRefRegexp = new RegExp(`^${CELL_REFERENCE_PATTERN}$`);
82879
- const r1c1CellRefRegexp = new RegExp(`^${R1C1_CELL_REFERENCE_PATTERN}$`);
82880
- const namedExpRegexp = new RegExp(`^${NAMED_EXPRESSION_PATTERN}$`);
82881
- if (a1CellRefRegexp.test(expressionName) || r1c1CellRefRegexp.test(expressionName)) {
82882
- return false;
82883
- }
82884
- return namedExpRegexp.test(expressionName);
82885
- }
82886
- addNamedExpression(expressionName, sheetId, options) {
82887
- const store2 = sheetId === void 0 ? this.workbookStore : this.worksheetStoreOrCreate(sheetId);
82888
- let namedExpression = store2.get(expressionName);
82889
- if (namedExpression !== void 0) {
82890
- namedExpression.added = true;
82891
- namedExpression.displayName = expressionName;
82892
- namedExpression.options = options;
82893
- }
82894
- else {
82895
- namedExpression = new InternalNamedExpression(expressionName, this.nextAddress(), true, options);
82896
- store2.add(namedExpression);
82897
- }
82898
- this.addressCache.set(namedExpression.address.row, namedExpression);
82899
- return namedExpression;
82900
- }
82901
- restoreNamedExpression(namedExpression, sheetId) {
82902
- const store2 = sheetId === void 0 ? this.workbookStore : this.worksheetStoreOrCreate(sheetId);
82903
- namedExpression.added = true;
82904
- store2.add(namedExpression);
82905
- this.addressCache.set(namedExpression.address.row, namedExpression);
82906
- return namedExpression;
82907
- }
82908
- namedExpressionOrPlaceholder(expressionName, sheetId) {
82909
- var _a;
82910
- return (_a = this.worksheetStoreOrCreate(sheetId).get(expressionName)) !== null && _a !== void 0 ? _a : this.workbookNamedExpressionOrPlaceholder(expressionName);
82911
- }
82912
- workbookNamedExpressionOrPlaceholder(expressionName) {
82913
- let namedExpression = this.workbookStore.get(expressionName);
82914
- if (namedExpression === void 0) {
82915
- namedExpression = new InternalNamedExpression(expressionName, this.nextAddress(), false);
82916
- this.workbookStore.add(namedExpression);
82917
- }
82918
- return namedExpression;
82919
- }
82920
- remove(expressionName, sheetId) {
82921
- let store2;
82922
- if (sheetId === void 0) {
82923
- store2 = this.workbookStore;
82924
- }
82925
- else {
82926
- store2 = this.worksheetStore(sheetId);
82927
- }
82928
- const namedExpression = store2 === null || store2 === void 0 ? void 0 : store2.get(expressionName);
82929
- if (store2 === void 0 || namedExpression === void 0 || !namedExpression.added) {
82930
- throw Error("Named expression does not exist");
82931
- }
82932
- store2.remove(expressionName);
82933
- if (store2 instanceof WorksheetStore && store2.mapping.size === 0) {
82934
- this.worksheetStores.delete(sheetId);
82935
- }
82936
- this.addressCache.delete(namedExpression.address.row);
82937
- }
82938
- getAllNamedExpressionsNamesInScope(sheetId) {
82939
- return this.getAllNamedExpressions().filter(({ scope }) => scope === sheetId).map((ne) => ne.expression.displayName);
82940
- }
82941
- getAllNamedExpressionsNames() {
82942
- return this.getAllNamedExpressions().map((ne) => ne.expression.displayName);
82943
- }
82944
- getAllNamedExpressions() {
82945
- const storedNamedExpressions = [];
82946
- this.workbookStore.getAllNamedExpressions().forEach((expr) => {
82947
- storedNamedExpressions.push({
82948
- expression: expr,
82949
- scope: void 0
82950
- });
82951
- });
82952
- this.worksheetStores.forEach((store2, sheetNum) => {
82953
- store2.getAllNamedExpressions().forEach((expr) => {
82954
- storedNamedExpressions.push({
82955
- expression: expr,
82956
- scope: sheetNum
82957
- });
82958
- });
82959
- });
82960
- return storedNamedExpressions;
82961
- }
82962
- getAllNamedExpressionsForScope(scope) {
82963
- var _a, _b;
82964
- if (scope === void 0) {
82965
- return this.workbookStore.getAllNamedExpressions();
82966
- }
82967
- else {
82968
- return (_b = (_a = this.worksheetStores.get(scope)) === null || _a === void 0 ? void 0 : _a.getAllNamedExpressions()) !== null && _b !== void 0 ? _b : [];
82969
- }
82970
- }
82971
- worksheetStoreOrCreate(sheetId) {
82972
- let store2 = this.worksheetStores.get(sheetId);
82973
- if (!store2) {
82974
- store2 = new WorksheetStore();
82975
- this.worksheetStores.set(sheetId, store2);
82976
- }
82977
- return store2;
82978
- }
82979
- worksheetStore(sheetId) {
82980
- return this.worksheetStores.get(sheetId);
82981
- }
82982
- nextAddress() {
82983
- return simpleCellAddress(NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS, 0, this.nextNamedExpressionRow++);
82984
- }
82985
- }
82986
- NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS = -1;
82987
- const doesContainRelativeReferences = (ast) => {
82988
- switch (ast.type) {
82989
- case AstNodeType.EMPTY:
82990
- case AstNodeType.NUMBER:
82991
- case AstNodeType.STRING:
82992
- case AstNodeType.ERROR:
82993
- case AstNodeType.ERROR_WITH_RAW_INPUT:
82994
- return false;
82995
- case AstNodeType.CELL_REFERENCE:
82996
- return !ast.reference.isAbsolute();
82997
- case AstNodeType.CELL_RANGE:
82998
- case AstNodeType.COLUMN_RANGE:
82999
- case AstNodeType.ROW_RANGE:
83000
- return !ast.start.isAbsolute();
83001
- case AstNodeType.NAMED_EXPRESSION:
83002
- return false;
83003
- case AstNodeType.PERCENT_OP:
83004
- case AstNodeType.PLUS_UNARY_OP:
83005
- case AstNodeType.MINUS_UNARY_OP: {
83006
- return doesContainRelativeReferences(ast.value);
83007
- }
83008
- case AstNodeType.CONCATENATE_OP:
83009
- case AstNodeType.EQUALS_OP:
83010
- case AstNodeType.NOT_EQUAL_OP:
83011
- case AstNodeType.LESS_THAN_OP:
83012
- case AstNodeType.GREATER_THAN_OP:
83013
- case AstNodeType.LESS_THAN_OR_EQUAL_OP:
83014
- case AstNodeType.GREATER_THAN_OR_EQUAL_OP:
83015
- case AstNodeType.MINUS_OP:
83016
- case AstNodeType.PLUS_OP:
83017
- case AstNodeType.TIMES_OP:
83018
- case AstNodeType.DIV_OP:
83019
- case AstNodeType.POWER_OP:
83020
- return doesContainRelativeReferences(ast.left) || doesContainRelativeReferences(ast.right);
83021
- case AstNodeType.PARENTHESIS:
83022
- return doesContainRelativeReferences(ast.expression);
83023
- case AstNodeType.FUNCTION_CALL: {
83024
- return ast.args.some((arg) => doesContainRelativeReferences(arg));
83025
- }
83026
- case AstNodeType.ARRAY: {
83027
- return ast.args.some((row) => row.some((arg) => doesContainRelativeReferences(arg)));
83028
- }
83029
- }
83030
- };
83031
83621
  class Transformer {
83032
83622
  performEagerTransformations(graph, parser2) {
83033
83623
  for (const node2 of graph.arrayFormulaNodes()) {
@@ -83729,77 +84319,107 @@ class RemoveRowsTransformer extends Transformer {
83729
84319
  }
83730
84320
  }
83731
84321
  }
83732
- class RemoveSheetTransformer extends Transformer {
83733
- constructor(sheet) {
84322
+ class RenameSheetTransformer extends Transformer {
84323
+ constructor(sheetIdToKeep, sheetBeingMerged) {
83734
84324
  super();
83735
- this.sheet = sheet;
84325
+ this.sheetIdToKeep = sheetIdToKeep;
84326
+ this.sheetBeingMerged = sheetBeingMerged;
83736
84327
  }
84328
+ /**
84329
+ * Returns id of sheet that survives merge operation.
84330
+ *
84331
+ * @returns {number} sheet identifier.
84332
+ */
84333
+ get sheet() {
84334
+ return this.sheetIdToKeep;
84335
+ }
84336
+ /**
84337
+ * Sheet merge cannot be undone because original sheet id is lost.
84338
+ *
84339
+ * @returns {boolean} always true to indicate transformation irreversibility.
84340
+ */
83737
84341
  isIrreversible() {
83738
84342
  return true;
83739
84343
  }
83740
- performEagerTransformations(graph, _parser) {
83741
- for (const node2 of graph.arrayFormulaNodes()) {
83742
- const [newAst] = this.transformSingleAst(node2.getFormula(graph.lazilyTransformingAstService), node2.getAddress(graph.lazilyTransformingAstService));
83743
- node2.setFormula(newAst);
83744
- }
83745
- }
83746
- fixNodeAddress(address) {
83747
- return address;
83748
- }
84344
+ /**
84345
+ * Updates cell address sheet when it points to merged sheet.
84346
+ *
84347
+ * @param {T} dependencyAddress - dependency address needing sheet update.
84348
+ * @param {SimpleCellAddress} _formulaAddress - location of formula (unused but required by base class).
84349
+ * @returns {T | false} updated address or false when nothing changes.
84350
+ */
83749
84351
  transformCellAddress(dependencyAddress, _formulaAddress) {
83750
- return this.transformAddress(dependencyAddress);
83751
- }
83752
- transformCellRange(start, _end, _formulaAddress) {
83753
- return this.transformAddress(start);
84352
+ return this.updateSheetInAddress(dependencyAddress);
83754
84353
  }
83755
- transformColumnRange(start, _end, _formulaAddress) {
83756
- return this.transformAddress(start);
84354
+ /**
84355
+ * Updates sheet for both ends of cell range.
84356
+ *
84357
+ * @param {CellAddress} start - start address of range.
84358
+ * @param {CellAddress} end - end address of range.
84359
+ * @param {SimpleCellAddress} _formulaAddress - formula location (unused).
84360
+ * @returns {[CellAddress, CellAddress] | false} updated range tuple or false when unchanged.
84361
+ */
84362
+ transformCellRange(start, end, _formulaAddress) {
84363
+ return this.transformRange(start, end);
83757
84364
  }
83758
- transformRowRange(start, _end, _formulaAddress) {
83759
- return this.transformAddress(start);
84365
+ /**
84366
+ * Updates sheet for both ends of column range.
84367
+ *
84368
+ * @param {ColumnAddress} start - beginning column of range.
84369
+ * @param {ColumnAddress} end - ending column of range.
84370
+ * @param {SimpleCellAddress} _formulaAddress - formula location (unused).
84371
+ * @returns {[ColumnAddress, ColumnAddress] | false} updated column range or false.
84372
+ */
84373
+ transformColumnRange(start, end, _formulaAddress) {
84374
+ return this.transformRange(start, end);
83760
84375
  }
83761
- transformAddress(address) {
83762
- if (address.sheet === this.sheet) {
83763
- return ErrorType.REF;
83764
- }
83765
- return false;
84376
+ /**
84377
+ * Updates sheet for both ends of row range.
84378
+ *
84379
+ * @param {RowAddress} start - beginning row address.
84380
+ * @param {RowAddress} end - ending row address.
84381
+ * @param {SimpleCellAddress} _formulaAddress - formula location (unused).
84382
+ * @returns {[RowAddress, RowAddress] | false} updated row range or false.
84383
+ */
84384
+ transformRowRange(start, end, _formulaAddress) {
84385
+ return this.transformRange(start, end);
83766
84386
  }
83767
- }
83768
- function validateAsSheet(sheet) {
83769
- if (!Array.isArray(sheet)) {
83770
- throw new InvalidArgumentsError("an array of arrays.");
84387
+ /**
84388
+ * Node addresses are already absolute, so no change is needed.
84389
+ *
84390
+ * @param {SimpleCellAddress} address - node address to inspect.
84391
+ * @returns {SimpleCellAddress} original address unchanged.
84392
+ */
84393
+ fixNodeAddress(address) {
84394
+ return address;
83771
84395
  }
83772
- for (let i = 0; i < sheet.length; i++) {
83773
- if (!Array.isArray(sheet[i])) {
83774
- throw new InvalidArgumentsError("an array of arrays.");
84396
+ /**
84397
+ * Updates sheet identifier for both range ends if needed.
84398
+ *
84399
+ * @param {T} start - range start address.
84400
+ * @param {T} end - range end address.
84401
+ * @returns {[T, T] | false} tuple with updated addresses or false when no updates happen.
84402
+ */
84403
+ transformRange(start, end) {
84404
+ const newStart = this.updateSheetInAddress(start);
84405
+ const newEnd = this.updateSheetInAddress(end);
84406
+ if (newStart || newEnd) {
84407
+ return [newStart || start, newEnd || end];
83775
84408
  }
84409
+ return false;
83776
84410
  }
83777
- }
83778
- function findBoundaries(sheet) {
83779
- let width = 0;
83780
- let height = 0;
83781
- let cellsCount = 0;
83782
- for (let currentRow = 0; currentRow < sheet.length; currentRow++) {
83783
- let currentRowWidth = 0;
83784
- for (let currentCol = 0; currentCol < sheet[currentRow].length; currentCol++) {
83785
- const currentValue = sheet[currentRow][currentCol];
83786
- if (currentValue === void 0 || currentValue === null) {
83787
- continue;
83788
- }
83789
- currentRowWidth = currentCol + 1;
83790
- ++cellsCount;
83791
- }
83792
- width = Math.max(width, currentRowWidth);
83793
- if (currentRowWidth > 0) {
83794
- height = currentRow + 1;
84411
+ /**
84412
+ * Replaces sheet id in address when it points to merged sheet.
84413
+ *
84414
+ * @param {T} address - address to update.
84415
+ * @returns {T | false} address with new sheet id or false when no change occurs.
84416
+ */
84417
+ updateSheetInAddress(address) {
84418
+ if (address.sheet === this.sheetBeingMerged) {
84419
+ return address.withSheet(this.sheetIdToKeep);
83795
84420
  }
84421
+ return false;
83796
84422
  }
83797
- const sheetSize = width * height;
83798
- return {
83799
- height,
83800
- width,
83801
- fill: sheetSize === 0 ? 0 : cellsCount / sheetSize
83802
- };
83803
84423
  }
83804
84424
  class RemoveRowsCommand {
83805
84425
  constructor(sheet, indexes) {
@@ -83900,38 +84520,78 @@ class Operations {
83900
84520
  }
83901
84521
  return columnsRemovals;
83902
84522
  }
83903
- removeSheet(sheetId) {
83904
- this.dependencyGraph.removeSheet(sheetId);
83905
- let version = 0;
83906
- this.stats.measure(StatType.TRANSFORM_ASTS, () => {
83907
- const transformation = new RemoveSheetTransformer(sheetId);
83908
- transformation.performEagerTransformations(this.dependencyGraph, this.parser);
83909
- version = this.lazilyTransformingAstService.addTransformation(transformation);
83910
- });
83911
- this.sheetMapping.removeSheet(sheetId);
84523
+ /**
84524
+ * Clears the sheet content.
84525
+ */
84526
+ clearSheet(sheetId) {
84527
+ this.dependencyGraph.clearSheet(sheetId);
83912
84528
  this.columnSearch.removeSheet(sheetId);
83913
- const scopedNamedExpressions = this.namedExpressions.getAllNamedExpressionsForScope(sheetId).map((namedExpression) => this.removeNamedExpression(namedExpression.normalizeExpressionName(), sheetId));
84529
+ }
84530
+ /**
84531
+ * Adds a new sheet to the workbook.
84532
+ */
84533
+ addSheet(name) {
84534
+ const sheetId = this.sheetMapping.addSheet(name);
84535
+ this.dependencyGraph.addSheet(sheetId);
83914
84536
  return {
83915
- version,
83916
- scopedNamedExpressions
84537
+ sheetName: this.sheetMapping.getSheetNameOrThrowError(sheetId),
84538
+ sheetId
83917
84539
  };
83918
84540
  }
83919
- removeSheetByName(sheetName) {
83920
- const sheetId = this.sheetMapping.fetch(sheetName);
83921
- return this.removeSheet(sheetId);
84541
+ /**
84542
+ * Adds a sheet with a specific ID for redo operations.
84543
+ */
84544
+ addSheetWithId(sheetId, name) {
84545
+ this.sheetMapping.addSheetWithId(sheetId, name);
84546
+ this.dependencyGraph.addSheet(sheetId);
83922
84547
  }
83923
- clearSheet(sheetId) {
83924
- this.dependencyGraph.clearSheet(sheetId);
84548
+ /**
84549
+ * Adds a placeholder sheet with a specific ID for undo operations.
84550
+ * Used to restore previously merged placeholder sheets.
84551
+ *
84552
+ * Note: Unlike `addSheetWithId`, this does NOT call `dependencyGraph.addSheet()`
84553
+ * because placeholders don't need dirty marking or strategy changes - they only
84554
+ * need to exist in the mappings so formulas can reference them again.
84555
+ */
84556
+ addPlaceholderSheetWithId(sheetId, name) {
84557
+ this.sheetMapping.addPlaceholderWithId(sheetId, name);
84558
+ this.addressMapping.addSheetStrategyPlaceholderIfNotExists(sheetId);
84559
+ }
84560
+ /**
84561
+ * Removes a sheet from the workbook.
84562
+ */
84563
+ removeSheet(sheetId) {
84564
+ this.dependencyGraph.removeSheet(sheetId);
83925
84565
  this.columnSearch.removeSheet(sheetId);
84566
+ const scopedNamedExpressions = this.namedExpressions.getAllNamedExpressionsForScope(sheetId).map((namedExpression) => this.removeNamedExpression(namedExpression.normalizeExpressionName(), sheetId));
84567
+ return scopedNamedExpressions;
83926
84568
  }
83927
- addSheet(name) {
83928
- const sheetId = this.sheetMapping.addSheet(name);
83929
- const sheet = [];
83930
- this.dependencyGraph.addressMapping.autoAddSheet(sheetId, findBoundaries(sheet));
83931
- return this.sheetMapping.fetchDisplayName(sheetId);
84569
+ /**
84570
+ * Removes a sheet from the workbook by name.
84571
+ */
84572
+ removeSheetByName(sheetName) {
84573
+ const sheetId = this.sheetMapping.getSheetIdOrThrowError(sheetName);
84574
+ return this.removeSheet(sheetId);
83932
84575
  }
84576
+ /**
84577
+ * Renames a sheet in the workbook.
84578
+ */
83933
84579
  renameSheet(sheetId, newName) {
83934
- return this.sheetMapping.renameSheet(sheetId, newName);
84580
+ const { previousDisplayName, mergedWithPlaceholderSheet } = this.sheetMapping.renameSheet(sheetId, newName);
84581
+ let version;
84582
+ if (mergedWithPlaceholderSheet !== void 0) {
84583
+ this.dependencyGraph.mergeSheets(sheetId, mergedWithPlaceholderSheet);
84584
+ this.stats.measure(StatType.TRANSFORM_ASTS, () => {
84585
+ const transformation = new RenameSheetTransformer(sheetId, mergedWithPlaceholderSheet);
84586
+ transformation.performEagerTransformations(this.dependencyGraph, this.parser);
84587
+ version = this.lazilyTransformingAstService.addTransformation(transformation);
84588
+ });
84589
+ }
84590
+ return {
84591
+ previousDisplayName,
84592
+ version,
84593
+ mergedPlaceholderSheetId: mergedWithPlaceholderSheet
84594
+ };
83935
84595
  }
83936
84596
  moveRows(sheet, startRow, numberOfRows, targetRow) {
83937
84597
  const rowsToAdd = RowsSpan.fromNumberOfRows(sheet, targetRow, numberOfRows);
@@ -84070,7 +84730,7 @@ class Operations {
84070
84730
  return [namedExpression, content];
84071
84731
  }
84072
84732
  ensureItIsPossibleToMoveCells(sourceLeftCorner, width, height, destinationLeftCorner) {
84073
- if (invalidSimpleCellAddress(sourceLeftCorner) || !(isPositiveInteger$1(width) && isPositiveInteger$1(height) || isRowOrColumnRange(sourceLeftCorner, width, height)) || invalidSimpleCellAddress(destinationLeftCorner) || !this.sheetMapping.hasSheetWithId(sourceLeftCorner.sheet) || !this.sheetMapping.hasSheetWithId(destinationLeftCorner.sheet)) {
84733
+ if (isColOrRowInvalid(sourceLeftCorner) || !(isPositiveInteger$1(width) && isPositiveInteger$1(height) || isRowOrColumnRange(sourceLeftCorner, width, height)) || isColOrRowInvalid(destinationLeftCorner) || !this.sheetMapping.hasSheetWithId(sourceLeftCorner.sheet) || !this.sheetMapping.hasSheetWithId(destinationLeftCorner.sheet)) {
84074
84734
  throw new InvalidArgumentsError("a valid range of cells to move.");
84075
84735
  }
84076
84736
  const sourceRange = AbsoluteCellRange.spanFrom(sourceLeftCorner, width, height);
@@ -84098,8 +84758,6 @@ class Operations {
84098
84758
  }
84099
84759
  /**
84100
84760
  * Restores a single cell.
84101
- * @param {SimpleCellAddress} address
84102
- * @param {ClipboardCell} clipboardCell
84103
84761
  */
84104
84762
  restoreCell(address, clipboardCell) {
84105
84763
  switch (clipboardCell.type) {
@@ -84160,7 +84818,7 @@ class Operations {
84160
84818
  type: ClipboardCellType.VALUE
84161
84819
  }, vertex.getValues());
84162
84820
  }
84163
- else if (vertex instanceof ArrayVertex) {
84821
+ else if (vertex instanceof ArrayFormulaVertex) {
84164
84822
  const val2 = vertex.getArrayCellValue(address);
84165
84823
  if (val2 === EmptyValue) {
84166
84824
  return {
@@ -84173,7 +84831,7 @@ class Operations {
84173
84831
  rawValue: vertex.getArrayCellRawValue(address)
84174
84832
  };
84175
84833
  }
84176
- else if (vertex instanceof FormulaCellVertex) {
84834
+ else if (vertex instanceof ScalarFormulaVertex) {
84177
84835
  return {
84178
84836
  type: ClipboardCellType.FORMULA,
84179
84837
  hash: this.parser.computeHashFromAst(vertex.getFormula(this.lazilyTransformingAstService))
@@ -84257,37 +84915,49 @@ class Operations {
84257
84915
  }
84258
84916
  }
84259
84917
  }
84918
+ /**
84919
+ * Sets cell content to an instance of parsing error.
84920
+ * Creates a ParsingErrorVertex and updates the dependency graph and column search index.
84921
+ */
84260
84922
  setParsingErrorToCell(rawInput, errors2, address) {
84261
- const oldValue = this.dependencyGraph.getCellValue(address);
84923
+ this.removeCellValueFromColumnSearch(address);
84262
84924
  const vertex = new ParsingErrorVertex(errors2, rawInput);
84263
84925
  const arrayChanges = this.dependencyGraph.setParsingErrorToCell(address, vertex);
84264
- this.columnSearch.remove(getRawValue(oldValue), address);
84265
84926
  this.columnSearch.applyChanges(arrayChanges.getChanges());
84266
84927
  this.changes.addAll(arrayChanges);
84267
84928
  this.changes.addChange(vertex.getCellValue(), address);
84268
84929
  }
84930
+ /**
84931
+ * Sets cell content to a formula.
84932
+ * Creates a ScalarFormulaVertex and updates the dependency graph and column search index.
84933
+ */
84269
84934
  setFormulaToCell(address, size2, { ast, hasVolatileFunction, hasStructuralChangeFunction, dependencies }) {
84270
- const oldValue = this.dependencyGraph.getCellValue(address);
84935
+ this.removeCellValueFromColumnSearch(address);
84271
84936
  const arrayChanges = this.dependencyGraph.setFormulaToCell(address, ast, absolutizeDependencies(dependencies, address), size2, hasVolatileFunction, hasStructuralChangeFunction);
84272
- this.columnSearch.remove(getRawValue(oldValue), address);
84273
84937
  this.columnSearch.applyChanges(arrayChanges.getChanges());
84274
84938
  this.changes.addAll(arrayChanges);
84275
84939
  }
84940
+ /**
84941
+ * Sets cell content to a value.
84942
+ * Creates a ValueCellVertex and updates the dependency graph and column search index.
84943
+ */
84276
84944
  setValueToCell(value, address) {
84277
- const oldValue = this.dependencyGraph.getCellValue(address);
84945
+ this.changeCellValueInColumnSearch(address, value.parsedValue);
84278
84946
  const arrayChanges = this.dependencyGraph.setValueToCell(address, value);
84279
- this.columnSearch.change(getRawValue(oldValue), getRawValue(value.parsedValue), address);
84280
84947
  this.columnSearch.applyChanges(arrayChanges.getChanges().filter((change) => !equalSimpleCellAddress(change.address, address)));
84281
84948
  this.changes.addAll(arrayChanges);
84282
84949
  this.changes.addChange(value.parsedValue, address);
84283
84950
  }
84951
+ /**
84952
+ * Sets cell content to an empty value.
84953
+ * Creates an EmptyCellVertex and updates the dependency graph and column search index.
84954
+ */
84284
84955
  setCellEmpty(address) {
84285
84956
  if (this.dependencyGraph.isArrayInternalCell(address)) {
84286
84957
  return;
84287
84958
  }
84288
- const oldValue = this.dependencyGraph.getCellValue(address);
84959
+ this.removeCellValueFromColumnSearch(address);
84289
84960
  const arrayChanges = this.dependencyGraph.setCellEmpty(address);
84290
- this.columnSearch.remove(getRawValue(oldValue), address);
84291
84961
  this.columnSearch.applyChanges(arrayChanges.getChanges());
84292
84962
  this.changes.addAll(arrayChanges);
84293
84963
  this.changes.addChange(EmptyValue, address);
@@ -84307,7 +84977,7 @@ class Operations {
84307
84977
  * @param {number} sheet - sheet ID number
84308
84978
  */
84309
84979
  rowEffectivelyNotInSheet(row, sheet) {
84310
- const height = this.dependencyGraph.addressMapping.getHeight(sheet);
84980
+ const height = this.dependencyGraph.addressMapping.getSheetHeight(sheet);
84311
84981
  return row >= height;
84312
84982
  }
84313
84983
  getAndClearContentChanges() {
@@ -84436,7 +85106,7 @@ class Operations {
84436
85106
  * @param {number} sheet - sheet ID number
84437
85107
  */
84438
85108
  columnEffectivelyNotInSheet(column, sheet) {
84439
- const width = this.dependencyGraph.addressMapping.getWidth(sheet);
85109
+ const width = this.dependencyGraph.addressMapping.getSheetWidth(sheet);
84440
85110
  return column >= width;
84441
85111
  }
84442
85112
  adjustNamedExpressionEdges(namedExpression, expressionName, sheetId) {
@@ -84449,7 +85119,7 @@ class Operations {
84449
85119
  const { vertex: globalVertex, id: maybeGlobalVertexId } = this.dependencyGraph.fetchCellOrCreateEmpty(globalNamedExpression.address);
84450
85120
  const globalVertexId = maybeGlobalVertexId !== null && maybeGlobalVertexId !== void 0 ? maybeGlobalVertexId : this.dependencyGraph.graph.getNodeId(globalVertex);
84451
85121
  for (const adjacentNode of this.dependencyGraph.graph.adjacentNodes(globalVertex)) {
84452
- if (adjacentNode instanceof FormulaCellVertex && adjacentNode.getAddress(this.lazilyTransformingAstService).sheet === sheetId) {
85122
+ if (adjacentNode instanceof ScalarFormulaVertex && adjacentNode.getAddress(this.lazilyTransformingAstService).sheet === sheetId) {
84453
85123
  const ast = adjacentNode.getFormula(this.lazilyTransformingAstService);
84454
85124
  const formulaAddress = adjacentNode.getAddress(this.lazilyTransformingAstService);
84455
85125
  const { dependencies } = this.parser.fetchCachedResultForAst(ast);
@@ -84489,8 +85159,10 @@ class Operations {
84489
85159
  const addedGlobalNamedExpressions = [];
84490
85160
  const targetRange = AbsoluteCellRange.spanFrom(destinationLeftCorner, width, height);
84491
85161
  for (const formulaAddress of targetRange.addresses(this.dependencyGraph)) {
84492
- const vertex = this.addressMapping.fetchCell(formulaAddress);
84493
- if (vertex instanceof FormulaCellVertex && formulaAddress.sheet !== sourceLeftCorner.sheet) {
85162
+ const vertex = this.addressMapping.getCell(formulaAddress, {
85163
+ throwIfCellNotExists: true
85164
+ });
85165
+ if (vertex instanceof ScalarFormulaVertex && formulaAddress.sheet !== sourceLeftCorner.sheet) {
84494
85166
  const ast = vertex.getFormula(this.lazilyTransformingAstService);
84495
85167
  const { dependencies } = this.parser.fetchCachedResultForAst(ast);
84496
85168
  addedGlobalNamedExpressions.push(...this.updateNamedExpressionsForTargetAddress(sourceLeftCorner.sheet, formulaAddress, dependencies));
@@ -84503,7 +85175,7 @@ class Operations {
84503
85175
  return [];
84504
85176
  }
84505
85177
  const addedGlobalNamedExpressions = [];
84506
- const vertex = this.addressMapping.fetchCell(targetAddress);
85178
+ const vertex = this.addressMapping.getCellOrThrow(targetAddress);
84507
85179
  for (const namedExpressionDependency of absolutizeDependencies(dependencies, targetAddress)) {
84508
85180
  if (!(namedExpressionDependency instanceof NamedExpressionDependency)) {
84509
85181
  continue;
@@ -84520,14 +85192,14 @@ class Operations {
84520
85192
  return addedGlobalNamedExpressions;
84521
85193
  }
84522
85194
  allocateNamedExpressionAddressSpace() {
84523
- this.dependencyGraph.addressMapping.addSheet(NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS, new SparseStrategy(0, 0));
85195
+ this.dependencyGraph.addressMapping.addSheetWithStrategy(NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS, new SparseStrategy(0, 0));
84524
85196
  }
84525
85197
  copyOrFetchGlobalNamedExpressionVertex(expressionName, sourceVertex, addedNamedExpressions) {
84526
85198
  let expression = this.namedExpressions.namedExpressionForScope(expressionName);
84527
85199
  if (expression === void 0) {
84528
85200
  expression = this.namedExpressions.addNamedExpression(expressionName);
84529
85201
  addedNamedExpressions.push(expression.normalizeExpressionName());
84530
- if (sourceVertex instanceof FormulaCellVertex) {
85202
+ if (sourceVertex instanceof ScalarFormulaVertex) {
84531
85203
  const parsingResult = this.parser.fetchCachedResultForAst(sourceVertex.getFormula(this.lazilyTransformingAstService));
84532
85204
  const { ast, hasVolatileFunction, hasStructuralChangeFunction, dependencies } = parsingResult;
84533
85205
  this.dependencyGraph.setFormulaToCell(expression.address, ast, absolutizeDependencies(dependencies, expression.address), ArraySize.scalar(), hasVolatileFunction, hasStructuralChangeFunction);
@@ -84541,6 +85213,38 @@ class Operations {
84541
85213
  }
84542
85214
  return this.dependencyGraph.fetchCellOrCreateEmpty(expression.address).vertex;
84543
85215
  }
85216
+ /**
85217
+ * Removes a cell value from the columnSearch index.
85218
+ * Ignores the non-computed formula vertices.
85219
+ */
85220
+ removeCellValueFromColumnSearch(address) {
85221
+ if (this.isNotComputed(address)) {
85222
+ return;
85223
+ }
85224
+ const oldValue = this.dependencyGraph.getCellValue(address);
85225
+ this.columnSearch.remove(getRawValue(oldValue), address);
85226
+ }
85227
+ /**
85228
+ * Changes a cell value in the columnSearch index.
85229
+ * Ignores the non-computed formula vertices.
85230
+ */
85231
+ changeCellValueInColumnSearch(address, newValue) {
85232
+ if (this.isNotComputed(address)) {
85233
+ return;
85234
+ }
85235
+ const oldValue = this.dependencyGraph.getCellValue(address);
85236
+ this.columnSearch.change(getRawValue(oldValue), getRawValue(newValue), address);
85237
+ }
85238
+ /**
85239
+ * Checks if the ScalarFormulaVertex or ArrayFormulaVertex at the given address is not computed.
85240
+ */
85241
+ isNotComputed(address) {
85242
+ const vertex = this.dependencyGraph.getCell(address);
85243
+ if (!vertex) {
85244
+ return false;
85245
+ }
85246
+ return "isComputed" in vertex && !vertex.isComputed();
85247
+ }
84544
85248
  }
84545
85249
  function normalizeRemovedIndexes(indexes) {
84546
85250
  if (indexes.length <= 1) {
@@ -84742,9 +85446,10 @@ class RemoveColumnsUndoEntry extends BaseUndoEntry {
84742
85446
  }
84743
85447
  }
84744
85448
  class AddSheetUndoEntry extends BaseUndoEntry {
84745
- constructor(sheetName) {
85449
+ constructor(sheetName, sheetId) {
84746
85450
  super();
84747
85451
  this.sheetName = sheetName;
85452
+ this.sheetId = sheetId;
84748
85453
  }
84749
85454
  doUndo(undoRedo) {
84750
85455
  undoRedo.undoAddSheet(this);
@@ -84754,13 +85459,12 @@ class AddSheetUndoEntry extends BaseUndoEntry {
84754
85459
  }
84755
85460
  }
84756
85461
  class RemoveSheetUndoEntry extends BaseUndoEntry {
84757
- constructor(sheetName, sheetId, oldSheetContent, scopedNamedExpressions, version) {
85462
+ constructor(sheetName, sheetId, oldSheetContent, scopedNamedExpressions) {
84758
85463
  super();
84759
85464
  this.sheetName = sheetName;
84760
85465
  this.sheetId = sheetId;
84761
85466
  this.oldSheetContent = oldSheetContent;
84762
85467
  this.scopedNamedExpressions = scopedNamedExpressions;
84763
- this.version = version;
84764
85468
  }
84765
85469
  doUndo(undoRedo) {
84766
85470
  undoRedo.undoRemoveSheet(this);
@@ -84770,11 +85474,13 @@ class RemoveSheetUndoEntry extends BaseUndoEntry {
84770
85474
  }
84771
85475
  }
84772
85476
  class RenameSheetUndoEntry extends BaseUndoEntry {
84773
- constructor(sheetId, oldName, newName) {
85477
+ constructor(sheetId, oldName, newName, version, mergedPlaceholderSheetId) {
84774
85478
  super();
84775
85479
  this.sheetId = sheetId;
84776
85480
  this.oldName = oldName;
84777
85481
  this.newName = newName;
85482
+ this.version = version;
85483
+ this.mergedPlaceholderSheetId = mergedPlaceholderSheetId;
84778
85484
  }
84779
85485
  doUndo(undoRedo) {
84780
85486
  undoRedo.undoRenameSheet(this);
@@ -85025,8 +85731,8 @@ class UndoRedo {
85025
85731
  }
85026
85732
  undoRemoveSheet(operation) {
85027
85733
  this.operations.forceApplyPostponedTransformations();
85028
- const { oldSheetContent, sheetId } = operation;
85029
- this.operations.addSheet(operation.sheetName);
85734
+ const { oldSheetContent, sheetId, scopedNamedExpressions, sheetName } = operation;
85735
+ this.operations.addSheetWithId(sheetId, sheetName);
85030
85736
  for (let rowIndex = 0; rowIndex < oldSheetContent.length; rowIndex++) {
85031
85737
  const row = oldSheetContent[rowIndex];
85032
85738
  for (let col = 0; col < row.length; col++) {
@@ -85035,13 +85741,17 @@ class UndoRedo {
85035
85741
  this.operations.restoreCell(address, cellType);
85036
85742
  }
85037
85743
  }
85038
- for (const [namedexpression, content] of operation.scopedNamedExpressions) {
85744
+ for (const [namedexpression, content] of scopedNamedExpressions) {
85039
85745
  this.operations.restoreNamedExpression(namedexpression, content, sheetId);
85040
85746
  }
85041
- this.restoreOldDataFromVersion(operation.version - 1);
85042
85747
  }
85043
85748
  undoRenameSheet(operation) {
85749
+ this.operations.forceApplyPostponedTransformations();
85044
85750
  this.operations.renameSheet(operation.sheetId, operation.oldName);
85751
+ if (operation.mergedPlaceholderSheetId !== void 0 && operation.version !== void 0) {
85752
+ this.operations.addPlaceholderSheetWithId(operation.mergedPlaceholderSheetId, operation.newName);
85753
+ this.restoreOldDataFromVersion(operation.version - 1);
85754
+ }
85045
85755
  }
85046
85756
  undoClearSheet(operation) {
85047
85757
  const { oldSheetContent, sheetId } = operation;
@@ -85129,7 +85839,7 @@ class UndoRedo {
85129
85839
  this.operations.removeSheetByName(operation.sheetName);
85130
85840
  }
85131
85841
  redoAddSheet(operation) {
85132
- this.operations.addSheet(operation.sheetName);
85842
+ this.operations.addSheetWithId(operation.sheetId, operation.sheetName);
85133
85843
  }
85134
85844
  redoRenameSheet(operation) {
85135
85845
  this.operations.renameSheet(operation.sheetId, operation.newName);
@@ -85302,27 +86012,27 @@ class CrudOperations {
85302
86012
  this.ensureItIsPossibleToAddSheet(name);
85303
86013
  }
85304
86014
  this.undoRedo.clearRedoStack();
85305
- const addedSheetName = this.operations.addSheet(name);
85306
- this.undoRedo.saveOperation(new AddSheetUndoEntry(addedSheetName));
85307
- return addedSheetName;
86015
+ const { sheetName, sheetId } = this.operations.addSheet(name);
86016
+ this.undoRedo.saveOperation(new AddSheetUndoEntry(sheetName, sheetId));
86017
+ return sheetName;
85308
86018
  }
85309
86019
  removeSheet(sheetId) {
85310
86020
  this.ensureScopeIdIsValid(sheetId);
85311
86021
  this.undoRedo.clearRedoStack();
85312
86022
  this.clipboardOperations.abortCut();
85313
- const originalName = this.sheetMapping.fetchDisplayName(sheetId);
86023
+ const originalName = this.sheetMapping.getSheetNameOrThrowError(sheetId);
85314
86024
  const oldSheetContent = this.operations.getSheetClipboardCells(sheetId);
85315
- const { version, scopedNamedExpressions } = this.operations.removeSheet(sheetId);
85316
- this.undoRedo.saveOperation(new RemoveSheetUndoEntry(originalName, sheetId, oldSheetContent, scopedNamedExpressions, version));
86025
+ const scopedNamedExpressions = this.operations.removeSheet(sheetId);
86026
+ this.undoRedo.saveOperation(new RemoveSheetUndoEntry(originalName, sheetId, oldSheetContent, scopedNamedExpressions));
85317
86027
  }
85318
86028
  renameSheet(sheetId, newName) {
85319
86029
  this.ensureItIsPossibleToRenameSheet(sheetId, newName);
85320
- const oldName = this.operations.renameSheet(sheetId, newName);
85321
- if (oldName !== void 0) {
86030
+ const { previousDisplayName, version, mergedPlaceholderSheetId } = this.operations.renameSheet(sheetId, newName);
86031
+ if (previousDisplayName !== void 0) {
85322
86032
  this.undoRedo.clearRedoStack();
85323
- this.undoRedo.saveOperation(new RenameSheetUndoEntry(sheetId, oldName, newName));
86033
+ this.undoRedo.saveOperation(new RenameSheetUndoEntry(sheetId, previousDisplayName, newName, version, mergedPlaceholderSheetId));
85324
86034
  }
85325
- return oldName;
86035
+ return previousDisplayName;
85326
86036
  }
85327
86037
  clearSheet(sheetId) {
85328
86038
  this.ensureScopeIdIsValid(sheetId);
@@ -85563,7 +86273,7 @@ class CrudOperations {
85563
86273
  this.ensureItIsPossibleToAddRows(sheet, [targetRow, numberOfRows]);
85564
86274
  const sourceStart = simpleCellAddress(sheet, 0, startRow);
85565
86275
  const targetStart = simpleCellAddress(sheet, 0, targetRow);
85566
- if (!this.sheetMapping.hasSheetWithId(sheet) || invalidSimpleCellAddress(sourceStart) || invalidSimpleCellAddress(targetStart) || !isPositiveInteger(numberOfRows) || targetRow <= startRow + numberOfRows && targetRow >= startRow) {
86276
+ if (!this.sheetMapping.hasSheetWithId(sheet) || isColOrRowInvalid(sourceStart) || isColOrRowInvalid(targetStart) || !isPositiveInteger(numberOfRows) || targetRow <= startRow + numberOfRows && targetRow >= startRow) {
85567
86277
  throw new InvalidArgumentsError("a valid range of rows to move.");
85568
86278
  }
85569
86279
  const width = this.dependencyGraph.getSheetWidth(sheet);
@@ -85579,7 +86289,7 @@ class CrudOperations {
85579
86289
  this.ensureItIsPossibleToAddColumns(sheet, [targetColumn, numberOfColumns]);
85580
86290
  const sourceStart = simpleCellAddress(sheet, startColumn, 0);
85581
86291
  const targetStart = simpleCellAddress(sheet, targetColumn, 0);
85582
- if (!this.sheetMapping.hasSheetWithId(sheet) || invalidSimpleCellAddress(sourceStart) || invalidSimpleCellAddress(targetStart) || !isPositiveInteger(numberOfColumns) || targetColumn <= startColumn + numberOfColumns && targetColumn >= startColumn) {
86292
+ if (!this.sheetMapping.hasSheetWithId(sheet) || isColOrRowInvalid(sourceStart) || isColOrRowInvalid(targetStart) || !isPositiveInteger(numberOfColumns) || targetColumn <= startColumn + numberOfColumns && targetColumn >= startColumn) {
85583
86293
  throw new InvalidArgumentsError("a valid range of columns to move.");
85584
86294
  }
85585
86295
  const sheetHeight = this.dependencyGraph.getSheetHeight(sheet);
@@ -85600,13 +86310,13 @@ class CrudOperations {
85600
86310
  if (!this.sheetMapping.hasSheetWithId(sheetId)) {
85601
86311
  throw new NoSheetWithIdError(sheetId);
85602
86312
  }
85603
- const existingSheetId = this.sheetMapping.get(name);
86313
+ const existingSheetId = this.sheetMapping.getSheetId(name);
85604
86314
  if (existingSheetId !== void 0 && existingSheetId !== sheetId) {
85605
86315
  throw new SheetNameAlreadyTakenError(name);
85606
86316
  }
85607
86317
  }
85608
86318
  ensureItIsPossibleToChangeContent(address) {
85609
- if (invalidSimpleCellAddress(address)) {
86319
+ if (isColOrRowInvalid(address)) {
85610
86320
  throw new InvalidAddressError(address);
85611
86321
  }
85612
86322
  if (!this.sheetMapping.hasSheetWithId(address.sheet)) {
@@ -85705,37 +86415,7 @@ class Evaluator {
85705
86415
  partialRun(vertices) {
85706
86416
  const changes = ContentChanges.empty();
85707
86417
  this.stats.measure(StatType.EVALUATION, () => {
85708
- this.dependencyGraph.graph.getTopSortedWithSccSubgraphFrom(vertices, (vertex) => {
85709
- if (vertex instanceof FormulaVertex) {
85710
- const currentValue = vertex.isComputed() ? vertex.getCellValue() : void 0;
85711
- const newCellValue = this.recomputeFormulaVertexValue(vertex);
85712
- if (newCellValue !== currentValue) {
85713
- const address = vertex.getAddress(this.lazilyTransformingAstService);
85714
- changes.addChange(newCellValue, address);
85715
- this.columnSearch.change(getRawValue(currentValue), getRawValue(newCellValue), address);
85716
- return true;
85717
- }
85718
- return false;
85719
- }
85720
- else if (vertex instanceof RangeVertex) {
85721
- vertex.clearCache();
85722
- return true;
85723
- }
85724
- else {
85725
- return true;
85726
- }
85727
- }, (vertex) => {
85728
- if (vertex instanceof RangeVertex) {
85729
- vertex.clearCache();
85730
- }
85731
- else if (vertex instanceof FormulaVertex) {
85732
- const address = vertex.getAddress(this.lazilyTransformingAstService);
85733
- this.columnSearch.remove(getRawValue(vertex.valueOrUndef()), address);
85734
- const error = new CellError(ErrorType.CYCLE, void 0, vertex);
85735
- vertex.setCellValue(error);
85736
- changes.addChange(error, address);
85737
- }
85738
- });
86418
+ this.dependencyGraph.graph.getTopSortedWithSccSubgraphFrom(vertices, (vertex) => this.recomputeVertex(vertex, changes), (vertex) => this.processVertexOnCycle(vertex, changes));
85739
86419
  });
85740
86420
  return changes;
85741
86421
  }
@@ -85746,17 +86426,55 @@ class Evaluator {
85746
86426
  const range2 = dep;
85747
86427
  if (this.dependencyGraph.getRange(range2.start, range2.end) === void 0) {
85748
86428
  const rangeVertex = new RangeVertex(range2);
85749
- this.dependencyGraph.rangeMapping.setRange(rangeVertex);
86429
+ this.dependencyGraph.rangeMapping.addOrUpdateVertex(rangeVertex);
85750
86430
  tmpRanges.push(rangeVertex);
85751
86431
  }
85752
86432
  }
85753
86433
  }
85754
86434
  const ret = this.evaluateAstToCellValue(ast, new InterpreterState(address, this.config.useArrayArithmetic));
85755
86435
  tmpRanges.forEach((rangeVertex) => {
85756
- this.dependencyGraph.rangeMapping.removeRange(rangeVertex);
86436
+ this.dependencyGraph.rangeMapping.removeVertexIfExists(rangeVertex);
85757
86437
  });
85758
86438
  return ret;
85759
86439
  }
86440
+ /**
86441
+ * Recalculates the value of a single vertex assuming its dependencies have already been recalculated
86442
+ */
86443
+ recomputeVertex(vertex, changes) {
86444
+ if (vertex instanceof FormulaVertex) {
86445
+ const currentValue = vertex.isComputed() ? vertex.getCellValue() : void 0;
86446
+ const newCellValue = this.recomputeFormulaVertexValue(vertex);
86447
+ if (newCellValue !== currentValue) {
86448
+ const address = vertex.getAddress(this.lazilyTransformingAstService);
86449
+ changes.addChange(newCellValue, address);
86450
+ this.columnSearch.change(getRawValue(currentValue), getRawValue(newCellValue), address);
86451
+ return true;
86452
+ }
86453
+ return false;
86454
+ }
86455
+ else if (vertex instanceof RangeVertex) {
86456
+ vertex.clearCache();
86457
+ return true;
86458
+ }
86459
+ else {
86460
+ return true;
86461
+ }
86462
+ }
86463
+ /**
86464
+ * Processes a vertex that is part of a cycle in dependency graph
86465
+ */
86466
+ processVertexOnCycle(vertex, changes) {
86467
+ if (vertex instanceof RangeVertex) {
86468
+ vertex.clearCache();
86469
+ }
86470
+ else if (vertex instanceof FormulaVertex) {
86471
+ const address = vertex.getAddress(this.lazilyTransformingAstService);
86472
+ this.columnSearch.remove(getRawValue(vertex.valueOrUndef()), address);
86473
+ const error = new CellError(ErrorType.CYCLE, void 0, vertex);
86474
+ vertex.setCellValue(error);
86475
+ changes.addChange(error, address);
86476
+ }
86477
+ }
85760
86478
  /**
85761
86479
  * Recalculates formulas in the topological sort order
85762
86480
  */
@@ -85779,7 +86497,7 @@ class Evaluator {
85779
86497
  }
85780
86498
  recomputeFormulaVertexValue(vertex) {
85781
86499
  const address = vertex.getAddress(this.lazilyTransformingAstService);
85782
- if (vertex instanceof ArrayVertex && (vertex.array.size.isRef || !this.dependencyGraph.isThereSpaceForArray(vertex))) {
86500
+ if (vertex instanceof ArrayFormulaVertex && (vertex.array.size.isRef || !this.dependencyGraph.isThereSpaceForArray(vertex))) {
85783
86501
  return vertex.setNoSpace();
85784
86502
  }
85785
86503
  else {
@@ -85826,10 +86544,10 @@ class ExportedNamedExpressionChange {
85826
86544
  }
85827
86545
  }
85828
86546
  class Exporter {
85829
- constructor(config2, namedExpressions, sheetIndexMapping, lazilyTransformingService) {
86547
+ constructor(config2, namedExpressions, sheetMapping, lazilyTransformingService) {
85830
86548
  this.config = config2;
85831
86549
  this.namedExpressions = namedExpressions;
85832
- this.sheetIndexMapping = sheetIndexMapping;
86550
+ this.sheetMapping = sheetMapping;
85833
86551
  this.lazilyTransformingService = lazilyTransformingService;
85834
86552
  }
85835
86553
  exportChange(change) {
@@ -85887,7 +86605,7 @@ class Exporter {
85887
86605
  address = (_b = this.namedExpressions.namedExpressionInAddress(originAddress.row)) === null || _b === void 0 ? void 0 : _b.displayName;
85888
86606
  }
85889
86607
  else {
85890
- address = simpleCellAddressToString(this.sheetIndexMapping, originAddress, -1);
86608
+ address = simpleCellAddressToString(this.sheetMapping.getSheetNameOrThrowError.bind(this.sheetMapping), originAddress, -1);
85891
86609
  }
85892
86610
  }
85893
86611
  return new DetailedCellError(error, this.config.translationPackage.getErrorTranslation(error.type), address);
@@ -85964,7 +86682,7 @@ class SimpleStrategy {
85964
86682
  this.shrinkArrayIfNeeded(address);
85965
86683
  const size2 = this.arraySizePredictor.checkArraySize(parseResult.ast, address);
85966
86684
  if (size2.isScalar()) {
85967
- const vertex = new FormulaCellVertex(parseResult.ast, address, 0);
86685
+ const vertex = new ScalarFormulaVertex(parseResult.ast, address, 0);
85968
86686
  dependencies.set(vertex, absolutizeDependencies(parseResult.dependencies, address));
85969
86687
  this.dependencyGraph.addVertex(address, vertex);
85970
86688
  if (parseResult.hasVolatileFunction) {
@@ -85975,7 +86693,7 @@ class SimpleStrategy {
85975
86693
  }
85976
86694
  }
85977
86695
  else {
85978
- const vertex = new ArrayVertex(parseResult.ast, address, new ArraySize(size2.width, size2.height));
86696
+ const vertex = new ArrayFormulaVertex(parseResult.ast, address, new ArraySize(size2.width, size2.height));
85979
86697
  dependencies.set(vertex, absolutizeDependencies(parseResult.dependencies, address));
85980
86698
  this.dependencyGraph.addArrayVertex(address, vertex);
85981
86699
  }
@@ -85996,7 +86714,7 @@ class SimpleStrategy {
85996
86714
  }
85997
86715
  shrinkArrayIfNeeded(address) {
85998
86716
  const vertex = this.dependencyGraph.getCell(address);
85999
- if (vertex instanceof ArrayVertex) {
86717
+ if (vertex instanceof ArrayFormulaVertex) {
86000
86718
  this.dependencyGraph.shrinkArrayToCorner(vertex);
86001
86719
  }
86002
86720
  }
@@ -86497,8 +87215,8 @@ class Interpreter {
86497
87215
  /**
86498
87216
  * Calculates cell value from formula abstract syntax tree
86499
87217
  *
86500
- * @param formula - abstract syntax tree of formula
86501
- * @param formulaAddress - address of the cell in which formula is located
87218
+ * @param {Ast} ast - abstract syntax tree of formula
87219
+ * @param {InterpreterState} state - interpreter state
86502
87220
  */
86503
87221
  evaluateAstWithoutPostprocessing(ast, state) {
86504
87222
  switch (ast.type) {
@@ -86507,9 +87225,12 @@ class Interpreter {
86507
87225
  }
86508
87226
  case AstNodeType.CELL_REFERENCE: {
86509
87227
  const address = ast.reference.toSimpleCellAddress(state.formulaAddress);
86510
- if (invalidSimpleCellAddress(address)) {
87228
+ if (isColOrRowInvalid(address)) {
86511
87229
  return new CellError(ErrorType.REF, ErrorMessage.BadRef);
86512
87230
  }
87231
+ if (!this.isSheetValid(ast.reference)) {
87232
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
87233
+ }
86513
87234
  return this.dependencyGraph.getCellValue(address);
86514
87235
  }
86515
87236
  case AstNodeType.NUMBER:
@@ -86610,6 +87331,9 @@ class Interpreter {
86610
87331
  }
86611
87332
  }
86612
87333
  case AstNodeType.CELL_RANGE: {
87334
+ if (!this.isSheetValid(ast.start) || !this.isSheetValid(ast.end)) {
87335
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
87336
+ }
86613
87337
  if (!this.rangeSpansOneSheet(ast)) {
86614
87338
  return new CellError(ErrorType.REF, ErrorMessage.RangeManySheets);
86615
87339
  }
@@ -86630,11 +87354,12 @@ class Interpreter {
86630
87354
  throw new Error("Unknown array");
86631
87355
  }
86632
87356
  }
86633
- else {
86634
- return SimpleRangeValue.onlyRange(range2, this.dependencyGraph);
86635
- }
87357
+ return SimpleRangeValue.onlyRange(range2, this.dependencyGraph);
86636
87358
  }
86637
87359
  case AstNodeType.COLUMN_RANGE: {
87360
+ if (!this.isSheetValid(ast.start) || !this.isSheetValid(ast.end)) {
87361
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
87362
+ }
86638
87363
  if (!this.rangeSpansOneSheet(ast)) {
86639
87364
  return new CellError(ErrorType.REF, ErrorMessage.RangeManySheets);
86640
87365
  }
@@ -86642,6 +87367,9 @@ class Interpreter {
86642
87367
  return SimpleRangeValue.onlyRange(range2, this.dependencyGraph);
86643
87368
  }
86644
87369
  case AstNodeType.ROW_RANGE: {
87370
+ if (!this.isSheetValid(ast.start) || !this.isSheetValid(ast.end)) {
87371
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
87372
+ }
86645
87373
  if (!this.rangeSpansOneSheet(ast)) {
86646
87374
  return new CellError(ErrorType.REF, ErrorMessage.RangeManySheets);
86647
87375
  }
@@ -86693,6 +87421,18 @@ class Interpreter {
86693
87421
  }
86694
87422
  }
86695
87423
  }
87424
+ /**
87425
+ * Sheet is valid if:
87426
+ * - sheet is undefined OR
87427
+ * - sheet is a named expressions store OR
87428
+ * - sheet exists in sheet mapping
87429
+ * - sheet is not a placeholder
87430
+ */
87431
+ isSheetValid(address) {
87432
+ return address.sheet === void 0 || address.sheet === NamedExpressions.SHEET_FOR_WORKBOOK_EXPRESSIONS || this.dependencyGraph.sheetMapping.hasSheetWithId(address.sheet, {
87433
+ includePlaceholders: false
87434
+ });
87435
+ }
86696
87436
  rangeSpansOneSheet(ast) {
86697
87437
  return ast.start.sheet === ast.end.sheet;
86698
87438
  }
@@ -87378,7 +88118,7 @@ class Serialization {
87378
88118
  }
87379
88119
  getCellHyperlink(address) {
87380
88120
  const formulaVertex = this.dependencyGraph.getCell(address);
87381
- if (formulaVertex instanceof FormulaCellVertex) {
88121
+ if (formulaVertex instanceof ScalarFormulaVertex) {
87382
88122
  const formula = formulaVertex.getFormula(this.dependencyGraph.lazilyTransformingAstService);
87383
88123
  if ("HYPERLINK" === formula.procedureName) {
87384
88124
  return formula.hyperlink;
@@ -87388,12 +88128,12 @@ class Serialization {
87388
88128
  }
87389
88129
  getCellFormula(address, targetAddress) {
87390
88130
  const formulaVertex = this.dependencyGraph.getCell(address);
87391
- if (formulaVertex instanceof FormulaCellVertex) {
88131
+ if (formulaVertex instanceof ScalarFormulaVertex) {
87392
88132
  const formula = formulaVertex.getFormula(this.dependencyGraph.lazilyTransformingAstService);
87393
88133
  targetAddress = targetAddress !== null && targetAddress !== void 0 ? targetAddress : address;
87394
88134
  return this.unparser.unparse(formula, targetAddress);
87395
88135
  }
87396
- else if (formulaVertex instanceof ArrayVertex) {
88136
+ else if (formulaVertex instanceof ArrayFormulaVertex) {
87397
88137
  const arrayVertexAddress = formulaVertex.getAddress(this.dependencyGraph.lazilyTransformingAstService);
87398
88138
  if (arrayVertexAddress.row !== address.row || arrayVertexAddress.col !== address.col || arrayVertexAddress.sheet !== address.sheet) {
87399
88139
  return void 0;
@@ -87456,8 +88196,8 @@ class Serialization {
87456
88196
  }
87457
88197
  genericAllSheetsGetter(sheetGetter) {
87458
88198
  const result = {};
87459
- for (const sheetName of this.dependencyGraph.sheetMapping.displayNames()) {
87460
- const sheetId = this.dependencyGraph.sheetMapping.fetch(sheetName);
88199
+ for (const sheetName of this.dependencyGraph.sheetMapping.iterateSheetNames()) {
88200
+ const sheetId = this.dependencyGraph.sheetMapping.getSheetIdOrThrowError(sheetName);
87461
88201
  result[sheetName] = sheetGetter(sheetId);
87462
88202
  }
87463
88203
  return result;
@@ -87477,8 +88217,8 @@ class Serialization {
87477
88217
  getAllNamedExpressionsSerialized() {
87478
88218
  const idMap = [];
87479
88219
  let id2 = 0;
87480
- for (const sheetName of this.dependencyGraph.sheetMapping.displayNames()) {
87481
- const sheetId = this.dependencyGraph.sheetMapping.fetch(sheetName);
88220
+ for (const sheetName of this.dependencyGraph.sheetMapping.iterateSheetNames()) {
88221
+ const sheetId = this.dependencyGraph.sheetMapping.getSheetIdOrThrowError(sheetName);
87482
88222
  idMap[sheetId] = id2;
87483
88223
  id2++;
87484
88224
  }
@@ -87492,7 +88232,7 @@ class Serialization {
87492
88232
  });
87493
88233
  }
87494
88234
  withNewConfig(newConfig, namedExpressions) {
87495
- const newUnparser = new Unparser(newConfig, buildLexerConfig(newConfig), this.dependencyGraph.sheetMapping.fetchDisplayName, namedExpressions);
88235
+ const newUnparser = new Unparser(newConfig, this.dependencyGraph.sheetMapping, namedExpressions);
87496
88236
  return new Serialization(this.dependencyGraph, newUnparser, this.exporter);
87497
88237
  }
87498
88238
  }
@@ -87532,12 +88272,14 @@ class BuildEngineFactory {
87532
88272
  throw new SheetSizeLimitExceededError();
87533
88273
  }
87534
88274
  const sheetId = sheetMapping.addSheet(sheetName);
87535
- addressMapping.autoAddSheet(sheetId, boundaries);
88275
+ addressMapping.addSheetAndSetStrategyBasedOnBoundaries(sheetId, boundaries, {
88276
+ throwIfSheetAlreadyExists: true
88277
+ });
87536
88278
  }
87537
88279
  }
87538
- const parser2 = new ParserWithCaching(config2, functionRegistry, sheetMapping.get);
88280
+ const parser2 = new ParserWithCaching(config2, functionRegistry, dependencyGraph.sheetReferenceRegistrar.ensureSheetRegistered.bind(dependencyGraph.sheetReferenceRegistrar));
87539
88281
  lazilyTransformingAstService.parser = parser2;
87540
- const unparser = new Unparser(config2, buildLexerConfig(config2), sheetMapping.fetchDisplayName, namedExpressions);
88282
+ const unparser = new Unparser(config2, sheetMapping, namedExpressions);
87541
88283
  const dateTimeHelper = new DateTimeHelper(config2);
87542
88284
  const numberLiteralHelper = new NumberLiteralHelper(config2);
87543
88285
  const arithmeticHelper = new ArithmeticHelper(config2, dateTimeHelper, numberLiteralHelper);
@@ -87548,7 +88290,7 @@ class BuildEngineFactory {
87548
88290
  lazilyTransformingAstService.undoRedo = undoRedo;
87549
88291
  const clipboardOperations = new ClipboardOperations(config2, dependencyGraph, operations);
87550
88292
  const crudOperations = new CrudOperations(config2, operations, undoRedo, clipboardOperations, dependencyGraph, columnSearch, parser2, cellContentParser, lazilyTransformingAstService, namedExpressions);
87551
- const exporter = new Exporter(config2, namedExpressions, sheetMapping.fetchDisplayName, lazilyTransformingAstService);
88293
+ const exporter = new Exporter(config2, namedExpressions, sheetMapping, lazilyTransformingAstService);
87552
88294
  const serialization = new Serialization(dependencyGraph, unparser, exporter);
87553
88295
  const interpreter = new Interpreter(config2, dependencyGraph, columnSearch, stats, arithmeticHelper, functionRegistry, namedExpressions, serialization, arraySizePredictor, dateTimeHelper);
87554
88296
  stats.measure(StatType.GRAPH_BUILD, () => {
@@ -90061,6 +90803,8 @@ class HyperFormula {
90061
90803
  /**
90062
90804
  * Adds a new sheet to the HyperFormula instance. Returns given or autogenerated name of a new sheet.
90063
90805
  *
90806
+ * Note that this method may trigger dependency graph recalculation.
90807
+ *
90064
90808
  * @param {string} [sheetName] - if not specified, name is autogenerated
90065
90809
  *
90066
90810
  * @fires [[sheetAdded]] after the sheet was added
@@ -90090,6 +90834,7 @@ class HyperFormula {
90090
90834
  validateArgToType(sheetName, "string", "sheetName");
90091
90835
  }
90092
90836
  const addedSheetName = this._crudOperations.addSheet(sheetName);
90837
+ this.recomputeIfDependencyGraphNeedsIt();
90093
90838
  this._emitter.emit(Events.SheetAdded, addedSheetName);
90094
90839
  return addedSheetName;
90095
90840
  }
@@ -90160,7 +90905,7 @@ class HyperFormula {
90160
90905
  */
90161
90906
  removeSheet(sheetId) {
90162
90907
  validateArgToType(sheetId, "number", "sheetId");
90163
- const displayName = this.sheetMapping.getDisplayName(sheetId);
90908
+ const displayName = this.sheetMapping.getSheetName(sheetId);
90164
90909
  this._crudOperations.removeSheet(sheetId);
90165
90910
  const changes = this.recomputeIfDependencyGraphNeedsIt();
90166
90911
  this._emitter.emit(Events.SheetRemoved, displayName, changes);
@@ -90336,7 +91081,7 @@ class HyperFormula {
90336
91081
  simpleCellAddressFromString(cellAddress, contextSheetId) {
90337
91082
  validateArgToType(cellAddress, "string", "cellAddress");
90338
91083
  validateArgToType(contextSheetId, "number", "sheetId");
90339
- return simpleCellAddressFromString(this.sheetMapping.get, cellAddress, contextSheetId);
91084
+ return simpleCellAddressFromString(this.sheetMapping.getSheetId.bind(this.sheetMapping), cellAddress, contextSheetId);
90340
91085
  }
90341
91086
  /**
90342
91087
  * Computes simple (absolute) address of a cell range based on its string representation.
@@ -90364,7 +91109,7 @@ class HyperFormula {
90364
91109
  simpleCellRangeFromString(cellRange, contextSheetId) {
90365
91110
  validateArgToType(cellRange, "string", "cellRange");
90366
91111
  validateArgToType(contextSheetId, "number", "sheetId");
90367
- return simpleCellRangeFromString(this.sheetMapping.get, cellRange, contextSheetId);
91112
+ return simpleCellRangeFromString(this.sheetMapping.getSheetId.bind(this.sheetMapping), cellRange, contextSheetId);
90368
91113
  }
90369
91114
  /**
90370
91115
  * Computes string representation of an absolute address in A1 notation. If `cellAddress.sheet` is not present in the engine, returns `undefined`.
@@ -90405,7 +91150,7 @@ class HyperFormula {
90405
91150
  throw new ExpectedValueOfTypeError("SimpleCellAddress", "cellAddress");
90406
91151
  }
90407
91152
  const contextSheetId = typeof optionsOrContextSheetId === "number" ? optionsOrContextSheetId : optionsOrContextSheetId.includeSheetName ? cellAddress.sheet + 1 : cellAddress.sheet;
90408
- return simpleCellAddressToString(this.sheetMapping.fetchDisplayName, cellAddress, contextSheetId);
91153
+ return simpleCellAddressToString(this.sheetMapping.getSheetNameOrThrowError.bind(this.sheetMapping), cellAddress, contextSheetId);
90409
91154
  }
90410
91155
  /**
90411
91156
  * Computes string representation of an absolute range in A1 notation.
@@ -90453,7 +91198,7 @@ class HyperFormula {
90453
91198
  throw new ExpectedValueOfTypeError("SimpleCellRange", "cellRange");
90454
91199
  }
90455
91200
  const contextSheetId = typeof optionsOrContextSheetId === "number" ? optionsOrContextSheetId : optionsOrContextSheetId.includeSheetName ? cellRange.start.sheet + cellRange.end.sheet + 1 : cellRange.start.sheet;
90456
- return simpleCellRangeToString(this.sheetMapping.fetchDisplayName, cellRange, contextSheetId);
91201
+ return simpleCellRangeToString(this.sheetMapping.getSheetNameOrThrowError.bind(this.sheetMapping), cellRange, contextSheetId);
90457
91202
  }
90458
91203
  /**
90459
91204
  * Returns all the out-neighbors in the [dependency graph](../../guide/dependency-graph.md) for a given cell address or range. Including:
@@ -90486,7 +91231,7 @@ class HyperFormula {
90486
91231
  vertex = this._dependencyGraph.addressMapping.getCell(address);
90487
91232
  }
90488
91233
  else if (isSimpleCellRange(address)) {
90489
- vertex = this._dependencyGraph.rangeMapping.getRange(address.start, address.end);
91234
+ vertex = this._dependencyGraph.rangeMapping.getRangeVertex(address.start, address.end);
90490
91235
  }
90491
91236
  else {
90492
91237
  throw new ExpectedValueOfTypeError("SimpleCellAddress | SimpleCellRange", address);
@@ -90525,7 +91270,7 @@ class HyperFormula {
90525
91270
  vertex = this._dependencyGraph.addressMapping.getCell(address);
90526
91271
  }
90527
91272
  else if (isSimpleCellRange(address)) {
90528
- vertex = this._dependencyGraph.rangeMapping.getRange(address.start, address.end);
91273
+ vertex = this._dependencyGraph.rangeMapping.getRangeVertex(address.start, address.end);
90529
91274
  }
90530
91275
  else {
90531
91276
  throw new ExpectedValueOfTypeError("SimpleCellAddress | SimpleCellRange", address);
@@ -90557,7 +91302,7 @@ class HyperFormula {
90557
91302
  */
90558
91303
  getSheetName(sheetId) {
90559
91304
  validateArgToType(sheetId, "number", "sheetId");
90560
- return this.sheetMapping.getDisplayName(sheetId);
91305
+ return this.sheetMapping.getSheetName(sheetId);
90561
91306
  }
90562
91307
  /**
90563
91308
  * List all sheet names.
@@ -90577,7 +91322,7 @@ class HyperFormula {
90577
91322
  * @category Sheets
90578
91323
  */
90579
91324
  getSheetNames() {
90580
- return this.sheetMapping.sheetNames();
91325
+ return this.sheetMapping.getSheetNames();
90581
91326
  }
90582
91327
  /**
90583
91328
  * Returns a unique sheet ID assigned to the sheet with a given name or `undefined` if the sheet does not exist.
@@ -90601,7 +91346,7 @@ class HyperFormula {
90601
91346
  */
90602
91347
  getSheetId(sheetName) {
90603
91348
  validateArgToType(sheetName, "string", "sheetName");
90604
- return this.sheetMapping.get(sheetName);
91349
+ return this.sheetMapping.getSheetId(sheetName);
90605
91350
  }
90606
91351
  /**
90607
91352
  * Returns `true` whether sheet with a given name exists. The method accepts sheet name to be checked.
@@ -90935,6 +91680,8 @@ class HyperFormula {
90935
91680
  /**
90936
91681
  * Renames a specified sheet.
90937
91682
  *
91683
+ * Note that this method may trigger dependency graph recalculation.
91684
+ *
90938
91685
  * @param {number} sheetId - a sheet ID
90939
91686
  * @param {string} newName - a name of the sheet to be given, if is the same as the old one the method does nothing
90940
91687
  *
@@ -90961,6 +91708,7 @@ class HyperFormula {
90961
91708
  validateArgToType(sheetId, "number", "sheetId");
90962
91709
  validateArgToType(newName, "string", "newName");
90963
91710
  const oldName = this._crudOperations.renameSheet(sheetId, newName);
91711
+ this.recomputeIfDependencyGraphNeedsIt();
90964
91712
  if (oldName !== void 0) {
90965
91713
  this._emitter.emit(Events.SheetRenamed, oldName, newName);
90966
91714
  }
@@ -92020,9 +92768,9 @@ class HyperFormula {
92020
92768
  }
92021
92769
  }
92022
92770
  }
92023
- HyperFormula.version = "3.1.0";
92024
- HyperFormula.buildDate = "14/10/2025 09:41:56";
92025
- HyperFormula.releaseDate = "14/10/2025";
92771
+ HyperFormula.version = "3.1.1";
92772
+ HyperFormula.buildDate = "18/12/2025 11:47:25";
92773
+ HyperFormula.releaseDate = "18/12/2025";
92026
92774
  HyperFormula.languages = {};
92027
92775
  HyperFormula.registeredLanguages = /* @__PURE__ */ new Map();
92028
92776
  const privatePool = /* @__PURE__ */ new WeakMap();
@@ -95261,7 +96009,7 @@ class InformationPlugin extends FunctionPlugin {
95261
96009
  */
95262
96010
  sheet(ast, state) {
95263
96011
  return this.runFunctionWithReferenceArgument(ast.args, state, this.metadata("SHEET"), () => state.formulaAddress.sheet + 1, (reference) => reference.sheet + 1, (value) => {
95264
- const sheetNumber = this.dependencyGraph.sheetMapping.get(value);
96012
+ const sheetNumber = this.dependencyGraph.sheetMapping.getSheetId(value);
95265
96013
  if (sheetNumber !== void 0) {
95266
96014
  return sheetNumber + 1;
95267
96015
  }
@@ -96237,13 +96985,13 @@ class NumericAggregationPlugin extends FunctionPlugin {
96237
96985
  /**
96238
96986
  * Performs range operation on given range
96239
96987
  *
96240
- * @param ast - cell range ast
96241
- * @param state
96242
- * @param initialAccValue - initial accumulator value for reducing function
96243
- * @param functionName - function name to use as cache key
96244
- * @param reducingFunction - reducing function
96245
- * @param mapFunction
96246
- * @param coercionFunction
96988
+ * @param {CellRangeAst | ColumnRangeAst | RowRangeAst} ast - cell range ast
96989
+ * @param {InterpreterState} state - interpreter state
96990
+ * @param {T} initialAccValue - initial accumulator value for reducing function
96991
+ * @param {string} functionName - function name to use as cache key
96992
+ * @param {BinaryOperation<T>} reducingFunction - reducing function
96993
+ * @param {MapOperation<T>} mapFunction - mapper transforming coerced scalar
96994
+ * @param {coercionOperation} coercionFunction - scalar-to-number coercer
96247
96995
  */
96248
96996
  evaluateRange(ast, state, initialAccValue, functionName2, reducingFunction, mapFunction, coercionFunction) {
96249
96997
  let range2;
@@ -96258,6 +97006,9 @@ class NumericAggregationPlugin extends FunctionPlugin {
96258
97006
  throw err;
96259
97007
  }
96260
97008
  }
97009
+ if (!this.isSheetValid(range2)) {
97010
+ return new CellError(ErrorType.REF, ErrorMessage.SheetRef);
97011
+ }
96261
97012
  const rangeVertex = this.dependencyGraph.getRange(range2.start, range2.end);
96262
97013
  if (rangeVertex === void 0) {
96263
97014
  throw new Error("Range does not exists in graph");
@@ -96280,6 +97031,16 @@ class NumericAggregationPlugin extends FunctionPlugin {
96280
97031
  }
96281
97032
  return value;
96282
97033
  }
97034
+ /**
97035
+ * Checks whether both ends of a range point to existing sheets (placeholders excluded).
97036
+ */
97037
+ isSheetValid(range2) {
97038
+ return this.dependencyGraph.sheetMapping.hasSheetWithId(range2.start.sheet, {
97039
+ includePlaceholders: false
97040
+ }) && this.dependencyGraph.sheetMapping.hasSheetWithId(range2.end.sheet, {
97041
+ includePlaceholders: false
97042
+ });
97043
+ }
96283
97044
  /**
96284
97045
  * Returns list of values for given range and function name
96285
97046
  *
@@ -102004,7 +102765,7 @@ function getHasTransactionsQuery(schedules) {
102004
102765
  function recurConfigToRSchedule(config2) {
102005
102766
  const base = {
102006
102767
  start: parseDate$1(config2.start),
102007
- // @ts-ignore: issues with https://gitlab.com/john.carroll.p/rschedule/-/issues/86
102768
+ // @ts-expect-error: issues with https://gitlab.com/john.carroll.p/rschedule/-/issues/86
102008
102769
  frequency: config2.frequency.toUpperCase(),
102009
102770
  byHourOfDay: [12]
102010
102771
  };
@@ -111686,7 +112447,7 @@ function requireDefineProperties() {
111686
112447
  return defineProperties_1;
111687
112448
  hasRequiredDefineProperties = 1;
111688
112449
  var keys2 = requireObjectKeys();
111689
- var hasSymbols2 = typeof Symbol === "function" && typeof Symbol("foo") === "symbol";
112450
+ var hasSymbols2 = typeof Symbol === "function" && typeof /* @__PURE__ */ Symbol("foo") === "symbol";
111690
112451
  var toStr = Object.prototype.toString;
111691
112452
  var concat = Array.prototype.concat;
111692
112453
  var defineDataProperty2 = /* @__PURE__ */ requireDefineDataProperty();
@@ -111875,7 +112636,7 @@ function requireShams$1() {
111875
112636
  return true;
111876
112637
  }
111877
112638
  var obj = {};
111878
- var sym = Symbol("test");
112639
+ var sym = /* @__PURE__ */ Symbol("test");
111879
112640
  var symObj = Object(sym);
111880
112641
  if (typeof sym === "string") {
111881
112642
  return false;
@@ -111934,7 +112695,7 @@ function requireHasSymbols() {
111934
112695
  if (typeof origSymbol("foo") !== "symbol") {
111935
112696
  return false;
111936
112697
  }
111937
- if (typeof Symbol("bar") !== "symbol") {
112698
+ if (typeof /* @__PURE__ */ Symbol("bar") !== "symbol") {
111938
112699
  return false;
111939
112700
  }
111940
112701
  return hasSymbolSham();
@@ -121495,7 +122256,7 @@ function requireMd5() {
121495
122256
  }
121496
122257
  var md5Exports = requireMd5();
121497
122258
  const md5 = /* @__PURE__ */ getDefaultExportFromCjs(md5Exports);
121498
- async function runMigration$3(db2) {
122259
+ async function runMigration$4(db2) {
121499
122260
  function getValue(node2) {
121500
122261
  return node2.expr != null ? node2.expr : node2.cachedValue;
121501
122262
  }
@@ -121592,7 +122353,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
121592
122353
  VACUUM;
121593
122354
  `);
121594
122355
  }
121595
- async function runMigration$2(db2) {
122356
+ async function runMigration$3(db2) {
121596
122357
  const categories = await db2.runQuery("SELECT id FROM categories WHERE tombstone = 0", [], true);
121597
122358
  const customReports = await db2.runQuery("SELECT id, selected_categories, conditions FROM custom_reports WHERE tombstone = 0 AND selected_categories IS NOT NULL", [], true);
121598
122359
  for (const report of customReports) {
@@ -121878,7 +122639,7 @@ const DEFAULT_DASHBOARD_STATE = [
121878
122639
  }
121879
122640
  }
121880
122641
  ];
121881
- async function runMigration$1(db2) {
122642
+ async function runMigration$2(db2) {
121882
122643
  db2.transaction(() => {
121883
122644
  const reports = db2.runQuery("SELECT id FROM custom_reports WHERE tombstone = 0 ORDER BY name COLLATE NOCASE ASC", [], true);
121884
122645
  db2.execQuery(`
@@ -121943,7 +122704,7 @@ const SYNCED_PREF_KEYS = [
121943
122704
  "budgetType",
121944
122705
  /^flags\./
121945
122706
  ];
121946
- async function runMigration(db2, { fs: fs2, fileId }) {
122707
+ async function runMigration$1(db2, { fs: fs2, fileId }) {
121947
122708
  await db2.execQuery(`
121948
122709
  CREATE TABLE preferences
121949
122710
  (id TEXT PRIMARY KEY,
@@ -121969,12 +122730,34 @@ async function runMigration(db2, { fs: fs2, fileId }) {
121969
122730
  catch {
121970
122731
  }
121971
122732
  }
122733
+ async function runMigration(db2) {
122734
+ db2.transaction(() => {
122735
+ db2.execQuery(`
122736
+ CREATE TABLE dashboard_pages
122737
+ (id TEXT PRIMARY KEY,
122738
+ name TEXT,
122739
+ tombstone INTEGER DEFAULT 0);
122740
+ `);
122741
+ db2.execQuery(`
122742
+ ALTER TABLE dashboard ADD COLUMN dashboard_page_id TEXT;
122743
+ `);
122744
+ const defaultDashboardId = v4();
122745
+ db2.runQuery(`INSERT INTO dashboard_pages (id, name) VALUES (?, ?)`, [
122746
+ defaultDashboardId,
122747
+ "Main"
122748
+ ]);
122749
+ db2.runQuery(`UPDATE dashboard SET dashboard_page_id = ?`, [
122750
+ defaultDashboardId
122751
+ ]);
122752
+ });
122753
+ }
121972
122754
  let MIGRATIONS_DIR = migrationsPath;
121973
122755
  const javascriptMigrations = {
121974
- 1632571489012: runMigration$3,
121975
- 1722717601e3: runMigration$2,
121976
- 1722804019e3: runMigration$1,
121977
- 1723665565e3: runMigration
122756
+ 1632571489012: runMigration$4,
122757
+ 1722717601e3: runMigration$3,
122758
+ 1722804019e3: runMigration$2,
122759
+ 1723665565e3: runMigration$1,
122760
+ 1765518577215: runMigration
121978
122761
  };
121979
122762
  function getMigrationId(name) {
121980
122763
  return parseInt(name.match(/^(\d)+/)[0]);
@@ -122277,7 +123060,6 @@ app$d.method("validate-budget-name", handleValidateBudgetName);
122277
123060
  app$d.method("unique-budget-name", handleUniqueBudgetName);
122278
123061
  app$d.method("get-budgets", getBudgets);
122279
123062
  app$d.method("get-remote-files", getRemoteFiles);
122280
- app$d.method("get-user-file-info", getUserFileInfo);
122281
123063
  app$d.method("reset-budget-cache", mutator(resetBudgetCache));
122282
123064
  app$d.method("upload-budget", uploadBudget);
122283
123065
  app$d.method("download-budget", downloadBudget);
@@ -122332,9 +123114,6 @@ async function getBudgets() {
122332
123114
  async function getRemoteFiles() {
122333
123115
  return listRemoteFiles();
122334
123116
  }
122335
- async function getUserFileInfo(fileId) {
122336
- return getRemoteFile(fileId);
122337
- }
122338
123117
  async function resetBudgetCache() {
122339
123118
  await loadUserBudgets(db$1);
122340
123119
  get$3().recomputeAll();
@@ -124461,6 +125240,19 @@ app$c.method("report/delete", mutator(undoable(deleteReport)));
124461
125240
  function isExportedCustomReportWidget(widget) {
124462
125241
  return widget.type === "custom-report";
124463
125242
  }
125243
+ function isWidgetType(type2) {
125244
+ return [
125245
+ "net-worth-card",
125246
+ "cash-flow-card",
125247
+ "spending-card",
125248
+ "crossover-card",
125249
+ "markdown-card",
125250
+ "summary-card",
125251
+ "calendar-card",
125252
+ "formula-card",
125253
+ "custom-report"
125254
+ ].includes(type2);
125255
+ }
124464
125256
  const exportModel = {
124465
125257
  validate(dashboard) {
124466
125258
  requiredFields("Dashboard", dashboard, ["version", "widgets"]);
@@ -124488,17 +125280,7 @@ const exportModel = {
124488
125280
  if (!Number.isInteger(widget.height)) {
124489
125281
  throw new ValidationError(`Invalid widget.${idx}.height data-type for value ${widget.height}.`);
124490
125282
  }
124491
- if (![
124492
- "net-worth-card",
124493
- "cash-flow-card",
124494
- "spending-card",
124495
- "crossover-card",
124496
- "custom-report",
124497
- "markdown-card",
124498
- "summary-card",
124499
- "calendar-card",
124500
- "formula-card"
124501
- ].includes(widget.type)) {
125283
+ if (!isWidgetType(widget.type)) {
124502
125284
  throw new ValidationError(`Invalid widget.${idx}.type value ${widget.type}.`);
124503
125285
  }
124504
125286
  if (isExportedCustomReportWidget(widget)) {
@@ -124507,6 +125289,28 @@ const exportModel = {
124507
125289
  });
124508
125290
  }
124509
125291
  };
125292
+ async function getDashboardPages() {
125293
+ return all("SELECT * FROM dashboard_pages WHERE tombstone = 0");
125294
+ }
125295
+ async function createDashboardPage({ name }) {
125296
+ const id2 = v4();
125297
+ await insertWithSchema("dashboard_pages", { id: id2, name });
125298
+ return id2;
125299
+ }
125300
+ async function deleteDashboardPage(id2) {
125301
+ const res = await first$2("SELECT count(*) as c FROM dashboard_pages WHERE tombstone = 0");
125302
+ if ((res?.c ?? 0) <= 1) {
125303
+ throw new Error("Cannot delete the last dashboard page");
125304
+ }
125305
+ const deleting_widgets = await all("SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [id2]);
125306
+ await batchMessages(async () => {
125307
+ await delete_("dashboard_pages", id2);
125308
+ await Promise.all(deleting_widgets.map(({ id: id22 }) => delete_("dashboard", id22)));
125309
+ });
125310
+ }
125311
+ async function renameDashboardPage({ id: id2, name }) {
125312
+ await updateWithSchema("dashboard_pages", { id: id2, name });
125313
+ }
124510
125314
  async function updateDashboard(widgets) {
124511
125315
  const { data: dbWidgets } = await aqlQuery(q("dashboard").filter({ id: { $oneof: widgets.map(({ id: id2 }) => id2) } }).select("*"));
124512
125316
  const dbWidgetMap = new Map(dbWidgets.map((widget) => [widget.id, widget]));
@@ -124515,19 +125319,20 @@ async function updateDashboard(widgets) {
124515
125319
  async function updateDashboardWidget(widget) {
124516
125320
  await updateWithSchema("dashboard", widget);
124517
125321
  }
124518
- async function resetDashboard() {
125322
+ async function resetDashboard(id2) {
124519
125323
  await batchMessages(async () => {
125324
+ const widgets = await selectWithSchema("dashboard", "SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [id2]);
124520
125325
  await Promise.all([
124521
- // Delete all widgets
124522
- deleteAll("dashboard"),
125326
+ // Delete all widgets for this dashboard
125327
+ ...widgets.map(({ id: id22 }) => delete_("dashboard", id22)),
124523
125328
  // Insert the default state
124524
- ...DEFAULT_DASHBOARD_STATE.map((widget) => insertWithSchema("dashboard", widget))
125329
+ ...DEFAULT_DASHBOARD_STATE.map((widget) => insertWithSchema("dashboard", { ...widget, dashboard_page_id: id2 }))
124525
125330
  ]);
124526
125331
  });
124527
125332
  }
124528
125333
  async function addDashboardWidget(widget) {
124529
125334
  if (!("x" in widget) && !("y" in widget)) {
124530
- const data = await first$2("SELECT x, y, width, height FROM dashboard WHERE tombstone = 0 ORDER BY y DESC, x DESC");
125335
+ const data = await first$2("SELECT x, y, width, height FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0 ORDER BY y DESC, x DESC", [widget.dashboard_page_id]);
124531
125336
  if (!data) {
124532
125337
  widget.x = 0;
124533
125338
  widget.y = 0;
@@ -124538,12 +125343,37 @@ async function addDashboardWidget(widget) {
124538
125343
  widget.y = data.y + (xBoundaryCheck > 12 ? data.height : 0);
124539
125344
  }
124540
125345
  }
124541
- await insertWithSchema("dashboard", widget);
125346
+ const { dashboard_page_id, ...widgetWithoutDashboardPageId } = widget;
125347
+ await insertWithSchema("dashboard", {
125348
+ ...widgetWithoutDashboardPageId,
125349
+ dashboard_page_id
125350
+ });
124542
125351
  }
124543
125352
  async function removeDashboardWidget(widgetId) {
124544
125353
  await delete_("dashboard", widgetId);
124545
125354
  }
124546
- async function importDashboard({ filepath }) {
125355
+ async function copyDashboardWidget({ widgetId, targetDashboardPageId }) {
125356
+ const widget = await first$2("SELECT * FROM dashboard WHERE id = ? AND tombstone = 0", [widgetId]);
125357
+ if (!widget) {
125358
+ throw new Error(`Widget not found: ${widgetId}`);
125359
+ }
125360
+ await batchMessages(async () => {
125361
+ if (isWidgetType(widget.type)) {
125362
+ const newWidget = {
125363
+ type: widget.type,
125364
+ width: widget.width,
125365
+ height: widget.height,
125366
+ meta: widget.meta ? JSON.parse(widget.meta) : {},
125367
+ dashboard_page_id: targetDashboardPageId
125368
+ };
125369
+ await addDashboardWidget(newWidget);
125370
+ }
125371
+ else {
125372
+ throw new Error(`Unsupported widget type: ${widget.type}`);
125373
+ }
125374
+ });
125375
+ }
125376
+ async function importDashboard({ filepath, dashboardPageId }) {
124547
125377
  try {
124548
125378
  if (!await exists(filepath)) {
124549
125379
  throw new Error(`File not found at the provided path: ${filepath}`);
@@ -124553,10 +125383,11 @@ async function importDashboard({ filepath }) {
124553
125383
  exportModel.validate(parsedContent);
124554
125384
  const customReportIds = await all("SELECT id from custom_reports");
124555
125385
  const customReportIdSet = new Set(customReportIds.map(({ id: id2 }) => id2));
125386
+ const existingWidgets = await selectWithSchema("dashboard", "SELECT id FROM dashboard WHERE dashboard_page_id = ? AND tombstone = 0", [dashboardPageId]);
124556
125387
  await batchMessages(async () => {
124557
125388
  await Promise.all([
124558
125389
  // Delete all widgets
124559
- deleteAll("dashboard"),
125390
+ ...existingWidgets.map(({ id: id2 }) => delete_("dashboard", id2)),
124560
125391
  // Insert new widgets
124561
125392
  ...parsedContent.widgets.map((widget) => insertWithSchema("dashboard", {
124562
125393
  type: widget.type,
@@ -124564,6 +125395,7 @@ async function importDashboard({ filepath }) {
124564
125395
  height: widget.height,
124565
125396
  x: widget.x,
124566
125397
  y: widget.y,
125398
+ dashboard_page_id: dashboardPageId,
124567
125399
  meta: isExportedCustomReportWidget(widget) ? { id: widget.meta.id } : widget.meta
124568
125400
  })),
124569
125401
  // Insert new custom reports
@@ -124597,11 +125429,16 @@ async function importDashboard({ filepath }) {
124597
125429
  }
124598
125430
  }
124599
125431
  const app$b = createApp();
125432
+ app$b.method("dashboard_pages-get", getDashboardPages);
125433
+ app$b.method("dashboard-create", mutator(undoable(createDashboardPage)));
125434
+ app$b.method("dashboard-delete", mutator(undoable(deleteDashboardPage)));
125435
+ app$b.method("dashboard-rename", mutator(undoable(renameDashboardPage)));
124600
125436
  app$b.method("dashboard-update", mutator(undoable(updateDashboard)));
124601
125437
  app$b.method("dashboard-update-widget", mutator(undoable(updateDashboardWidget)));
124602
125438
  app$b.method("dashboard-reset", mutator(undoable(resetDashboard)));
124603
125439
  app$b.method("dashboard-add-widget", mutator(undoable(addDashboardWidget)));
124604
125440
  app$b.method("dashboard-remove-widget", mutator(undoable(removeDashboardWidget)));
125441
+ app$b.method("dashboard-copy-widget", mutator(undoable(copyDashboardWidget)));
124605
125442
  app$b.method("dashboard-import", mutator(undoable(importDashboard)));
124606
125443
  const app$a = createApp();
124607
125444
  app$a.method("key-make", keyMake);
@@ -134260,7 +135097,21 @@ async function init(config2) {
134260
135097
  _setDocumentDir(dataDir || process.cwd());
134261
135098
  if (serverURL) {
134262
135099
  setServer(serverURL);
134263
- if (config2.password) {
135100
+ if ("sessionToken" in config2 && config2.sessionToken) {
135101
+ await runHandler(exports.handlers["subscribe-set-token"], {
135102
+ token: config2.sessionToken
135103
+ });
135104
+ const user = await runHandler(exports.handlers["subscribe-get-user"], void 0);
135105
+ if (!user || user.tokenExpired === true) {
135106
+ await runHandler(exports.handlers["subscribe-set-token"], { token: "" });
135107
+ throw new Error("Authentication failed: invalid or expired session token");
135108
+ }
135109
+ if (user.offline === true) {
135110
+ await runHandler(exports.handlers["subscribe-set-token"], { token: "" });
135111
+ throw new Error("Authentication failed: server offline or unreachable");
135112
+ }
135113
+ }
135114
+ else if ("password" in config2 && config2.password) {
134264
135115
  const result = await runHandler(exports.handlers["subscribe-sign-in"], {
134265
135116
  password: config2.password
134266
135117
  });