@orkestrel/table 0.0.11 → 0.0.13

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.
@@ -1,7 +1,7 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  let _orkestrel_contract = require("@orkestrel/contract");
3
3
  let _orkestrel_emitter = require("@orkestrel/emitter");
4
- //#region src/core/constants.ts
4
+ // src/core/constants.ts
5
5
  /** Lists every column cell, in the order declared by the public contract. */
6
6
  var COLUMN_CELLS = Object.freeze([
7
7
  "text",
@@ -23,8 +23,7 @@ var STRING_LIMIT = 65536;
23
23
  var TEXT_LIMIT = 1048576;
24
24
  /** Names the maximum total number of records, arrays, and leaves one schema retains: 16384. */
25
25
  var NODE_LIMIT = 16384;
26
- //#endregion
27
- //#region src/core/errors.ts
26
+ // src/core/errors.ts
28
27
  /**
29
28
  * Represents an error raised by the table domain — a machine-readable `code` and optional
30
29
  * structured `context`.
@@ -43,6 +42,7 @@ var TableError = class extends Error {
43
42
  */
44
43
  constructor(code, message, context) {
45
44
  super(message);
45
+ _orkestrel_contract.INTRINSICS.define(this, Symbol.for("@orkestrel/table.TableError"), { value: this });
46
46
  this.name = "TableError";
47
47
  this.code = code;
48
48
  if (context !== void 0) this.context = context;
@@ -52,14 +52,45 @@ var TableError = class extends Error {
52
52
  * Determines whether a caught value is a table error, so a `catch` branches on `code` without an
53
53
  * assertion.
54
54
  *
55
+ * @remarks
56
+ * Recognizes self-branded errors across copies and subclasses and refuses transparent proxies.
57
+ * Validates the declared code and optional JSON context.
58
+ *
55
59
  * @param input - The value to inspect.
56
60
  * @returns True if the value is a {@link TableError} instance; false otherwise.
57
61
  */
58
62
  function isTableError(input) {
59
- return (0, _orkestrel_contract.isInstance)(input, TableError);
63
+ return (0, _orkestrel_contract.holds)(() => {
64
+ if (!(input instanceof Error) || _orkestrel_contract.INTRINSICS.prototype(input) === Error.prototype) return false;
65
+ if (_orkestrel_contract.INTRINSICS.describe(input, Symbol.for("@orkestrel/table.TableError"))?.value !== input) return false;
66
+ const code = _orkestrel_contract.INTRINSICS.reflect.read(input, "code");
67
+ const context = _orkestrel_contract.INTRINSICS.reflect.read(input, "context");
68
+ if (code !== "SCHEMA" && code !== "COLUMN" && code !== "KEY" && code !== "CELL" && code !== "DESTROYED") return false;
69
+ if (context === void 0) return true;
70
+ if (!(0, _orkestrel_contract.isRecord)(context)) return false;
71
+ const pending = [{
72
+ value: context,
73
+ ancestors: []
74
+ }];
75
+ for (const { value, ancestors } of pending) {
76
+ if (value === null || [
77
+ "string",
78
+ "number",
79
+ "boolean"
80
+ ].includes(typeof value)) continue;
81
+ if (!Array.isArray(value) && !(0, _orkestrel_contract.isRecord)(value)) return false;
82
+ if (ancestors.length >= _orkestrel_contract.GUARD_DEPTH_LIMIT || ancestors.includes(value)) return false;
83
+ const path = [...ancestors, value];
84
+ const children = Array.isArray(value) ? Array.from({ length: value.length }, (_, index) => value[index]) : Object.values(value);
85
+ for (const child of children) pending.push({
86
+ value: child,
87
+ ancestors: path
88
+ });
89
+ }
90
+ return true;
91
+ });
60
92
  }
61
- //#endregion
62
- //#region src/core/helpers.ts
93
+ // src/core/helpers.ts
63
94
  /**
64
95
  * Finds one column by key; `undefined` when the schema declares no such column.
65
96
  *
@@ -282,88 +313,102 @@ function sortRows(schema, rows, orders, comparators) {
282
313
  */
283
314
  function auditTable(schema) {
284
315
  const faults = [];
285
- const columns = /* @__PURE__ */ new Set();
286
- let choiceExceeded;
287
- let nameExceeded = schema.name !== void 0 && schema.name.length > 128;
316
+ const columns = [];
317
+ const longName = schema.name !== void 0 && schema.name.length > 128;
288
318
  if (schema.columns.length > 256) faults.push(`schema declares more than 256 columns`);
289
319
  const columnCount = Math.min(schema.columns.length, 257);
290
- for (let index = 0; index < columnCount; index += 1) {
320
+ const indices = Array.from({ length: columnCount }, (_, index) => index);
321
+ const [choiceExceeded, nameExceeded] = indices.reduce(([choice, name], index) => {
291
322
  const column = schema.columns[index];
292
- if (column === void 0) continue;
293
- if (column.key.length > 128) nameExceeded = true;
294
- if (choiceExceeded === void 0 && column.cell === "choice" && column.choices.length > 1024) choiceExceeded = column.key;
295
- }
323
+ if (column === void 0) return [choice, name];
324
+ const exceeded = column.key.length > 128;
325
+ return [choice === void 0 && column.cell === "choice" && column.choices.length > 1024 ? column.key : choice, name || exceeded];
326
+ }, [void 0, longName]);
296
327
  if (choiceExceeded !== void 0) faults.push(`column "${choiceExceeded}" offers more than ${CHOICE_LIMIT} choices`);
297
328
  if (nameExceeded) faults.push(`schema contains a name longer than 128`);
298
329
  const pending = [schema];
299
330
  const metadata = [false];
300
- let position = 0;
301
- let stringExceeded = false;
302
- let textExceeded = false;
303
- let nodeExceeded = false;
304
- let text = 0;
305
- while (position < pending.length) {
306
- const node = pending[position];
331
+ const measurements = [];
332
+ for (const [position, node] of pending.entries()) {
307
333
  const inMeta = metadata[position] === true;
308
- position += 1;
309
334
  if ((0, _orkestrel_contract.isString)(node)) {
310
- if (node.length > 65536) stringExceeded = true;
311
- text = Math.min(TEXT_LIMIT + 1, text + node.length);
312
- if (text > 1048576) textExceeded = true;
335
+ measurements.push([
336
+ node.length,
337
+ node.length > STRING_LIMIT,
338
+ false
339
+ ]);
313
340
  continue;
314
341
  }
315
342
  if ((0, _orkestrel_contract.isArray)(node)) {
316
343
  const read = (0, _orkestrel_contract.readArrayEntries)(node);
317
344
  if (!read.success || !read.value.dense) continue;
318
- for (const entry of read.value.entries) {
319
- if (pending.length >= 16384) {
320
- nodeExceeded = true;
321
- continue;
322
- }
345
+ const exceeded = read.value.entries.reduce((refused, entry) => {
346
+ if (pending.length >= 16384) return true;
323
347
  pending.push(entry);
324
348
  metadata.push(inMeta);
325
- }
349
+ return refused;
350
+ }, false);
351
+ measurements.push([
352
+ 0,
353
+ false,
354
+ exceeded
355
+ ]);
326
356
  continue;
327
357
  }
328
358
  if (!(0, _orkestrel_contract.isRecord)(node)) continue;
329
359
  const keys = (0, _orkestrel_contract.attempt)(() => Object.keys(node));
330
360
  if (!keys.success) continue;
331
- for (const key of keys.value) {
332
- if (inMeta) {
333
- if (key.length > 65536) stringExceeded = true;
334
- text = Math.min(TEXT_LIMIT + 1, text + key.length);
335
- if (text > 1048576) textExceeded = true;
336
- }
361
+ const measured = keys.value.reduce(([text, string, refused], key) => {
362
+ const length = text + (inMeta ? key.length : 0);
363
+ const oversized = string || inMeta && key.length > 65536;
337
364
  const value = (0, _orkestrel_contract.attempt)(() => node[key]);
338
- if (!value.success || value.value === void 0) continue;
339
- if (pending.length >= 16384) {
340
- nodeExceeded = true;
341
- continue;
342
- }
365
+ if (!value.success || value.value === void 0) return [
366
+ length,
367
+ oversized,
368
+ refused
369
+ ];
370
+ if (pending.length >= 16384) return [
371
+ length,
372
+ oversized,
373
+ true
374
+ ];
343
375
  pending.push(value.value);
344
376
  metadata.push(inMeta || key === "meta");
345
- }
346
- }
377
+ return [
378
+ length,
379
+ oversized,
380
+ refused
381
+ ];
382
+ }, [
383
+ 0,
384
+ false,
385
+ false
386
+ ]);
387
+ measurements.push(measured);
388
+ }
389
+ const stringExceeded = measurements.some((entry) => entry[1]);
390
+ const textExceeded = measurements.reduce((total, entry) => total + entry[0], 0) > TEXT_LIMIT;
391
+ const nodeExceeded = measurements.some((entry) => entry[2]);
347
392
  if (stringExceeded) faults.push(`schema contains a string longer than ${STRING_LIMIT}`);
348
393
  if (textExceeded) faults.push(`schema retains more than ${TEXT_LIMIT} string code units`);
349
394
  if (nodeExceeded) faults.push(`schema retains more than ${NODE_LIMIT} nodes`);
350
- for (let index = 0; index < columnCount; index += 1) {
395
+ for (const index of indices) {
351
396
  const column = schema.columns[index];
352
397
  if (column === void 0) continue;
353
398
  if (!nodeExceeded && column.meta !== void 0) {
354
399
  if (!(0, _orkestrel_contract.attempt)(() => (0, _orkestrel_contract.cloneJSONRecord)(column.meta)).success) faults.push(`column "${column.key}" has metadata that cannot be owned`);
355
400
  }
356
401
  if (column.key.length === 0) faults.push("column \"\" has an empty key");
357
- if (columns.has(column.key)) faults.push(`column "${column.key}" is declared more than once`);
358
- columns.add(column.key);
402
+ if (columns.includes(column.key)) faults.push(`column "${column.key}" is declared more than once`);
403
+ columns.push(column.key);
359
404
  if (column.cell === "choice") {
360
- const choices = /* @__PURE__ */ new Set();
405
+ const choices = [];
361
406
  const choiceCount = Math.min(column.choices.length, CHOICE_LIMIT + 1);
362
- for (let choiceIndex = 0; choiceIndex < choiceCount; choiceIndex += 1) {
407
+ for (const choiceIndex of Array.from({ length: choiceCount }, (_, position) => position)) {
363
408
  const choice = column.choices[choiceIndex];
364
409
  if (choice === void 0) continue;
365
- if (choices.has(choice.value)) faults.push(`column "${column.key}" offers choice "${choice.value}" more than once`);
366
- choices.add(choice.value);
410
+ if (choices.includes(choice.value)) faults.push(`column "${column.key}" offers choice "${choice.value}" more than once`);
411
+ choices.push(choice.value);
367
412
  }
368
413
  if (column.choices.length === 0) faults.push(`column "${column.key}" offers no choices`);
369
414
  }
@@ -448,8 +493,7 @@ function serializeRows(schema, rows) {
448
493
  function matchesTableRow(left, right) {
449
494
  return left !== void 0 && Object.keys(left).length === Object.keys(right).length && Object.keys(right).every((key) => Object.hasOwn(left, key) && left[key] === right[key]);
450
495
  }
451
- //#endregion
452
- //#region src/core/validators.ts
496
+ // src/core/validators.ts
453
497
  /**
454
498
  * Determines whether an unknown value has a table cell shape — a string, a finite number, or a
455
499
  * boolean.
@@ -580,8 +624,7 @@ function isTableSchema(input) {
580
624
  const outcome = (0, _orkestrel_contract.attempt)(() => isStructuralTableSchema(input) && auditTable(input).length === 0);
581
625
  return outcome.success && outcome.value;
582
626
  }
583
- //#endregion
584
- //#region src/core/cloners.ts
627
+ // src/core/cloners.ts
585
628
  /**
586
629
  * Clones one row into an owned frozen snapshot.
587
630
  *
@@ -602,13 +645,12 @@ function cloneSchema(schema) {
602
645
  return Object.freeze({
603
646
  ...schema,
604
647
  columns: Object.freeze(schema.columns.map((column) => {
605
- let meta = {};
606
- if (column.meta !== void 0) try {
607
- meta = { meta: (0, _orkestrel_contract.cloneJSONRecord)(column.meta) };
608
- } catch (error) {
609
- if (!(0, _orkestrel_contract.isContractError)(error)) throw error;
648
+ const owned = column.meta === void 0 ? void 0 : (0, _orkestrel_contract.attempt)(() => (0, _orkestrel_contract.cloneJSONRecord)(column.meta));
649
+ if (owned !== void 0 && !owned.success) {
650
+ if (!(0, _orkestrel_contract.isContractError)(owned.error)) throw owned.error;
610
651
  throw new TableError("SCHEMA", `column "${column.key}" has metadata that cannot be owned`, { column: column.key });
611
652
  }
653
+ const meta = owned === void 0 ? {} : { meta: owned.value };
612
654
  if (column.cell === "choice") return Object.freeze({
613
655
  ...column,
614
656
  ...meta,
@@ -621,8 +663,7 @@ function cloneSchema(schema) {
621
663
  }))
622
664
  });
623
665
  }
624
- //#endregion
625
- //#region src/core/parsers.ts
666
+ // src/core/parsers.ts
626
667
  /**
627
668
  * Parses unknown wire data into an owned, structurally valid, semantically sound table schema.
628
669
  *
@@ -660,12 +701,8 @@ function parseRows(schema, input) {
660
701
  const column = extractColumn(schema, key);
661
702
  if (column === void 0) return void 0;
662
703
  const inputCell = candidate[key];
663
- let cell = inputCell;
664
- if (column.cell === "number" && (0, _orkestrel_contract.isString)(inputCell)) {
665
- if (inputCell.length > 65536) return void 0;
666
- cell = (0, _orkestrel_contract.parseNumber)(inputCell);
667
- } else if (column.cell === "flag" && inputCell === "true") cell = true;
668
- else if (column.cell === "flag" && inputCell === "false") cell = false;
704
+ if (column.cell === "number" && (0, _orkestrel_contract.isString)(inputCell) && inputCell.length > 65536) return void 0;
705
+ const cell = column.cell === "number" && (0, _orkestrel_contract.isString)(inputCell) ? (0, _orkestrel_contract.parseNumber)(inputCell) : column.cell === "flag" && inputCell === "true" ? true : column.cell === "flag" && inputCell === "false" ? false : inputCell;
669
706
  if (!matchesCell(column, cell)) return void 0;
670
707
  Object.defineProperty(row, key, {
671
708
  value: cell,
@@ -684,8 +721,7 @@ function parseRows(schema, input) {
684
721
  });
685
722
  return outcome.success ? outcome.value : void 0;
686
723
  }
687
- //#endregion
688
- //#region src/core/tables/KeyManager.ts
724
+ // src/core/tables/KeyManager.ts
689
725
  /** Manages the key set one table axis holds, and the event it announces when that set moves. */
690
726
  var KeyManager = class {
691
727
  #emitter;
@@ -712,7 +748,7 @@ var KeyManager = class {
712
748
  this.#read = read;
713
749
  this.#write = write;
714
750
  }
715
- /** Returns the keys held right now. */
751
+ /** Returns the keys held. */
716
752
  get keys() {
717
753
  return new Set(this.#read());
718
754
  }
@@ -736,8 +772,7 @@ var KeyManager = class {
736
772
  return input === void 0 ? void 0 : true;
737
773
  }
738
774
  };
739
- //#endregion
740
- //#region src/core/tables/ExpansionManager.ts
775
+ // src/core/tables/ExpansionManager.ts
741
776
  /** Manages the keys of the rows somebody has opened. */
742
777
  var ExpansionManager = class {
743
778
  #keys;
@@ -753,7 +788,7 @@ var ExpansionManager = class {
753
788
  constructor(emitter, gate, rows, read, write) {
754
789
  this.#keys = new KeyManager(emitter, "expand", gate, rows, read, write);
755
790
  }
756
- /** Returns the keys of the rows opened right now. */
791
+ /** Returns the keys of the rows opened. */
757
792
  get keys() {
758
793
  return this.#keys.keys;
759
794
  }
@@ -770,8 +805,7 @@ var ExpansionManager = class {
770
805
  return this.#keys.change(input, (included) => !included) === true;
771
806
  }
772
807
  };
773
- //#endregion
774
- //#region src/core/tables/FilterManager.ts
808
+ // src/core/tables/FilterManager.ts
775
809
  /** Manages the filters one table applies with and-only composition. */
776
810
  var FilterManager = class {
777
811
  #schema;
@@ -845,8 +879,7 @@ var FilterManager = class {
845
879
  return left.operator === "equals" && right.operator === "equals" && left.value === right.value;
846
880
  }
847
881
  };
848
- //#endregion
849
- //#region src/core/tables/PaginationManager.ts
882
+ // src/core/tables/PaginationManager.ts
850
883
  /** Manages the page arithmetic over one table's filtered rows. */
851
884
  var PaginationManager = class {
852
885
  #emitter;
@@ -920,8 +953,7 @@ var PaginationManager = class {
920
953
  return (0, _orkestrel_contract.isFiniteNumber)(value) ? Math.max(1, Math.trunc(value)) : 1;
921
954
  }
922
955
  };
923
- //#endregion
924
- //#region src/core/tables/RowManager.ts
956
+ // src/core/tables/RowManager.ts
925
957
  /** Manages the rows one table holds in its own order. */
926
958
  var RowManager = class {
927
959
  #schema;
@@ -995,8 +1027,7 @@ var RowManager = class {
995
1027
  }
996
1028
  const next = [...current];
997
1029
  const moved = [];
998
- for (let index = 0; index < updates.length; index += 1) {
999
- const update = updates[index];
1030
+ for (const [index, update] of updates.entries()) {
1000
1031
  const location = locations[index];
1001
1032
  if (update === void 0 || location === void 0) continue;
1002
1033
  const previous = next[location];
@@ -1122,8 +1153,7 @@ var RowManager = class {
1122
1153
  throw new TableError("KEY", message, { key });
1123
1154
  }
1124
1155
  };
1125
- //#endregion
1126
- //#region src/core/tables/SelectionManager.ts
1156
+ // src/core/tables/SelectionManager.ts
1127
1157
  /** Manages the keys of the rows somebody has picked. */
1128
1158
  var SelectionManager = class {
1129
1159
  #keys;
@@ -1139,7 +1169,7 @@ var SelectionManager = class {
1139
1169
  constructor(emitter, gate, rows, read, write) {
1140
1170
  this.#keys = new KeyManager(emitter, "select", gate, rows, read, write);
1141
1171
  }
1142
- /** Returns the keys of the rows picked right now. */
1172
+ /** Returns the keys of the rows picked. */
1143
1173
  get keys() {
1144
1174
  return this.#keys.keys;
1145
1175
  }
@@ -1156,8 +1186,7 @@ var SelectionManager = class {
1156
1186
  return this.#keys.change(input, (included) => !included) === true;
1157
1187
  }
1158
1188
  };
1159
- //#endregion
1160
- //#region src/core/tables/SortManager.ts
1189
+ // src/core/tables/SortManager.ts
1161
1190
  /** Manages the ordered sort terms of one table. */
1162
1191
  var SortManager = class {
1163
1192
  #schema;
@@ -1216,8 +1245,7 @@ var SortManager = class {
1216
1245
  if (extractColumn(this.#schema, column) === void 0) throw new TableError("COLUMN", `The schema declares no column named "${column}"`, { column });
1217
1246
  }
1218
1247
  };
1219
- //#endregion
1220
- //#region src/core/Table.ts
1248
+ // src/core/Table.ts
1221
1249
  /**
1222
1250
  * Holds a schema, its rows, and the lens through which they are read, implementing
1223
1251
  * {@link TableInterface} exactly.
@@ -1386,8 +1414,7 @@ var Table = class {
1386
1414
  if (this.#destroyed) throw new TableError("DESTROYED", "The table was destroyed and cannot change");
1387
1415
  }
1388
1416
  };
1389
- //#endregion
1390
- //#region src/core/factories.ts
1417
+ // src/core/factories.ts
1391
1418
  /**
1392
1419
  * Opens a table against a schema. The schema is copied, and the copy is what the table declares.
1393
1420
  *
@@ -1431,7 +1458,6 @@ var Table = class {
1431
1458
  function createTable(schema, options) {
1432
1459
  return new Table(schema, options);
1433
1460
  }
1434
- //#endregion
1435
1461
  exports.CHOICE_LIMIT = CHOICE_LIMIT;
1436
1462
  exports.COLUMN_CELLS = COLUMN_CELLS;
1437
1463
  exports.COLUMN_LIMIT = COLUMN_LIMIT;