@lotics/cli 0.196.0 → 0.197.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -248,7 +248,11 @@ Workspaces live inside the active org. If the org has more than one, select befo
248
248
  ```bash
249
249
  lotics workspace # list workspaces in the active org (marks current)
250
250
  lotics workspace select wks_... # set the workspace for the active scope (pin or profile)
251
- lotics workspace create "Sales" # create a new workspace (admin only)
251
+ lotics workspace create "Sales" --timezone America/New_York --currency USD
252
+ # create a new workspace (admin only); without the flags it
253
+ # takes the org's oldest workspace's zone and currency
254
+ lotics workspace settings --currency USD --timezone America/New_York
255
+ # change the current workspace's name/currency/zone
252
256
  lotics workspace delete wks_... --yes # delete a workspace (admin only; soft delete, recoverable)
253
257
  ```
254
258
 
@@ -268,8 +272,8 @@ lotics run query_records '{"table_id":"tbl_...","field_keys":["name"]}'
268
272
  # Large args (a knowledge-doc `content`, a bulk update) exceed the OS arg limit —
269
273
  # read them from a file or stdin instead of an inline arg:
270
274
  lotics run create_knowledge @args.json
271
- cat args.json | lotics run create_knowledge
272
- echo '{"table_id":"tbl_..."}' | lotics run query_records
275
+ cat args.json | lotics run create_knowledge - # the trailing - reads stdin
276
+ echo '{"table_id":"tbl_..."}' | lotics run query_records -
273
277
 
274
278
  # Upload files (multiple files and directories supported)
275
279
  lotics upload ./report.pdf ./data.csv ./documents/
@@ -278,6 +282,10 @@ lotics upload ./report.pdf ./data.csv ./documents/
278
282
  lotics run generate_excel_from_template '{"..."}'
279
283
  lotics download <file_id> -o ./reports/
280
284
 
285
+ # What is in the store, newest first — one page, with the command for the next one
286
+ lotics file list --limit 50
287
+ lotics file delete <file_id> # refused while anything still references it
288
+
281
289
  # CI / non-interactive (key inline)
282
290
  LOTICS_API_KEY=ltk_... lotics run query_tables '{}'
283
291
 
@@ -348,7 +356,7 @@ lotics app check
348
356
  # Running an app's alias is a TOOL call, like every other tool. Exits non-zero
349
357
  # when the RUN failed, not only when the call did.
350
358
  lotics run run_app_workflow '{"app_id":"app_...","alias":"issueInvoice","inputs":{"record_id":"rec_..."}}'
351
- cat args.json | lotics run run_app_workflow # bulk inputs bypass ARG_MAX
359
+ cat args.json | lotics run run_app_workflow - # bulk inputs bypass ARG_MAX
352
360
  # Honest post-run harvest: created records + a paste-ready cleanup plan + the
353
361
  # caveat (external/notification calls can't be auto-undone; sub-workflows may run).
354
362
  lotics run run_app_workflow '{...}' --print-created
@@ -361,7 +369,8 @@ lotics run run_app_workflow '{...}' --cleanup # also deletes created records (
361
369
  # JS-subset parser + type-check locally, so a body that passes is one `set` will accept
362
370
  # (`set` still adds name resolution + lint + structural checks, which need the workspace):
363
371
  lotics app workflow pull # rewrite src/workflows/*.ts + globals from the server
364
- lotics app workflow check # parse + typecheck every body locally ([alias] for one)
372
+ lotics app workflow check # parse + typecheck every body locally ([alias...] for some)
373
+ lotics app workflow diff issueInvoice # how the local body differs from the one the server runs
365
374
  lotics app workflow set issueInvoice # push the edited src/workflows/issueInvoice.ts
366
375
 
367
376
  # Iterate on a named query WITHOUT a deploy: push package.json#lotics.queries.<alias>
@@ -373,7 +382,7 @@ lotics app query set openInvoices # push package.json#lotics.queries.o
373
382
  # + member auth). Streams progress to stderr; reports the SETTLED run (structured
374
383
  # output / final text) to stdout; exits 0 only when the run completed.
375
384
  lotics run run_app_agent '{"app_id":"app_abc","alias":"recognize","input":{"image_file_id":"fil_..."}}'
376
- cat input.json | lotics run run_app_agent # inputs via stdin/@file
385
+ cat input.json | lotics run run_app_agent - # inputs via stdin/@file
377
386
  lotics run run_app_agent '{...}' --json # full run summary to stdout
378
387
  # A run that outlives the call's bounded wait keeps going server-side; read it with
379
388
  lotics run get_app_agent_run '{"app_id":"app_abc","run_id":"run_..."}'
@@ -52856,6 +52856,7 @@ ${e.toString()}`);
52856
52856
  // ../xlsx/src/ooxml_sheet.ts
52857
52857
  var MAX_ROWS_PER_SHEET = 1e4;
52858
52858
  var MAX_IMAGES = 50;
52859
+ var LAST_COLUMN = 16384;
52859
52860
  function extractElementText(node) {
52860
52861
  if (node === void 0 || node === null) return void 0;
52861
52862
  if (typeof node === "object") {
@@ -52897,8 +52898,12 @@ ${e.toString()}`);
52897
52898
  const defaultRowHeight = sheetFormatPr?.["@_defaultRowHeight"] ? parseFloat(sheetFormatPr["@_defaultRowHeight"]) : 15;
52898
52899
  const defaultColWidth = sheetFormatPr?.["@_defaultColWidth"] ? parseFloat(sheetFormatPr["@_defaultColWidth"]) : 8;
52899
52900
  const { freezePane, showGridLines } = parseSheetViews(worksheet);
52900
- const { columns: parsedCols, colHidden, colOutlineLevels } = parseCols(worksheet, defaultColWidth);
52901
+ const parsedCols = parseCols(worksheet, defaultColWidth);
52902
+ const backdrop = parsedCols.filter((c) => c.max >= LAST_COLUMN).pop();
52903
+ const sheetColWidth = backdrop?.width ?? defaultColWidth;
52901
52904
  const hyperlinkMap = parseHyperlinks(worksheet, rels);
52905
+ const styleRuns = parsedCols.filter((c) => c.styleIndex !== void 0);
52906
+ const colStyleIndex = (col) => styleRuns.find((r) => col >= r.min && col <= r.max)?.styleIndex ?? 0;
52902
52907
  const {
52903
52908
  rows,
52904
52909
  totalRowCount,
@@ -52906,9 +52911,20 @@ ${e.toString()}`);
52906
52911
  maxCol,
52907
52912
  maxContentWidth,
52908
52913
  rowOutlineLevels
52909
- } = parseSheetData(worksheet, styles, sharedStrings, hyperlinkMap, defaultRowHeight, date1904, maxRows);
52910
- const colCount = Math.max(parsedCols.length > 0 ? parsedCols[parsedCols.length - 1].max : 0, maxCol);
52911
- const columns = buildColumns(parsedCols, colHidden, maxContentWidth, colCount, defaultColWidth);
52914
+ } = parseSheetData(
52915
+ worksheet,
52916
+ styles,
52917
+ sharedStrings,
52918
+ hyperlinkMap,
52919
+ defaultRowHeight,
52920
+ date1904,
52921
+ maxRows,
52922
+ colStyleIndex
52923
+ );
52924
+ const declaredMax = parsedCols.reduce((m, c) => c.max >= LAST_COLUMN ? m : Math.max(m, c.max), 0);
52925
+ const colCount = Math.max(declaredMax, maxCol);
52926
+ const { colHidden, colOutlineLevels } = expandColRuns(parsedCols, colCount);
52927
+ const columns = buildColumns(parsedCols, colHidden, maxContentWidth, colCount, styles);
52912
52928
  const mergedCells = parseMergedCells(worksheet);
52913
52929
  const conditionalFormats = parseConditionalFormats(worksheet, theme, indexedColors, styles.dxfs);
52914
52930
  const images = parseImages(rels, zipEntries);
@@ -52923,7 +52939,7 @@ ${e.toString()}`);
52923
52939
  totalRowCount,
52924
52940
  truncated,
52925
52941
  defaultRowHeight,
52926
- defaultColWidth,
52942
+ defaultColWidth: sheetColWidth,
52927
52943
  showGridLines,
52928
52944
  freezePane,
52929
52945
  conditionalFormats,
@@ -53046,11 +53062,9 @@ ${e.toString()}`);
53046
53062
  }
53047
53063
  function parseCols(worksheet, defaultColWidth) {
53048
53064
  const colsEl = worksheet["cols"];
53049
- const colHidden = /* @__PURE__ */ new Set();
53050
- const colOutlineLevels = /* @__PURE__ */ new Map();
53051
- if (!colsEl) return { columns: [], colHidden, colOutlineLevels };
53065
+ if (!colsEl) return [];
53052
53066
  const colArr = colsEl["col"];
53053
- if (!colArr) return { columns: [], colHidden, colOutlineLevels };
53067
+ if (!colArr) return [];
53054
53068
  const columns = [];
53055
53069
  for (const col of colArr) {
53056
53070
  const min = parseInt(col["@_min"] ?? "1", 10);
@@ -53059,21 +53073,32 @@ ${e.toString()}`);
53059
53073
  const hidden = col["@_hidden"] === "1" || col["@_hidden"] === "true";
53060
53074
  const customWidth = col["@_customWidth"] === "1" || col["@_customWidth"] === "true";
53061
53075
  const outlineLevel = parseInt(col["@_outlineLevel"] ?? "0", 10);
53062
- columns.push({ min, max: max2, width, hidden, customWidth, outlineLevel });
53063
- for (let c = min; c <= max2; c++) {
53064
- if (hidden) colHidden.add(c);
53065
- if (outlineLevel > 0) colOutlineLevels.set(c, outlineLevel);
53076
+ const styleIndex = col["@_style"] !== void 0 ? parseInt(col["@_style"], 10) : void 0;
53077
+ columns.push({ min, max: max2, width, hidden, customWidth, outlineLevel, styleIndex });
53078
+ }
53079
+ return columns;
53080
+ }
53081
+ function expandColRuns(colDefs, colCount) {
53082
+ const colHidden = /* @__PURE__ */ new Set();
53083
+ const colOutlineLevels = /* @__PURE__ */ new Map();
53084
+ for (const def of colDefs) {
53085
+ if (!def.hidden && def.outlineLevel <= 0) continue;
53086
+ for (let c = def.min; c <= Math.min(def.max, colCount); c++) {
53087
+ if (def.hidden) colHidden.add(c);
53088
+ if (def.outlineLevel > 0) colOutlineLevels.set(c, def.outlineLevel);
53066
53089
  }
53067
53090
  }
53068
- return { columns, colHidden, colOutlineLevels };
53091
+ return { colHidden, colOutlineLevels };
53069
53092
  }
53070
- function buildColumns(colDefs, colHidden, maxContentWidth, colCount, _defaultColWidth) {
53093
+ function buildColumns(colDefs, colHidden, maxContentWidth, colCount, styles) {
53071
53094
  const explicitWidth = /* @__PURE__ */ new Map();
53072
53095
  const pinned = /* @__PURE__ */ new Set();
53096
+ const styleIndexes = /* @__PURE__ */ new Map();
53073
53097
  for (const def of colDefs) {
53074
- for (let c = def.min; c <= def.max; c++) {
53098
+ for (let c = def.min; c <= Math.min(def.max, colCount); c++) {
53075
53099
  explicitWidth.set(c, def.width);
53076
53100
  if (def.customWidth) pinned.add(c);
53101
+ if (def.styleIndex !== void 0) styleIndexes.set(c, def.styleIndex);
53077
53102
  }
53078
53103
  }
53079
53104
  const columns = [];
@@ -53087,11 +53112,28 @@ ${e.toString()}`);
53087
53112
  } else {
53088
53113
  width = Math.max(8, Math.min(contentChars + 2, 40));
53089
53114
  }
53090
- columns.push({ index: c, width, hidden, ...pinned.has(c) ? { customWidth: true } : {} });
53115
+ columns.push({
53116
+ index: c,
53117
+ width,
53118
+ hidden,
53119
+ ...pinned.has(c) ? { customWidth: true } : {},
53120
+ ...resolveAxisFormat(styles, styleIndexes.get(c))
53121
+ });
53091
53122
  }
53092
53123
  return columns;
53093
53124
  }
53094
- function parseSheetData(worksheet, styles, sharedStrings, hyperlinkMap, defaultRowHeight, date1904, maxRows) {
53125
+ function resolveAxisFormat(styles, xfIndex) {
53126
+ if (xfIndex === void 0 || xfIndex === 0) return {};
53127
+ const numFmt = styles.getNumFmt(xfIndex);
53128
+ return {
53129
+ style: styles.resolveStyle(xfIndex),
53130
+ ...numFmt !== "General" ? { numFmtCode: numFmt } : {},
53131
+ // An index naming no `cellXfs` entry expresses nothing to preserve, and
53132
+ // recording it would let the writer re-emit an index the file cannot resolve.
53133
+ ...styles.hasXf(xfIndex) ? { originalXfIndex: xfIndex } : {}
53134
+ };
53135
+ }
53136
+ function parseSheetData(worksheet, styles, sharedStrings, hyperlinkMap, defaultRowHeight, date1904, maxRows, colStyleIndex) {
53095
53137
  const sheetData = worksheet["sheetData"];
53096
53138
  if (!sheetData) {
53097
53139
  return {
@@ -53132,11 +53174,15 @@ ${e.toString()}`);
53132
53174
  if (rowCount > maxRows) continue;
53133
53175
  const height = rowEl["@_ht"] ? parseFloat(rowEl["@_ht"]) : defaultRowHeight;
53134
53176
  const customHeight = rowEl["@_customHeight"] === "1" || rowEl["@_customHeight"] === "true";
53177
+ const customFormat = rowEl["@_customFormat"] === "1" || rowEl["@_customFormat"] === "true";
53178
+ const rowXfIndex = customFormat ? parseInt(rowEl["@_s"] ?? "0", 10) : 0;
53179
+ const rowFormat = resolveAxisFormat(styles, rowXfIndex);
53180
+ const inheritedXfIndex = (col) => rowXfIndex > 0 ? rowXfIndex : colStyleIndex(col);
53135
53181
  const cellArr = rowEl["c"];
53136
53182
  const cells = [];
53137
53183
  if (cellArr) {
53138
53184
  for (const cellEl of cellArr) {
53139
- const parsed = parseCell(cellEl, styles, sharedStrings, hyperlinkMap, date1904);
53185
+ const parsed = parseCell(cellEl, styles, sharedStrings, hyperlinkMap, date1904, inheritedXfIndex);
53140
53186
  if (parsed) {
53141
53187
  cells.push(parsed);
53142
53188
  if (parsed.column > maxCol) maxCol = parsed.column;
@@ -53154,7 +53200,8 @@ ${e.toString()}`);
53154
53200
  height,
53155
53201
  cells,
53156
53202
  hidden: rowHidden,
53157
- ...customHeight ? { customHeight: true } : {}
53203
+ ...customHeight ? { customHeight: true } : {},
53204
+ ...rowFormat
53158
53205
  });
53159
53206
  }
53160
53207
  return {
@@ -53171,13 +53218,14 @@ ${e.toString()}`);
53171
53218
  if (!match) return void 0;
53172
53219
  return { col: colLettersToNum(match[1]), row: parseInt(match[2], 10) };
53173
53220
  }
53174
- function parseCell(cellEl, styles, sharedStrings, hyperlinkMap, date1904) {
53221
+ function parseCell(cellEl, styles, sharedStrings, hyperlinkMap, date1904, inheritedXfIndex) {
53175
53222
  const ref2 = cellEl["@_r"];
53176
53223
  if (!ref2) return void 0;
53177
53224
  const cellRef = parseCellRef(ref2);
53178
53225
  if (!cellRef) return void 0;
53179
53226
  const type = cellEl["@_t"] ?? "";
53180
- const styleIndex = parseInt(cellEl["@_s"] ?? "0", 10);
53227
+ const declaredStyle = cellEl["@_s"];
53228
+ const styleIndex = declaredStyle !== void 0 ? parseInt(declaredStyle, 10) : inheritedXfIndex(cellRef.col);
53181
53229
  const rawValue = extractElementText(cellEl["v"]);
53182
53230
  let inlineStr;
53183
53231
  if (type === "inlineStr") {
@@ -54238,18 +54286,18 @@ ${e.toString()}`);
54238
54286
  return original !== void 0 && original.styleIndex === styleIndex && original.numFmtCode === (numFmtCode === "" ? "General" : numFmtCode);
54239
54287
  }
54240
54288
  /**
54241
- * True when the xf index the writer emits for `cell` in styles-passthrough
54242
- * mode still expresses the cell's style. A cell CARRYING an index always
54243
- * does — every write path drops that index the moment the style or number
54244
- * format moves off it. The question left is the one no cell states: a cell
54245
- * the file never carried emits no `s=` and so inherits the file's xf 0,
54289
+ * True when the xf index the writer emits for `format` in styles-passthrough
54290
+ * mode still expresses its style. A cell, column or row CARRYING an index
54291
+ * always does — every write path drops that index the moment the style or
54292
+ * number format moves off it. The question left is the one nothing states: a
54293
+ * cell the file never carried emits no `s=` and so inherits the file's xf 0,
54246
54294
  * which is right only when that entry expresses the style the model gives
54247
54295
  * it. Neither half reads cell protection or `quotePrefix`, which this model
54248
54296
  * does not carry, so an xf differing only there compares equal.
54249
54297
  */
54250
- keepsOriginalXf(cell) {
54251
- if (cell.originalXfIndex !== void 0) return true;
54252
- return this.originalXfExpresses(0, cell.styleIndex, cell.numFmtCode);
54298
+ keepsOriginalXf(format) {
54299
+ if (format.originalXfIndex !== void 0) return true;
54300
+ return this.originalXfExpresses(0, format.styleIndex, format.numFmtCode);
54253
54301
  }
54254
54302
  /**
54255
54303
  * Reset the `dirty` flag and snapshot the current numFmt set as the
@@ -54303,6 +54351,12 @@ ${e.toString()}`);
54303
54351
  this.hiddenCols = /* @__PURE__ */ new Set();
54304
54352
  this.rowOutlineLevels = /* @__PURE__ */ new Map();
54305
54353
  this.colOutlineLevels = /* @__PURE__ */ new Map();
54354
+ /** A whole column's / whole row's default format, keyed by 1-based index.
54355
+ * The cheapest way a template says "this column is money", and the writer
54356
+ * must restate it or the regenerated sheet says less than the one it
54357
+ * replaces. */
54358
+ this.colFormats = /* @__PURE__ */ new Map();
54359
+ this.rowFormats = /* @__PURE__ */ new Map();
54306
54360
  this.conditionalFormats = [];
54307
54361
  this.images = [];
54308
54362
  this.charts = [];
@@ -54385,17 +54439,31 @@ ${e.toString()}`);
54385
54439
  getCellAt(row, col) {
54386
54440
  return this.cells.getAt(row, col);
54387
54441
  }
54442
+ /**
54443
+ * The format the cell at (row, col) HAS: its own when the grid holds one,
54444
+ * else the default its row declares, else its column's, else the sheet's.
54445
+ * This is what `<col style>` and `<row s customFormat>` mean — an EMPTY cell
54446
+ * in a money column is still a money cell, and a value written into one
54447
+ * arrives as money rather than at the sheet default.
54448
+ */
54449
+ effectiveFormat(row, col) {
54450
+ return this.cells.getAt(row, col) ?? this.rowFormats.get(row) ?? this.colFormats.get(col) ?? { styleIndex: 0, numFmtCode: "General" };
54451
+ }
54388
54452
  /**
54389
54453
  * Set cell value with optional inline style. Interns style via the
54390
- * StyleRegistry when available. When `style` is supplied and matches the
54391
- * existing cell's style (or is identical to a previously interned style),
54392
- * the cell's `originalXfIndex` is preserved so that the writer can use
54393
- * styles-passthrough mode if no other mutation has dirtied the registry.
54454
+ * StyleRegistry when available. What the caller leaves unstated is what the
54455
+ * cell already HAS — its own format, or the one its row or column declares —
54456
+ * so a number written into a money column arrives as money. When the result
54457
+ * still expresses that format, its `originalXfIndex` is carried, so the
54458
+ * writer can use styles-passthrough mode if no other mutation has dirtied the
54459
+ * registry.
54394
54460
  */
54395
54461
  set(ref2, value2, style, numFmt, formula) {
54396
54462
  const existing = this.cells.get(ref2);
54397
- const styleIndex = style && this.styles ? this.styles.intern(style) : existing?.styleIndex ?? 0;
54398
- const numFmtCode = numFmt ?? existing?.numFmtCode ?? "General";
54463
+ const rc = existing ? void 0 : refToRowCol(ref2);
54464
+ const inherited = existing ?? (rc ? this.effectiveFormat(rc.row, rc.col) : { styleIndex: 0, numFmtCode: "General" });
54465
+ const styleIndex = style && this.styles ? this.styles.intern(style) : inherited.styleIndex;
54466
+ const numFmtCode = numFmt ?? inherited.numFmtCode;
54399
54467
  if (this.styles) this.styles.registerNumFmt(numFmtCode);
54400
54468
  const displayValue = computeDisplayValue(value2, numFmtCode);
54401
54469
  const content = buildContentFromValue(displayValue, this.hyperlinks.get(ref2));
@@ -54407,8 +54475,8 @@ ${e.toString()}`);
54407
54475
  numFmtCode,
54408
54476
  content
54409
54477
  };
54410
- if (existing && existing.styleIndex === styleIndex && existing.numFmtCode === numFmtCode && existing.originalXfIndex !== void 0) {
54411
- cell.originalXfIndex = existing.originalXfIndex;
54478
+ if (inherited.originalXfIndex !== void 0 && inherited.styleIndex === styleIndex && inherited.numFmtCode === numFmtCode) {
54479
+ cell.originalXfIndex = inherited.originalXfIndex;
54412
54480
  }
54413
54481
  this.cells.set(ref2, cell);
54414
54482
  return cell;
@@ -54553,6 +54621,12 @@ ${e.toString()}`);
54553
54621
  for (const cell of sheet.cells.values()) {
54554
54622
  if (!this.styles.keepsOriginalXf(cell)) return false;
54555
54623
  }
54624
+ for (const format of sheet.colFormats.values()) {
54625
+ if (!this.styles.keepsOriginalXf(format)) return false;
54626
+ }
54627
+ for (const format of sheet.rowFormats.values()) {
54628
+ if (!this.styles.keepsOriginalXf(format)) return false;
54629
+ }
54556
54630
  for (const cf of sheet.conditionalFormats) {
54557
54631
  for (const rule of cf.rules) {
54558
54632
  if (rule.ruleType !== "style") continue;
@@ -54570,6 +54644,13 @@ ${e.toString()}`);
54570
54644
  };
54571
54645
  }
54572
54646
  };
54647
+ function snapshotAxisFormat(format, styles) {
54648
+ if (!format) return {};
54649
+ return {
54650
+ style: styles.get(format.styleIndex),
54651
+ ...format.numFmtCode !== "General" ? { numFmtCode: format.numFmtCode } : {}
54652
+ };
54653
+ }
54573
54654
  function sheetToSnapshot(sheet, styles) {
54574
54655
  const { maxRow, maxCol } = sheet.getUsedRange();
54575
54656
  const rowMap = /* @__PURE__ */ new Map();
@@ -54597,6 +54678,9 @@ ${e.toString()}`);
54597
54678
  if (cell.arrayRange) parsedCell.arrayRange = cell.arrayRange;
54598
54679
  arr.push(parsedCell);
54599
54680
  }
54681
+ for (const rowNum of sheet.rowHeights.keys()) if (!rowMap.has(rowNum)) rowMap.set(rowNum, []);
54682
+ for (const rowNum of sheet.hiddenRows) if (!rowMap.has(rowNum)) rowMap.set(rowNum, []);
54683
+ for (const rowNum of sheet.rowFormats.keys()) if (!rowMap.has(rowNum)) rowMap.set(rowNum, []);
54600
54684
  const rows = [];
54601
54685
  const sortedRowNums = Array.from(rowMap.keys()).sort((a, b) => a - b);
54602
54686
  for (const rowNum of sortedRowNums) {
@@ -54606,15 +54690,21 @@ ${e.toString()}`);
54606
54690
  index: rowNum,
54607
54691
  height: sheet.rowHeights.get(rowNum) ?? sheet.defaultRowHeight,
54608
54692
  cells,
54609
- hidden: sheet.hiddenRows.has(rowNum)
54693
+ hidden: sheet.hiddenRows.has(rowNum),
54694
+ ...snapshotAxisFormat(sheet.rowFormats.get(rowNum), styles)
54610
54695
  });
54611
54696
  }
54612
54697
  const columns = [];
54613
- for (let c = 1; c <= maxCol; c++) {
54698
+ let colBound = maxCol;
54699
+ for (const c of sheet.colWidths.keys()) if (c > colBound) colBound = c;
54700
+ for (const c of sheet.hiddenCols) if (c > colBound) colBound = c;
54701
+ for (const c of sheet.colFormats.keys()) if (c > colBound) colBound = c;
54702
+ for (let c = 1; c <= colBound; c++) {
54614
54703
  columns.push({
54615
54704
  index: c,
54616
54705
  width: sheet.colWidths.get(c) ?? sheet.defaultColWidth,
54617
- hidden: sheet.hiddenCols.has(c)
54706
+ hidden: sheet.hiddenCols.has(c),
54707
+ ...snapshotAxisFormat(sheet.colFormats.get(c), styles)
54618
54708
  });
54619
54709
  }
54620
54710
  const mergedCells = sheet.mergedCells.map((ref2) => {
@@ -54725,6 +54815,8 @@ ${e.toString()}`);
54725
54815
  if (col.hidden) {
54726
54816
  sheet.hiddenCols.add(col.index);
54727
54817
  }
54818
+ const format = loadAxisFormat(col, styles, hasCellXfs, `${ps.name} column ${col.index}`);
54819
+ if (format) sheet.colFormats.set(col.index, format);
54728
54820
  }
54729
54821
  sheet.mergedCells = ps.mergedCells.map((mc) => {
54730
54822
  const startRef = rowColToRef(mc.startRow, mc.startCol);
@@ -54738,6 +54830,8 @@ ${e.toString()}`);
54738
54830
  if (row.hidden) {
54739
54831
  sheet.hiddenRows.add(row.index);
54740
54832
  }
54833
+ const rowFormat = loadAxisFormat(row, styles, hasCellXfs, `${ps.name} row ${row.index}`);
54834
+ if (rowFormat) sheet.rowFormats.set(row.index, rowFormat);
54741
54835
  for (const cell of row.cells) {
54742
54836
  const ref2 = rowColToRef(row.index, cell.column);
54743
54837
  const styleIndex = styles.intern(cell.style);
@@ -54777,6 +54871,23 @@ ${e.toString()}`);
54777
54871
  }
54778
54872
  return sheet;
54779
54873
  }
54874
+ function loadAxisFormat(source, styles, hasCellXfs, label) {
54875
+ if (!source.style) return void 0;
54876
+ styles.registerNumFmt(source.numFmtCode);
54877
+ const format = {
54878
+ styleIndex: styles.intern(source.style),
54879
+ numFmtCode: source.numFmtCode ?? "General"
54880
+ };
54881
+ if (source.originalXfIndex !== void 0) {
54882
+ if (!hasCellXfs) {
54883
+ throw new InvalidModelError(
54884
+ `${label} carries originalXfIndex ${source.originalXfIndex} but the snapshot has no cellXfs table`
54885
+ );
54886
+ }
54887
+ format.originalXfIndex = source.originalXfIndex;
54888
+ }
54889
+ return format;
54890
+ }
54780
54891
  function applyAutoFilterHiddenRows(sheet) {
54781
54892
  const af = sheet.autoFilter;
54782
54893
  if (!af) return;