@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.cjs CHANGED
@@ -495,6 +495,54 @@ var DateConverter = {
495
495
  }
496
496
  };
497
497
 
498
+ // src/exceptions.ts
499
+ var SchemaException = class _SchemaException extends Error {
500
+ constructor(errors, message) {
501
+ super(message ?? summarize(errors));
502
+ this.name = "SchemaException";
503
+ this.errors = errors;
504
+ Object.setPrototypeOf(this, _SchemaException.prototype);
505
+ }
506
+ static fromErrors(errors) {
507
+ return new _SchemaException(errors);
508
+ }
509
+ getErrors() {
510
+ return this.errors;
511
+ }
512
+ };
513
+ function summarize(errors) {
514
+ if (errors.length === 1) {
515
+ const e = errors[0];
516
+ return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
517
+ }
518
+ const first2 = errors[0];
519
+ const rest = errors.length - 1;
520
+ return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
521
+ }
522
+ var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
523
+ constructor(message, path = null, mimetype = null) {
524
+ super(message);
525
+ this.name = "UnsupportedFormatException";
526
+ this.path = path;
527
+ this.mimetype = mimetype;
528
+ Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
529
+ }
530
+ static notAZip(path = null) {
531
+ return new _UnsupportedFormatException(
532
+ `[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
533
+ path
534
+ );
535
+ }
536
+ static unknownPackage(path, mimetype) {
537
+ const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
538
+ return new _UnsupportedFormatException(
539
+ `[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
540
+ path,
541
+ mimetype !== "" ? mimetype : null
542
+ );
543
+ }
544
+ };
545
+
498
546
  // src/schema/theme.ts
499
547
  var Theme = class {
500
548
  constructor(key) {
@@ -572,7 +620,7 @@ var Normalizer = class {
572
620
  const columnFormat = columnFormats.get(c) ?? null;
573
621
  const rowBand = theme.dataFormat(r);
574
622
  const merged = rowBand !== null ? columnFormat ? columnFormat.mergeWith(rowBand) : rowBand : columnFormat;
575
- cells.set(address, this.buildCell(address, value, merged));
623
+ cells.set(address, this.buildCell(address, value, merged, name));
576
624
  });
577
625
  });
578
626
  if (sheet.totals && isPlainObject(sheet.totals) && Object.keys(sheet.totals).length > 0 && rows.length > 0 && columns.length > 0) {
@@ -596,7 +644,7 @@ var Normalizer = class {
596
644
  }
597
645
  }
598
646
  if (sheet.cells != null) {
599
- for (const [address, cell] of this.normalizeCellMap(sheet.cells)) {
647
+ for (const [address, cell] of this.normalizeCellMap(sheet.cells, name)) {
600
648
  const beneath = cells.get(address);
601
649
  cells.set(
602
650
  address,
@@ -620,14 +668,18 @@ var Normalizer = class {
620
668
  toInt(sheet.frozenCols ?? 0)
621
669
  );
622
670
  }
623
- normalizeCellMap(map) {
671
+ normalizeCellMap(map, sheetName2) {
624
672
  const cells = /* @__PURE__ */ new Map();
625
673
  for (const [address, cellData] of Object.entries(map)) {
626
- if (!isPlainObject(cellData)) {
674
+ if (!isCellSpec(cellData)) {
627
675
  const [bare, formula] = promoteFormula(cellData);
628
676
  cells.set(
629
677
  address,
630
- new Cell(address, formula !== null ? null : this.coerceValue(bare, null), formula)
678
+ new Cell(
679
+ address,
680
+ formula !== null ? null : this.coerceValue(bare, null, address, sheetName2),
681
+ formula
682
+ )
631
683
  );
632
684
  continue;
633
685
  }
@@ -642,7 +694,7 @@ var Normalizer = class {
642
694
  address,
643
695
  new Cell(
644
696
  address,
645
- this.coerceValue(rawValue, format),
697
+ this.coerceValue(rawValue, format, address, sheetName2),
646
698
  cellData?.formula ?? null,
647
699
  format,
648
700
  comment,
@@ -723,8 +775,8 @@ var Normalizer = class {
723
775
  return null;
724
776
  }
725
777
  }
726
- buildCell(address, value, columnFormat) {
727
- if (isPlainObject(value)) {
778
+ buildCell(address, value, columnFormat, sheetName2) {
779
+ if (isCellSpec(value)) {
728
780
  const cellFormat = isPlainObject(value.format) ? CellFormat.fromInput(value.format) : null;
729
781
  const merged = columnFormat ? columnFormat.mergeWith(cellFormat) : cellFormat;
730
782
  const comment = isPlainObject(value.comment) ? new CellComment(
@@ -735,7 +787,7 @@ var Normalizer = class {
735
787
  const rawValue = value.value ?? null;
736
788
  return new Cell(
737
789
  address,
738
- this.coerceValue(rawValue, merged),
790
+ this.coerceValue(rawValue, merged, address, sheetName2),
739
791
  value.formula ?? null,
740
792
  merged,
741
793
  comment,
@@ -745,12 +797,12 @@ var Normalizer = class {
745
797
  const [bare, formula] = promoteFormula(value);
746
798
  return new Cell(
747
799
  address,
748
- formula !== null ? null : this.coerceValue(bare, columnFormat),
800
+ formula !== null ? null : this.coerceValue(bare, columnFormat, address, sheetName2),
749
801
  formula,
750
802
  columnFormat
751
803
  );
752
804
  }
753
- coerceValue(value, format) {
805
+ coerceValue(value, format, address = "?", sheetName2) {
754
806
  if (value === null || value === void 0) return null;
755
807
  const df = format?.displayFormat;
756
808
  if (df === "date" || df === "datetime") {
@@ -764,12 +816,36 @@ var Normalizer = class {
764
816
  if (value instanceof Date) {
765
817
  return DateConverter.toSerial(value, true);
766
818
  }
767
- if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
819
+ if (typeof value === "bigint") {
820
+ return String(value);
821
+ }
822
+ if (typeof value === "object" && !Array.isArray(value) && hasOwnToString(value)) {
768
823
  return String(value);
769
824
  }
825
+ if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
826
+ const where = sheetName2 === void 0 ? address : `${sheetName2}!${address}`;
827
+ const got = typeOf(value);
828
+ throw SchemaException.fromErrors([
829
+ {
830
+ path: where,
831
+ expected: "a string, number, bool, null, Date, or an object with its own toString",
832
+ got,
833
+ value,
834
+ 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."
835
+ }
836
+ ]);
837
+ }
770
838
  return value;
771
839
  }
772
840
  };
841
+ function isCellSpec(value) {
842
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
843
+ return Object.getPrototypeOf(value) === Object.prototype;
844
+ }
845
+ function hasOwnToString(value) {
846
+ const fn = value.toString;
847
+ return typeof fn === "function" && fn !== Object.prototype.toString;
848
+ }
773
849
  function promoteFormula(value) {
774
850
  if (typeof value === "string" && value.length > 1 && value[0] === "=") {
775
851
  return [null, value.slice(1)];
@@ -1301,54 +1377,6 @@ function phpRound(x, n) {
1301
1377
  return Math.sign(x) * Math.round(Math.abs(x) * factor) / factor;
1302
1378
  }
1303
1379
 
1304
- // src/exceptions.ts
1305
- var SchemaException = class _SchemaException extends Error {
1306
- constructor(errors, message) {
1307
- super(message ?? summarize(errors));
1308
- this.name = "SchemaException";
1309
- this.errors = errors;
1310
- Object.setPrototypeOf(this, _SchemaException.prototype);
1311
- }
1312
- static fromErrors(errors) {
1313
- return new _SchemaException(errors);
1314
- }
1315
- getErrors() {
1316
- return this.errors;
1317
- }
1318
- };
1319
- function summarize(errors) {
1320
- if (errors.length === 1) {
1321
- const e = errors[0];
1322
- return `[holy-sheet] schema invalid at ${e.path}: expected ${e.expected}, got ${e.got}`;
1323
- }
1324
- const first2 = errors[0];
1325
- const rest = errors.length - 1;
1326
- return `[holy-sheet] schema invalid at ${first2.path}: expected ${first2.expected}, got ${first2.got} (+${rest} more)`;
1327
- }
1328
- var UnsupportedFormatException = class _UnsupportedFormatException extends Error {
1329
- constructor(message, path = null, mimetype = null) {
1330
- super(message);
1331
- this.name = "UnsupportedFormatException";
1332
- this.path = path;
1333
- this.mimetype = mimetype;
1334
- Object.setPrototypeOf(this, _UnsupportedFormatException.prototype);
1335
- }
1336
- static notAZip(path = null) {
1337
- return new _UnsupportedFormatException(
1338
- `[holy-sheet] cannot read ${path ?? "this file"}: it is not a zip archive, and xlsx and ods both are`,
1339
- path
1340
- );
1341
- }
1342
- static unknownPackage(path, mimetype) {
1343
- const what = mimetype !== null && mimetype !== "" ? `its mimetype is ${mimetype}` : "it has neither xl/workbook.xml nor an OpenDocument mimetype";
1344
- return new _UnsupportedFormatException(
1345
- `[holy-sheet] cannot read ${path ?? "this file"}: ${what}. Supported: xlsx, ods`,
1346
- path,
1347
- mimetype !== "" ? mimetype : null
1348
- );
1349
- }
1350
- };
1351
-
1352
1380
  // src/schema/repairer.ts
1353
1381
  var VALID_THEMES = ["default", "minimal", "plain", "business"];
1354
1382
  var ISO_DATE2 = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}(:\d{2})?(\.\d+)?(Z|[+-]\d{2}:?\d{2})?)?$/;
@@ -1595,7 +1623,21 @@ var Validator = class {
1595
1623
  "Each row is an array of cell values, in column order."
1596
1624
  )
1597
1625
  );
1626
+ return;
1598
1627
  }
1628
+ row.forEach((cell, k) => {
1629
+ if (Array.isArray(cell)) {
1630
+ errors.push(
1631
+ error(
1632
+ `${path}.rows[${j}][${k}]`,
1633
+ "a cell value or a cell object",
1634
+ "array",
1635
+ cell,
1636
+ '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: {...}}.'
1637
+ )
1638
+ );
1639
+ }
1640
+ });
1599
1641
  });
1600
1642
  }
1601
1643
  }
@@ -5179,7 +5221,7 @@ var holy_sheet_schema_default = {
5179
5221
  };
5180
5222
 
5181
5223
  // src/agent.ts
5182
- var VERSION = "2.5.0";
5224
+ var VERSION = "2.6.0";
5183
5225
  function toU8(input) {
5184
5226
  return input instanceof Uint8Array ? input : new Uint8Array(input);
5185
5227
  }