@particle-academy/holy-sheet 2.5.0 → 2.6.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/dist/index.d.cts CHANGED
@@ -223,7 +223,7 @@ interface SetMetaOp {
223
223
  }
224
224
 
225
225
  /** This package's own version, pinned to package.json by `version.test.ts`. */
226
- declare const VERSION = "2.5.0";
226
+ declare const VERSION = "2.6.0";
227
227
  type Any$6 = any;
228
228
  /**
229
229
  * Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
@@ -295,7 +295,7 @@ type Any$5 = any;
295
295
  * over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
296
296
  */
297
297
  declare class HolySheet {
298
- static readonly VERSION = "2.5.0";
298
+ static readonly VERSION = "2.6.0";
299
299
  validate(schema: Any$5): ValidationError[];
300
300
  toBytes(schema: Any$5): Uint8Array;
301
301
  write(schema: Any$5, path: string): Promise<WriteResult>;
package/dist/index.d.ts CHANGED
@@ -223,7 +223,7 @@ interface SetMetaOp {
223
223
  }
224
224
 
225
225
  /** This package's own version, pinned to package.json by `version.test.ts`. */
226
- declare const VERSION = "2.5.0";
226
+ declare const VERSION = "2.6.0";
227
227
  type Any$6 = any;
228
228
  /**
229
229
  * Agent — the structured-tool surface for Holy Sheet. Mirrors PHP `Agent`.
@@ -295,7 +295,7 @@ type Any$5 = any;
295
295
  * over `Agent`. Provided for parity / DI ergonomics; most callers use `Agent`.
296
296
  */
297
297
  declare class HolySheet {
298
- static readonly VERSION = "2.5.0";
298
+ static readonly VERSION = "2.6.0";
299
299
  validate(schema: Any$5): ValidationError[];
300
300
  toBytes(schema: Any$5): Uint8Array;
301
301
  write(schema: Any$5, path: string): Promise<WriteResult>;
package/dist/index.js CHANGED
@@ -493,6 +493,54 @@ var DateConverter = {
493
493
  }
494
494
  };
495
495
 
496
+ // src/exceptions.ts
497
+ var SchemaException = class _SchemaException extends Error {
498
+ constructor(errors, message) {
499
+ super(message ?? summarize(errors));
500
+ this.name = "SchemaException";
501
+ this.errors = errors;
502
+ Object.setPrototypeOf(this, _SchemaException.prototype);
503
+ }
504
+ static fromErrors(errors) {
505
+ return new _SchemaException(errors);
506
+ }
507
+ getErrors() {
508
+ return this.errors;
509
+ }
510
+ };
511
+ function summarize(errors) {
512
+ if (errors.length === 1) {
513
+ const e = errors[0];
514
+ return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
515
+ }
516
+ const first2 = errors[0];
517
+ const rest = errors.length - 1;
518
+ return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
519
+ }
520
+ var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
521
+ constructor(message, path = null, mimetype = null) {
522
+ super(message);
523
+ this.name = "UnsupportedFormatException";
524
+ this.path = path;
525
+ this.mimetype = mimetype;
526
+ Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
527
+ }
528
+ static notAZip(path = null) {
529
+ return new _UnsupportedFormatException(
530
+ `[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
531
+ path
532
+ );
533
+ }
534
+ static unknownPackage(path, mimetype) {
535
+ const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
536
+ return new _UnsupportedFormatException(
537
+ `[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
538
+ path,
539
+ mimetype !== "" ? mimetype : null
540
+ );
541
+ }
542
+ };
543
+
496
544
  // src/schema/theme.ts
497
545
  var Theme = class {
498
546
  constructor(key) {
@@ -570,7 +618,7 @@ var Normalizer = class {
570
618
  const columnFormat = columnFormats.get(c) ?? null;
571
619
  const rowBand = theme.dataFormat(r);
572
620
  const merged = rowBand !== null ? columnFormat ? columnFormat.mergeWith(rowBand) : rowBand : columnFormat;
573
- cells.set(address, this.buildCell(address, value, merged));
621
+ cells.set(address, this.buildCell(address, value, merged, name));
574
622
  });
575
623
  });
576
624
  if (sheet.totals && isPlainObject(sheet.totals) && Object.keys(sheet.totals).length > 0 && rows.length > 0 && columns.length > 0) {
@@ -594,7 +642,7 @@ var Normalizer = class {
594
642
  }
595
643
  }
596
644
  if (sheet.cells != null) {
597
- for (const [address, cell] of this.normalizeCellMap(sheet.cells)) {
645
+ for (const [address, cell] of this.normalizeCellMap(sheet.cells, name)) {
598
646
  const beneath = cells.get(address);
599
647
  cells.set(
600
648
  address,
@@ -618,14 +666,18 @@ var Normalizer = class {
618
666
  toInt(sheet.frozenCols ?? 0)
619
667
  );
620
668
  }
621
- normalizeCellMap(map) {
669
+ normalizeCellMap(map, sheetName2) {
622
670
  const cells = /* @__PURE__ */ new Map();
623
671
  for (const [address, cellData] of Object.entries(map)) {
624
- if (!isPlainObject(cellData)) {
672
+ if (!isCellSpec(cellData)) {
625
673
  const [bare, formula] = promoteFormula(cellData);
626
674
  cells.set(
627
675
  address,
628
- new Cell(address, formula !== null ? null : this.coerceValue(bare, null), formula)
676
+ new Cell(
677
+ address,
678
+ formula !== null ? null : this.coerceValue(bare, null, address, sheetName2),
679
+ formula
680
+ )
629
681
  );
630
682
  continue;
631
683
  }
@@ -640,7 +692,7 @@ var Normalizer = class {
640
692
  address,
641
693
  new Cell(
642
694
  address,
643
- this.coerceValue(rawValue, format),
695
+ this.coerceValue(rawValue, format, address, sheetName2),
644
696
  cellData?.formula ?? null,
645
697
  format,
646
698
  comment,
@@ -721,8 +773,8 @@ var Normalizer = class {
721
773
  return null;
722
774
  }
723
775
  }
724
- buildCell(address, value, columnFormat) {
725
- if (isPlainObject(value)) {
776
+ buildCell(address, value, columnFormat, sheetName2) {
777
+ if (isCellSpec(value)) {
726
778
  const cellFormat = isPlainObject(value.format) ? CellFormat.fromInput(value.format) : null;
727
779
  const merged = columnFormat ? columnFormat.mergeWith(cellFormat) : cellFormat;
728
780
  const comment = isPlainObject(value.comment) ? new CellComment(
@@ -733,7 +785,7 @@ var Normalizer = class {
733
785
  const rawValue = value.value ?? null;
734
786
  return new Cell(
735
787
  address,
736
- this.coerceValue(rawValue, merged),
788
+ this.coerceValue(rawValue, merged, address, sheetName2),
737
789
  value.formula ?? null,
738
790
  merged,
739
791
  comment,
@@ -743,12 +795,12 @@ var Normalizer = class {
743
795
  const [bare, formula] = promoteFormula(value);
744
796
  return new Cell(
745
797
  address,
746
- formula !== null ? null : this.coerceValue(bare, columnFormat),
798
+ formula !== null ? null : this.coerceValue(bare, columnFormat, address, sheetName2),
747
799
  formula,
748
800
  columnFormat
749
801
  );
750
802
  }
751
- coerceValue(value, format) {
803
+ coerceValue(value, format, address = "?", sheetName2) {
752
804
  if (value === null || value === void 0) return null;
753
805
  const df = format?.displayFormat;
754
806
  if (df === "date" || df === "datetime") {
@@ -762,12 +814,36 @@ var Normalizer = class {
762
814
  if (value instanceof Date) {
763
815
  return DateConverter.toSerial(value, true);
764
816
  }
765
- if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
817
+ if (typeof value === "bigint") {
818
+ return String(value);
819
+ }
820
+ if (typeof value === "object" && !Array.isArray(value) && hasOwnToString(value)) {
766
821
  return String(value);
767
822
  }
823
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
824
+ const where = sheetName2 === void 0 ? address : `${sheetName2}!${address}`;
825
+ const got = typeOf(value);
826
+ throw SchemaException.fromErrors([
827
+ {
828
+ path: where,
829
+ expected: "a string, number, bool, null, Date, or an object with its own toString",
830
+ got,
831
+ value,
832
+ hint: Array.isArray(value) ? 'This cell holds an array. The usual cause is a `rows` entry nested one level too deep: `rows: [[["x"]]]` makes cell A1 an array, where `rows: [["x"]]` makes it the string "x". For a cell with formatting use the object form: {value: "x", format: {...}}.' : "Give the cell a scalar or a Date, or define toString() on the object so the conversion is yours rather than implicit."
833
+ }
834
+ ]);
835
+ }
768
836
  return value;
769
837
  }
770
838
  };
839
+ function isCellSpec(value) {
840
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
841
+ return Object.getPrototypeOf(value) === Object.prototype;
842
+ }
843
+ function hasOwnToString(value) {
844
+ const fn = value.toString;
845
+ return typeof fn === "function" && fn !== Object.prototype.toString;
846
+ }
771
847
  function promoteFormula(value) {
772
848
  if (typeof value === "string" && value.length > 1 && value[0] === "=") {
773
849
  return [null, value.slice(1)];
@@ -1299,54 +1375,6 @@ function phpRound(x, n) {
1299
1375
  return Math.sign(x) * Math.round(Math.abs(x) * factor) / factor;
1300
1376
  }
1301
1377
 
1302
- // src/exceptions.ts
1303
- var SchemaException = class _SchemaException extends Error {
1304
- constructor(errors, message) {
1305
- super(message ?? summarize(errors));
1306
- this.name = "SchemaException";
1307
- this.errors = errors;
1308
- Object.setPrototypeOf(this, _SchemaException.prototype);
1309
- }
1310
- static fromErrors(errors) {
1311
- return new _SchemaException(errors);
1312
- }
1313
- getErrors() {
1314
- return this.errors;
1315
- }
1316
- };
1317
- function summarize(errors) {
1318
- if (errors.length === 1) {
1319
- const e = errors[0];
1320
- return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
1321
- }
1322
- const first2 = errors[0];
1323
- const rest = errors.length - 1;
1324
- return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
1325
- }
1326
- var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
1327
- constructor(message, path = null, mimetype = null) {
1328
- super(message);
1329
- this.name = "UnsupportedFormatException";
1330
- this.path = path;
1331
- this.mimetype = mimetype;
1332
- Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
1333
- }
1334
- static notAZip(path = null) {
1335
- return new _UnsupportedFormatException(
1336
- `[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
1337
- path
1338
- );
1339
- }
1340
- static unknownPackage(path, mimetype) {
1341
- const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
1342
- return new _UnsupportedFormatException(
1343
- `[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
1344
- path,
1345
- mimetype !== "" ? mimetype : null
1346
- );
1347
- }
1348
- };
1349
-
1350
1378
  // src/schema/repairer.ts
1351
1379
  var VALID_THEMES = ["default", "minimal", "plain", "business"];
1352
1380
  var ISO_DATE2 = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?$/;
@@ -1593,7 +1621,21 @@ var Validator = class {
1593
1621
  "Each row is an array of cell values, in column order."
1594
1622
  )
1595
1623
  );
1624
+ return;
1596
1625
  }
1626
+ row.forEach((cell, k) => {
1627
+ if (Array.isArray(cell)) {
1628
+ errors.push(
1629
+ error(
1630
+ `${path}.rows[${j}][${k}]`,
1631
+ "a cell value or a cell object",
1632
+ "array",
1633
+ cell,
1634
+ 'This cell is an array, which usually means the row is nested one level too deep: `rows: [[["x"]]]` makes cell A1 an array, where `rows: [["x"]]` makes it "x". For a cell with formatting use the object form: {value: "x", format: {...}}.'
1635
+ )
1636
+ );
1637
+ }
1638
+ });
1597
1639
  });
1598
1640
  }
1599
1641
  }
@@ -5177,7 +5219,7 @@ var holy_sheet_schema_default = {
5177
5219
  };
5178
5220
 
5179
5221
  // src/agent.ts
5180
- var VERSION = "2.5.0";
5222
+ var VERSION = "2.6.0";
5181
5223
  function toU8(input) {
5182
5224
  return input instanceof Uint8Array ? input : new Uint8Array(input);
5183
5225
  }