@rljson/io 0.0.70 → 0.0.71

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.public.md CHANGED
@@ -78,6 +78,11 @@ The `Io` interface is the core abstraction that defines a standard set of operat
78
78
  - **Data Operations**: `write()`, `readRows()`, `dump()`
79
79
  - **Schema Management**: `createOrExtendTable()`, `tableExists()`, `rawTableCfgs()`
80
80
  - **Metadata**: `contentType()`, `rowCount()`, `lastUpdate()`
81
+ - **Optional Batch Reads**: `readRowsByHashes()` — answers many content
82
+ hash lookups in one request. Implementations may omit it; callers must
83
+ fall back to `readRows()` then. `IoMem`, `IoMulti` (per-hash cascade
84
+ across its members) and `IoPeer`/`IoServer` (one socket round trip,
85
+ with automatic per-hash fallback against older remotes) support it.
81
86
 
82
87
  All implementations (in-memory, remote, multi-source) conform to this interface.
83
88
 
@@ -78,6 +78,11 @@ The `Io` interface is the core abstraction that defines a standard set of operat
78
78
  - **Data Operations**: `write()`, `readRows()`, `dump()`
79
79
  - **Schema Management**: `createOrExtendTable()`, `tableExists()`, `rawTableCfgs()`
80
80
  - **Metadata**: `contentType()`, `rowCount()`, `lastUpdate()`
81
+ - **Optional Batch Reads**: `readRowsByHashes()` — answers many content
82
+ hash lookups in one request. Implementations may omit it; callers must
83
+ fall back to `readRows()` then. `IoMem`, `IoMulti` (per-hash cascade
84
+ across its members) and `IoPeer`/`IoServer` (one socket round trip,
85
+ with automatic per-hash fallback against older remotes) support it.
81
86
 
82
87
  All implementations (in-memory, remote, multi-source) conform to this interface.
83
88
 
package/dist/io-mem.d.ts CHANGED
@@ -23,6 +23,10 @@ export declare class IoMem implements Io {
23
23
  [column: string]: JsonValue;
24
24
  };
25
25
  }): Promise<Rljson>;
26
+ readRowsByHashes(request: {
27
+ table: string;
28
+ hashes: string[];
29
+ }): Promise<Rljson>;
26
30
  rowCount(table: string): Promise<number>;
27
31
  write(request: {
28
32
  data: Rljson;
@@ -112,6 +112,23 @@ export declare class IoMulti implements Io {
112
112
  * @returns A promise that resolves to the row count of the table.
113
113
  */
114
114
  rowCount(table: string): Promise<number>;
115
+ /**
116
+ * Batch read with PER-HASH cascade: every hash not found in a
117
+ * higher-priority readable is looked up in the next one. Readables
118
+ * without readRowsByHashes are queried per hash via readRows.
119
+ * @param request - The table and the row hashes to read
120
+ */
121
+ readRowsByHashes(request: {
122
+ table: string;
123
+ hashes: string[];
124
+ }): Promise<Rljson>;
125
+ /**
126
+ * Per-hash fallback for readables without readRowsByHashes.
127
+ * @param io - The readable io
128
+ * @param table - The table to read from
129
+ * @param hashes - The row hashes to read
130
+ */
131
+ private static _readHashesViaReadRows;
115
132
  /**
116
133
  * Gets the list of underlying readable Io instances, sorted by priority.
117
134
  */
package/dist/io-peer.d.ts CHANGED
@@ -88,6 +88,21 @@ export declare class IoPeer implements Io {
88
88
  [column: string]: JsonValue | null;
89
89
  };
90
90
  }): Promise<Rljson>;
91
+ /**
92
+ * True once the remote side signalled that it does not support batch
93
+ * reads — all further batch reads then use per-hash readRows.
94
+ */
95
+ private _batchReadsUnsupported;
96
+ /**
97
+ * Batch read over the socket. Falls back to per-hash readRows when
98
+ * the remote side does not support it (older server) and remembers
99
+ * the capability for subsequent calls.
100
+ * @param request - The table and the row hashes to read
101
+ */
102
+ readRowsByHashes(request: {
103
+ table: string;
104
+ hashes: string[];
105
+ }): Promise<Rljson>;
91
106
  /**
92
107
  * Retrieves the number of rows in a specific table.
93
108
  * @param table The name of the table to count rows in.
package/dist/io.d.ts CHANGED
@@ -50,6 +50,17 @@ export interface Io {
50
50
  [column: string]: JsonValue | null;
51
51
  };
52
52
  }): Promise<Rljson>;
53
+ /**
54
+ * Optional batch read: returns the rows matching the given content
55
+ * hashes in one request. Hashes without a matching row are simply
56
+ * absent from the result. Implementations answering many hash lookups
57
+ * in one round trip should provide this; callers MUST fall back to
58
+ * readRows when the method is not implemented.
59
+ */
60
+ readRowsByHashes?(request: {
61
+ table: string;
62
+ hashes: string[];
63
+ }): Promise<Rljson>;
53
64
  /** Returns the number of rows in the given table */
54
65
  rowCount(table: string): Promise<number>;
55
66
  }
package/dist/io.js CHANGED
@@ -411,6 +411,27 @@ class IoMem {
411
411
  readRows(request) {
412
412
  return this._readRows(request);
413
413
  }
414
+ async readRowsByHashes(request) {
415
+ await this._ioTools.throwWhenTableDoesNotExist(request.table);
416
+ const table = this._mem[request.table];
417
+ const rowIndex = this._rowIndexFor(request.table);
418
+ const seen = /* @__PURE__ */ new Set();
419
+ const rows = [];
420
+ for (const hash of request.hashes) {
421
+ if (seen.has(hash)) continue;
422
+ seen.add(hash);
423
+ const row = rowIndex.get(hash);
424
+ if (row) {
425
+ rows.push(row);
426
+ }
427
+ }
428
+ const tableFiltered = {
429
+ _type: table._type,
430
+ _data: rows
431
+ };
432
+ this._ioTools.sortTableDataAndUpdateHash(tableFiltered);
433
+ return { [request.table]: tableFiltered };
434
+ }
414
435
  async rowCount(table) {
415
436
  const tableData = this._mem[table];
416
437
  if (!tableData) {
@@ -1108,6 +1129,65 @@ class IoPeer {
1108
1129
  );
1109
1130
  }
1110
1131
  // ...........................................................................
1132
+ /**
1133
+ * True once the remote side signalled that it does not support batch
1134
+ * reads — all further batch reads then use per-hash readRows.
1135
+ */
1136
+ _batchReadsUnsupported = false;
1137
+ /**
1138
+ * Batch read over the socket. Falls back to per-hash readRows when
1139
+ * the remote side does not support it (older server) and remembers
1140
+ * the capability for subsequent calls.
1141
+ * @param request - The table and the row hashes to read
1142
+ */
1143
+ async readRowsByHashes(request) {
1144
+ if (!this._batchReadsUnsupported) {
1145
+ try {
1146
+ return await this._withTimeout(
1147
+ new Promise((resolve, reject) => {
1148
+ this._socket.emit(
1149
+ "readRowsByHashes",
1150
+ request,
1151
+ (result, error) => {
1152
+ if (error) reject(error);
1153
+ resolve(result);
1154
+ }
1155
+ );
1156
+ }),
1157
+ "readRowsByHashes"
1158
+ );
1159
+ } catch (error) {
1160
+ const message = String(error.message);
1161
+ const unsupported = message.includes("not found on Io instance") || message.includes("not supported") || message.includes("Timeout after");
1162
+ if (!unsupported) {
1163
+ throw error;
1164
+ }
1165
+ this._batchReadsUnsupported = true;
1166
+ }
1167
+ }
1168
+ const hashes = Array.from(new Set(request.hashes));
1169
+ const results = await Promise.all(
1170
+ hashes.map(
1171
+ (hash) => this.readRows({ table: request.table, where: { _hash: hash } })
1172
+ )
1173
+ );
1174
+ let type = void 0;
1175
+ const rows = [];
1176
+ for (const result of results) {
1177
+ const tableData = result[request.table];
1178
+ type ??= tableData._type;
1179
+ rows.push(...tableData._data);
1180
+ }
1181
+ if (type === void 0) {
1182
+ const empty = await this.readRows({
1183
+ table: request.table,
1184
+ where: { _hash: "__NONE__" }
1185
+ });
1186
+ type = empty[request.table]._type;
1187
+ }
1188
+ return { [request.table]: { _data: rows, _type: type } };
1189
+ }
1190
+ // ...........................................................................
1111
1191
  /**
1112
1192
  * Retrieves the number of rows in a specific table.
1113
1193
  * @param table The name of the table to count rows in.
@@ -1448,6 +1528,103 @@ class IoMulti {
1448
1528
  return Promise.resolve(tableData._data.length);
1449
1529
  }
1450
1530
  // ...........................................................................
1531
+ /**
1532
+ * Batch read with PER-HASH cascade: every hash not found in a
1533
+ * higher-priority readable is looked up in the next one. Readables
1534
+ * without readRowsByHashes are queried per hash via readRows.
1535
+ * @param request - The table and the row hashes to read
1536
+ */
1537
+ async readRowsByHashes(request) {
1538
+ if (this.readables.length === 0) {
1539
+ throw new Error("No readable Io available");
1540
+ }
1541
+ let tableExistsAny = false;
1542
+ const rows = /* @__PURE__ */ new Map();
1543
+ let type = void 0;
1544
+ let readFrom = "";
1545
+ const errors = [];
1546
+ let remaining = Array.from(new Set(request.hashes));
1547
+ for (const readable of this.readables) {
1548
+ if (remaining.length === 0) break;
1549
+ try {
1550
+ let result;
1551
+ if (readable.io.readRowsByHashes) {
1552
+ result = await readable.io.readRowsByHashes({
1553
+ table: request.table,
1554
+ hashes: remaining
1555
+ });
1556
+ } else {
1557
+ result = await IoMulti._readHashesViaReadRows(
1558
+ readable.io,
1559
+ request.table,
1560
+ remaining
1561
+ );
1562
+ }
1563
+ const tableData = result[request.table];
1564
+ tableExistsAny = true;
1565
+ type = tableData._type;
1566
+ if (tableData._data.length > 0) {
1567
+ readFrom = readable.id ?? "";
1568
+ for (const tableRow of tableData._data) {
1569
+ rows.set(tableRow._hash, tableRow);
1570
+ }
1571
+ remaining = remaining.filter((hash) => !rows.has(hash));
1572
+ }
1573
+ } catch (e) {
1574
+ errors.push(e);
1575
+ }
1576
+ }
1577
+ if (!tableExistsAny) {
1578
+ if (errors.length === 0) {
1579
+ throw new Error(`Table "${request.table}" not found`);
1580
+ } else {
1581
+ const preciseErrors = errors.filter(
1582
+ (err) => !err.message.includes(`Table "${request.table}" not found`)
1583
+ );
1584
+ if (preciseErrors.length > 0) {
1585
+ throw preciseErrors[0];
1586
+ } else {
1587
+ throw errors[0];
1588
+ }
1589
+ }
1590
+ }
1591
+ const rljson = {
1592
+ [request.table]: hip({ _data: Array.from(rows.values()), _type: type })
1593
+ };
1594
+ if (this.writables.length > 0 && rows.size > 0) {
1595
+ for (const writeable of this.writables) {
1596
+ if (writeable.id === readFrom) {
1597
+ continue;
1598
+ }
1599
+ try {
1600
+ await writeable.io.write({ data: rljson });
1601
+ } catch {
1602
+ continue;
1603
+ }
1604
+ }
1605
+ }
1606
+ return rljson;
1607
+ }
1608
+ /**
1609
+ * Per-hash fallback for readables without readRowsByHashes.
1610
+ * @param io - The readable io
1611
+ * @param table - The table to read from
1612
+ * @param hashes - The row hashes to read
1613
+ */
1614
+ static async _readHashesViaReadRows(io, table, hashes) {
1615
+ const results = await Promise.all(
1616
+ hashes.map((hash) => io.readRows({ table, where: { _hash: hash } }))
1617
+ );
1618
+ let type = void 0;
1619
+ const rows = [];
1620
+ for (const result of results) {
1621
+ const tableData = result[table];
1622
+ type ??= tableData._type;
1623
+ rows.push(...tableData._data);
1624
+ }
1625
+ return { [table]: { _data: rows, _type: type } };
1626
+ }
1627
+ // ...........................................................................
1451
1628
  /**
1452
1629
  * Gets the list of underlying readable Io instances, sorted by priority.
1453
1630
  */
@@ -1547,6 +1724,7 @@ class IoPeerBridge {
1547
1724
  "createOrExtendTable",
1548
1725
  "write",
1549
1726
  "readRows",
1727
+ "readRowsByHashes",
1550
1728
  "rowCount",
1551
1729
  "dumpTable",
1552
1730
  "dump",
@@ -1734,6 +1912,11 @@ class IoServer {
1734
1912
  rawTableCfgs: () => this._io.rawTableCfgs(),
1735
1913
  write: (request) => this._io.write(request),
1736
1914
  readRows: (request) => this._io.readRows(request),
1915
+ readRowsByHashes: (request) => this._io.readRowsByHashes ? this._io.readRowsByHashes(request) : Promise.reject(
1916
+ new Error(
1917
+ 'Method "readRowsByHashes" not found on Io instance'
1918
+ )
1919
+ ),
1737
1920
  rowCount: (table) => this._io.rowCount(table)
1738
1921
  });
1739
1922
  }
package/dist/io.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"io.js","sources":["/Users/maximilianheller/Documents/Development/rljson-io/src/io-db-name-mapping.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-tools.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-mem.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/peer-socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-peer.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-multi.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-peer-bridge.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-server.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-test-setup.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/reverse-ref.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/directional-socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/socket.ts"],"sourcesContent":["// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nexport class IoDbNameMapping {\n // The primary key column is always named '_hash'\n public primaryKeyColumn: string = '_hash';\n public dataSection: string = '_data';\n public typeColumn: string = 'type';\n public keyColumn: string = 'key';\n\n // Names for the main tables in the database\n public tableNames: { [key: string]: string } = {\n main: 'tableCfgs',\n revision: 'revisions',\n };\n\n /// Suffix handling for the database\n private _suffix: { [key: string]: string } = {\n col: '_col',\n tbl: '_tbl',\n tmp: '_tmp',\n };\n\n // ********************************************************************\n // add and remove suffixes for use in SQL statements\n private _addFix(name: string, fix: string): string {\n return name.endsWith(fix) ? name : name + fix;\n }\n\n public addTableSuffix(name: string): string {\n return this._addFix(name, this._suffix.tbl);\n }\n\n public addColumnSuffix(name: string): string {\n return this._addFix(name, this._suffix.col);\n }\n\n public addTmpSuffix(name: string): string {\n return this._addFix(name, this._suffix.tmp);\n }\n\n private _removeFix(name: string, fix: string): string {\n return name.endsWith(fix) ? name.slice(0, -fix.length) : name;\n }\n\n public removeTableSuffix(name: string): string {\n return this._removeFix(name, this._suffix.tbl);\n }\n\n public removeColumnSuffix(name: string): string {\n return this._removeFix(name, this._suffix.col);\n }\n\n public removeTmpSuffix(name: string): string {\n return this._removeFix(name, this._suffix.tmp);\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip } from '@rljson/hash';\nimport {\n iterateTables,\n Rljson,\n TableCfg,\n TableKey,\n TableType,\n throwOnInvalidTableCfg,\n validateRljsonAgainstTableCfg,\n} from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { Io } from './io.ts';\n\nexport type IoObserver = (data: Rljson) => void;\n\n/**\n * Provides utility functions for the Io interface.\n */\nexport class IoTools {\n /**\n * Constructor\n * @param io The Io interface to use\n */\n constructor(public readonly io: Io) {}\n\n /**\n * Returns the table configuration of the tableCfgs table.\n */\n static get tableCfgsTableCfg() {\n const tableCfg = hip<TableCfg>({\n _hash: '',\n key: 'tableCfgs',\n type: 'tableCfgs',\n isHead: false,\n isRoot: false,\n isShared: true,\n previous: '',\n\n columns: [\n {\n key: '_hash',\n type: 'string',\n titleShort: 'Hash',\n titleLong: 'Row Hash',\n },\n {\n key: 'key',\n type: 'string',\n titleShort: 'Key',\n titleLong: 'Table Key',\n },\n {\n key: 'type',\n type: 'string',\n titleShort: 'Type',\n titleLong: 'Content Type',\n },\n {\n key: 'isHead',\n type: 'boolean',\n titleShort: 'Is Head',\n titleLong: 'Is Head Table',\n },\n {\n key: 'isRoot',\n type: 'boolean',\n titleShort: 'Is Root',\n titleLong: 'Is Root Table',\n },\n {\n key: 'isShared',\n type: 'boolean',\n titleShort: 'Is Shared',\n titleLong: 'Is Shared Table',\n },\n {\n key: 'previous',\n type: 'string',\n titleShort: 'Previous',\n titleLong: 'Previous Table Configuration Hash',\n },\n {\n key: 'columns',\n type: 'jsonArray',\n titleShort: 'Columns',\n titleLong: 'Column Configurations',\n },\n ],\n });\n\n return tableCfg;\n }\n\n /**\n * Initializes the revisions table.\n */\n initRevisionsTable = async () => {\n const tableCfg: TableCfg = {\n key: 'revisions',\n type: 'revisions',\n isHead: true,\n isRoot: true,\n isShared: false,\n\n columns: [\n {\n key: '_hash',\n type: 'string',\n titleShort: 'Hash',\n titleLong: 'Row Hash',\n },\n {\n key: 'table',\n type: 'string',\n titleShort: 'Table',\n titleLong: 'Table Key',\n },\n {\n key: 'predecessor',\n type: 'string',\n titleShort: 'Predecessor',\n titleLong: 'Predecessor Revision Hash',\n },\n {\n key: 'successor',\n type: 'string',\n titleShort: 'Successor',\n titleLong: 'Successor Revision Hash',\n },\n {\n key: 'timestamp',\n type: 'number',\n titleShort: 'Timestamp',\n titleLong: 'Revision Timestamp',\n },\n {\n key: 'id',\n type: 'string',\n titleShort: 'ID',\n titleLong: 'Revision ID',\n },\n ],\n };\n\n await this.io.createOrExtendTable({ tableCfg });\n };\n\n /**\n * Example object for test purposes\n * @returns An instance of io tools\n */\n static example = async () => {\n const io = await IoMem.example();\n await io.init();\n await io.isReady();\n return new IoTools(io);\n };\n\n /**\n * Throws if the table does not exist\n */\n async throwWhenTableDoesNotExist(table: TableKey): Promise<void> {\n const exists = await this.io.tableExists(table);\n if (!exists) {\n throw new Error(`Table \"${table}\" not found`);\n }\n }\n\n /**\n * Throws if any of the tables in rljson do not exist\n * @param rljson - The Rljson object to check\n */\n async throwWhenTablesDoNotExist(rljson: Rljson): Promise<void> {\n try {\n await iterateTables(rljson, async (tableKey) => {\n const exists = await this.io.tableExists(tableKey);\n if (!exists) {\n throw new Error(`Table \"${tableKey}\" not found`);\n }\n });\n } catch (e) {\n const missingTables = (e as Array<any>).map((e) => e.tableKey);\n\n throw new Error(\n `The following tables do not exist: ${missingTables.join(', ')}`,\n );\n }\n }\n\n /**\n * Returns the current table cfgs of all tables\n * @returns The table configuration of all tables\n */\n async tableCfgs(): Promise<TableCfg[]> {\n const tables = await this.io.rawTableCfgs();\n\n // Take the latest version of each type key\n const newestVersion: Record<TableKey, TableCfg> = {};\n for (let i = tables.length - 1; i >= 0; i--) {\n const table = tables[i];\n const existing = newestVersion[table.key];\n if (!existing || existing.columns.length < table.columns.length) {\n newestVersion[table.key] = table;\n }\n }\n\n // Sort the tables by key\n /* v8 ignore next -- @preserve */\n const resultData = Object.values(newestVersion).sort((a, b) => {\n if (a.key < b.key) {\n return -1;\n }\n if (a.key > b.key) {\n return 1;\n }\n\n return 0;\n });\n return resultData;\n }\n\n /**\n * Returns a list with all table names\n */\n async allTableKeys(): Promise<string[]> {\n const result = (await this.tableCfgs()).map((e) => e.key);\n return result;\n }\n\n /**\n * Returns the configuration of a given table\n */\n async tableCfg(table: TableKey): Promise<TableCfg> {\n const tableCfg = await this.tableCfgOrNull(table);\n if (!tableCfg) {\n throw new Error(`Table \"${table}\" not found`);\n }\n\n return tableCfg!;\n }\n\n /**\n * Returns the configuration of a given table or null if it does not exist.\n\n */\n async tableCfgOrNull(table: TableKey): Promise<TableCfg | null> {\n const tableCfgs = await this.tableCfgs();\n const tableCfg = tableCfgs.find((e) => e.key === table);\n return tableCfg ?? null;\n }\n\n /**\n * Returns a list of all column names of a given table\n */\n async allColumnKeys(table: TableKey): Promise<string[]> {\n const tableCfg = await this.tableCfg(table);\n const result = tableCfg.columns.map((column) => column.key);\n return result;\n }\n\n /**\n * Throws when a column does not exist in a given table\n * @param table - The table to check\n * @param columns - The column to check\n */\n async throwWhenColumnDoesNotExist(\n table: TableKey,\n columns: string[],\n ): Promise<void> {\n const tableCfg = await this.tableCfg(table);\n const columnKeys = tableCfg.columns.map((column) => column.key);\n const missingColumns = columns.filter(\n (column) => !columnKeys.includes(column),\n );\n if (missingColumns.length > 0) {\n throw new Error(\n `The following columns do not exist in table \"${table}\": ${missingColumns.join(\n ', ',\n )}.`,\n );\n }\n }\n\n /**\n * Throws when a table update is not compatible with the current table\n * configuration.\n */\n async throwWhenTableIsNotCompatible(update: TableCfg): Promise<void> {\n const prefix = `Invalid update of table able \"${update.key}\"`;\n\n throwOnInvalidTableCfg(update);\n\n // Check compatibility with existing table\n const existing = await this.tableCfgOrNull(update.key);\n if (existing) {\n // Have columns been deleted?\n if (existing.columns.length > update.columns.length) {\n const deletedColumnKeys = existing.columns\n .map((column) => column.key)\n .filter(\n (key) => !update.columns.some((column) => column.key === key),\n );\n /* v8 ignore next -- @preserve */\n if (deletedColumnKeys.length > 0) {\n const deletedColumns = deletedColumnKeys.join(', ');\n throw new Error(\n `${prefix}: Columns must not be deleted. ` +\n `Deleted columns: ${deletedColumns}}`,\n );\n }\n }\n\n // Have column keys changed?\n for (let i = 0; i < existing.columns.length; i++) {\n const before = existing.columns[i].key;\n const after = update.columns[i].key;\n if (before !== after) {\n throw new Error(\n `${prefix}: ` +\n `Column keys must not change! ` +\n `Column \"${before}\" was renamed into \"${after}\".`,\n );\n }\n }\n\n // Have column types changed?\n for (let i = 0; i < existing.columns.length; i++) {\n const column = existing.columns[i].key;\n const before = existing.columns[i].type;\n const after = update.columns[i].type;\n if (before !== after) {\n throw new Error(\n `${prefix}: ` +\n `Column types must not change! ` +\n `Type of column \"${column}\" was changed from \"${before}\" to ${after}.`,\n );\n }\n }\n }\n }\n\n /**\n * Throws if the data in the table do not match the table configuration\n */\n async throwWhenTableDataDoesNotMatchCfg(data: Rljson) {\n const errors: string[] = [];\n\n await iterateTables(data, async (tableKey) => {\n const tableCfg = await this.tableCfg(tableKey);\n const table = data[tableKey];\n\n // Ignore tableCfgs table\n /* v8 ignore next -- @preserve */\n if (table._type === 'tableCfgs') return;\n\n errors.push(...validateRljsonAgainstTableCfg(table._data, tableCfg));\n });\n\n if (errors.length > 0) {\n throw new Error(\n `Table data does not match the configuration.\\n\\nErrors:\\n${errors\n .map((e) => `- ${e}`)\n .join('\\n')}`,\n );\n }\n }\n\n /**\n * Sorts the data of a table by the hash and updates the table hash in place\n */\n sortTableDataAndUpdateHash(table: TableType): void {\n table._data.sort((a, b) => {\n const hashA = a._hash as string;\n const hashB = b._hash as string;\n /* v8 ignore next -- @preserve */\n if (hashA < hashB) {\n return -1;\n }\n /* v8 ignore next -- @preserve */\n if (hashA > hashB) {\n return 1;\n }\n\n /* v8 ignore next -- @preserve */\n return 0;\n });\n\n table._hash = '';\n hip(table, {\n updateExistingHashes: false,\n throwOnWrongHashes: false,\n });\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip, hsh } from '@rljson/hash';\nimport { IsReady } from '@rljson/is-ready';\nimport { copy, equals, JsonValue } from '@rljson/json';\nimport {\n ContentType,\n iterateTablesSync,\n Rljson,\n TableCfg,\n TableKey,\n TableType,\n validateRljsonAgainstTableCfg,\n} from '@rljson/rljson';\n\nimport { IoTools } from './io-tools.ts';\nimport { Io } from './io.ts';\n\n\n/**\n * In-Memory implementation of the Rljson Io interface.\n */\nexport class IoMem implements Io {\n // ...........................................................................\n // Constructor & example\n\n init(): Promise<void> {\n this._isOpen = true;\n return this._init();\n }\n\n close(): Promise<void> {\n this._isOpen = false;\n return Promise.resolve();\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n static example = async () => {\n const io = new IoMem();\n await io.init();\n return io;\n };\n\n // ...........................................................................\n // General\n isReady() {\n return this._isReady.promise;\n }\n\n // ...........................................................................\n // Dump\n\n dump(): Promise<Rljson> {\n return this._dump();\n }\n\n async dumpTable(request: { table: string }): Promise<Rljson> {\n return this._dumpTable(request);\n }\n\n // ...........................................................................\n // Meta Data\n\n async contentType(request: { table: string }): Promise<ContentType> {\n return this._contentType(request);\n }\n\n // ...........................................................................\n // Rows\n\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue };\n }): Promise<Rljson> {\n return this._readRows(request);\n }\n\n async rowCount(table: string): Promise<number> {\n const tableData = this._mem[table] as TableType;\n if (!tableData) {\n throw new Error(`Table \"${table}\" not found`);\n }\n return Promise.resolve(tableData._data.length);\n }\n\n // ...........................................................................\n // Write\n\n write(request: { data: Rljson }): Promise<void> {\n return this._write(request);\n }\n\n // ...........................................................................\n // Table management\n async tableExists(tableKey: TableKey): Promise<boolean> {\n const table = this._mem[tableKey] as TableType;\n return table ? true : false;\n }\n\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n return this._createOrExtendTable(request);\n }\n\n async rawTableCfgs(): Promise<TableCfg[]> {\n const tables = this._mem.tableCfgs._data as TableCfg[];\n return tables;\n }\n\n // ######################\n // Private\n // ######################\n\n private _ioTools!: IoTools;\n\n private _isReady = new IsReady();\n private _isOpen = false;\n\n private _mem: Rljson = hip({} as Rljson);\n\n /**\n * Latest table configuration per table (the one with the most\n * columns). Kept in sync by _createTable/_extendTable so that reads\n * and writes need no repeated scan over all configurations.\n */\n private readonly _latestCfgs = new Map<TableKey, TableCfg>();\n\n /** Column key sets per table, derived from _latestCfgs */\n private readonly _columnKeys = new Map<TableKey, Set<string>>();\n\n /**\n * Per-table index of rows by content hash. Rows are only ever added,\n * never removed, so the index cannot go stale.\n */\n private readonly _rowIndex = new Map<TableKey, Map<string, any>>();\n\n /**\n * Tables whose table hash (and thus the global hash) is outdated\n * after writes. Hashes are refreshed lazily before they become\n * observable (dump, dumpTable, create/extend) instead of after every\n * single write — row hashes themselves are always up to date.\n */\n private readonly _dirtyTableHashes = new Set<TableKey>();\n\n // ...........................................................................\n /**\n * Recomputes the hashes of all dirty tables and the global hash.\n * Produces exactly the state an eager per-write update would have\n * produced (hashes are deterministic over the same data).\n */\n private _refreshHashes(): void {\n if (this._dirtyTableHashes.size === 0) {\n return;\n }\n\n for (const tableKey of this._dirtyTableHashes) {\n const table = this._mem[tableKey] as TableType;\n table._hash = '';\n hip(table, {\n updateExistingHashes: false,\n throwOnWrongHashes: false,\n });\n }\n this._dirtyTableHashes.clear();\n\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n /**\n * Returns the row index of a table, building it lazily from the\n * table data on first access.\n * @param table - The table to index\n */\n private _rowIndexFor(table: TableKey): Map<string, any> {\n let index = this._rowIndex.get(table);\n if (!index) {\n index = new Map();\n const tableData = (this._mem[table] as TableType)._data;\n for (const row of tableData) {\n index.set(row._hash as string, row);\n }\n this._rowIndex.set(table, index);\n }\n return index;\n }\n\n // ...........................................................................\n /**\n * Inserts a row into hash-sorted table data at its sorted position —\n * preserves the order sortTableDataAndUpdateHash establishes without\n * a full re-sort.\n * @param data - The hash-sorted table data\n * @param row - The row to insert\n */\n private static _insertSortedByHash(data: any[], row: any): void {\n const hash = row._hash as string;\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((data[mid]._hash as string) < hash) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n data.splice(lo, 0, row);\n }\n\n // ...........................................................................\n /**\n * The row filter predicate of readRows. Extracted so that the indexed\n * fast path and the full scan share identical semantics.\n * @param row - The row to check\n * @param where - The where clause\n */\n private static _rowMatchesWhere(\n row: any,\n where: { [column: string]: JsonValue },\n ): boolean {\n for (const column in where) {\n const a = row[column];\n const b = where[column];\n if (b === null && a === undefined) {\n return true;\n }\n\n if (!equals(a, b)) {\n return false;\n }\n }\n return true;\n }\n\n // ...........................................................................\n /**\n * Returns the latest table configuration, filling the cache lazily\n * from IoTools (which picks the config with the most columns).\n * @param table - The table to get the configuration for\n */\n private async _latestCfg(table: TableKey): Promise<TableCfg> {\n let cfg = this._latestCfgs.get(table);\n if (!cfg) {\n cfg = await this._ioTools.tableCfg(table);\n this._latestCfgs.set(table, cfg);\n }\n return cfg;\n }\n\n /**\n * Updates the cached latest configuration of a table\n * @param cfg - The new latest configuration\n */\n private _setLatestCfg(cfg: TableCfg): void {\n this._latestCfgs.set(cfg.key, cfg);\n this._columnKeys.set(cfg.key, new Set(cfg.columns.map((c) => c.key)));\n }\n\n /**\n * Throws when one of the given columns does not exist in the table.\n * Mirrors IoTools.throwWhenColumnDoesNotExist but uses the cached\n * configuration.\n * @param table - The table to check\n * @param columns - The columns to check\n */\n private async _throwWhenColumnDoesNotExist(\n table: TableKey,\n columns: string[],\n ): Promise<void> {\n let columnKeys = this._columnKeys.get(table);\n if (!columnKeys) {\n const cfg = await this._latestCfg(table);\n columnKeys = new Set(cfg.columns.map((c) => c.key));\n this._columnKeys.set(table, columnKeys);\n }\n\n const missingColumns = columns.filter((column) => !columnKeys.has(column));\n if (missingColumns.length > 0) {\n throw new Error(\n `The following columns do not exist in table \"${table}\": ${missingColumns.join(\n ', ',\n )}.`,\n );\n }\n }\n\n /**\n * Throws when the data does not match the table configurations.\n * Mirrors IoTools.throwWhenTableDataDoesNotMatchCfg but uses the\n * cached configurations.\n * @param data - The data to validate\n */\n private async _throwWhenTableDataDoesNotMatchCfg(\n data: Rljson,\n ): Promise<void> {\n const errors: string[] = [];\n\n for (const tableKey of Object.keys(data)) {\n const table = data[tableKey] as TableType;\n\n // Skip non-table values (like _hash) — mirrors iterateTables\n if (typeof table !== 'object' || !Array.isArray(table?._data)) continue;\n\n // Ignore tableCfgs table\n /* v8 ignore next -- @preserve */\n if (table._type === 'tableCfgs') continue;\n\n const tableCfg = await this._latestCfg(tableKey);\n errors.push(...validateRljsonAgainstTableCfg(table._data, tableCfg));\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Table data does not match the configuration.\\n\\nErrors:\\n${errors\n .map((e) => `- ${e}`)\n .join('\\n')}`,\n );\n }\n }\n\n // ...........................................................................\n private async _init() {\n // Fold pending lazy hash updates — a re-init validates all hashes\n this._refreshHashes();\n\n // Reset caches — a re-init replaces the tableCfgs table, so cached\n // configs and indexes must be rebuilt\n this._rowIndex.clear();\n this._latestCfgs.clear();\n this._columnKeys.clear();\n\n this._ioTools = new IoTools(this);\n this._initTableCfgs();\n this._updateGlobalHash();\n await this._ioTools.initRevisionsTable();\n hsh(this._mem);\n\n this._isReady.resolve();\n }\n\n // ...........................................................................\n private _initTableCfgs = () => {\n const tableCfg = IoTools.tableCfgsTableCfg;\n\n this._mem.tableCfgs = hip({\n _type: 'tableCfgs',\n _data: [tableCfg],\n _tableCfg: tableCfg._hash as string,\n });\n };\n\n // ...........................................................................\n private _updateGlobalHash() {\n (this._mem as any)._hash = '';\n hip(this._mem, {\n updateExistingHashes: false,\n });\n }\n\n // ...........................................................................\n private _updateTableHash(tableKey: TableKey) {\n const table = this._mem[tableKey] as TableType;\n table._hash = '';\n hip(table, { updateExistingHashes: false });\n }\n\n // ...........................................................................\n private async _createOrExtendTable(request: {\n tableCfg: TableCfg;\n }): Promise<void> {\n // Fold pending lazy hash updates before the eager global hash\n // update of the create/extend paths\n this._refreshHashes();\n\n // Make sure that the table config is compatible\n // with an potential existing table\n const tableCfg = request.tableCfg;\n await this._ioTools.throwWhenTableIsNotCompatible(tableCfg);\n\n const { key } = tableCfg;\n\n // Recreate hashes in the case the existing hashes are wrong\n const newConfig = hsh(tableCfg);\n\n // Find an existing table config with the same hash\n const existingConfig = await this._ioTools.tableCfgOrNull(key);\n\n // Write the new config into the database\n if (!existingConfig) {\n this._createTable(newConfig, key);\n } else {\n this._extendTable(existingConfig, newConfig);\n }\n }\n\n // ...........................................................................\n private _createTable(newConfig: TableCfg, tableKey: TableKey) {\n // Write the table config into the database\n newConfig = hsh(newConfig);\n this._mem.tableCfgs._data.push(newConfig);\n this._ioTools.sortTableDataAndUpdateHash(this._mem.tableCfgs);\n this._setLatestCfg(newConfig);\n this._rowIndex.get('tableCfgs')?.set(newConfig._hash as string, newConfig);\n\n // Create a table and write it into the database\n const table: TableType = {\n _type: newConfig.type,\n _data: [],\n _tableCfg: newConfig._hash as string,\n };\n\n this._mem[tableKey] ??= hip(table);\n\n // Update hashes\n this._updateTableHash(tableKey);\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n private _extendTable(existingConfig: TableCfg, newConfig: TableCfg) {\n // No columns added? Return.\n if (existingConfig.columns.length === newConfig.columns.length) {\n return;\n }\n\n // Write the new table config into the database\n newConfig = hsh(newConfig);\n this._mem.tableCfgs._data.push(newConfig);\n this._ioTools.sortTableDataAndUpdateHash(this._mem.tableCfgs);\n this._setLatestCfg(newConfig);\n this._rowIndex.get('tableCfgs')?.set(newConfig._hash as string, newConfig);\n\n // Update the config of the existing table\n const table = this._mem[newConfig.key] as TableType;\n table._tableCfg = newConfig._hash as string;\n\n // Update the hashes\n this._updateTableHash(newConfig.key);\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n\n private async _dump(): Promise<Rljson> {\n this._refreshHashes();\n return copy(this._mem);\n }\n\n // ...........................................................................\n private async _dumpTable(request: { table: string }): Promise<Rljson> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n\n this._refreshHashes();\n const table = this._mem[request.table] as TableType;\n\n return {\n [request.table]: copy(table),\n };\n }\n\n // ...........................................................................\n private async _contentType(request: { table: string }): Promise<ContentType> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n\n return (this._mem[request.table] as TableType)._type;\n }\n\n // ...........................................................................\n private async _write(request: { data: Rljson }): Promise<void> {\n const addedData = hsh(request.data);\n const removedNullValues = this._removeNullValues(addedData);\n const tables = Object.keys(addedData);\n\n // Row hashes only change when null values were actually removed\n if (removedNullValues) {\n hsh(addedData);\n }\n\n await this._ioTools.throwWhenTablesDoNotExist(request.data);\n await this._throwWhenTableDataDoesNotMatchCfg(request.data);\n\n for (const table of tables) {\n if (table.startsWith('_')) {\n continue;\n }\n\n const oldTable = this._mem[table] as TableType;\n const newTable = addedData[table] as TableType;\n const rowIndex = this._rowIndexFor(table);\n\n // Table exists. Merge data — O(1) dedup via the row index and\n // sorted insert instead of a linear scan plus full re-sort\n for (const item of newTable._data) {\n const hash = item._hash as string;\n if (!rowIndex.has(hash)) {\n rowIndex.set(hash, item);\n IoMem._insertSortedByHash(oldTable._data, item);\n }\n }\n\n // Table and global hash are refreshed lazily before they become\n // observable — see _refreshHashes\n this._dirtyTableHashes.add(table);\n }\n }\n\n // ...........................................................................\n private async _readRows(request: {\n table: string;\n where: { [column: string]: JsonValue };\n }): Promise<Rljson> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n await this._throwWhenColumnDoesNotExist(\n request.table,\n Object.keys(request.where),\n );\n\n // Read table from data\n const table = this._mem[request.table] as TableType;\n\n // Filter table data. Lookups by content hash use the row index\n // instead of scanning the whole table.\n const whereHash = request.where['_hash'];\n let tableDataFiltered: any[];\n if (typeof whereHash === 'string') {\n const row = this._rowIndexFor(request.table).get(whereHash);\n tableDataFiltered =\n row && IoMem._rowMatchesWhere(row, request.where) ? [row] : [];\n } else {\n tableDataFiltered = table._data.filter((row) =>\n IoMem._rowMatchesWhere(row, request.where),\n );\n }\n\n // Create an table\n const tableFiltered: TableType = {\n _type: table._type,\n _data: tableDataFiltered,\n };\n\n this._ioTools.sortTableDataAndUpdateHash(tableFiltered);\n\n const result: Rljson = {\n [request.table]: tableFiltered,\n };\n\n return result;\n }\n\n _removeNullValues(rljson: Rljson): boolean {\n let removedAny = false;\n\n iterateTablesSync(rljson, (table) => {\n const data = rljson[table]._data;\n\n for (const row of data) {\n for (const key in row) {\n if (row[key] === null) {\n delete row[key];\n removedAny = true;\n }\n }\n }\n });\n\n return removedAny;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\nexport class PeerSocketMock implements Socket {\n private _listenersMap: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n\n connected: boolean = false;\n disconnected: boolean = true;\n\n constructor(private _io: Io) {}\n\n // ............................................................................\n /**\n * Removes a specific listener for the specified event.\n * @param eventName - The name of the event.\n * @param listener - The callback function to remove.\n * @returns The PeerSocketMock instance for chaining.\n */\n off(eventName: string | symbol, listener: (...args: any[]) => void): this {\n /* v8 ignore next -- @preserve */\n const listeners = this._listenersMap.get(eventName) || [];\n const index = listeners.indexOf(listener);\n /* v8 ignore else -- @preserve */\n if (index !== -1) {\n listeners.splice(index, 1);\n this._listenersMap.set(eventName, listeners);\n }\n return this;\n }\n\n // ............................................................................\n /**\n * Removes all listeners for the specified event, or all listeners if no event is specified.\n * @param eventName - (Optional) The name of the event.\n * @returns The PeerSocketMock instance for chaining.\n */\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName) {\n this._listenersMap.delete(eventName);\n } else {\n this._listenersMap.clear();\n }\n return this;\n }\n\n // ............................................................................\n /**\n * Registers an event listener for the specified event.\n * @param eventName - The name of the event to listen for.\n * @param listener - The callback function to invoke when the event is emitted.\n * @returns The PeerSocketMock instance for chaining.\n */\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listenersMap.has(eventName)) {\n this._listenersMap.set(eventName, []);\n }\n this._listenersMap.get(eventName)!.push(listener);\n return this;\n }\n\n // ...........................................................................\n /**\n * Simulates a connection event.\n *\n * Emits the 'connect' event to all registered listeners.\n */\n connect(): void {\n this.connected = true;\n this.disconnected = false;\n\n const listeners = this._listenersMap.get('connect') || [];\n for (const cb of listeners) {\n cb({});\n }\n }\n\n // ...........................................................................\n /**\n * Simulates a disconnection event.\n *\n * Emits the 'disconnect' event to all registered listeners.\n */\n disconnect(): void {\n this.connected = false;\n this.disconnected = true;\n\n const listeners = this._listenersMap.get('disconnect') || [];\n for (const cb of listeners) {\n cb({});\n }\n }\n\n // ............................................................................\n /**\n * Emits an event, invoking the corresponding method on the Io instance.\n * @param eventName - The name of the event to emit.\n * @param args - The arguments to pass to the event listener.\n * @returns\n */\n emit(eventName: string | symbol, ...args: any[]): boolean {\n const fn = (this._io as any)[eventName] as (...args: any[]) => Promise<any>;\n if (typeof fn !== 'function') {\n throw new Error(`Event ${eventName.toString()} not supported`);\n }\n const cb = args[args.length - 1];\n fn.apply(this._io, args.slice(0, -1))\n .then((result) => {\n cb(result, null);\n })\n .catch((err) => {\n cb(null, err);\n });\n\n return true;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { ContentType, Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { Io } from './io.ts';\nimport { PeerSocketMock } from './peer-socket-mock.ts';\nimport { Socket } from './socket.ts';\n\n\nexport class IoPeer implements Io {\n isOpen: boolean = false;\n\n constructor(\n private _socket: Socket,\n private _requestTimeoutMs: number = 30_000,\n ) {}\n\n // ...........................................................................\n /**\n * Wraps a promise with a timeout. If the promise does not settle within\n * `_requestTimeoutMs`, the returned promise rejects with a timeout error.\n * Clears the timer on settlement to avoid leaks and unhandled rejections.\n */\n private _withTimeout<T>(promise: Promise<T>, operation: string): Promise<T> {\n if (this._requestTimeoutMs <= 0) return promise;\n let timer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(\n new Error(\n `Timeout after ${this._requestTimeoutMs}ms: ${operation}`,\n ),\n );\n }, this._requestTimeoutMs);\n });\n return Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timer!);\n });\n }\n\n // ...........................................................................\n /**\n *\n * Initializes the Peer connection.\n * @returns\n */\n async init(): Promise<void> {\n // Update isOpen on connect/disconnect\n this._socket.on('connect', () => {\n this.isOpen = true;\n });\n this._socket.on('disconnect', () => {\n this.isOpen = false;\n });\n\n // Connect the socket\n this._socket.connect();\n\n // Wait for the socket to connect before returning\n return new Promise<void>((resolve) => {\n /* v8 ignore else -- @preserve */\n if (this._socket.connected) {\n this.isOpen = true;\n resolve();\n } else {\n this._socket.on('connect', () => {\n resolve();\n });\n }\n });\n }\n\n // ...........................................................................\n /**\n * Closes the Peer connection.\n * @returns\n */\n\n async close(): Promise<void> {\n // Disconnect the socket and wait for it to complete\n if (!this._socket.connected) return;\n\n return new Promise<void>((resolve) => {\n this._socket.on('disconnect', () => {\n resolve();\n });\n this._socket.disconnect();\n });\n }\n\n // ...........................................................................\n /**\n * Returns a promise that resolves once the Peer connection is ready.\n * @returns\n */\n async isReady(): Promise<void> {\n if (!!this._socket && this._socket.connected === true) this.isOpen = true;\n else this.isOpen = false;\n\n return !!this.isOpen ? Promise.resolve() : Promise.reject();\n }\n\n // ...........................................................................\n /**\n * Dumps the entire database content.\n * @returns A promise that resolves to the dumped database content.\n */\n async dump(): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request dump, resolve once the data is received (ack)\n this._socket.emit('dump', (data: Rljson) => {\n resolve(data);\n });\n }),\n 'dump',\n );\n }\n\n // ...........................................................................\n /**\n * Dumps a specific table from the database.\n * @param request An object containing the table name to dump.\n * @returns A promise that resolves to the dumped table data.\n */\n dumpTable(request: { table: string }): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request dumpTable, resolve once the data is received (ack)\n this._socket.emit(\n 'dumpTable',\n request,\n (data: Rljson, error?: Error) => {\n if (error) reject(error);\n resolve(data);\n },\n );\n }),\n 'dumpTable',\n );\n }\n\n // ...........................................................................\n /**\n * Gets the content type of a specific table.\n * @param request An object containing the table name to get the content type for.\n * @returns A promise that resolves to the content type of the specified table.\n */\n contentType(request: { table: string }): Promise<ContentType> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request contentType, resolve once the data is received (ack)\n this._socket.emit(\n 'contentType',\n request,\n (data: ContentType, error?: Error) => {\n /* v8 ignore next -- @preserve */\n if (error) reject(error);\n resolve(data);\n },\n );\n }),\n 'contentType',\n );\n }\n\n // ...........................................................................\n /**\n * Checks if a specific table exists in the database.\n * @param tableKey The key of the table to check for existence.\n * @returns A promise that resolves to true if the table exists, false otherwise.\n */\n tableExists(tableKey: TableKey): Promise<boolean> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request tableExists, resolve once the data is received (ack)\n this._socket.emit('tableExists', tableKey, (exists: boolean) => {\n resolve(exists);\n });\n }),\n 'tableExists',\n );\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table with the given configuration.\n * @param request An object containing the table configuration.\n * @returns A promise that resolves once the table is created or extended.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request createOrExtendTable, resolve once the data is received (ack)\n this._socket.emit(\n 'createOrExtendTable',\n request,\n (_?: boolean, error?: Error) => {\n if (error) reject(error);\n resolve();\n },\n );\n }),\n 'createOrExtendTable',\n );\n }\n\n // ...........................................................................\n /**\n * Retrieves the raw table configurations from the database.\n * @returns A promise that resolves to an array of table configurations.\n */\n rawTableCfgs(): Promise<TableCfg[]> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request rawTableCfgs, resolve once the data is received (ack)\n this._socket.emit('rawTableCfgs', (data: TableCfg[]) => {\n resolve(data);\n });\n }),\n 'rawTableCfgs',\n );\n }\n\n // ...........................................................................\n /**\n * Writes data to the database.\n * @param request An object containing the data to write.\n * @returns A promise that resolves once the data is written.\n */\n write(request: { data: Rljson }): Promise<void> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request write, resolve once the data is received (ack)\n this._socket.emit('write', request, (_?: boolean, error?: Error) => {\n if (error) reject(error);\n resolve();\n });\n }),\n 'write',\n );\n }\n\n // ...........................................................................\n /**\n * Reads rows from a specific table that match the given criteria.\n * @param request An object containing the table name and the criteria for selecting rows.\n * @returns A promise that resolves to the selected rows.\n */\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request readRows, resolve once the data is received (ack)\n this._socket.emit(\n 'readRows',\n request,\n (result?: Rljson, error?: Error) => {\n if (error) reject(error);\n resolve(result!);\n },\n );\n }),\n 'readRows',\n );\n }\n\n // ...........................................................................\n /**\n * Retrieves the number of rows in a specific table.\n * @param table The name of the table to count rows in.\n * @returns A promise that resolves to the number of rows in the specified table.\n */\n rowCount(table: string): Promise<number> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request rowCount, resolve once the data is received (ack)\n this._socket.emit(\n 'rowCount',\n table,\n (count?: number, error?: Error) => {\n if (error) reject(error);\n resolve(count!);\n },\n );\n }),\n 'rowCount',\n );\n }\n\n // ...........................................................................\n static example = async () => {\n const ioMem = await IoMem.example();\n const socket = new PeerSocketMock(ioMem);\n const io = new IoPeer(socket);\n await io.init();\n return io;\n };\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip } from '@rljson/hash';\nimport { Json, JsonValue, merge } from '@rljson/json';\nimport { ContentType, Rljson, RljsonTable, TableCfg, TableKey, TableType } from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { IoPeer } from './io-peer.ts';\nimport { Io } from './io.ts';\nimport { PeerSocketMock } from './peer-socket-mock.ts';\n\n\n// ...........................................................................\n/**\n * Type representing an Io instance along with its capabilities and priority.\n */\nexport type IoMultiIo = {\n io: Io;\n id?: string;\n priority: number;\n read: boolean;\n write: boolean;\n dump: boolean;\n};\n\n// ...........................................................................\n/**\n * Multi Io implementation that combines multiple underlying Io instances\n * with different capabilities (read, write, dump) and priorities.\n */\nexport class IoMulti implements Io {\n isOpen: boolean = false;\n\n constructor(private _ios: Array<IoMultiIo>) {}\n\n // ...........................................................................\n /**\n *\n * Initializes all underlying Io instances.\n * @returns\n */\n async init(): Promise<void> {\n for (let idx = 0; idx < this._ios.length; idx++) {\n const { io } = this._ios[idx];\n if (io.isOpen === false) {\n throw new Error(\n 'All underlying Io instances must be initialized before initializing IoMulti',\n );\n }\n\n this._ios[idx] = { ...this._ios[idx], id: `io-${idx}` };\n }\n\n this.isOpen = true;\n return Promise.resolve();\n }\n\n // ...........................................................................\n /**\n * Closes all underlying Io instances.\n * @returns\n */\n async close(): Promise<void> {\n await Promise.all(this._ios.map((ioMultiIo) => ioMultiIo.io.close()));\n\n this.isOpen = false;\n\n return Promise.resolve();\n }\n\n // ...........................................................................\n /**\n * Returns a promise that resolves once all underlying Io instances are ready.\n * @returns\n */\n isReady(): Promise<void> {\n return Promise.all(\n this._ios.map((ioMultiIo) => ioMultiIo.io.isReady()),\n ).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Dumps the entire database content by merging dumps from all dumpable underlying Io instances.\n * @returns\n */\n async dump(): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumps = await Promise.all(\n this.dumpables.map(({ io: dumpable }) => dumpable.dump()),\n );\n\n return merge(...dumps) as Rljson;\n }\n\n // ...........................................................................\n /**\n * Dumps a specific table by merging dumps from all dumpable underlying Io instances that contain the table.\n * @param request An object containing the table name to dump.\n * @returns A promise that resolves to the dumped table data.\n */\n async dumpTable(request: { table: string }): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumps: Rljson[] = [];\n\n for (const { io: dumpable } of this.dumpables) {\n try {\n const dump = await dumpable.dumpTable(request);\n dumps.push(dump);\n } catch {\n continue; // Table does not exist in this dumpable Io\n }\n }\n\n if (dumps.length === 0) {\n throw new Error(`Table \"${request.table}\" not found`);\n }\n\n return merge(...dumps) as Rljson;\n }\n\n // ...........................................................................\n /**\n * Retrieves the content type of a specific table from the first underlying readable Io instance that contains the table.\n * @param request An object containing the table name.\n * @returns A promise that resolves to the content type of the table.\n */\n async contentType(request: { table: string }): Promise<ContentType> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n for (const { io: readable } of this.readables) {\n return readable.contentType(request);\n }\n /* v8 ignore next -- @preserve */\n throw new Error(`Table \"${request.table}\" not found`);\n }\n\n // ...........................................................................\n /**\n * Checks if a specific table exists in any of the underlying readable Io\n * instances. Readables at the same priority level are queried in parallel\n * so that one slow peer does not block others.\n * @param tableKey The key of the table to check.\n * @returns A promise that resolves to true if the table exists in any readable Io, false otherwise.\n */\n async tableExists(tableKey: TableKey): Promise<boolean> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n const groups = IoMulti._groupByPriority(this.readables);\n for (const group of groups) {\n if (group.length === 1) {\n const exists = await group[0].io.tableExists(tableKey);\n if (exists) return true;\n } else {\n const results = await Promise.allSettled(\n group.map((r) => r.io.tableExists(tableKey)),\n );\n for (const result of results) {\n if (result.status === 'fulfilled' && result.value) return true;\n }\n }\n }\n return false;\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table in all underlying writable Io instances.\n * @param request An object containing the table configuration.\n * @returns A promise that resolves once the table has been created or extended in all writable Io instances.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n /* v8 ignore next -- @preserve */\n if (this.writables.length === 0) {\n throw new Error('No writable Io available');\n }\n //Create or extend table in all writables in parallel and resolve when all have completed\n const creations = this.writables.map(({ io: writable }) =>\n writable.createOrExtendTable(request),\n );\n return Promise.all(creations).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Retrieves the raw table configurations from the highest priority underlying\n * readable Io instance that has any. Stops after the first readable that\n * returns results — this avoids expensive network round-trips to lower-\n * priority peers when the local cache (IoMem, priority 1) already has the\n * answer.\n * @returns A promise that resolves to an array of table configurations.\n */\n async rawTableCfgs(): Promise<TableCfg[]> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n const rawTableCfgs: Map<string, TableCfg> = new Map();\n for (const { io: readable } of this.readables) {\n const cfgs = await readable.rawTableCfgs();\n /* v8 ignore else -- @preserve */\n if (cfgs.length > 0) {\n for (const tableCfg of cfgs) {\n if (!rawTableCfgs.has(tableCfg.key)) {\n rawTableCfgs.set(tableCfg.key, tableCfg);\n }\n }\n break; // Stop after the first readable that has table configs\n }\n }\n return Array.from(rawTableCfgs.values());\n }\n\n // ...........................................................................\n /**\n * Writes data to all underlying writable Io instances.\n * @param request - An object containing the data to write.\n * @returns A promise that resolves once the data has been written to all writable Io instances.\n */\n write(request: { data: Rljson }): Promise<void> {\n /* v8 ignore next -- @preserve */\n if (this.writables.length === 0) {\n throw new Error('No writable Io available');\n }\n\n // Write to all writables in parallel and resolve when all have completed\n const writes = this.writables.map(({ io: writable }) =>\n writable.write(request),\n );\n return Promise.all(writes).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Reads rows from a specific table. Readables are grouped by priority:\n * priorities are tried in ascending order. Within a priority group,\n * all readables are queried **in parallel** — only the first one to\n * return rows wins. This prevents one slow/stale peer from blocking\n * others at the same priority level.\n *\n * @param request An object containing the table name and where clause.\n * @returns A promise that resolves to the read rows.\n */\n async readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n let tableExistsAny = false;\n const rows: Map<string, Json> = new Map();\n let type: ContentType | undefined = undefined;\n let readFrom: string = '';\n\n const errors: Error[] = [];\n\n // Group readables by priority (already sorted by priority)\n const groups = IoMulti._groupByPriority(this.readables);\n\n for (const group of groups) {\n if (group.length === 1) {\n // Single readable at this priority — query directly (no race overhead)\n const readable = group[0];\n try {\n const { [request.table]: tableData } = await readable.io.readRows(\n request,\n );\n const tableRows = (tableData as RljsonTable<Json, ContentType>)\n ._data;\n const tableType = (tableData as RljsonTable<Json, ContentType>)\n ._type;\n tableExistsAny = true;\n type ??= tableType;\n\n if (tableRows.length > 0) {\n /* v8 ignore next -- @preserve */\n readFrom = readable.id ?? '';\n /* v8 ignore else -- @preserve */\n for (const tableRow of tableRows) {\n const ref = tableRow._hash as string;\n rows.set(ref, tableRow);\n }\n break; // Got rows — done\n }\n } catch (e) {\n errors.push(e as Error);\n }\n } else {\n // Multiple readables at the same priority — race them in parallel.\n // Collect all settled results and pick the first with rows.\n const results = await Promise.allSettled(\n group.map(async (readable) => {\n const { [request.table]: tableData } = await readable.io.readRows(\n request,\n );\n return {\n readable,\n tableRows: (tableData as RljsonTable<Json, ContentType>)._data,\n tableType: (tableData as RljsonTable<Json, ContentType>)._type,\n };\n }),\n );\n\n let foundRows = false;\n for (const result of results) {\n if (result.status === 'rejected') {\n errors.push(result.reason as Error);\n continue;\n }\n tableExistsAny = true;\n const { readable, tableRows, tableType } = result.value;\n type ??= tableType;\n if (tableRows.length > 0 && !foundRows) {\n foundRows = true;\n readFrom = readable.id ?? '';\n /* v8 ignore else -- @preserve */\n for (const tableRow of tableRows) {\n const ref = tableRow._hash as string;\n rows.set(ref, tableRow);\n }\n }\n }\n\n if (foundRows) break; // Got rows — done\n }\n }\n\n if (!tableExistsAny) {\n /* v8 ignore if -- @preserve */\n if (errors.length === 0) {\n throw new Error(`Table \"${request.table}\" not found`);\n } else {\n const preciseErrors = errors.filter(\n (err) => !err.message.includes(`Table \"${request.table}\" not found`),\n );\n if (preciseErrors.length > 0) {\n throw preciseErrors[0];\n } else {\n throw errors[0];\n }\n }\n } else {\n const rljson = {\n [request.table]: hip({ _data: Array.from(rows.values()), _type: type }),\n } as Rljson;\n\n // Write merged rows back to all writables (hot-swapping cache)\n if (this.writables.length > 0 && rows.size > 0) {\n for (const writeable of this.writables) {\n if (writeable.id === readFrom) {\n continue; // Skip writing back to the source readable Io\n }\n /* v8 ignore next -- @preserve */\n try {\n await writeable.io.write({\n data: rljson,\n });\n } catch {\n continue; // Table does not exist in this writable Io\n }\n }\n }\n\n // Return merged rows\n return rljson;\n }\n }\n\n // ...........................................................................\n /**\n * Retrieves the row count of a specific table by aggregating row counts from all dumpable underlying Io instances.\n * @param table The name of the table.\n * @returns A promise that resolves to the row count of the table.\n */\n async rowCount(table: string): Promise<number> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumpTable = await this.dumpTable({ table });\n const tableData: TableType = dumpTable[table];\n /* v8 ignore next -- @preserve */\n if (!tableData) {\n throw new Error(`Table \"${table}\" not found`);\n }\n return Promise.resolve(tableData._data.length);\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying readable Io instances, sorted by priority.\n */\n get readables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.read)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying writable Io instances, sorted by priority.\n */\n get writables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.write)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying dumpable Io instances, sorted by priority.\n */\n get dumpables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.dump)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Groups IoMultiIo entries by their priority value.\n * Input must already be sorted by priority (ascending).\n * Returns an array of groups, each group containing entries with the same\n * priority.\n */\n static _groupByPriority(ios: Array<IoMultiIo>): Array<Array<IoMultiIo>> {\n const groups: Array<Array<IoMultiIo>> = [];\n let current: Array<IoMultiIo> = [];\n let currentPriority: number | null = null;\n\n for (const io of ios) {\n if (io.priority !== currentPriority) {\n if (current.length > 0) groups.push(current);\n current = [io];\n currentPriority = io.priority;\n } else {\n current.push(io);\n }\n }\n if (current.length > 0) groups.push(current);\n\n return groups;\n }\n\n // ...........................................................................\n static example = async () => {\n const ioPeerMem = await IoMem.example();\n await ioPeerMem.init();\n\n const ioPeerSocket = new PeerSocketMock(ioPeerMem);\n const ioPeer = new IoPeer(ioPeerSocket);\n await ioPeer.init();\n\n const ioMem = await IoMem.example();\n await ioMem.init();\n\n const ios: Array<IoMultiIo> = [\n { io: ioPeer, priority: 1, read: true, write: false, dump: false },\n { io: ioMem, priority: 0, read: true, write: true, dump: true },\n ];\n\n const ioMulti = new IoMulti(ios);\n await ioMulti.init();\n\n return ioMulti;\n };\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\n\n/**\n * Bridges Socket events to Io method calls.\n *\n * This class listens to socket events and translates them into corresponding\n * Io method calls, automatically registering all Io interface methods.\n */\nexport class IoPeerBridge {\n private _eventHandlers: Map<string | symbol, (...args: any[]) => void> =\n new Map();\n\n constructor(private _io: Io, private _socket: Socket) {}\n\n /**\n * Starts the bridge by setting up connection event handlers and\n * automatically registering all Io methods.\n */\n start(): void {\n this._socket.on('connect', () => this._handleConnect());\n this._socket.on('disconnect', () => this._handleDisconnect());\n\n // Automatically register all Io interface methods\n this._registerIoMethods();\n }\n\n /**\n * Stops the bridge by removing all event handlers.\n */\n stop(): void {\n /* v8 ignore next -- @preserve */\n this._socket.off('connect', () => this._handleConnect());\n /* v8 ignore next -- @preserve */\n this._socket.off('disconnect', () => this._handleDisconnect());\n\n for (const [eventName, handler] of this._eventHandlers) {\n this._socket.off(eventName, handler);\n }\n this._eventHandlers.clear();\n }\n\n /**\n * Automatically registers all Io interface methods as socket event handlers.\n */\n private _registerIoMethods(): void {\n // Core Io interface methods\n const ioMethods = [\n 'init',\n 'isReady',\n 'close',\n 'tableExists',\n 'createOrExtendTable',\n 'write',\n 'readRows',\n 'rowCount',\n 'dumpTable',\n 'dump',\n 'contentType',\n 'rawTableCfgs',\n ];\n\n for (const methodName of ioMethods) {\n this.registerEvent(methodName);\n }\n }\n\n /**\n * Registers a socket event to be translated to an Io method call.\n *\n * @param eventName - The socket event name (should match an Io method name)\n * @param ioMethodName - (Optional) The Io method name if different from eventName\n */\n registerEvent(eventName: string, ioMethodName?: string): void {\n const methodName = ioMethodName || eventName;\n\n /* v8 ignore next -- @preserve */\n const handler = (...args: any[]) => {\n // The last argument is expected to be a callback function\n const callback = args[args.length - 1];\n const methodArgs = args.slice(0, -1);\n\n // Get the Io method\n const ioMethod = (this._io as any)[methodName];\n\n /* v8 ignore next -- @preserve */\n if (typeof ioMethod !== 'function') {\n const error = new Error(\n `Method \"${methodName}\" not found on Io instance`,\n );\n if (typeof callback === 'function') {\n callback(null, error);\n }\n return;\n }\n\n // Call the Io method and handle the response\n /* v8 ignore next -- @preserve */\n ioMethod\n .apply(this._io, methodArgs)\n .then((result: any) => {\n if (typeof callback === 'function') {\n // Call callback with just the result (no error parameter when successful)\n callback(result, null); // Two arguments\n }\n })\n .catch((error: any) => {\n if (typeof callback === 'function') {\n // For errors, send null as result and error as second parameter\n callback(null, error); // Two arguments\n }\n });\n };\n\n this._eventHandlers.set(eventName, handler);\n this._socket.on(eventName, handler);\n }\n\n /**\n * Registers multiple socket events at once.\n *\n * @param eventNames - Array of event names to register\n */\n registerEvents(eventNames: string[]): void {\n for (const eventName of eventNames) {\n this.registerEvent(eventName);\n }\n }\n\n /**\n * Unregisters a socket event handler.\n *\n * @param eventName - The event name to unregister\n */\n unregisterEvent(eventName: string | symbol): void {\n const handler = this._eventHandlers.get(eventName);\n if (handler) {\n this._socket.off(eventName, handler);\n this._eventHandlers.delete(eventName);\n }\n }\n\n /**\n * Emits a result back through the socket.\n *\n * @param eventName - The event name to emit\n * @param data - The data to send\n */\n emitToSocket(eventName: string | symbol, ...data: any[]): void {\n this._socket.emit(eventName, ...data);\n }\n\n /**\n * Calls an Io method directly and emits the result through the socket.\n *\n * @param ioMethodName - The Io method to call\n * @param socketEventName - The socket event to emit with the result\n * @param args - Arguments to pass to the Io method\n */\n async callIoAndEmit(\n ioMethodName: string,\n socketEventName: string | symbol,\n ...args: any[]\n ): Promise<void> {\n try {\n const ioMethod = (this._io as any)[ioMethodName];\n\n if (typeof ioMethod !== 'function') {\n throw new Error(`Method \"${ioMethodName}\" not found on Io instance`);\n }\n\n const result = await ioMethod.apply(this._io, args);\n this._socket.emit(socketEventName, result, null);\n } catch (error) {\n this._socket.emit(socketEventName, null, error);\n }\n }\n\n /* v8 ignore next -- @preserve */\n private _handleConnect(): void {\n // Override this method in subclasses to handle connection events\n }\n\n /* v8 ignore next -- @preserve */\n private _handleDisconnect(): void {\n // Override this method in subclasses to handle disconnection events\n }\n\n /**\n * Gets the current socket instance.\n */\n get socket(): Socket {\n return this._socket;\n }\n\n /**\n * Gets the current Io instance.\n */\n get io(): Io {\n return this._io;\n }\n\n /**\n * Returns whether the socket is currently connected.\n */\n get isConnected(): boolean {\n return this._socket.connected;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\n\nexport class IoServer {\n private _sockets: Socket[] = [];\n\n constructor(private _io: Io) {}\n\n // ...........................................................................\n /**\n * Adds a socket to the IoServer instance.\n * @param socket - The socket to add.\n */\n async addSocket(socket: Socket): Promise<void> {\n // Add transport layer to the socket\n await this._addTransportLayer(socket);\n\n // Add socket to the list of sockets\n this._sockets.push(socket);\n }\n\n // ...........................................................................\n /**\n * Removes a transport layer from the given socket.\n * @param socket - The socket to remove the transport layer from.\n */\n removeSocket(socket: Socket): void {\n this._sockets = this._sockets.filter((s) => s !== socket);\n }\n\n // ...........................................................................\n /**\n * Adds a transport layer to the given socket.\n * @param socket - The socket to add the transport layer to.\n */\n private async _addTransportLayer(socket: Socket): Promise<void> {\n // CRUD operations — use arrow functions that read this._io at call time,\n // so that when _io is replaced (e.g. after _rebuildMultis), existing\n // socket handlers automatically use the latest Io instance.\n const crud = this._generateTransportLayerCRUD();\n for (const [key, fn] of Object.entries(crud)) {\n socket.on(key, (...args: any[]) => {\n const cb = args[args.length - 1];\n\n fn.apply(this, args.slice(0, -1))\n .then((result) => {\n cb(result, null);\n })\n .catch((err) => {\n cb(null, err);\n });\n });\n }\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table with the given configuration.\n * @param request - An object containing the table configuration.\n */\n private async createOrExtendTable(request: {\n tableCfg: TableCfg;\n }): Promise<void> {\n return this._io.createOrExtendTable(request);\n }\n\n // ...........................................................................\n /**\n * Generates a transport layer object that always delegates to the current\n * this._io. Each method is an arrow function reading this._io at call\n * time so that external code can replace _io after construction and all\n * existing socket handlers pick up the new instance.\n */\n private _generateTransportLayerCRUD = () =>\n ({\n init: () => this._io.init(),\n close: () => this._io.close(),\n isOpen: () =>\n new Promise((resolve) => resolve(this._io.isOpen)) as Promise<boolean>,\n isReady: () => this._io.isReady(),\n dump: () => this._io.dump(),\n dumpTable: (request: { table: string }) => this._io.dumpTable(request),\n contentType: (request: { table: string }) =>\n this._io.contentType(request),\n tableExists: (tableKey: TableKey) => this._io.tableExists(tableKey),\n createOrExtendTable: (request: { tableCfg: TableCfg }) =>\n this.createOrExtendTable(request),\n rawTableCfgs: () => this._io.rawTableCfgs(),\n write: (request: { data: Rljson }) => this._io.write(request),\n readRows: (request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }) => this._io.readRows(request),\n rowCount: (table: string) => this._io.rowCount(table),\n } as { [key: string]: (...args: any[]) => Promise<any> });\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io, IoMem } from './index.ts';\n\n// .............................................................................\n/**\n * Io implementation need to implement this interface to be used in\n * conformance tests.\n */\nexport interface IoTestSetup {\n /** setup before the single setups */\n beforeAll: () => Promise<void>;\n\n /**\n * Initializes the io implementation.\n * @returns The io implementation.\n */\n beforeEach: () => Promise<void>;\n\n /**\n * Tears down the io implementation.\n * @returns The io implementation.\n */\n afterEach: () => Promise<void>;\n\n /** cleanup after all tests */\n afterAll: () => Promise<void>;\n\n /**\n * The io implementation to be used in the conformance tests.\n */\n io: Io;\n}\n\n// .............................................................................\n// Example implementation of the IoTestSetup interface\nexport const exampleTestSetup = (): IoTestSetup => {\n return {\n io: new IoMem(),\n beforeAll: async () => {\n // This method can be used for any additional setup required before init.\n // Currently, it does nothing.\n },\n\n beforeEach: async () => {\n // Initialize the io implementation\n },\n afterEach: async () => {\n // Tear down the io implementation\n },\n\n afterAll: async () => {\n // This method can be used for any additional cleanup after tearDown.\n },\n };\n};\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { ContentType, Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\n\n// .............................................................................\nexport interface Io {\n // ...........................................................................\n // General\n\n /** Starts the initialization */\n init(): Promise<void>;\n\n /** Closes the io */\n close(): Promise<void>;\n\n /** Returns true if io is opened */\n isOpen: boolean;\n\n /** A promise resolving once the Io interface is ready\n *\n * 💡 Use @rljson/is-ready\n */\n isReady(): Promise<void>;\n\n // ...........................................................................\n // Dump\n\n /** Returns the complete db content as Rljson */\n dump(): Promise<Rljson>;\n\n /** Returns the dump of a complete table */\n dumpTable(request: { table: string }): Promise<Rljson>;\n\n // ...........................................................................\n // Meta Data\n contentType(request: { table: string }): Promise<ContentType>;\n\n // ...........................................................................\n // Tables\n\n /**\n * Returns true if the table exists\n */\n tableExists(tableKey: TableKey): Promise<boolean>;\n\n /**\n * Creates a table with a given config.\n * If the table already exists, new columns are added to the existing table.\n * If the table does not exist, it is created with the given config.\n * If the table exists and columns are removed, an error is thrown.\n * If the table exists and the column type is changed, an error is thrown.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void>;\n\n /**\n * Returns a json structure returning current table configurations\n */\n rawTableCfgs(): Promise<TableCfg[]>;\n\n // ...........................................................................\n // Write\n\n /** Writes Rljson data into the database */\n write(request: { data: Rljson }): Promise<void>;\n\n // ...........................................................................\n // Read rows\n\n /** Queries a list of rows */\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson>;\n\n /** Returns the number of rows in the given table */\n rowCount(table: string): Promise<number>;\n}\n\n// .............................................................................\nexport const exampleIo =\n 'Checkout @rljson/io-mem for an example implementation';\n","/* v8 ignore file -- @preserve */\n// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Json } from '@rljson/json';\nimport {\n Buffet,\n Cake,\n iterateTablesSync,\n Layer,\n Ref,\n Rljson,\n TableKey,\n} from '@rljson/rljson';\n\n// .............................................................................\n/**\n * Describes a row that references a child table row\n */\nexport interface ParentRef {\n /**\n * The parent table that references the child table\n */\n [parentTable: TableKey]: {\n /**\n * The parent row that references the child row\n */\n [parentRow: Ref]: {\n /**\n * Details about the reference, e.g. an array index etc.\n */\n details?: Json;\n };\n };\n}\n\n// .............................................................................\n/**\n * Describes the parent table rows referencing a child table row\n */\nexport interface ReverseRefs {\n /**\n * The child table we need the referencing rows for\n */\n [childTable: TableKey]: {\n /**\n * The row hashwe need the referencing rows for\n */\n [childRow: Ref]: ParentRef;\n };\n}\n\n/* v8 ignore start -- @preserve */\n\n// .............................................................................\n/**\n * Calculates the reverse references for a given rljson object\n */\nexport const calcReverseRefs = (rljson: Rljson): ReverseRefs => {\n const result: ReverseRefs = {};\n\n // ......................\n // Prepare data structure\n iterateTablesSync(rljson, (childTableKey, table) => {\n const childTable: { [childRowHash: string]: ParentRef } = {};\n result[childTableKey] = childTable;\n for (const childRow of table._data) {\n childTable[childRow._hash] = {};\n }\n });\n\n // ............................\n // Generate reverse references\n iterateTablesSync(rljson, (parentTableKey, parentTable) => {\n // Iterate all rows of each table\n for (const parentTableRow of parentTable._data) {\n // Find out whe other tables & rows are referenced by this row\n // Write these information intto result\n switch (parentTable._type) {\n case 'components':\n _writeComponentRefs(parentTableKey, parentTableRow, result);\n break;\n\n case 'layers': {\n _writeLayerRefs(parentTableKey, parentTableRow, result);\n break;\n }\n\n case 'sliceIds': {\n // Slice ids do not reference other tables\n break;\n }\n\n case 'cakes': {\n _writeCakeRefs(parentTableKey, parentTableRow, result);\n break;\n }\n\n case 'buffets': {\n _writeBuffetRefs(parentTableKey, parentTableRow, result);\n break;\n }\n }\n }\n });\n\n return result;\n};\n\n/* v8 ignore stop -- @preserve */\n\n// .............................................................................\nconst _writeComponentRefs = (\n parentTableName: TableKey,\n parentRow: Json,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const parentColumnName in parentRow) {\n if (parentColumnName.startsWith('_')) {\n continue;\n }\n\n if (!parentColumnName.endsWith('Ref')) {\n continue;\n }\n\n const childTableName = parentColumnName.slice(0, -3);\n const childRowHash = parentRow[parentColumnName] as string;\n\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _writeLayerRefs = (\n parentTableName: TableKey,\n parentRow: Layer,\n result: ReverseRefs,\n) => {\n const childTableName = parentRow.componentsTable;\n const parentRowHash = parentRow._hash as string;\n\n for (const sliceId in parentRow.add) {\n if (sliceId.startsWith('_')) {\n continue;\n }\n\n const sliceHash = parentRow.add[sliceId] as string;\n\n _write(result, childTableName, sliceHash, parentTableName, parentRowHash);\n }\n};\n\n// .............................................................................\nconst _writeCakeRefs = (\n parentTableName: TableKey,\n parentRow: Cake,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const layer in parentRow.layers) {\n const childTableName = layer;\n const childRowHash = parentRow.layers[layer] as string;\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _writeBuffetRefs = (\n parentTableName: TableKey,\n parentRow: Buffet,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const item of parentRow.items) {\n const childTableName = item.table;\n const childRowHash = item.ref;\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _write = (\n result: ReverseRefs,\n childTableName: string,\n childRowHash: string,\n parentTableName: string,\n parentRowHash: string,\n) => {\n const referencesForChildTable = (result[childTableName] ??= {});\n const referencesForChildTableRow = (referencesForChildTable[childRowHash] ??=\n {});\n\n referencesForChildTableRow[parentTableName] ??= {};\n referencesForChildTableRow[parentTableName][parentRowHash] ??= {};\n};\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n/* v8 ignore file -- @preserve */\nimport { Socket } from './socket.ts';\n\nexport class SocketMock implements Socket {\n public connected: boolean = false;\n public disconnected: boolean = true;\n\n private _listeners: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n private _onceListeners: Map<\n string | symbol,\n Array<(...args: any[]) => void>\n > = new Map();\n\n connect(): void {\n if (!this.connected) {\n this.connected = true;\n this.disconnected = false;\n this.emit('connect');\n }\n }\n\n disconnect(): void {\n if (this.connected) {\n this.connected = false;\n this.disconnected = true;\n this.emit('disconnect');\n }\n }\n\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName)!.push(listener);\n return this;\n }\n\n once(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._onceListeners.has(eventName)) {\n this._onceListeners.set(eventName, []);\n }\n this._onceListeners.get(eventName)!.push(listener);\n return this;\n }\n\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this {\n if (listener) {\n // Remove specific listener\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n const index = regularListeners.indexOf(listener);\n if (index > -1) {\n regularListeners.splice(index, 1);\n }\n }\n\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const index = onceListeners.indexOf(listener);\n if (index > -1) {\n onceListeners.splice(index, 1);\n }\n }\n } else {\n // Remove all listeners for the event\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n }\n return this;\n }\n\n emit(eventName: string | symbol, ...args: any[]): boolean {\n let hasListeners = false;\n\n // Emit to regular listeners\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners && regularListeners.length > 0) {\n hasListeners = true;\n // Create a copy to avoid issues if listeners are removed during emission\n [...regularListeners].forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n // In a real EventEmitter, this would be handled differently\n console.error(\n `Error in listener for event ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n\n // Emit to once listeners and remove them\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners && onceListeners.length > 0) {\n hasListeners = true;\n // Create a copy and clear the original array\n const listenersToCall = [...onceListeners];\n this._onceListeners.delete(eventName);\n\n listenersToCall.forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(\n `Error in once listener for event ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n\n return hasListeners;\n }\n\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName !== undefined) {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n } else {\n this._listeners.clear();\n this._onceListeners.clear();\n }\n return this;\n }\n\n listenerCount(eventName: string | symbol): number {\n const regularCount = this._listeners.get(eventName)?.length || 0;\n const onceCount = this._onceListeners.get(eventName)?.length || 0;\n return regularCount + onceCount;\n }\n\n listeners(eventName: string | symbol): Array<(...args: any[]) => void> {\n const regularListeners = this._listeners.get(eventName) || [];\n const onceListeners = this._onceListeners.get(eventName) || [];\n return [...regularListeners, ...onceListeners];\n }\n\n eventNames(): Array<string | symbol> {\n const allEvents = new Set([\n ...this._listeners.keys(),\n ...this._onceListeners.keys(),\n ]);\n return Array.from(allEvents);\n }\n\n // Test helper methods\n reset(): void {\n this.connected = false;\n this.disconnected = true;\n this.removeAllListeners();\n }\n\n simulateError(error: Error): void {\n this.emit('error', error);\n }\n\n simulateMessage(message: any): void {\n this.emit('message', message);\n }\n\n // Get internal state for testing\n getListeners(): Map<string | symbol, Array<(...args: any[]) => void>> {\n return new Map(this._listeners);\n }\n\n getOnceListeners(): Map<string | symbol, Array<(...args: any[]) => void>> {\n return new Map(this._onceListeners);\n }\n}\n\n// ...existing code...\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Socket } from './socket.ts';\n\n\n/**\n * Creates a pair of connected sockets that properly route messages between them.\n * Unlike SocketMock, this maintains directionality - when socketA emits, only socketB's\n * listeners fire, not socketA's own listeners.\n *\n * This is essential for client-server testing where both use the same socket instance\n * but need separate event handling.\n */\nexport function createSocketPair(): [\n DirectionalSocketMock,\n DirectionalSocketMock,\n] {\n const socketA = new DirectionalSocketMock();\n const socketB = new DirectionalSocketMock();\n\n // Connect them bidirectionally\n socketA._setPeer(socketB);\n socketB._setPeer(socketA);\n\n return [socketA, socketB];\n}\n\nexport class DirectionalSocketMock implements Socket {\n public connected: boolean = false;\n public disconnected: boolean = true;\n\n private _peer?: DirectionalSocketMock;\n private _listeners: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n private _onceListeners: Map<\n string | symbol,\n Array<(...args: any[]) => void>\n > = new Map();\n\n _setPeer(peer: DirectionalSocketMock): void {\n this._peer = peer;\n }\n\n connect(): void {\n if (!this.connected) {\n this.connected = true;\n this.disconnected = false;\n // Trigger local 'connect' event\n this._triggerLocal('connect');\n // Trigger peer's 'connect' event\n if (this._peer) {\n this._peer._triggerLocal('connect');\n }\n }\n }\n\n disconnect(): void {\n if (this.connected) {\n this.connected = false;\n this.disconnected = true;\n this._triggerLocal('disconnect');\n if (this._peer) {\n this._peer._triggerLocal('disconnect');\n }\n }\n }\n\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName)!.push(listener);\n return this;\n }\n\n once(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._onceListeners.has(eventName)) {\n this._onceListeners.set(eventName, []);\n }\n this._onceListeners.get(eventName)!.push(listener);\n return this;\n }\n\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this {\n if (listener) {\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n const index = regularListeners.indexOf(listener);\n if (index > -1) regularListeners.splice(index, 1);\n }\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const index = onceListeners.indexOf(listener);\n if (index > -1) onceListeners.splice(index, 1);\n }\n } else {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n }\n return this;\n }\n\n /**\n * Emits an event to the PEER socket (cross-socket emission).\n * This is the key difference from SocketMock - emit() sends to the other side,\n * not to local listeners.\n *\n * Implements Socket.IO acknowledgement pattern: the last argument can be a callback\n * that the peer will invoke to send a response back.\n */\n emit(eventName: string | symbol, ...args: any[]): boolean {\n if (!this._peer) {\n console.warn(\n `DirectionalSocketMock.emit: No peer connected for event ${String(eventName)}`,\n );\n return false;\n }\n\n // Trigger the event on the PEER socket, not locally\n this._peer._triggerLocal(eventName, ...args);\n return true;\n }\n\n /**\n * Triggers listeners on THIS socket (local emission).\n * Used internally when receiving events from peer.\n */\n private _triggerLocal(eventName: string | symbol, ...args: any[]): void {\n // Trigger regular listeners\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n [...regularListeners].forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(`Error in listener for ${String(eventName)}:`, error);\n }\n });\n }\n\n // Trigger and remove once listeners\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const listenersToCall = [...onceListeners];\n this._onceListeners.delete(eventName);\n listenersToCall.forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(\n `Error in once listener for ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n }\n\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName !== undefined) {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n } else {\n this._listeners.clear();\n this._onceListeners.clear();\n }\n return this;\n }\n\n listenerCount(eventName: string | symbol): number {\n const regularCount = this._listeners.get(eventName)?.length || 0;\n const onceCount = this._onceListeners.get(eventName)?.length || 0;\n return regularCount + onceCount;\n }\n\n listeners(eventName: string | symbol): Array<(...args: any[]) => void> {\n const regularListeners = this._listeners.get(eventName) || [];\n const onceListeners = this._onceListeners.get(eventName) || [];\n return [...regularListeners, ...onceListeners];\n }\n\n eventNames(): Array<string | symbol> {\n const allEvents = new Set([\n ...this._listeners.keys(),\n ...this._onceListeners.keys(),\n ]);\n return Array.from(allEvents);\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\n//Interface for a generic Socket, similar to Node.js EventEmitter\n//This is a simplified version and may not cover all features of a full EventEmitter\nexport interface Socket {\n connected: boolean;\n disconnected: boolean;\n connect(): void;\n disconnect(): void;\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n emit(eventName: string | symbol, ...args: any[]): boolean | this;\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this;\n removeAllListeners(eventName?: string | symbol): this;\n}\n\nexport const socketExample = (): Socket => ({\n connected: false,\n disconnected: true,\n connect() {\n this.connected = true;\n this.disconnected = false;\n this.emit('connect');\n },\n disconnect() {\n this.connected = false;\n this.disconnected = true;\n this.emit('disconnect');\n },\n /* v8 ignore next -- @preserve */\n on() {\n // Implementation of event listener registration\n return this;\n },\n /* v8 ignore next -- @preserve */\n emit() {\n // Implementation of event emission\n return true;\n },\n /* v8 ignore next -- @preserve */\n off() {\n // Implementation of event listener removal\n return this;\n },\n /* v8 ignore next -- @preserve */\n removeAllListeners() {\n // Implementation of removing all listeners\n return this;\n },\n});\n"],"names":["e"],"mappings":"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"}
1
+ {"version":3,"file":"io.js","sources":["/Users/maximilianheller/Documents/Development/rljson-io/src/io-db-name-mapping.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-tools.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-mem.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/peer-socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-peer.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-multi.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-peer-bridge.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-server.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io-test-setup.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/io.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/reverse-ref.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/directional-socket-mock.ts","/Users/maximilianheller/Documents/Development/rljson-io/src/socket.ts"],"sourcesContent":["// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nexport class IoDbNameMapping {\n // The primary key column is always named '_hash'\n public primaryKeyColumn: string = '_hash';\n public dataSection: string = '_data';\n public typeColumn: string = 'type';\n public keyColumn: string = 'key';\n\n // Names for the main tables in the database\n public tableNames: { [key: string]: string } = {\n main: 'tableCfgs',\n revision: 'revisions',\n };\n\n /// Suffix handling for the database\n private _suffix: { [key: string]: string } = {\n col: '_col',\n tbl: '_tbl',\n tmp: '_tmp',\n };\n\n // ********************************************************************\n // add and remove suffixes for use in SQL statements\n private _addFix(name: string, fix: string): string {\n return name.endsWith(fix) ? name : name + fix;\n }\n\n public addTableSuffix(name: string): string {\n return this._addFix(name, this._suffix.tbl);\n }\n\n public addColumnSuffix(name: string): string {\n return this._addFix(name, this._suffix.col);\n }\n\n public addTmpSuffix(name: string): string {\n return this._addFix(name, this._suffix.tmp);\n }\n\n private _removeFix(name: string, fix: string): string {\n return name.endsWith(fix) ? name.slice(0, -fix.length) : name;\n }\n\n public removeTableSuffix(name: string): string {\n return this._removeFix(name, this._suffix.tbl);\n }\n\n public removeColumnSuffix(name: string): string {\n return this._removeFix(name, this._suffix.col);\n }\n\n public removeTmpSuffix(name: string): string {\n return this._removeFix(name, this._suffix.tmp);\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip } from '@rljson/hash';\nimport {\n iterateTables,\n Rljson,\n TableCfg,\n TableKey,\n TableType,\n throwOnInvalidTableCfg,\n validateRljsonAgainstTableCfg,\n} from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { Io } from './io.ts';\n\nexport type IoObserver = (data: Rljson) => void;\n\n/**\n * Provides utility functions for the Io interface.\n */\nexport class IoTools {\n /**\n * Constructor\n * @param io The Io interface to use\n */\n constructor(public readonly io: Io) {}\n\n /**\n * Returns the table configuration of the tableCfgs table.\n */\n static get tableCfgsTableCfg() {\n const tableCfg = hip<TableCfg>({\n _hash: '',\n key: 'tableCfgs',\n type: 'tableCfgs',\n isHead: false,\n isRoot: false,\n isShared: true,\n previous: '',\n\n columns: [\n {\n key: '_hash',\n type: 'string',\n titleShort: 'Hash',\n titleLong: 'Row Hash',\n },\n {\n key: 'key',\n type: 'string',\n titleShort: 'Key',\n titleLong: 'Table Key',\n },\n {\n key: 'type',\n type: 'string',\n titleShort: 'Type',\n titleLong: 'Content Type',\n },\n {\n key: 'isHead',\n type: 'boolean',\n titleShort: 'Is Head',\n titleLong: 'Is Head Table',\n },\n {\n key: 'isRoot',\n type: 'boolean',\n titleShort: 'Is Root',\n titleLong: 'Is Root Table',\n },\n {\n key: 'isShared',\n type: 'boolean',\n titleShort: 'Is Shared',\n titleLong: 'Is Shared Table',\n },\n {\n key: 'previous',\n type: 'string',\n titleShort: 'Previous',\n titleLong: 'Previous Table Configuration Hash',\n },\n {\n key: 'columns',\n type: 'jsonArray',\n titleShort: 'Columns',\n titleLong: 'Column Configurations',\n },\n ],\n });\n\n return tableCfg;\n }\n\n /**\n * Initializes the revisions table.\n */\n initRevisionsTable = async () => {\n const tableCfg: TableCfg = {\n key: 'revisions',\n type: 'revisions',\n isHead: true,\n isRoot: true,\n isShared: false,\n\n columns: [\n {\n key: '_hash',\n type: 'string',\n titleShort: 'Hash',\n titleLong: 'Row Hash',\n },\n {\n key: 'table',\n type: 'string',\n titleShort: 'Table',\n titleLong: 'Table Key',\n },\n {\n key: 'predecessor',\n type: 'string',\n titleShort: 'Predecessor',\n titleLong: 'Predecessor Revision Hash',\n },\n {\n key: 'successor',\n type: 'string',\n titleShort: 'Successor',\n titleLong: 'Successor Revision Hash',\n },\n {\n key: 'timestamp',\n type: 'number',\n titleShort: 'Timestamp',\n titleLong: 'Revision Timestamp',\n },\n {\n key: 'id',\n type: 'string',\n titleShort: 'ID',\n titleLong: 'Revision ID',\n },\n ],\n };\n\n await this.io.createOrExtendTable({ tableCfg });\n };\n\n /**\n * Example object for test purposes\n * @returns An instance of io tools\n */\n static example = async () => {\n const io = await IoMem.example();\n await io.init();\n await io.isReady();\n return new IoTools(io);\n };\n\n /**\n * Throws if the table does not exist\n */\n async throwWhenTableDoesNotExist(table: TableKey): Promise<void> {\n const exists = await this.io.tableExists(table);\n if (!exists) {\n throw new Error(`Table \"${table}\" not found`);\n }\n }\n\n /**\n * Throws if any of the tables in rljson do not exist\n * @param rljson - The Rljson object to check\n */\n async throwWhenTablesDoNotExist(rljson: Rljson): Promise<void> {\n try {\n await iterateTables(rljson, async (tableKey) => {\n const exists = await this.io.tableExists(tableKey);\n if (!exists) {\n throw new Error(`Table \"${tableKey}\" not found`);\n }\n });\n } catch (e) {\n const missingTables = (e as Array<any>).map((e) => e.tableKey);\n\n throw new Error(\n `The following tables do not exist: ${missingTables.join(', ')}`,\n );\n }\n }\n\n /**\n * Returns the current table cfgs of all tables\n * @returns The table configuration of all tables\n */\n async tableCfgs(): Promise<TableCfg[]> {\n const tables = await this.io.rawTableCfgs();\n\n // Take the latest version of each type key\n const newestVersion: Record<TableKey, TableCfg> = {};\n for (let i = tables.length - 1; i >= 0; i--) {\n const table = tables[i];\n const existing = newestVersion[table.key];\n if (!existing || existing.columns.length < table.columns.length) {\n newestVersion[table.key] = table;\n }\n }\n\n // Sort the tables by key\n /* v8 ignore next -- @preserve */\n const resultData = Object.values(newestVersion).sort((a, b) => {\n if (a.key < b.key) {\n return -1;\n }\n if (a.key > b.key) {\n return 1;\n }\n\n return 0;\n });\n return resultData;\n }\n\n /**\n * Returns a list with all table names\n */\n async allTableKeys(): Promise<string[]> {\n const result = (await this.tableCfgs()).map((e) => e.key);\n return result;\n }\n\n /**\n * Returns the configuration of a given table\n */\n async tableCfg(table: TableKey): Promise<TableCfg> {\n const tableCfg = await this.tableCfgOrNull(table);\n if (!tableCfg) {\n throw new Error(`Table \"${table}\" not found`);\n }\n\n return tableCfg!;\n }\n\n /**\n * Returns the configuration of a given table or null if it does not exist.\n\n */\n async tableCfgOrNull(table: TableKey): Promise<TableCfg | null> {\n const tableCfgs = await this.tableCfgs();\n const tableCfg = tableCfgs.find((e) => e.key === table);\n return tableCfg ?? null;\n }\n\n /**\n * Returns a list of all column names of a given table\n */\n async allColumnKeys(table: TableKey): Promise<string[]> {\n const tableCfg = await this.tableCfg(table);\n const result = tableCfg.columns.map((column) => column.key);\n return result;\n }\n\n /**\n * Throws when a column does not exist in a given table\n * @param table - The table to check\n * @param columns - The column to check\n */\n async throwWhenColumnDoesNotExist(\n table: TableKey,\n columns: string[],\n ): Promise<void> {\n const tableCfg = await this.tableCfg(table);\n const columnKeys = tableCfg.columns.map((column) => column.key);\n const missingColumns = columns.filter(\n (column) => !columnKeys.includes(column),\n );\n if (missingColumns.length > 0) {\n throw new Error(\n `The following columns do not exist in table \"${table}\": ${missingColumns.join(\n ', ',\n )}.`,\n );\n }\n }\n\n /**\n * Throws when a table update is not compatible with the current table\n * configuration.\n */\n async throwWhenTableIsNotCompatible(update: TableCfg): Promise<void> {\n const prefix = `Invalid update of table able \"${update.key}\"`;\n\n throwOnInvalidTableCfg(update);\n\n // Check compatibility with existing table\n const existing = await this.tableCfgOrNull(update.key);\n if (existing) {\n // Have columns been deleted?\n if (existing.columns.length > update.columns.length) {\n const deletedColumnKeys = existing.columns\n .map((column) => column.key)\n .filter(\n (key) => !update.columns.some((column) => column.key === key),\n );\n /* v8 ignore next -- @preserve */\n if (deletedColumnKeys.length > 0) {\n const deletedColumns = deletedColumnKeys.join(', ');\n throw new Error(\n `${prefix}: Columns must not be deleted. ` +\n `Deleted columns: ${deletedColumns}}`,\n );\n }\n }\n\n // Have column keys changed?\n for (let i = 0; i < existing.columns.length; i++) {\n const before = existing.columns[i].key;\n const after = update.columns[i].key;\n if (before !== after) {\n throw new Error(\n `${prefix}: ` +\n `Column keys must not change! ` +\n `Column \"${before}\" was renamed into \"${after}\".`,\n );\n }\n }\n\n // Have column types changed?\n for (let i = 0; i < existing.columns.length; i++) {\n const column = existing.columns[i].key;\n const before = existing.columns[i].type;\n const after = update.columns[i].type;\n if (before !== after) {\n throw new Error(\n `${prefix}: ` +\n `Column types must not change! ` +\n `Type of column \"${column}\" was changed from \"${before}\" to ${after}.`,\n );\n }\n }\n }\n }\n\n /**\n * Throws if the data in the table do not match the table configuration\n */\n async throwWhenTableDataDoesNotMatchCfg(data: Rljson) {\n const errors: string[] = [];\n\n await iterateTables(data, async (tableKey) => {\n const tableCfg = await this.tableCfg(tableKey);\n const table = data[tableKey];\n\n // Ignore tableCfgs table\n /* v8 ignore next -- @preserve */\n if (table._type === 'tableCfgs') return;\n\n errors.push(...validateRljsonAgainstTableCfg(table._data, tableCfg));\n });\n\n if (errors.length > 0) {\n throw new Error(\n `Table data does not match the configuration.\\n\\nErrors:\\n${errors\n .map((e) => `- ${e}`)\n .join('\\n')}`,\n );\n }\n }\n\n /**\n * Sorts the data of a table by the hash and updates the table hash in place\n */\n sortTableDataAndUpdateHash(table: TableType): void {\n table._data.sort((a, b) => {\n const hashA = a._hash as string;\n const hashB = b._hash as string;\n /* v8 ignore next -- @preserve */\n if (hashA < hashB) {\n return -1;\n }\n /* v8 ignore next -- @preserve */\n if (hashA > hashB) {\n return 1;\n }\n\n /* v8 ignore next -- @preserve */\n return 0;\n });\n\n table._hash = '';\n hip(table, {\n updateExistingHashes: false,\n throwOnWrongHashes: false,\n });\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip, hsh } from '@rljson/hash';\nimport { IsReady } from '@rljson/is-ready';\nimport { copy, equals, JsonValue } from '@rljson/json';\nimport {\n ContentType,\n iterateTablesSync,\n Rljson,\n TableCfg,\n TableKey,\n TableType,\n validateRljsonAgainstTableCfg,\n} from '@rljson/rljson';\n\nimport { IoTools } from './io-tools.ts';\nimport { Io } from './io.ts';\n\n\n/**\n * In-Memory implementation of the Rljson Io interface.\n */\nexport class IoMem implements Io {\n // ...........................................................................\n // Constructor & example\n\n init(): Promise<void> {\n this._isOpen = true;\n return this._init();\n }\n\n close(): Promise<void> {\n this._isOpen = false;\n return Promise.resolve();\n }\n\n get isOpen(): boolean {\n return this._isOpen;\n }\n\n static example = async () => {\n const io = new IoMem();\n await io.init();\n return io;\n };\n\n // ...........................................................................\n // General\n isReady() {\n return this._isReady.promise;\n }\n\n // ...........................................................................\n // Dump\n\n dump(): Promise<Rljson> {\n return this._dump();\n }\n\n async dumpTable(request: { table: string }): Promise<Rljson> {\n return this._dumpTable(request);\n }\n\n // ...........................................................................\n // Meta Data\n\n async contentType(request: { table: string }): Promise<ContentType> {\n return this._contentType(request);\n }\n\n // ...........................................................................\n // Rows\n\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue };\n }): Promise<Rljson> {\n return this._readRows(request);\n }\n\n async readRowsByHashes(request: {\n table: string;\n hashes: string[];\n }): Promise<Rljson> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n\n const table = this._mem[request.table] as TableType;\n const rowIndex = this._rowIndexFor(request.table);\n\n const seen = new Set<string>();\n const rows: any[] = [];\n for (const hash of request.hashes) {\n if (seen.has(hash)) continue;\n seen.add(hash);\n const row = rowIndex.get(hash);\n if (row) {\n rows.push(row);\n }\n }\n\n const tableFiltered: TableType = {\n _type: table._type,\n _data: rows,\n };\n this._ioTools.sortTableDataAndUpdateHash(tableFiltered);\n\n return { [request.table]: tableFiltered };\n }\n\n async rowCount(table: string): Promise<number> {\n const tableData = this._mem[table] as TableType;\n if (!tableData) {\n throw new Error(`Table \"${table}\" not found`);\n }\n return Promise.resolve(tableData._data.length);\n }\n\n // ...........................................................................\n // Write\n\n write(request: { data: Rljson }): Promise<void> {\n return this._write(request);\n }\n\n // ...........................................................................\n // Table management\n async tableExists(tableKey: TableKey): Promise<boolean> {\n const table = this._mem[tableKey] as TableType;\n return table ? true : false;\n }\n\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n return this._createOrExtendTable(request);\n }\n\n async rawTableCfgs(): Promise<TableCfg[]> {\n const tables = this._mem.tableCfgs._data as TableCfg[];\n return tables;\n }\n\n // ######################\n // Private\n // ######################\n\n private _ioTools!: IoTools;\n\n private _isReady = new IsReady();\n private _isOpen = false;\n\n private _mem: Rljson = hip({} as Rljson);\n\n /**\n * Latest table configuration per table (the one with the most\n * columns). Kept in sync by _createTable/_extendTable so that reads\n * and writes need no repeated scan over all configurations.\n */\n private readonly _latestCfgs = new Map<TableKey, TableCfg>();\n\n /** Column key sets per table, derived from _latestCfgs */\n private readonly _columnKeys = new Map<TableKey, Set<string>>();\n\n /**\n * Per-table index of rows by content hash. Rows are only ever added,\n * never removed, so the index cannot go stale.\n */\n private readonly _rowIndex = new Map<TableKey, Map<string, any>>();\n\n /**\n * Tables whose table hash (and thus the global hash) is outdated\n * after writes. Hashes are refreshed lazily before they become\n * observable (dump, dumpTable, create/extend) instead of after every\n * single write — row hashes themselves are always up to date.\n */\n private readonly _dirtyTableHashes = new Set<TableKey>();\n\n // ...........................................................................\n /**\n * Recomputes the hashes of all dirty tables and the global hash.\n * Produces exactly the state an eager per-write update would have\n * produced (hashes are deterministic over the same data).\n */\n private _refreshHashes(): void {\n if (this._dirtyTableHashes.size === 0) {\n return;\n }\n\n for (const tableKey of this._dirtyTableHashes) {\n const table = this._mem[tableKey] as TableType;\n table._hash = '';\n hip(table, {\n updateExistingHashes: false,\n throwOnWrongHashes: false,\n });\n }\n this._dirtyTableHashes.clear();\n\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n /**\n * Returns the row index of a table, building it lazily from the\n * table data on first access.\n * @param table - The table to index\n */\n private _rowIndexFor(table: TableKey): Map<string, any> {\n let index = this._rowIndex.get(table);\n if (!index) {\n index = new Map();\n const tableData = (this._mem[table] as TableType)._data;\n for (const row of tableData) {\n index.set(row._hash as string, row);\n }\n this._rowIndex.set(table, index);\n }\n return index;\n }\n\n // ...........................................................................\n /**\n * Inserts a row into hash-sorted table data at its sorted position —\n * preserves the order sortTableDataAndUpdateHash establishes without\n * a full re-sort.\n * @param data - The hash-sorted table data\n * @param row - The row to insert\n */\n private static _insertSortedByHash(data: any[], row: any): void {\n const hash = row._hash as string;\n let lo = 0;\n let hi = data.length;\n while (lo < hi) {\n const mid = (lo + hi) >> 1;\n if ((data[mid]._hash as string) < hash) {\n lo = mid + 1;\n } else {\n hi = mid;\n }\n }\n data.splice(lo, 0, row);\n }\n\n // ...........................................................................\n /**\n * The row filter predicate of readRows. Extracted so that the indexed\n * fast path and the full scan share identical semantics.\n * @param row - The row to check\n * @param where - The where clause\n */\n private static _rowMatchesWhere(\n row: any,\n where: { [column: string]: JsonValue },\n ): boolean {\n for (const column in where) {\n const a = row[column];\n const b = where[column];\n if (b === null && a === undefined) {\n return true;\n }\n\n if (!equals(a, b)) {\n return false;\n }\n }\n return true;\n }\n\n // ...........................................................................\n /**\n * Returns the latest table configuration, filling the cache lazily\n * from IoTools (which picks the config with the most columns).\n * @param table - The table to get the configuration for\n */\n private async _latestCfg(table: TableKey): Promise<TableCfg> {\n let cfg = this._latestCfgs.get(table);\n if (!cfg) {\n cfg = await this._ioTools.tableCfg(table);\n this._latestCfgs.set(table, cfg);\n }\n return cfg;\n }\n\n /**\n * Updates the cached latest configuration of a table\n * @param cfg - The new latest configuration\n */\n private _setLatestCfg(cfg: TableCfg): void {\n this._latestCfgs.set(cfg.key, cfg);\n this._columnKeys.set(cfg.key, new Set(cfg.columns.map((c) => c.key)));\n }\n\n /**\n * Throws when one of the given columns does not exist in the table.\n * Mirrors IoTools.throwWhenColumnDoesNotExist but uses the cached\n * configuration.\n * @param table - The table to check\n * @param columns - The columns to check\n */\n private async _throwWhenColumnDoesNotExist(\n table: TableKey,\n columns: string[],\n ): Promise<void> {\n let columnKeys = this._columnKeys.get(table);\n if (!columnKeys) {\n const cfg = await this._latestCfg(table);\n columnKeys = new Set(cfg.columns.map((c) => c.key));\n this._columnKeys.set(table, columnKeys);\n }\n\n const missingColumns = columns.filter((column) => !columnKeys.has(column));\n if (missingColumns.length > 0) {\n throw new Error(\n `The following columns do not exist in table \"${table}\": ${missingColumns.join(\n ', ',\n )}.`,\n );\n }\n }\n\n /**\n * Throws when the data does not match the table configurations.\n * Mirrors IoTools.throwWhenTableDataDoesNotMatchCfg but uses the\n * cached configurations.\n * @param data - The data to validate\n */\n private async _throwWhenTableDataDoesNotMatchCfg(\n data: Rljson,\n ): Promise<void> {\n const errors: string[] = [];\n\n for (const tableKey of Object.keys(data)) {\n const table = data[tableKey] as TableType;\n\n // Skip non-table values (like _hash) — mirrors iterateTables\n if (typeof table !== 'object' || !Array.isArray(table?._data)) continue;\n\n // Ignore tableCfgs table\n /* v8 ignore next -- @preserve */\n if (table._type === 'tableCfgs') continue;\n\n const tableCfg = await this._latestCfg(tableKey);\n errors.push(...validateRljsonAgainstTableCfg(table._data, tableCfg));\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Table data does not match the configuration.\\n\\nErrors:\\n${errors\n .map((e) => `- ${e}`)\n .join('\\n')}`,\n );\n }\n }\n\n // ...........................................................................\n private async _init() {\n // Fold pending lazy hash updates — a re-init validates all hashes\n this._refreshHashes();\n\n // Reset caches — a re-init replaces the tableCfgs table, so cached\n // configs and indexes must be rebuilt\n this._rowIndex.clear();\n this._latestCfgs.clear();\n this._columnKeys.clear();\n\n this._ioTools = new IoTools(this);\n this._initTableCfgs();\n this._updateGlobalHash();\n await this._ioTools.initRevisionsTable();\n hsh(this._mem);\n\n this._isReady.resolve();\n }\n\n // ...........................................................................\n private _initTableCfgs = () => {\n const tableCfg = IoTools.tableCfgsTableCfg;\n\n this._mem.tableCfgs = hip({\n _type: 'tableCfgs',\n _data: [tableCfg],\n _tableCfg: tableCfg._hash as string,\n });\n };\n\n // ...........................................................................\n private _updateGlobalHash() {\n (this._mem as any)._hash = '';\n hip(this._mem, {\n updateExistingHashes: false,\n });\n }\n\n // ...........................................................................\n private _updateTableHash(tableKey: TableKey) {\n const table = this._mem[tableKey] as TableType;\n table._hash = '';\n hip(table, { updateExistingHashes: false });\n }\n\n // ...........................................................................\n private async _createOrExtendTable(request: {\n tableCfg: TableCfg;\n }): Promise<void> {\n // Fold pending lazy hash updates before the eager global hash\n // update of the create/extend paths\n this._refreshHashes();\n\n // Make sure that the table config is compatible\n // with an potential existing table\n const tableCfg = request.tableCfg;\n await this._ioTools.throwWhenTableIsNotCompatible(tableCfg);\n\n const { key } = tableCfg;\n\n // Recreate hashes in the case the existing hashes are wrong\n const newConfig = hsh(tableCfg);\n\n // Find an existing table config with the same hash\n const existingConfig = await this._ioTools.tableCfgOrNull(key);\n\n // Write the new config into the database\n if (!existingConfig) {\n this._createTable(newConfig, key);\n } else {\n this._extendTable(existingConfig, newConfig);\n }\n }\n\n // ...........................................................................\n private _createTable(newConfig: TableCfg, tableKey: TableKey) {\n // Write the table config into the database\n newConfig = hsh(newConfig);\n this._mem.tableCfgs._data.push(newConfig);\n this._ioTools.sortTableDataAndUpdateHash(this._mem.tableCfgs);\n this._setLatestCfg(newConfig);\n this._rowIndex.get('tableCfgs')?.set(newConfig._hash as string, newConfig);\n\n // Create a table and write it into the database\n const table: TableType = {\n _type: newConfig.type,\n _data: [],\n _tableCfg: newConfig._hash as string,\n };\n\n this._mem[tableKey] ??= hip(table);\n\n // Update hashes\n this._updateTableHash(tableKey);\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n private _extendTable(existingConfig: TableCfg, newConfig: TableCfg) {\n // No columns added? Return.\n if (existingConfig.columns.length === newConfig.columns.length) {\n return;\n }\n\n // Write the new table config into the database\n newConfig = hsh(newConfig);\n this._mem.tableCfgs._data.push(newConfig);\n this._ioTools.sortTableDataAndUpdateHash(this._mem.tableCfgs);\n this._setLatestCfg(newConfig);\n this._rowIndex.get('tableCfgs')?.set(newConfig._hash as string, newConfig);\n\n // Update the config of the existing table\n const table = this._mem[newConfig.key] as TableType;\n table._tableCfg = newConfig._hash as string;\n\n // Update the hashes\n this._updateTableHash(newConfig.key);\n this._updateGlobalHash();\n }\n\n // ...........................................................................\n\n private async _dump(): Promise<Rljson> {\n this._refreshHashes();\n return copy(this._mem);\n }\n\n // ...........................................................................\n private async _dumpTable(request: { table: string }): Promise<Rljson> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n\n this._refreshHashes();\n const table = this._mem[request.table] as TableType;\n\n return {\n [request.table]: copy(table),\n };\n }\n\n // ...........................................................................\n private async _contentType(request: { table: string }): Promise<ContentType> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n\n return (this._mem[request.table] as TableType)._type;\n }\n\n // ...........................................................................\n private async _write(request: { data: Rljson }): Promise<void> {\n const addedData = hsh(request.data);\n const removedNullValues = this._removeNullValues(addedData);\n const tables = Object.keys(addedData);\n\n // Row hashes only change when null values were actually removed\n if (removedNullValues) {\n hsh(addedData);\n }\n\n await this._ioTools.throwWhenTablesDoNotExist(request.data);\n await this._throwWhenTableDataDoesNotMatchCfg(request.data);\n\n for (const table of tables) {\n if (table.startsWith('_')) {\n continue;\n }\n\n const oldTable = this._mem[table] as TableType;\n const newTable = addedData[table] as TableType;\n const rowIndex = this._rowIndexFor(table);\n\n // Table exists. Merge data — O(1) dedup via the row index and\n // sorted insert instead of a linear scan plus full re-sort\n for (const item of newTable._data) {\n const hash = item._hash as string;\n if (!rowIndex.has(hash)) {\n rowIndex.set(hash, item);\n IoMem._insertSortedByHash(oldTable._data, item);\n }\n }\n\n // Table and global hash are refreshed lazily before they become\n // observable — see _refreshHashes\n this._dirtyTableHashes.add(table);\n }\n }\n\n // ...........................................................................\n private async _readRows(request: {\n table: string;\n where: { [column: string]: JsonValue };\n }): Promise<Rljson> {\n await this._ioTools.throwWhenTableDoesNotExist(request.table);\n await this._throwWhenColumnDoesNotExist(\n request.table,\n Object.keys(request.where),\n );\n\n // Read table from data\n const table = this._mem[request.table] as TableType;\n\n // Filter table data. Lookups by content hash use the row index\n // instead of scanning the whole table.\n const whereHash = request.where['_hash'];\n let tableDataFiltered: any[];\n if (typeof whereHash === 'string') {\n const row = this._rowIndexFor(request.table).get(whereHash);\n tableDataFiltered =\n row && IoMem._rowMatchesWhere(row, request.where) ? [row] : [];\n } else {\n tableDataFiltered = table._data.filter((row) =>\n IoMem._rowMatchesWhere(row, request.where),\n );\n }\n\n // Create an table\n const tableFiltered: TableType = {\n _type: table._type,\n _data: tableDataFiltered,\n };\n\n this._ioTools.sortTableDataAndUpdateHash(tableFiltered);\n\n const result: Rljson = {\n [request.table]: tableFiltered,\n };\n\n return result;\n }\n\n _removeNullValues(rljson: Rljson): boolean {\n let removedAny = false;\n\n iterateTablesSync(rljson, (table) => {\n const data = rljson[table]._data;\n\n for (const row of data) {\n for (const key in row) {\n if (row[key] === null) {\n delete row[key];\n removedAny = true;\n }\n }\n }\n });\n\n return removedAny;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\nexport class PeerSocketMock implements Socket {\n private _listenersMap: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n\n connected: boolean = false;\n disconnected: boolean = true;\n\n constructor(private _io: Io) {}\n\n // ............................................................................\n /**\n * Removes a specific listener for the specified event.\n * @param eventName - The name of the event.\n * @param listener - The callback function to remove.\n * @returns The PeerSocketMock instance for chaining.\n */\n off(eventName: string | symbol, listener: (...args: any[]) => void): this {\n /* v8 ignore next -- @preserve */\n const listeners = this._listenersMap.get(eventName) || [];\n const index = listeners.indexOf(listener);\n /* v8 ignore else -- @preserve */\n if (index !== -1) {\n listeners.splice(index, 1);\n this._listenersMap.set(eventName, listeners);\n }\n return this;\n }\n\n // ............................................................................\n /**\n * Removes all listeners for the specified event, or all listeners if no event is specified.\n * @param eventName - (Optional) The name of the event.\n * @returns The PeerSocketMock instance for chaining.\n */\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName) {\n this._listenersMap.delete(eventName);\n } else {\n this._listenersMap.clear();\n }\n return this;\n }\n\n // ............................................................................\n /**\n * Registers an event listener for the specified event.\n * @param eventName - The name of the event to listen for.\n * @param listener - The callback function to invoke when the event is emitted.\n * @returns The PeerSocketMock instance for chaining.\n */\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listenersMap.has(eventName)) {\n this._listenersMap.set(eventName, []);\n }\n this._listenersMap.get(eventName)!.push(listener);\n return this;\n }\n\n // ...........................................................................\n /**\n * Simulates a connection event.\n *\n * Emits the 'connect' event to all registered listeners.\n */\n connect(): void {\n this.connected = true;\n this.disconnected = false;\n\n const listeners = this._listenersMap.get('connect') || [];\n for (const cb of listeners) {\n cb({});\n }\n }\n\n // ...........................................................................\n /**\n * Simulates a disconnection event.\n *\n * Emits the 'disconnect' event to all registered listeners.\n */\n disconnect(): void {\n this.connected = false;\n this.disconnected = true;\n\n const listeners = this._listenersMap.get('disconnect') || [];\n for (const cb of listeners) {\n cb({});\n }\n }\n\n // ............................................................................\n /**\n * Emits an event, invoking the corresponding method on the Io instance.\n * @param eventName - The name of the event to emit.\n * @param args - The arguments to pass to the event listener.\n * @returns\n */\n emit(eventName: string | symbol, ...args: any[]): boolean {\n const fn = (this._io as any)[eventName] as (...args: any[]) => Promise<any>;\n if (typeof fn !== 'function') {\n throw new Error(`Event ${eventName.toString()} not supported`);\n }\n const cb = args[args.length - 1];\n fn.apply(this._io, args.slice(0, -1))\n .then((result) => {\n cb(result, null);\n })\n .catch((err) => {\n cb(null, err);\n });\n\n return true;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { ContentType, Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { Io } from './io.ts';\nimport { PeerSocketMock } from './peer-socket-mock.ts';\nimport { Socket } from './socket.ts';\n\n\nexport class IoPeer implements Io {\n isOpen: boolean = false;\n\n constructor(\n private _socket: Socket,\n private _requestTimeoutMs: number = 30_000,\n ) {}\n\n // ...........................................................................\n /**\n * Wraps a promise with a timeout. If the promise does not settle within\n * `_requestTimeoutMs`, the returned promise rejects with a timeout error.\n * Clears the timer on settlement to avoid leaks and unhandled rejections.\n */\n private _withTimeout<T>(promise: Promise<T>, operation: string): Promise<T> {\n if (this._requestTimeoutMs <= 0) return promise;\n let timer: ReturnType<typeof setTimeout>;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n reject(\n new Error(\n `Timeout after ${this._requestTimeoutMs}ms: ${operation}`,\n ),\n );\n }, this._requestTimeoutMs);\n });\n return Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timer!);\n });\n }\n\n // ...........................................................................\n /**\n *\n * Initializes the Peer connection.\n * @returns\n */\n async init(): Promise<void> {\n // Update isOpen on connect/disconnect\n this._socket.on('connect', () => {\n this.isOpen = true;\n });\n this._socket.on('disconnect', () => {\n this.isOpen = false;\n });\n\n // Connect the socket\n this._socket.connect();\n\n // Wait for the socket to connect before returning\n return new Promise<void>((resolve) => {\n /* v8 ignore else -- @preserve */\n if (this._socket.connected) {\n this.isOpen = true;\n resolve();\n } else {\n this._socket.on('connect', () => {\n resolve();\n });\n }\n });\n }\n\n // ...........................................................................\n /**\n * Closes the Peer connection.\n * @returns\n */\n\n async close(): Promise<void> {\n // Disconnect the socket and wait for it to complete\n if (!this._socket.connected) return;\n\n return new Promise<void>((resolve) => {\n this._socket.on('disconnect', () => {\n resolve();\n });\n this._socket.disconnect();\n });\n }\n\n // ...........................................................................\n /**\n * Returns a promise that resolves once the Peer connection is ready.\n * @returns\n */\n async isReady(): Promise<void> {\n if (!!this._socket && this._socket.connected === true) this.isOpen = true;\n else this.isOpen = false;\n\n return !!this.isOpen ? Promise.resolve() : Promise.reject();\n }\n\n // ...........................................................................\n /**\n * Dumps the entire database content.\n * @returns A promise that resolves to the dumped database content.\n */\n async dump(): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request dump, resolve once the data is received (ack)\n this._socket.emit('dump', (data: Rljson) => {\n resolve(data);\n });\n }),\n 'dump',\n );\n }\n\n // ...........................................................................\n /**\n * Dumps a specific table from the database.\n * @param request An object containing the table name to dump.\n * @returns A promise that resolves to the dumped table data.\n */\n dumpTable(request: { table: string }): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request dumpTable, resolve once the data is received (ack)\n this._socket.emit(\n 'dumpTable',\n request,\n (data: Rljson, error?: Error) => {\n if (error) reject(error);\n resolve(data);\n },\n );\n }),\n 'dumpTable',\n );\n }\n\n // ...........................................................................\n /**\n * Gets the content type of a specific table.\n * @param request An object containing the table name to get the content type for.\n * @returns A promise that resolves to the content type of the specified table.\n */\n contentType(request: { table: string }): Promise<ContentType> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request contentType, resolve once the data is received (ack)\n this._socket.emit(\n 'contentType',\n request,\n (data: ContentType, error?: Error) => {\n /* v8 ignore next -- @preserve */\n if (error) reject(error);\n resolve(data);\n },\n );\n }),\n 'contentType',\n );\n }\n\n // ...........................................................................\n /**\n * Checks if a specific table exists in the database.\n * @param tableKey The key of the table to check for existence.\n * @returns A promise that resolves to true if the table exists, false otherwise.\n */\n tableExists(tableKey: TableKey): Promise<boolean> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request tableExists, resolve once the data is received (ack)\n this._socket.emit('tableExists', tableKey, (exists: boolean) => {\n resolve(exists);\n });\n }),\n 'tableExists',\n );\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table with the given configuration.\n * @param request An object containing the table configuration.\n * @returns A promise that resolves once the table is created or extended.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request createOrExtendTable, resolve once the data is received (ack)\n this._socket.emit(\n 'createOrExtendTable',\n request,\n (_?: boolean, error?: Error) => {\n if (error) reject(error);\n resolve();\n },\n );\n }),\n 'createOrExtendTable',\n );\n }\n\n // ...........................................................................\n /**\n * Retrieves the raw table configurations from the database.\n * @returns A promise that resolves to an array of table configurations.\n */\n rawTableCfgs(): Promise<TableCfg[]> {\n return this._withTimeout(\n new Promise((resolve) => {\n // Request rawTableCfgs, resolve once the data is received (ack)\n this._socket.emit('rawTableCfgs', (data: TableCfg[]) => {\n resolve(data);\n });\n }),\n 'rawTableCfgs',\n );\n }\n\n // ...........................................................................\n /**\n * Writes data to the database.\n * @param request An object containing the data to write.\n * @returns A promise that resolves once the data is written.\n */\n write(request: { data: Rljson }): Promise<void> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request write, resolve once the data is received (ack)\n this._socket.emit('write', request, (_?: boolean, error?: Error) => {\n if (error) reject(error);\n resolve();\n });\n }),\n 'write',\n );\n }\n\n // ...........................................................................\n /**\n * Reads rows from a specific table that match the given criteria.\n * @param request An object containing the table name and the criteria for selecting rows.\n * @returns A promise that resolves to the selected rows.\n */\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request readRows, resolve once the data is received (ack)\n this._socket.emit(\n 'readRows',\n request,\n (result?: Rljson, error?: Error) => {\n if (error) reject(error);\n resolve(result!);\n },\n );\n }),\n 'readRows',\n );\n }\n\n // ...........................................................................\n /**\n * True once the remote side signalled that it does not support batch\n * reads — all further batch reads then use per-hash readRows.\n */\n private _batchReadsUnsupported = false;\n\n /**\n * Batch read over the socket. Falls back to per-hash readRows when\n * the remote side does not support it (older server) and remembers\n * the capability for subsequent calls.\n * @param request - The table and the row hashes to read\n */\n async readRowsByHashes(request: {\n table: string;\n hashes: string[];\n }): Promise<Rljson> {\n if (!this._batchReadsUnsupported) {\n try {\n return await this._withTimeout(\n new Promise<Rljson>((resolve, reject) => {\n this._socket.emit(\n 'readRowsByHashes',\n request,\n (result?: Rljson, error?: Error) => {\n if (error) reject(error);\n resolve(result!);\n },\n );\n }),\n 'readRowsByHashes',\n );\n } catch (error) {\n const message = String((error as Error).message);\n const unsupported =\n message.includes('not found on Io instance') ||\n message.includes('not supported') ||\n message.includes('Timeout after');\n if (!unsupported) {\n throw error;\n }\n this._batchReadsUnsupported = true;\n }\n }\n\n // Per-hash fallback for remote sides without batch support\n const hashes = Array.from(new Set(request.hashes));\n const results = await Promise.all(\n hashes.map((hash) =>\n this.readRows({ table: request.table, where: { _hash: hash } }),\n ),\n );\n\n let type: ContentType | undefined = undefined;\n const rows: any[] = [];\n for (const result of results) {\n const tableData = result[request.table];\n type ??= tableData._type;\n rows.push(...tableData._data);\n }\n\n /* v8 ignore next -- @preserve */\n if (type === undefined) {\n // No hashes given — derive the table type from an empty query\n const empty = await this.readRows({\n table: request.table,\n where: { _hash: '__NONE__' },\n });\n type = empty[request.table]._type;\n }\n\n return { [request.table]: { _data: rows, _type: type } } as Rljson;\n }\n\n // ...........................................................................\n /**\n * Retrieves the number of rows in a specific table.\n * @param table The name of the table to count rows in.\n * @returns A promise that resolves to the number of rows in the specified table.\n */\n rowCount(table: string): Promise<number> {\n return this._withTimeout(\n new Promise((resolve, reject) => {\n // Request rowCount, resolve once the data is received (ack)\n this._socket.emit(\n 'rowCount',\n table,\n (count?: number, error?: Error) => {\n if (error) reject(error);\n resolve(count!);\n },\n );\n }),\n 'rowCount',\n );\n }\n\n // ...........................................................................\n static example = async () => {\n const ioMem = await IoMem.example();\n const socket = new PeerSocketMock(ioMem);\n const io = new IoPeer(socket);\n await io.init();\n return io;\n };\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { hip } from '@rljson/hash';\nimport { Json, JsonValue, merge } from '@rljson/json';\nimport { ContentType, Rljson, RljsonTable, TableCfg, TableKey, TableType } from '@rljson/rljson';\n\nimport { IoMem } from './io-mem.ts';\nimport { IoPeer } from './io-peer.ts';\nimport { Io } from './io.ts';\nimport { PeerSocketMock } from './peer-socket-mock.ts';\n\n\n// ...........................................................................\n/**\n * Type representing an Io instance along with its capabilities and priority.\n */\nexport type IoMultiIo = {\n io: Io;\n id?: string;\n priority: number;\n read: boolean;\n write: boolean;\n dump: boolean;\n};\n\n// ...........................................................................\n/**\n * Multi Io implementation that combines multiple underlying Io instances\n * with different capabilities (read, write, dump) and priorities.\n */\nexport class IoMulti implements Io {\n isOpen: boolean = false;\n\n constructor(private _ios: Array<IoMultiIo>) {}\n\n // ...........................................................................\n /**\n *\n * Initializes all underlying Io instances.\n * @returns\n */\n async init(): Promise<void> {\n for (let idx = 0; idx < this._ios.length; idx++) {\n const { io } = this._ios[idx];\n if (io.isOpen === false) {\n throw new Error(\n 'All underlying Io instances must be initialized before initializing IoMulti',\n );\n }\n\n this._ios[idx] = { ...this._ios[idx], id: `io-${idx}` };\n }\n\n this.isOpen = true;\n return Promise.resolve();\n }\n\n // ...........................................................................\n /**\n * Closes all underlying Io instances.\n * @returns\n */\n async close(): Promise<void> {\n await Promise.all(this._ios.map((ioMultiIo) => ioMultiIo.io.close()));\n\n this.isOpen = false;\n\n return Promise.resolve();\n }\n\n // ...........................................................................\n /**\n * Returns a promise that resolves once all underlying Io instances are ready.\n * @returns\n */\n isReady(): Promise<void> {\n return Promise.all(\n this._ios.map((ioMultiIo) => ioMultiIo.io.isReady()),\n ).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Dumps the entire database content by merging dumps from all dumpable underlying Io instances.\n * @returns\n */\n async dump(): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumps = await Promise.all(\n this.dumpables.map(({ io: dumpable }) => dumpable.dump()),\n );\n\n return merge(...dumps) as Rljson;\n }\n\n // ...........................................................................\n /**\n * Dumps a specific table by merging dumps from all dumpable underlying Io instances that contain the table.\n * @param request An object containing the table name to dump.\n * @returns A promise that resolves to the dumped table data.\n */\n async dumpTable(request: { table: string }): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumps: Rljson[] = [];\n\n for (const { io: dumpable } of this.dumpables) {\n try {\n const dump = await dumpable.dumpTable(request);\n dumps.push(dump);\n } catch {\n continue; // Table does not exist in this dumpable Io\n }\n }\n\n if (dumps.length === 0) {\n throw new Error(`Table \"${request.table}\" not found`);\n }\n\n return merge(...dumps) as Rljson;\n }\n\n // ...........................................................................\n /**\n * Retrieves the content type of a specific table from the first underlying readable Io instance that contains the table.\n * @param request An object containing the table name.\n * @returns A promise that resolves to the content type of the table.\n */\n async contentType(request: { table: string }): Promise<ContentType> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n for (const { io: readable } of this.readables) {\n return readable.contentType(request);\n }\n /* v8 ignore next -- @preserve */\n throw new Error(`Table \"${request.table}\" not found`);\n }\n\n // ...........................................................................\n /**\n * Checks if a specific table exists in any of the underlying readable Io\n * instances. Readables at the same priority level are queried in parallel\n * so that one slow peer does not block others.\n * @param tableKey The key of the table to check.\n * @returns A promise that resolves to true if the table exists in any readable Io, false otherwise.\n */\n async tableExists(tableKey: TableKey): Promise<boolean> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n const groups = IoMulti._groupByPriority(this.readables);\n for (const group of groups) {\n if (group.length === 1) {\n const exists = await group[0].io.tableExists(tableKey);\n if (exists) return true;\n } else {\n const results = await Promise.allSettled(\n group.map((r) => r.io.tableExists(tableKey)),\n );\n for (const result of results) {\n if (result.status === 'fulfilled' && result.value) return true;\n }\n }\n }\n return false;\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table in all underlying writable Io instances.\n * @param request An object containing the table configuration.\n * @returns A promise that resolves once the table has been created or extended in all writable Io instances.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void> {\n /* v8 ignore next -- @preserve */\n if (this.writables.length === 0) {\n throw new Error('No writable Io available');\n }\n //Create or extend table in all writables in parallel and resolve when all have completed\n const creations = this.writables.map(({ io: writable }) =>\n writable.createOrExtendTable(request),\n );\n return Promise.all(creations).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Retrieves the raw table configurations from the highest priority underlying\n * readable Io instance that has any. Stops after the first readable that\n * returns results — this avoids expensive network round-trips to lower-\n * priority peers when the local cache (IoMem, priority 1) already has the\n * answer.\n * @returns A promise that resolves to an array of table configurations.\n */\n async rawTableCfgs(): Promise<TableCfg[]> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n const rawTableCfgs: Map<string, TableCfg> = new Map();\n for (const { io: readable } of this.readables) {\n const cfgs = await readable.rawTableCfgs();\n /* v8 ignore else -- @preserve */\n if (cfgs.length > 0) {\n for (const tableCfg of cfgs) {\n if (!rawTableCfgs.has(tableCfg.key)) {\n rawTableCfgs.set(tableCfg.key, tableCfg);\n }\n }\n break; // Stop after the first readable that has table configs\n }\n }\n return Array.from(rawTableCfgs.values());\n }\n\n // ...........................................................................\n /**\n * Writes data to all underlying writable Io instances.\n * @param request - An object containing the data to write.\n * @returns A promise that resolves once the data has been written to all writable Io instances.\n */\n write(request: { data: Rljson }): Promise<void> {\n /* v8 ignore next -- @preserve */\n if (this.writables.length === 0) {\n throw new Error('No writable Io available');\n }\n\n // Write to all writables in parallel and resolve when all have completed\n const writes = this.writables.map(({ io: writable }) =>\n writable.write(request),\n );\n return Promise.all(writes).then(() => Promise.resolve());\n }\n\n // ...........................................................................\n /**\n * Reads rows from a specific table. Readables are grouped by priority:\n * priorities are tried in ascending order. Within a priority group,\n * all readables are queried **in parallel** — only the first one to\n * return rows wins. This prevents one slow/stale peer from blocking\n * others at the same priority level.\n *\n * @param request An object containing the table name and where clause.\n * @returns A promise that resolves to the read rows.\n */\n async readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n let tableExistsAny = false;\n const rows: Map<string, Json> = new Map();\n let type: ContentType | undefined = undefined;\n let readFrom: string = '';\n\n const errors: Error[] = [];\n\n // Group readables by priority (already sorted by priority)\n const groups = IoMulti._groupByPriority(this.readables);\n\n for (const group of groups) {\n if (group.length === 1) {\n // Single readable at this priority — query directly (no race overhead)\n const readable = group[0];\n try {\n const { [request.table]: tableData } = await readable.io.readRows(\n request,\n );\n const tableRows = (tableData as RljsonTable<Json, ContentType>)\n ._data;\n const tableType = (tableData as RljsonTable<Json, ContentType>)\n ._type;\n tableExistsAny = true;\n type ??= tableType;\n\n if (tableRows.length > 0) {\n /* v8 ignore next -- @preserve */\n readFrom = readable.id ?? '';\n /* v8 ignore else -- @preserve */\n for (const tableRow of tableRows) {\n const ref = tableRow._hash as string;\n rows.set(ref, tableRow);\n }\n break; // Got rows — done\n }\n } catch (e) {\n errors.push(e as Error);\n }\n } else {\n // Multiple readables at the same priority — race them in parallel.\n // Collect all settled results and pick the first with rows.\n const results = await Promise.allSettled(\n group.map(async (readable) => {\n const { [request.table]: tableData } = await readable.io.readRows(\n request,\n );\n return {\n readable,\n tableRows: (tableData as RljsonTable<Json, ContentType>)._data,\n tableType: (tableData as RljsonTable<Json, ContentType>)._type,\n };\n }),\n );\n\n let foundRows = false;\n for (const result of results) {\n if (result.status === 'rejected') {\n errors.push(result.reason as Error);\n continue;\n }\n tableExistsAny = true;\n const { readable, tableRows, tableType } = result.value;\n type ??= tableType;\n if (tableRows.length > 0 && !foundRows) {\n foundRows = true;\n readFrom = readable.id ?? '';\n /* v8 ignore else -- @preserve */\n for (const tableRow of tableRows) {\n const ref = tableRow._hash as string;\n rows.set(ref, tableRow);\n }\n }\n }\n\n if (foundRows) break; // Got rows — done\n }\n }\n\n if (!tableExistsAny) {\n /* v8 ignore if -- @preserve */\n if (errors.length === 0) {\n throw new Error(`Table \"${request.table}\" not found`);\n } else {\n const preciseErrors = errors.filter(\n (err) => !err.message.includes(`Table \"${request.table}\" not found`),\n );\n if (preciseErrors.length > 0) {\n throw preciseErrors[0];\n } else {\n throw errors[0];\n }\n }\n } else {\n const rljson = {\n [request.table]: hip({ _data: Array.from(rows.values()), _type: type }),\n } as Rljson;\n\n // Write merged rows back to all writables (hot-swapping cache)\n if (this.writables.length > 0 && rows.size > 0) {\n for (const writeable of this.writables) {\n if (writeable.id === readFrom) {\n continue; // Skip writing back to the source readable Io\n }\n /* v8 ignore next -- @preserve */\n try {\n await writeable.io.write({\n data: rljson,\n });\n } catch {\n continue; // Table does not exist in this writable Io\n }\n }\n }\n\n // Return merged rows\n return rljson;\n }\n }\n\n // ...........................................................................\n /**\n * Retrieves the row count of a specific table by aggregating row counts from all dumpable underlying Io instances.\n * @param table The name of the table.\n * @returns A promise that resolves to the row count of the table.\n */\n async rowCount(table: string): Promise<number> {\n /* v8 ignore next -- @preserve */\n if (this.dumpables.length === 0) {\n throw new Error('No dumpable Io available');\n }\n\n const dumpTable = await this.dumpTable({ table });\n const tableData: TableType = dumpTable[table];\n /* v8 ignore next -- @preserve */\n if (!tableData) {\n throw new Error(`Table \"${table}\" not found`);\n }\n return Promise.resolve(tableData._data.length);\n }\n\n // ...........................................................................\n /**\n * Batch read with PER-HASH cascade: every hash not found in a\n * higher-priority readable is looked up in the next one. Readables\n * without readRowsByHashes are queried per hash via readRows.\n * @param request - The table and the row hashes to read\n */\n async readRowsByHashes(request: {\n table: string;\n hashes: string[];\n }): Promise<Rljson> {\n /* v8 ignore next -- @preserve */\n if (this.readables.length === 0) {\n throw new Error('No readable Io available');\n }\n\n let tableExistsAny = false;\n const rows: Map<string, Json> = new Map();\n let type: ContentType | undefined = undefined;\n let readFrom: string = '';\n const errors: Error[] = [];\n\n let remaining = Array.from(new Set(request.hashes));\n\n for (const readable of this.readables) {\n if (remaining.length === 0) break;\n\n try {\n let result: Rljson;\n if (readable.io.readRowsByHashes) {\n result = await readable.io.readRowsByHashes({\n table: request.table,\n hashes: remaining,\n });\n } else {\n result = await IoMulti._readHashesViaReadRows(\n readable.io,\n request.table,\n remaining,\n );\n }\n\n const tableData = result[request.table] as RljsonTable<\n Json,\n ContentType\n >;\n tableExistsAny = true;\n // The table type is identical across all ios serving the table\n type = tableData._type;\n\n if (tableData._data.length > 0) {\n // Same hint as in readRows: both sides are exercised by tests\n // but v8 cannot attribute this branch across the await above\n /* v8 ignore next -- @preserve */\n readFrom = readable.id ?? '';\n for (const tableRow of tableData._data) {\n rows.set(tableRow._hash as string, tableRow);\n }\n remaining = remaining.filter((hash) => !rows.has(hash));\n }\n } catch (e) {\n errors.push(e as Error);\n }\n }\n\n if (!tableExistsAny) {\n /* v8 ignore if -- @preserve */\n if (errors.length === 0) {\n throw new Error(`Table \"${request.table}\" not found`);\n } else {\n const preciseErrors = errors.filter(\n (err) => !err.message.includes(`Table \"${request.table}\" not found`),\n );\n /* v8 ignore next -- @preserve */\n if (preciseErrors.length > 0) {\n throw preciseErrors[0];\n } else {\n throw errors[0];\n }\n }\n }\n\n const rljson = {\n [request.table]: hip({ _data: Array.from(rows.values()), _type: type }),\n } as Rljson;\n\n // Write merged rows back to all writables (hot-swapping cache) —\n // mirrors readRows\n if (this.writables.length > 0 && rows.size > 0) {\n for (const writeable of this.writables) {\n if (writeable.id === readFrom) {\n continue; // Skip writing back to the source readable Io\n }\n /* v8 ignore next -- @preserve */\n try {\n await writeable.io.write({ data: rljson });\n } catch {\n continue; // Table does not exist in this writable Io\n }\n }\n }\n\n return rljson;\n }\n\n /**\n * Per-hash fallback for readables without readRowsByHashes.\n * @param io - The readable io\n * @param table - The table to read from\n * @param hashes - The row hashes to read\n */\n private static async _readHashesViaReadRows(\n io: Io,\n table: string,\n hashes: string[],\n ): Promise<Rljson> {\n const results = await Promise.all(\n hashes.map((hash) => io.readRows({ table, where: { _hash: hash } })),\n );\n\n let type: ContentType | undefined = undefined;\n const rows: Json[] = [];\n for (const result of results) {\n const tableData = result[table] as RljsonTable<Json, ContentType>;\n type ??= tableData._type;\n rows.push(...tableData._data);\n }\n\n return { [table]: { _data: rows, _type: type } } as Rljson;\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying readable Io instances, sorted by priority.\n */\n get readables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.read)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying writable Io instances, sorted by priority.\n */\n get writables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.write)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Gets the list of underlying dumpable Io instances, sorted by priority.\n */\n get dumpables(): Array<IoMultiIo> {\n return this._ios\n .filter((ioMultiIo) => ioMultiIo.dump)\n .sort((a, b) => a.priority - b.priority);\n }\n\n // ...........................................................................\n /**\n * Groups IoMultiIo entries by their priority value.\n * Input must already be sorted by priority (ascending).\n * Returns an array of groups, each group containing entries with the same\n * priority.\n */\n static _groupByPriority(ios: Array<IoMultiIo>): Array<Array<IoMultiIo>> {\n const groups: Array<Array<IoMultiIo>> = [];\n let current: Array<IoMultiIo> = [];\n let currentPriority: number | null = null;\n\n for (const io of ios) {\n if (io.priority !== currentPriority) {\n if (current.length > 0) groups.push(current);\n current = [io];\n currentPriority = io.priority;\n } else {\n current.push(io);\n }\n }\n if (current.length > 0) groups.push(current);\n\n return groups;\n }\n\n // ...........................................................................\n static example = async () => {\n const ioPeerMem = await IoMem.example();\n await ioPeerMem.init();\n\n const ioPeerSocket = new PeerSocketMock(ioPeerMem);\n const ioPeer = new IoPeer(ioPeerSocket);\n await ioPeer.init();\n\n const ioMem = await IoMem.example();\n await ioMem.init();\n\n const ios: Array<IoMultiIo> = [\n { io: ioPeer, priority: 1, read: true, write: false, dump: false },\n { io: ioMem, priority: 0, read: true, write: true, dump: true },\n ];\n\n const ioMulti = new IoMulti(ios);\n await ioMulti.init();\n\n return ioMulti;\n };\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\n\n/**\n * Bridges Socket events to Io method calls.\n *\n * This class listens to socket events and translates them into corresponding\n * Io method calls, automatically registering all Io interface methods.\n */\nexport class IoPeerBridge {\n private _eventHandlers: Map<string | symbol, (...args: any[]) => void> =\n new Map();\n\n constructor(private _io: Io, private _socket: Socket) {}\n\n /**\n * Starts the bridge by setting up connection event handlers and\n * automatically registering all Io methods.\n */\n start(): void {\n this._socket.on('connect', () => this._handleConnect());\n this._socket.on('disconnect', () => this._handleDisconnect());\n\n // Automatically register all Io interface methods\n this._registerIoMethods();\n }\n\n /**\n * Stops the bridge by removing all event handlers.\n */\n stop(): void {\n /* v8 ignore next -- @preserve */\n this._socket.off('connect', () => this._handleConnect());\n /* v8 ignore next -- @preserve */\n this._socket.off('disconnect', () => this._handleDisconnect());\n\n for (const [eventName, handler] of this._eventHandlers) {\n this._socket.off(eventName, handler);\n }\n this._eventHandlers.clear();\n }\n\n /**\n * Automatically registers all Io interface methods as socket event handlers.\n */\n private _registerIoMethods(): void {\n // Core Io interface methods\n const ioMethods = [\n 'init',\n 'isReady',\n 'close',\n 'tableExists',\n 'createOrExtendTable',\n 'write',\n 'readRows',\n 'readRowsByHashes',\n 'rowCount',\n 'dumpTable',\n 'dump',\n 'contentType',\n 'rawTableCfgs',\n ];\n\n for (const methodName of ioMethods) {\n this.registerEvent(methodName);\n }\n }\n\n /**\n * Registers a socket event to be translated to an Io method call.\n *\n * @param eventName - The socket event name (should match an Io method name)\n * @param ioMethodName - (Optional) The Io method name if different from eventName\n */\n registerEvent(eventName: string, ioMethodName?: string): void {\n const methodName = ioMethodName || eventName;\n\n /* v8 ignore next -- @preserve */\n const handler = (...args: any[]) => {\n // The last argument is expected to be a callback function\n const callback = args[args.length - 1];\n const methodArgs = args.slice(0, -1);\n\n // Get the Io method\n const ioMethod = (this._io as any)[methodName];\n\n /* v8 ignore next -- @preserve */\n if (typeof ioMethod !== 'function') {\n const error = new Error(\n `Method \"${methodName}\" not found on Io instance`,\n );\n if (typeof callback === 'function') {\n callback(null, error);\n }\n return;\n }\n\n // Call the Io method and handle the response\n /* v8 ignore next -- @preserve */\n ioMethod\n .apply(this._io, methodArgs)\n .then((result: any) => {\n if (typeof callback === 'function') {\n // Call callback with just the result (no error parameter when successful)\n callback(result, null); // Two arguments\n }\n })\n .catch((error: any) => {\n if (typeof callback === 'function') {\n // For errors, send null as result and error as second parameter\n callback(null, error); // Two arguments\n }\n });\n };\n\n this._eventHandlers.set(eventName, handler);\n this._socket.on(eventName, handler);\n }\n\n /**\n * Registers multiple socket events at once.\n *\n * @param eventNames - Array of event names to register\n */\n registerEvents(eventNames: string[]): void {\n for (const eventName of eventNames) {\n this.registerEvent(eventName);\n }\n }\n\n /**\n * Unregisters a socket event handler.\n *\n * @param eventName - The event name to unregister\n */\n unregisterEvent(eventName: string | symbol): void {\n const handler = this._eventHandlers.get(eventName);\n if (handler) {\n this._socket.off(eventName, handler);\n this._eventHandlers.delete(eventName);\n }\n }\n\n /**\n * Emits a result back through the socket.\n *\n * @param eventName - The event name to emit\n * @param data - The data to send\n */\n emitToSocket(eventName: string | symbol, ...data: any[]): void {\n this._socket.emit(eventName, ...data);\n }\n\n /**\n * Calls an Io method directly and emits the result through the socket.\n *\n * @param ioMethodName - The Io method to call\n * @param socketEventName - The socket event to emit with the result\n * @param args - Arguments to pass to the Io method\n */\n async callIoAndEmit(\n ioMethodName: string,\n socketEventName: string | symbol,\n ...args: any[]\n ): Promise<void> {\n try {\n const ioMethod = (this._io as any)[ioMethodName];\n\n if (typeof ioMethod !== 'function') {\n throw new Error(`Method \"${ioMethodName}\" not found on Io instance`);\n }\n\n const result = await ioMethod.apply(this._io, args);\n this._socket.emit(socketEventName, result, null);\n } catch (error) {\n this._socket.emit(socketEventName, null, error);\n }\n }\n\n /* v8 ignore next -- @preserve */\n private _handleConnect(): void {\n // Override this method in subclasses to handle connection events\n }\n\n /* v8 ignore next -- @preserve */\n private _handleDisconnect(): void {\n // Override this method in subclasses to handle disconnection events\n }\n\n /**\n * Gets the current socket instance.\n */\n get socket(): Socket {\n return this._socket;\n }\n\n /**\n * Gets the current Io instance.\n */\n get io(): Io {\n return this._io;\n }\n\n /**\n * Returns whether the socket is currently connected.\n */\n get isConnected(): boolean {\n return this._socket.connected;\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\nimport { Io } from './io.ts';\nimport { Socket } from './socket.ts';\n\n\nexport class IoServer {\n private _sockets: Socket[] = [];\n\n constructor(private _io: Io) {}\n\n // ...........................................................................\n /**\n * Adds a socket to the IoServer instance.\n * @param socket - The socket to add.\n */\n async addSocket(socket: Socket): Promise<void> {\n // Add transport layer to the socket\n await this._addTransportLayer(socket);\n\n // Add socket to the list of sockets\n this._sockets.push(socket);\n }\n\n // ...........................................................................\n /**\n * Removes a transport layer from the given socket.\n * @param socket - The socket to remove the transport layer from.\n */\n removeSocket(socket: Socket): void {\n this._sockets = this._sockets.filter((s) => s !== socket);\n }\n\n // ...........................................................................\n /**\n * Adds a transport layer to the given socket.\n * @param socket - The socket to add the transport layer to.\n */\n private async _addTransportLayer(socket: Socket): Promise<void> {\n // CRUD operations — use arrow functions that read this._io at call time,\n // so that when _io is replaced (e.g. after _rebuildMultis), existing\n // socket handlers automatically use the latest Io instance.\n const crud = this._generateTransportLayerCRUD();\n for (const [key, fn] of Object.entries(crud)) {\n socket.on(key, (...args: any[]) => {\n const cb = args[args.length - 1];\n\n fn.apply(this, args.slice(0, -1))\n .then((result) => {\n cb(result, null);\n })\n .catch((err) => {\n cb(null, err);\n });\n });\n }\n }\n\n // ...........................................................................\n /**\n * Creates or extends a table with the given configuration.\n * @param request - An object containing the table configuration.\n */\n private async createOrExtendTable(request: {\n tableCfg: TableCfg;\n }): Promise<void> {\n return this._io.createOrExtendTable(request);\n }\n\n // ...........................................................................\n /**\n * Generates a transport layer object that always delegates to the current\n * this._io. Each method is an arrow function reading this._io at call\n * time so that external code can replace _io after construction and all\n * existing socket handlers pick up the new instance.\n */\n private _generateTransportLayerCRUD = () =>\n ({\n init: () => this._io.init(),\n close: () => this._io.close(),\n isOpen: () =>\n new Promise((resolve) => resolve(this._io.isOpen)) as Promise<boolean>,\n isReady: () => this._io.isReady(),\n dump: () => this._io.dump(),\n dumpTable: (request: { table: string }) => this._io.dumpTable(request),\n contentType: (request: { table: string }) =>\n this._io.contentType(request),\n tableExists: (tableKey: TableKey) => this._io.tableExists(tableKey),\n createOrExtendTable: (request: { tableCfg: TableCfg }) =>\n this.createOrExtendTable(request),\n rawTableCfgs: () => this._io.rawTableCfgs(),\n write: (request: { data: Rljson }) => this._io.write(request),\n readRows: (request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }) => this._io.readRows(request),\n readRowsByHashes: (request: { table: string; hashes: string[] }) =>\n this._io.readRowsByHashes\n ? this._io.readRowsByHashes(request)\n : Promise.reject(\n new Error(\n 'Method \"readRowsByHashes\" not found on Io instance',\n ),\n ),\n rowCount: (table: string) => this._io.rowCount(table),\n } as { [key: string]: (...args: any[]) => Promise<any> });\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Io, IoMem } from './index.ts';\n\n// .............................................................................\n/**\n * Io implementation need to implement this interface to be used in\n * conformance tests.\n */\nexport interface IoTestSetup {\n /** setup before the single setups */\n beforeAll: () => Promise<void>;\n\n /**\n * Initializes the io implementation.\n * @returns The io implementation.\n */\n beforeEach: () => Promise<void>;\n\n /**\n * Tears down the io implementation.\n * @returns The io implementation.\n */\n afterEach: () => Promise<void>;\n\n /** cleanup after all tests */\n afterAll: () => Promise<void>;\n\n /**\n * The io implementation to be used in the conformance tests.\n */\n io: Io;\n}\n\n// .............................................................................\n// Example implementation of the IoTestSetup interface\nexport const exampleTestSetup = (): IoTestSetup => {\n return {\n io: new IoMem(),\n beforeAll: async () => {\n // This method can be used for any additional setup required before init.\n // Currently, it does nothing.\n },\n\n beforeEach: async () => {\n // Initialize the io implementation\n },\n afterEach: async () => {\n // Tear down the io implementation\n },\n\n afterAll: async () => {\n // This method can be used for any additional cleanup after tearDown.\n },\n };\n};\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { JsonValue } from '@rljson/json';\nimport { ContentType, Rljson, TableCfg, TableKey } from '@rljson/rljson';\n\n\n// .............................................................................\nexport interface Io {\n // ...........................................................................\n // General\n\n /** Starts the initialization */\n init(): Promise<void>;\n\n /** Closes the io */\n close(): Promise<void>;\n\n /** Returns true if io is opened */\n isOpen: boolean;\n\n /** A promise resolving once the Io interface is ready\n *\n * 💡 Use @rljson/is-ready\n */\n isReady(): Promise<void>;\n\n // ...........................................................................\n // Dump\n\n /** Returns the complete db content as Rljson */\n dump(): Promise<Rljson>;\n\n /** Returns the dump of a complete table */\n dumpTable(request: { table: string }): Promise<Rljson>;\n\n // ...........................................................................\n // Meta Data\n contentType(request: { table: string }): Promise<ContentType>;\n\n // ...........................................................................\n // Tables\n\n /**\n * Returns true if the table exists\n */\n tableExists(tableKey: TableKey): Promise<boolean>;\n\n /**\n * Creates a table with a given config.\n * If the table already exists, new columns are added to the existing table.\n * If the table does not exist, it is created with the given config.\n * If the table exists and columns are removed, an error is thrown.\n * If the table exists and the column type is changed, an error is thrown.\n */\n createOrExtendTable(request: { tableCfg: TableCfg }): Promise<void>;\n\n /**\n * Returns a json structure returning current table configurations\n */\n rawTableCfgs(): Promise<TableCfg[]>;\n\n // ...........................................................................\n // Write\n\n /** Writes Rljson data into the database */\n write(request: { data: Rljson }): Promise<void>;\n\n // ...........................................................................\n // Read rows\n\n /** Queries a list of rows */\n readRows(request: {\n table: string;\n where: { [column: string]: JsonValue | null };\n }): Promise<Rljson>;\n\n /**\n * Optional batch read: returns the rows matching the given content\n * hashes in one request. Hashes without a matching row are simply\n * absent from the result. Implementations answering many hash lookups\n * in one round trip should provide this; callers MUST fall back to\n * readRows when the method is not implemented.\n */\n readRowsByHashes?(request: {\n table: string;\n hashes: string[];\n }): Promise<Rljson>;\n\n /** Returns the number of rows in the given table */\n rowCount(table: string): Promise<number>;\n}\n\n// .............................................................................\nexport const exampleIo =\n 'Checkout @rljson/io-mem for an example implementation';\n","/* v8 ignore file -- @preserve */\n// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Json } from '@rljson/json';\nimport {\n Buffet,\n Cake,\n iterateTablesSync,\n Layer,\n Ref,\n Rljson,\n TableKey,\n} from '@rljson/rljson';\n\n// .............................................................................\n/**\n * Describes a row that references a child table row\n */\nexport interface ParentRef {\n /**\n * The parent table that references the child table\n */\n [parentTable: TableKey]: {\n /**\n * The parent row that references the child row\n */\n [parentRow: Ref]: {\n /**\n * Details about the reference, e.g. an array index etc.\n */\n details?: Json;\n };\n };\n}\n\n// .............................................................................\n/**\n * Describes the parent table rows referencing a child table row\n */\nexport interface ReverseRefs {\n /**\n * The child table we need the referencing rows for\n */\n [childTable: TableKey]: {\n /**\n * The row hashwe need the referencing rows for\n */\n [childRow: Ref]: ParentRef;\n };\n}\n\n/* v8 ignore start -- @preserve */\n\n// .............................................................................\n/**\n * Calculates the reverse references for a given rljson object\n */\nexport const calcReverseRefs = (rljson: Rljson): ReverseRefs => {\n const result: ReverseRefs = {};\n\n // ......................\n // Prepare data structure\n iterateTablesSync(rljson, (childTableKey, table) => {\n const childTable: { [childRowHash: string]: ParentRef } = {};\n result[childTableKey] = childTable;\n for (const childRow of table._data) {\n childTable[childRow._hash] = {};\n }\n });\n\n // ............................\n // Generate reverse references\n iterateTablesSync(rljson, (parentTableKey, parentTable) => {\n // Iterate all rows of each table\n for (const parentTableRow of parentTable._data) {\n // Find out whe other tables & rows are referenced by this row\n // Write these information intto result\n switch (parentTable._type) {\n case 'components':\n _writeComponentRefs(parentTableKey, parentTableRow, result);\n break;\n\n case 'layers': {\n _writeLayerRefs(parentTableKey, parentTableRow, result);\n break;\n }\n\n case 'sliceIds': {\n // Slice ids do not reference other tables\n break;\n }\n\n case 'cakes': {\n _writeCakeRefs(parentTableKey, parentTableRow, result);\n break;\n }\n\n case 'buffets': {\n _writeBuffetRefs(parentTableKey, parentTableRow, result);\n break;\n }\n }\n }\n });\n\n return result;\n};\n\n/* v8 ignore stop -- @preserve */\n\n// .............................................................................\nconst _writeComponentRefs = (\n parentTableName: TableKey,\n parentRow: Json,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const parentColumnName in parentRow) {\n if (parentColumnName.startsWith('_')) {\n continue;\n }\n\n if (!parentColumnName.endsWith('Ref')) {\n continue;\n }\n\n const childTableName = parentColumnName.slice(0, -3);\n const childRowHash = parentRow[parentColumnName] as string;\n\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _writeLayerRefs = (\n parentTableName: TableKey,\n parentRow: Layer,\n result: ReverseRefs,\n) => {\n const childTableName = parentRow.componentsTable;\n const parentRowHash = parentRow._hash as string;\n\n for (const sliceId in parentRow.add) {\n if (sliceId.startsWith('_')) {\n continue;\n }\n\n const sliceHash = parentRow.add[sliceId] as string;\n\n _write(result, childTableName, sliceHash, parentTableName, parentRowHash);\n }\n};\n\n// .............................................................................\nconst _writeCakeRefs = (\n parentTableName: TableKey,\n parentRow: Cake,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const layer in parentRow.layers) {\n const childTableName = layer;\n const childRowHash = parentRow.layers[layer] as string;\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _writeBuffetRefs = (\n parentTableName: TableKey,\n parentRow: Buffet,\n result: ReverseRefs,\n) => {\n const parentRowHash = parentRow._hash as string;\n\n for (const item of parentRow.items) {\n const childTableName = item.table;\n const childRowHash = item.ref;\n _write(\n result,\n childTableName,\n childRowHash,\n parentTableName,\n parentRowHash,\n );\n }\n};\n\n// .............................................................................\nconst _write = (\n result: ReverseRefs,\n childTableName: string,\n childRowHash: string,\n parentTableName: string,\n parentRowHash: string,\n) => {\n const referencesForChildTable = (result[childTableName] ??= {});\n const referencesForChildTableRow = (referencesForChildTable[childRowHash] ??=\n {});\n\n referencesForChildTableRow[parentTableName] ??= {};\n referencesForChildTableRow[parentTableName][parentRowHash] ??= {};\n};\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n/* v8 ignore file -- @preserve */\nimport { Socket } from './socket.ts';\n\nexport class SocketMock implements Socket {\n public connected: boolean = false;\n public disconnected: boolean = true;\n\n private _listeners: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n private _onceListeners: Map<\n string | symbol,\n Array<(...args: any[]) => void>\n > = new Map();\n\n connect(): void {\n if (!this.connected) {\n this.connected = true;\n this.disconnected = false;\n this.emit('connect');\n }\n }\n\n disconnect(): void {\n if (this.connected) {\n this.connected = false;\n this.disconnected = true;\n this.emit('disconnect');\n }\n }\n\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName)!.push(listener);\n return this;\n }\n\n once(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._onceListeners.has(eventName)) {\n this._onceListeners.set(eventName, []);\n }\n this._onceListeners.get(eventName)!.push(listener);\n return this;\n }\n\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this {\n if (listener) {\n // Remove specific listener\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n const index = regularListeners.indexOf(listener);\n if (index > -1) {\n regularListeners.splice(index, 1);\n }\n }\n\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const index = onceListeners.indexOf(listener);\n if (index > -1) {\n onceListeners.splice(index, 1);\n }\n }\n } else {\n // Remove all listeners for the event\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n }\n return this;\n }\n\n emit(eventName: string | symbol, ...args: any[]): boolean {\n let hasListeners = false;\n\n // Emit to regular listeners\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners && regularListeners.length > 0) {\n hasListeners = true;\n // Create a copy to avoid issues if listeners are removed during emission\n [...regularListeners].forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n // In a real EventEmitter, this would be handled differently\n console.error(\n `Error in listener for event ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n\n // Emit to once listeners and remove them\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners && onceListeners.length > 0) {\n hasListeners = true;\n // Create a copy and clear the original array\n const listenersToCall = [...onceListeners];\n this._onceListeners.delete(eventName);\n\n listenersToCall.forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(\n `Error in once listener for event ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n\n return hasListeners;\n }\n\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName !== undefined) {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n } else {\n this._listeners.clear();\n this._onceListeners.clear();\n }\n return this;\n }\n\n listenerCount(eventName: string | symbol): number {\n const regularCount = this._listeners.get(eventName)?.length || 0;\n const onceCount = this._onceListeners.get(eventName)?.length || 0;\n return regularCount + onceCount;\n }\n\n listeners(eventName: string | symbol): Array<(...args: any[]) => void> {\n const regularListeners = this._listeners.get(eventName) || [];\n const onceListeners = this._onceListeners.get(eventName) || [];\n return [...regularListeners, ...onceListeners];\n }\n\n eventNames(): Array<string | symbol> {\n const allEvents = new Set([\n ...this._listeners.keys(),\n ...this._onceListeners.keys(),\n ]);\n return Array.from(allEvents);\n }\n\n // Test helper methods\n reset(): void {\n this.connected = false;\n this.disconnected = true;\n this.removeAllListeners();\n }\n\n simulateError(error: Error): void {\n this.emit('error', error);\n }\n\n simulateMessage(message: any): void {\n this.emit('message', message);\n }\n\n // Get internal state for testing\n getListeners(): Map<string | symbol, Array<(...args: any[]) => void>> {\n return new Map(this._listeners);\n }\n\n getOnceListeners(): Map<string | symbol, Array<(...args: any[]) => void>> {\n return new Map(this._onceListeners);\n }\n}\n\n// ...existing code...\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\nimport { Socket } from './socket.ts';\n\n\n/**\n * Creates a pair of connected sockets that properly route messages between them.\n * Unlike SocketMock, this maintains directionality - when socketA emits, only socketB's\n * listeners fire, not socketA's own listeners.\n *\n * This is essential for client-server testing where both use the same socket instance\n * but need separate event handling.\n */\nexport function createSocketPair(): [\n DirectionalSocketMock,\n DirectionalSocketMock,\n] {\n const socketA = new DirectionalSocketMock();\n const socketB = new DirectionalSocketMock();\n\n // Connect them bidirectionally\n socketA._setPeer(socketB);\n socketB._setPeer(socketA);\n\n return [socketA, socketB];\n}\n\nexport class DirectionalSocketMock implements Socket {\n public connected: boolean = false;\n public disconnected: boolean = true;\n\n private _peer?: DirectionalSocketMock;\n private _listeners: Map<string | symbol, Array<(...args: any[]) => void>> =\n new Map();\n private _onceListeners: Map<\n string | symbol,\n Array<(...args: any[]) => void>\n > = new Map();\n\n _setPeer(peer: DirectionalSocketMock): void {\n this._peer = peer;\n }\n\n connect(): void {\n if (!this.connected) {\n this.connected = true;\n this.disconnected = false;\n // Trigger local 'connect' event\n this._triggerLocal('connect');\n // Trigger peer's 'connect' event\n if (this._peer) {\n this._peer._triggerLocal('connect');\n }\n }\n }\n\n disconnect(): void {\n if (this.connected) {\n this.connected = false;\n this.disconnected = true;\n this._triggerLocal('disconnect');\n if (this._peer) {\n this._peer._triggerLocal('disconnect');\n }\n }\n }\n\n on(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._listeners.has(eventName)) {\n this._listeners.set(eventName, []);\n }\n this._listeners.get(eventName)!.push(listener);\n return this;\n }\n\n once(eventName: string | symbol, listener: (...args: any[]) => void): this {\n if (!this._onceListeners.has(eventName)) {\n this._onceListeners.set(eventName, []);\n }\n this._onceListeners.get(eventName)!.push(listener);\n return this;\n }\n\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this {\n if (listener) {\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n const index = regularListeners.indexOf(listener);\n if (index > -1) regularListeners.splice(index, 1);\n }\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const index = onceListeners.indexOf(listener);\n if (index > -1) onceListeners.splice(index, 1);\n }\n } else {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n }\n return this;\n }\n\n /**\n * Emits an event to the PEER socket (cross-socket emission).\n * This is the key difference from SocketMock - emit() sends to the other side,\n * not to local listeners.\n *\n * Implements Socket.IO acknowledgement pattern: the last argument can be a callback\n * that the peer will invoke to send a response back.\n */\n emit(eventName: string | symbol, ...args: any[]): boolean {\n if (!this._peer) {\n console.warn(\n `DirectionalSocketMock.emit: No peer connected for event ${String(eventName)}`,\n );\n return false;\n }\n\n // Trigger the event on the PEER socket, not locally\n this._peer._triggerLocal(eventName, ...args);\n return true;\n }\n\n /**\n * Triggers listeners on THIS socket (local emission).\n * Used internally when receiving events from peer.\n */\n private _triggerLocal(eventName: string | symbol, ...args: any[]): void {\n // Trigger regular listeners\n const regularListeners = this._listeners.get(eventName);\n if (regularListeners) {\n [...regularListeners].forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(`Error in listener for ${String(eventName)}:`, error);\n }\n });\n }\n\n // Trigger and remove once listeners\n const onceListeners = this._onceListeners.get(eventName);\n if (onceListeners) {\n const listenersToCall = [...onceListeners];\n this._onceListeners.delete(eventName);\n listenersToCall.forEach((listener) => {\n try {\n listener(...args);\n } catch (error) {\n console.error(\n `Error in once listener for ${String(eventName)}:`,\n error,\n );\n }\n });\n }\n }\n\n removeAllListeners(eventName?: string | symbol): this {\n if (eventName !== undefined) {\n this._listeners.delete(eventName);\n this._onceListeners.delete(eventName);\n } else {\n this._listeners.clear();\n this._onceListeners.clear();\n }\n return this;\n }\n\n listenerCount(eventName: string | symbol): number {\n const regularCount = this._listeners.get(eventName)?.length || 0;\n const onceCount = this._onceListeners.get(eventName)?.length || 0;\n return regularCount + onceCount;\n }\n\n listeners(eventName: string | symbol): Array<(...args: any[]) => void> {\n const regularListeners = this._listeners.get(eventName) || [];\n const onceListeners = this._onceListeners.get(eventName) || [];\n return [...regularListeners, ...onceListeners];\n }\n\n eventNames(): Array<string | symbol> {\n const allEvents = new Set([\n ...this._listeners.keys(),\n ...this._onceListeners.keys(),\n ]);\n return Array.from(allEvents);\n }\n}\n","// @license\n// Copyright (c) 2025 Rljson\n//\n// Use of this source code is governed by terms that can be\n// found in the LICENSE file in the root of this package.\n\n//Interface for a generic Socket, similar to Node.js EventEmitter\n//This is a simplified version and may not cover all features of a full EventEmitter\nexport interface Socket {\n connected: boolean;\n disconnected: boolean;\n connect(): void;\n disconnect(): void;\n on(eventName: string | symbol, listener: (...args: any[]) => void): this;\n emit(eventName: string | symbol, ...args: any[]): boolean | this;\n off(eventName: string | symbol, listener?: (...args: any[]) => void): this;\n removeAllListeners(eventName?: string | symbol): this;\n}\n\nexport const socketExample = (): Socket => ({\n connected: false,\n disconnected: true,\n connect() {\n this.connected = true;\n this.disconnected = false;\n this.emit('connect');\n },\n disconnect() {\n this.connected = false;\n this.disconnected = true;\n this.emit('disconnect');\n },\n /* v8 ignore next -- @preserve */\n on() {\n // Implementation of event listener registration\n return this;\n },\n /* v8 ignore next -- @preserve */\n emit() {\n // Implementation of event emission\n return true;\n },\n /* v8 ignore next -- @preserve */\n off() {\n // Implementation of event listener removal\n return this;\n },\n /* v8 ignore next -- @preserve */\n removeAllListeners() {\n // Implementation of removing all listeners\n return this;\n },\n});\n"],"names":["e"],"mappings":";;;;AAMO,MAAM,gBAAgB;AAAA;AAAA,EAEpB,mBAA2B;AAAA,EAC3B,cAAsB;AAAA,EACtB,aAAqB;AAAA,EACrB,YAAoB;AAAA;AAAA,EAGpB,aAAwC;AAAA,IAC7C,MAAM;AAAA,IACN,UAAU;AAAA,EAAA;AAAA;AAAA,EAIJ,UAAqC;AAAA,IAC3C,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EAAA;AAAA;AAAA;AAAA,EAKC,QAAQ,MAAc,KAAqB;AACjD,WAAO,KAAK,SAAS,GAAG,IAAI,OAAO,OAAO;AAAA,EAC5C;AAAA,EAEO,eAAe,MAAsB;AAC1C,WAAO,KAAK,QAAQ,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC5C;AAAA,EAEO,gBAAgB,MAAsB;AAC3C,WAAO,KAAK,QAAQ,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC5C;AAAA,EAEO,aAAa,MAAsB;AACxC,WAAO,KAAK,QAAQ,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC5C;AAAA,EAEQ,WAAW,MAAc,KAAqB;AACpD,WAAO,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,CAAC,IAAI,MAAM,IAAI;AAAA,EAC3D;AAAA,EAEO,kBAAkB,MAAsB;AAC7C,WAAO,KAAK,WAAW,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC/C;AAAA,EAEO,mBAAmB,MAAsB;AAC9C,WAAO,KAAK,WAAW,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC/C;AAAA,EAEO,gBAAgB,MAAsB;AAC3C,WAAO,KAAK,WAAW,MAAM,KAAK,QAAQ,GAAG;AAAA,EAC/C;AACF;AClCO,MAAM,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,EAKnB,YAA4B,IAAQ;AAAR,SAAA,KAAA;AAAA,EAAS;AAAA;AAAA;AAAA;AAAA,EAKrC,WAAW,oBAAoB;AAC7B,UAAM,WAAW,IAAc;AAAA,MAC7B,OAAO;AAAA,MACP,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,UAAU;AAAA,MAEV,SAAS;AAAA,QACP;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,MACb;AAAA,IACF,CACD;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,qBAAqB,YAAY;AAC/B,UAAM,WAAqB;AAAA,MACzB,KAAK;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MAEV,SAAS;AAAA,QACP;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,QAEb;AAAA,UACE,KAAK;AAAA,UACL,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,WAAW;AAAA,QAAA;AAAA,MACb;AAAA,IACF;AAGF,UAAM,KAAK,GAAG,oBAAoB,EAAE,UAAU;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,UAAU,YAAY;AAC3B,UAAM,KAAK,MAAM,MAAM,QAAA;AACvB,UAAM,GAAG,KAAA;AACT,UAAM,GAAG,QAAA;AACT,WAAO,IAAI,QAAQ,EAAE;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,2BAA2B,OAAgC;AAC/D,UAAM,SAAS,MAAM,KAAK,GAAG,YAAY,KAAK;AAC9C,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,UAAU,KAAK,aAAa;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,0BAA0B,QAA+B;AAC7D,QAAI;AACF,YAAM,cAAc,QAAQ,OAAO,aAAa;AAC9C,cAAM,SAAS,MAAM,KAAK,GAAG,YAAY,QAAQ;AACjD,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,MAAM,UAAU,QAAQ,aAAa;AAAA,QACjD;AAAA,MACF,CAAC;AAAA,IACH,SAAS,GAAG;AACV,YAAM,gBAAiB,EAAiB,IAAI,CAACA,OAAMA,GAAE,QAAQ;AAE7D,YAAM,IAAI;AAAA,QACR,sCAAsC,cAAc,KAAK,IAAI,CAAC;AAAA,MAAA;AAAA,IAElE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAiC;AACrC,UAAM,SAAS,MAAM,KAAK,GAAG,aAAA;AAG7B,UAAM,gBAA4C,CAAA;AAClD,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,YAAM,QAAQ,OAAO,CAAC;AACtB,YAAM,WAAW,cAAc,MAAM,GAAG;AACxC,UAAI,CAAC,YAAY,SAAS,QAAQ,SAAS,MAAM,QAAQ,QAAQ;AAC/D,sBAAc,MAAM,GAAG,IAAI;AAAA,MAC7B;AAAA,IACF;AAIA,UAAM,aAAa,OAAO,OAAO,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM;AAC7D,UAAI,EAAE,MAAM,EAAE,KAAK;AACjB,eAAO;AAAA,MACT;AACA,UAAI,EAAE,MAAM,EAAE,KAAK;AACjB,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,CAAC;AACD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAkC;AACtC,UAAM,UAAU,MAAM,KAAK,UAAA,GAAa,IAAI,CAAC,MAAM,EAAE,GAAG;AACxD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,OAAoC;AACjD,UAAM,WAAW,MAAM,KAAK,eAAe,KAAK;AAChD,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,UAAU,KAAK,aAAa;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eAAe,OAA2C;AAC9D,UAAM,YAAY,MAAM,KAAK,UAAA;AAC7B,UAAM,WAAW,UAAU,KAAK,CAAC,MAAM,EAAE,QAAQ,KAAK;AACtD,WAAO,YAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,OAAoC;AACtD,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK;AAC1C,UAAM,SAAS,SAAS,QAAQ,IAAI,CAAC,WAAW,OAAO,GAAG;AAC1D,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,4BACJ,OACA,SACe;AACf,UAAM,WAAW,MAAM,KAAK,SAAS,KAAK;AAC1C,UAAM,aAAa,SAAS,QAAQ,IAAI,CAAC,WAAW,OAAO,GAAG;AAC9D,UAAM,iBAAiB,QAAQ;AAAA,MAC7B,CAAC,WAAW,CAAC,WAAW,SAAS,MAAM;AAAA,IAAA;AAEzC,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR,gDAAgD,KAAK,MAAM,eAAe;AAAA,UACxE;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IAEL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,8BAA8B,QAAiC;AACnE,UAAM,SAAS,iCAAiC,OAAO,GAAG;AAE1D,2BAAuB,MAAM;AAG7B,UAAM,WAAW,MAAM,KAAK,eAAe,OAAO,GAAG;AACrD,QAAI,UAAU;AAEZ,UAAI,SAAS,QAAQ,SAAS,OAAO,QAAQ,QAAQ;AACnD,cAAM,oBAAoB,SAAS,QAChC,IAAI,CAAC,WAAW,OAAO,GAAG,EAC1B;AAAA,UACC,CAAC,QAAQ,CAAC,OAAO,QAAQ,KAAK,CAAC,WAAW,OAAO,QAAQ,GAAG;AAAA,QAAA;AAGhE,YAAI,kBAAkB,SAAS,GAAG;AAChC,gBAAM,iBAAiB,kBAAkB,KAAK,IAAI;AAClD,gBAAM,IAAI;AAAA,YACR,GAAG,MAAM,mDACa,cAAc;AAAA,UAAA;AAAA,QAExC;AAAA,MACF;AAGA,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,QAAQ,KAAK;AAChD,cAAM,SAAS,SAAS,QAAQ,CAAC,EAAE;AACnC,cAAM,QAAQ,OAAO,QAAQ,CAAC,EAAE;AAChC,YAAI,WAAW,OAAO;AACpB,gBAAM,IAAI;AAAA,YACR,GAAG,MAAM,0CAEI,MAAM,uBAAuB,KAAK;AAAA,UAAA;AAAA,QAEnD;AAAA,MACF;AAGA,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,QAAQ,KAAK;AAChD,cAAM,SAAS,SAAS,QAAQ,CAAC,EAAE;AACnC,cAAM,SAAS,SAAS,QAAQ,CAAC,EAAE;AACnC,cAAM,QAAQ,OAAO,QAAQ,CAAC,EAAE;AAChC,YAAI,WAAW,OAAO;AACpB,gBAAM,IAAI;AAAA,YACR,GAAG,MAAM,mDAEY,MAAM,uBAAuB,MAAM,QAAQ,KAAK;AAAA,UAAA;AAAA,QAEzE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kCAAkC,MAAc;AACpD,UAAM,SAAmB,CAAA;AAEzB,UAAM,cAAc,MAAM,OAAO,aAAa;AAC5C,YAAM,WAAW,MAAM,KAAK,SAAS,QAAQ;AAC7C,YAAM,QAAQ,KAAK,QAAQ;AAI3B,UAAI,MAAM,UAAU,YAAa;AAEjC,aAAO,KAAK,GAAG,8BAA8B,MAAM,OAAO,QAAQ,CAAC;AAAA,IACrE,CAAC;AAED,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI;AAAA,QACR;AAAA;AAAA;AAAA,EAA4D,OACzD,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EACnB,KAAK,IAAI,CAAC;AAAA,MAAA;AAAA,IAEjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,2BAA2B,OAAwB;AACjD,UAAM,MAAM,KAAK,CAAC,GAAG,MAAM;AACzB,YAAM,QAAQ,EAAE;AAChB,YAAM,QAAQ,EAAE;AAEhB,UAAI,QAAQ,OAAO;AACjB,eAAO;AAAA,MACT;AAEA,UAAI,QAAQ,OAAO;AACjB,eAAO;AAAA,MACT;AAGA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,QAAQ;AACd,QAAI,OAAO;AAAA,MACT,sBAAsB;AAAA,MACtB,oBAAoB;AAAA,IAAA,CACrB;AAAA,EACH;AACF;ACtXO,MAAM,MAAoB;AAAA;AAAA;AAAA,EAI/B,OAAsB;AACpB,SAAK,UAAU;AACf,WAAO,KAAK,MAAA;AAAA,EACd;AAAA,EAEA,QAAuB;AACrB,SAAK,UAAU;AACf,WAAO,QAAQ,QAAA;AAAA,EACjB;AAAA,EAEA,IAAI,SAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,UAAU,YAAY;AAC3B,UAAM,KAAK,IAAI,MAAA;AACf,UAAM,GAAG,KAAA;AACT,WAAO;AAAA,EACT;AAAA;AAAA;AAAA,EAIA,UAAU;AACR,WAAO,KAAK,SAAS;AAAA,EACvB;AAAA;AAAA;AAAA,EAKA,OAAwB;AACtB,WAAO,KAAK,MAAA;AAAA,EACd;AAAA,EAEA,MAAM,UAAU,SAA6C;AAC3D,WAAO,KAAK,WAAW,OAAO;AAAA,EAChC;AAAA;AAAA;AAAA,EAKA,MAAM,YAAY,SAAkD;AAClE,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA;AAAA;AAAA,EAKA,SAAS,SAGW;AAClB,WAAO,KAAK,UAAU,OAAO;AAAA,EAC/B;AAAA,EAEA,MAAM,iBAAiB,SAGH;AAClB,UAAM,KAAK,SAAS,2BAA2B,QAAQ,KAAK;AAE5D,UAAM,QAAQ,KAAK,KAAK,QAAQ,KAAK;AACrC,UAAM,WAAW,KAAK,aAAa,QAAQ,KAAK;AAEhD,UAAM,2BAAW,IAAA;AACjB,UAAM,OAAc,CAAA;AACpB,eAAW,QAAQ,QAAQ,QAAQ;AACjC,UAAI,KAAK,IAAI,IAAI,EAAG;AACpB,WAAK,IAAI,IAAI;AACb,YAAM,MAAM,SAAS,IAAI,IAAI;AAC7B,UAAI,KAAK;AACP,aAAK,KAAK,GAAG;AAAA,MACf;AAAA,IACF;AAEA,UAAM,gBAA2B;AAAA,MAC/B,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,IAAA;AAET,SAAK,SAAS,2BAA2B,aAAa;AAEtD,WAAO,EAAE,CAAC,QAAQ,KAAK,GAAG,cAAA;AAAA,EAC5B;AAAA,EAEA,MAAM,SAAS,OAAgC;AAC7C,UAAM,YAAY,KAAK,KAAK,KAAK;AACjC,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,UAAU,KAAK,aAAa;AAAA,IAC9C;AACA,WAAO,QAAQ,QAAQ,UAAU,MAAM,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA,EAKA,MAAM,SAA0C;AAC9C,WAAO,KAAK,OAAO,OAAO;AAAA,EAC5B;AAAA;AAAA;AAAA,EAIA,MAAM,YAAY,UAAsC;AACtD,UAAM,QAAQ,KAAK,KAAK,QAAQ;AAChC,WAAO,QAAQ,OAAO;AAAA,EACxB;AAAA,EAEA,oBAAoB,SAAgD;AAClE,WAAO,KAAK,qBAAqB,OAAO;AAAA,EAC1C;AAAA,EAEA,MAAM,eAAoC;AACxC,UAAM,SAAS,KAAK,KAAK,UAAU;AACnC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAMQ;AAAA,EAEA,WAAW,IAAI,QAAA;AAAA,EACf,UAAU;AAAA,EAEV,OAAe,IAAI,EAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOtB,kCAAkB,IAAA;AAAA;AAAA,EAGlB,kCAAkB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlB,gCAAgB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,wCAAwB,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC,iBAAuB;AAC7B,QAAI,KAAK,kBAAkB,SAAS,GAAG;AACrC;AAAA,IACF;AAEA,eAAW,YAAY,KAAK,mBAAmB;AAC7C,YAAM,QAAQ,KAAK,KAAK,QAAQ;AAChC,YAAM,QAAQ;AACd,UAAI,OAAO;AAAA,QACT,sBAAsB;AAAA,QACtB,oBAAoB;AAAA,MAAA,CACrB;AAAA,IACH;AACA,SAAK,kBAAkB,MAAA;AAEvB,SAAK,kBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,aAAa,OAAmC;AACtD,QAAI,QAAQ,KAAK,UAAU,IAAI,KAAK;AACpC,QAAI,CAAC,OAAO;AACV,kCAAY,IAAA;AACZ,YAAM,YAAa,KAAK,KAAK,KAAK,EAAgB;AAClD,iBAAW,OAAO,WAAW;AAC3B,cAAM,IAAI,IAAI,OAAiB,GAAG;AAAA,MACpC;AACA,WAAK,UAAU,IAAI,OAAO,KAAK;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,oBAAoB,MAAa,KAAgB;AAC9D,UAAM,OAAO,IAAI;AACjB,QAAI,KAAK;AACT,QAAI,KAAK,KAAK;AACd,WAAO,KAAK,IAAI;AACd,YAAM,MAAO,KAAK,MAAO;AACzB,UAAK,KAAK,GAAG,EAAE,QAAmB,MAAM;AACtC,aAAK,MAAM;AAAA,MACb,OAAO;AACL,aAAK;AAAA,MACP;AAAA,IACF;AACA,SAAK,OAAO,IAAI,GAAG,GAAG;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAe,iBACb,KACA,OACS;AACT,eAAW,UAAU,OAAO;AAC1B,YAAM,IAAI,IAAI,MAAM;AACpB,YAAM,IAAI,MAAM,MAAM;AACtB,UAAI,MAAM,QAAQ,MAAM,QAAW;AACjC,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,OAAO,GAAG,CAAC,GAAG;AACjB,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,WAAW,OAAoC;AAC3D,QAAI,MAAM,KAAK,YAAY,IAAI,KAAK;AACpC,QAAI,CAAC,KAAK;AACR,YAAM,MAAM,KAAK,SAAS,SAAS,KAAK;AACxC,WAAK,YAAY,IAAI,OAAO,GAAG;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,KAAqB;AACzC,SAAK,YAAY,IAAI,IAAI,KAAK,GAAG;AACjC,SAAK,YAAY,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,6BACZ,OACA,SACe;AACf,QAAI,aAAa,KAAK,YAAY,IAAI,KAAK;AAC3C,QAAI,CAAC,YAAY;AACf,YAAM,MAAM,MAAM,KAAK,WAAW,KAAK;AACvC,mBAAa,IAAI,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAClD,WAAK,YAAY,IAAI,OAAO,UAAU;AAAA,IACxC;AAEA,UAAM,iBAAiB,QAAQ,OAAO,CAAC,WAAW,CAAC,WAAW,IAAI,MAAM,CAAC;AACzE,QAAI,eAAe,SAAS,GAAG;AAC7B,YAAM,IAAI;AAAA,QACR,gDAAgD,KAAK,MAAM,eAAe;AAAA,UACxE;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,IAEL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,mCACZ,MACe;AACf,UAAM,SAAmB,CAAA;AAEzB,eAAW,YAAY,OAAO,KAAK,IAAI,GAAG;AACxC,YAAM,QAAQ,KAAK,QAAQ;AAG3B,UAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,OAAO,KAAK,EAAG;AAI/D,UAAI,MAAM,UAAU,YAAa;AAEjC,YAAM,WAAW,MAAM,KAAK,WAAW,QAAQ;AAC/C,aAAO,KAAK,GAAG,8BAA8B,MAAM,OAAO,QAAQ,CAAC;AAAA,IACrE;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI;AAAA,QACR;AAAA;AAAA;AAAA,EAA4D,OACzD,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EACnB,KAAK,IAAI,CAAC;AAAA,MAAA;AAAA,IAEjB;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,QAAQ;AAEpB,SAAK,eAAA;AAIL,SAAK,UAAU,MAAA;AACf,SAAK,YAAY,MAAA;AACjB,SAAK,YAAY,MAAA;AAEjB,SAAK,WAAW,IAAI,QAAQ,IAAI;AAChC,SAAK,eAAA;AACL,SAAK,kBAAA;AACL,UAAM,KAAK,SAAS,mBAAA;AACpB,QAAI,KAAK,IAAI;AAEb,SAAK,SAAS,QAAA;AAAA,EAChB;AAAA;AAAA,EAGQ,iBAAiB,MAAM;AAC7B,UAAM,WAAW,QAAQ;AAEzB,SAAK,KAAK,YAAY,IAAI;AAAA,MACxB,OAAO;AAAA,MACP,OAAO,CAAC,QAAQ;AAAA,MAChB,WAAW,SAAS;AAAA,IAAA,CACrB;AAAA,EACH;AAAA;AAAA,EAGQ,oBAAoB;AACzB,SAAK,KAAa,QAAQ;AAC3B,QAAI,KAAK,MAAM;AAAA,MACb,sBAAsB;AAAA,IAAA,CACvB;AAAA,EACH;AAAA;AAAA,EAGQ,iBAAiB,UAAoB;AAC3C,UAAM,QAAQ,KAAK,KAAK,QAAQ;AAChC,UAAM,QAAQ;AACd,QAAI,OAAO,EAAE,sBAAsB,MAAA,CAAO;AAAA,EAC5C;AAAA;AAAA,EAGA,MAAc,qBAAqB,SAEjB;AAGhB,SAAK,eAAA;AAIL,UAAM,WAAW,QAAQ;AACzB,UAAM,KAAK,SAAS,8BAA8B,QAAQ;AAE1D,UAAM,EAAE,QAAQ;AAGhB,UAAM,YAAY,IAAI,QAAQ;AAG9B,UAAM,iBAAiB,MAAM,KAAK,SAAS,eAAe,GAAG;AAG7D,QAAI,CAAC,gBAAgB;AACnB,WAAK,aAAa,WAAW,GAAG;AAAA,IAClC,OAAO;AACL,WAAK,aAAa,gBAAgB,SAAS;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA,EAGQ,aAAa,WAAqB,UAAoB;AAE5D,gBAAY,IAAI,SAAS;AACzB,SAAK,KAAK,UAAU,MAAM,KAAK,SAAS;AACxC,SAAK,SAAS,2BAA2B,KAAK,KAAK,SAAS;AAC5D,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,IAAI,WAAW,GAAG,IAAI,UAAU,OAAiB,SAAS;AAGzE,UAAM,QAAmB;AAAA,MACvB,OAAO,UAAU;AAAA,MACjB,OAAO,CAAA;AAAA,MACP,WAAW,UAAU;AAAA,IAAA;AAGvB,SAAK,KAAK,QAAQ,MAAM,IAAI,KAAK;AAGjC,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,kBAAA;AAAA,EACP;AAAA;AAAA,EAGQ,aAAa,gBAA0B,WAAqB;AAElE,QAAI,eAAe,QAAQ,WAAW,UAAU,QAAQ,QAAQ;AAC9D;AAAA,IACF;AAGA,gBAAY,IAAI,SAAS;AACzB,SAAK,KAAK,UAAU,MAAM,KAAK,SAAS;AACxC,SAAK,SAAS,2BAA2B,KAAK,KAAK,SAAS;AAC5D,SAAK,cAAc,SAAS;AAC5B,SAAK,UAAU,IAAI,WAAW,GAAG,IAAI,UAAU,OAAiB,SAAS;AAGzE,UAAM,QAAQ,KAAK,KAAK,UAAU,GAAG;AACrC,UAAM,YAAY,UAAU;AAG5B,SAAK,iBAAiB,UAAU,GAAG;AACnC,SAAK,kBAAA;AAAA,EACP;AAAA;AAAA,EAIA,MAAc,QAAyB;AACrC,SAAK,eAAA;AACL,WAAO,KAAK,KAAK,IAAI;AAAA,EACvB;AAAA;AAAA,EAGA,MAAc,WAAW,SAA6C;AACpE,UAAM,KAAK,SAAS,2BAA2B,QAAQ,KAAK;AAE5D,SAAK,eAAA;AACL,UAAM,QAAQ,KAAK,KAAK,QAAQ,KAAK;AAErC,WAAO;AAAA,MACL,CAAC,QAAQ,KAAK,GAAG,KAAK,KAAK;AAAA,IAAA;AAAA,EAE/B;AAAA;AAAA,EAGA,MAAc,aAAa,SAAkD;AAC3E,UAAM,KAAK,SAAS,2BAA2B,QAAQ,KAAK;AAE5D,WAAQ,KAAK,KAAK,QAAQ,KAAK,EAAgB;AAAA,EACjD;AAAA;AAAA,EAGA,MAAc,OAAO,SAA0C;AAC7D,UAAM,YAAY,IAAI,QAAQ,IAAI;AAClC,UAAM,oBAAoB,KAAK,kBAAkB,SAAS;AAC1D,UAAM,SAAS,OAAO,KAAK,SAAS;AAGpC,QAAI,mBAAmB;AACrB,UAAI,SAAS;AAAA,IACf;AAEA,UAAM,KAAK,SAAS,0BAA0B,QAAQ,IAAI;AAC1D,UAAM,KAAK,mCAAmC,QAAQ,IAAI;AAE1D,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,WAAW,GAAG,GAAG;AACzB;AAAA,MACF;AAEA,YAAM,WAAW,KAAK,KAAK,KAAK;AAChC,YAAM,WAAW,UAAU,KAAK;AAChC,YAAM,WAAW,KAAK,aAAa,KAAK;AAIxC,iBAAW,QAAQ,SAAS,OAAO;AACjC,cAAM,OAAO,KAAK;AAClB,YAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,mBAAS,IAAI,MAAM,IAAI;AACvB,gBAAM,oBAAoB,SAAS,OAAO,IAAI;AAAA,QAChD;AAAA,MACF;AAIA,WAAK,kBAAkB,IAAI,KAAK;AAAA,IAClC;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,UAAU,SAGJ;AAClB,UAAM,KAAK,SAAS,2BAA2B,QAAQ,KAAK;AAC5D,UAAM,KAAK;AAAA,MACT,QAAQ;AAAA,MACR,OAAO,KAAK,QAAQ,KAAK;AAAA,IAAA;AAI3B,UAAM,QAAQ,KAAK,KAAK,QAAQ,KAAK;AAIrC,UAAM,YAAY,QAAQ,MAAM,OAAO;AACvC,QAAI;AACJ,QAAI,OAAO,cAAc,UAAU;AACjC,YAAM,MAAM,KAAK,aAAa,QAAQ,KAAK,EAAE,IAAI,SAAS;AAC1D,0BACE,OAAO,MAAM,iBAAiB,KAAK,QAAQ,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;AAAA,IAChE,OAAO;AACL,0BAAoB,MAAM,MAAM;AAAA,QAAO,CAAC,QACtC,MAAM,iBAAiB,KAAK,QAAQ,KAAK;AAAA,MAAA;AAAA,IAE7C;AAGA,UAAM,gBAA2B;AAAA,MAC/B,OAAO,MAAM;AAAA,MACb,OAAO;AAAA,IAAA;AAGT,SAAK,SAAS,2BAA2B,aAAa;AAEtD,UAAM,SAAiB;AAAA,MACrB,CAAC,QAAQ,KAAK,GAAG;AAAA,IAAA;AAGnB,WAAO;AAAA,EACT;AAAA,EAEA,kBAAkB,QAAyB;AACzC,QAAI,aAAa;AAEjB,sBAAkB,QAAQ,CAAC,UAAU;AACnC,YAAM,OAAO,OAAO,KAAK,EAAE;AAE3B,iBAAW,OAAO,MAAM;AACtB,mBAAW,OAAO,KAAK;AACrB,cAAI,IAAI,GAAG,MAAM,MAAM;AACrB,mBAAO,IAAI,GAAG;AACd,yBAAa;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AACF;ACllBO,MAAM,eAAiC;AAAA,EAO5C,YAAoB,KAAS;AAAT,SAAA,MAAA;AAAA,EAAU;AAAA,EANtB,oCACF,IAAA;AAAA,EAEN,YAAqB;AAAA,EACrB,eAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWxB,IAAI,WAA4B,UAA0C;AAExE,UAAM,YAAY,KAAK,cAAc,IAAI,SAAS,KAAK,CAAA;AACvD,UAAM,QAAQ,UAAU,QAAQ,QAAQ;AAExC,QAAI,UAAU,IAAI;AAChB,gBAAU,OAAO,OAAO,CAAC;AACzB,WAAK,cAAc,IAAI,WAAW,SAAS;AAAA,IAC7C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,mBAAmB,WAAmC;AACpD,QAAI,WAAW;AACb,WAAK,cAAc,OAAO,SAAS;AAAA,IACrC,OAAO;AACL,WAAK,cAAc,MAAA;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,GAAG,WAA4B,UAA0C;AACvE,QAAI,CAAC,KAAK,cAAc,IAAI,SAAS,GAAG;AACtC,WAAK,cAAc,IAAI,WAAW,CAAA,CAAE;AAAA,IACtC;AACA,SAAK,cAAc,IAAI,SAAS,EAAG,KAAK,QAAQ;AAChD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAgB;AACd,SAAK,YAAY;AACjB,SAAK,eAAe;AAEpB,UAAM,YAAY,KAAK,cAAc,IAAI,SAAS,KAAK,CAAA;AACvD,eAAW,MAAM,WAAW;AAC1B,SAAG,CAAA,CAAE;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAmB;AACjB,SAAK,YAAY;AACjB,SAAK,eAAe;AAEpB,UAAM,YAAY,KAAK,cAAc,IAAI,YAAY,KAAK,CAAA;AAC1D,eAAW,MAAM,WAAW;AAC1B,SAAG,CAAA,CAAE;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,cAA+B,MAAsB;AACxD,UAAM,KAAM,KAAK,IAAY,SAAS;AACtC,QAAI,OAAO,OAAO,YAAY;AAC5B,YAAM,IAAI,MAAM,SAAS,UAAU,SAAA,CAAU,gBAAgB;AAAA,IAC/D;AACA,UAAM,KAAK,KAAK,KAAK,SAAS,CAAC;AAC/B,OAAG,MAAM,KAAK,KAAK,KAAK,MAAM,GAAG,EAAE,CAAC,EACjC,KAAK,CAAC,WAAW;AAChB,SAAG,QAAQ,IAAI;AAAA,IACjB,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,SAAG,MAAM,GAAG;AAAA,IACd,CAAC;AAEH,WAAO;AAAA,EACT;AACF;AC3GO,MAAM,OAAqB;AAAA,EAGhC,YACU,SACA,oBAA4B,KACpC;AAFQ,SAAA,UAAA;AACA,SAAA,oBAAA;AAAA,EACP;AAAA,EALH,SAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaV,aAAgB,SAAqB,WAA+B;AAC1E,QAAI,KAAK,qBAAqB,EAAG,QAAO;AACxC,QAAI;AACJ,UAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,cAAQ,WAAW,MAAM;AACvB;AAAA,UACE,IAAI;AAAA,YACF,iBAAiB,KAAK,iBAAiB,OAAO,SAAS;AAAA,UAAA;AAAA,QACzD;AAAA,MAEJ,GAAG,KAAK,iBAAiB;AAAA,IAC3B,CAAC;AACD,WAAO,QAAQ,KAAK,CAAC,SAAS,cAAc,CAAC,EAAE,QAAQ,MAAM;AAC3D,mBAAa,KAAM;AAAA,IACrB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAsB;AAE1B,SAAK,QAAQ,GAAG,WAAW,MAAM;AAC/B,WAAK,SAAS;AAAA,IAChB,CAAC;AACD,SAAK,QAAQ,GAAG,cAAc,MAAM;AAClC,WAAK,SAAS;AAAA,IAChB,CAAC;AAGD,SAAK,QAAQ,QAAA;AAGb,WAAO,IAAI,QAAc,CAAC,YAAY;AAEpC,UAAI,KAAK,QAAQ,WAAW;AAC1B,aAAK,SAAS;AACd,gBAAA;AAAA,MACF,OAAO;AACL,aAAK,QAAQ,GAAG,WAAW,MAAM;AAC/B,kBAAA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QAAuB;AAE3B,QAAI,CAAC,KAAK,QAAQ,UAAW;AAE7B,WAAO,IAAI,QAAc,CAAC,YAAY;AACpC,WAAK,QAAQ,GAAG,cAAc,MAAM;AAClC,gBAAA;AAAA,MACF,CAAC;AACD,WAAK,QAAQ,WAAA;AAAA,IACf,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAyB;AAC7B,QAAI,CAAC,CAAC,KAAK,WAAW,KAAK,QAAQ,cAAc,KAAM,MAAK,SAAS;AAAA,cAC3D,SAAS;AAEnB,WAAO,CAAC,CAAC,KAAK,SAAS,QAAQ,QAAA,IAAY,QAAQ,OAAA;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAwB;AAC5B,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,YAAY;AAEvB,aAAK,QAAQ,KAAK,QAAQ,CAAC,SAAiB;AAC1C,kBAAQ,IAAI;AAAA,QACd,CAAC;AAAA,MACH,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UAAU,SAA6C;AACrD,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA,CAAC,MAAc,UAAkB;AAC/B,gBAAI,cAAc,KAAK;AACvB,oBAAQ,IAAI;AAAA,UACd;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,SAAkD;AAC5D,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA,CAAC,MAAmB,UAAkB;AAEpC,gBAAI,cAAc,KAAK;AACvB,oBAAQ,IAAI;AAAA,UACd;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,UAAsC;AAChD,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,YAAY;AAEvB,aAAK,QAAQ,KAAK,eAAe,UAAU,CAAC,WAAoB;AAC9D,kBAAQ,MAAM;AAAA,QAChB,CAAC;AAAA,MACH,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,SAAgD;AAClE,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA,CAAC,GAAa,UAAkB;AAC9B,gBAAI,cAAc,KAAK;AACvB,oBAAA;AAAA,UACF;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAoC;AAClC,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,YAAY;AAEvB,aAAK,QAAQ,KAAK,gBAAgB,CAAC,SAAqB;AACtD,kBAAQ,IAAI;AAAA,QACd,CAAC;AAAA,MACH,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAA0C;AAC9C,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ,KAAK,SAAS,SAAS,CAAC,GAAa,UAAkB;AAClE,cAAI,cAAc,KAAK;AACvB,kBAAA;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,SAGW;AAClB,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA,CAAC,QAAiB,UAAkB;AAClC,gBAAI,cAAc,KAAK;AACvB,oBAAQ,MAAO;AAAA,UACjB;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,yBAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQjC,MAAM,iBAAiB,SAGH;AAClB,QAAI,CAAC,KAAK,wBAAwB;AAChC,UAAI;AACF,eAAO,MAAM,KAAK;AAAA,UAChB,IAAI,QAAgB,CAAC,SAAS,WAAW;AACvC,iBAAK,QAAQ;AAAA,cACX;AAAA,cACA;AAAA,cACA,CAAC,QAAiB,UAAkB;AAClC,oBAAI,cAAc,KAAK;AACvB,wBAAQ,MAAO;AAAA,cACjB;AAAA,YAAA;AAAA,UAEJ,CAAC;AAAA,UACD;AAAA,QAAA;AAAA,MAEJ,SAAS,OAAO;AACd,cAAM,UAAU,OAAQ,MAAgB,OAAO;AAC/C,cAAM,cACJ,QAAQ,SAAS,0BAA0B,KAC3C,QAAQ,SAAS,eAAe,KAChC,QAAQ,SAAS,eAAe;AAClC,YAAI,CAAC,aAAa;AAChB,gBAAM;AAAA,QACR;AACA,aAAK,yBAAyB;AAAA,MAChC;AAAA,IACF;AAGA,UAAM,SAAS,MAAM,KAAK,IAAI,IAAI,QAAQ,MAAM,CAAC;AACjD,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,OAAO;AAAA,QAAI,CAAC,SACV,KAAK,SAAS,EAAE,OAAO,QAAQ,OAAO,OAAO,EAAE,OAAO,KAAA,GAAQ;AAAA,MAAA;AAAA,IAChE;AAGF,QAAI,OAAgC;AACpC,UAAM,OAAc,CAAA;AACpB,eAAW,UAAU,SAAS;AAC5B,YAAM,YAAY,OAAO,QAAQ,KAAK;AACtC,eAAS,UAAU;AACnB,WAAK,KAAK,GAAG,UAAU,KAAK;AAAA,IAC9B;AAGA,QAAI,SAAS,QAAW;AAEtB,YAAM,QAAQ,MAAM,KAAK,SAAS;AAAA,QAChC,OAAO,QAAQ;AAAA,QACf,OAAO,EAAE,OAAO,WAAA;AAAA,MAAW,CAC5B;AACD,aAAO,MAAM,QAAQ,KAAK,EAAE;AAAA,IAC9B;AAEA,WAAO,EAAE,CAAC,QAAQ,KAAK,GAAG,EAAE,OAAO,MAAM,OAAO,OAAK;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,SAAS,OAAgC;AACvC,WAAO,KAAK;AAAA,MACV,IAAI,QAAQ,CAAC,SAAS,WAAW;AAE/B,aAAK,QAAQ;AAAA,UACX;AAAA,UACA;AAAA,UACA,CAAC,OAAgB,UAAkB;AACjC,gBAAI,cAAc,KAAK;AACvB,oBAAQ,KAAM;AAAA,UAChB;AAAA,QAAA;AAAA,MAEJ,CAAC;AAAA,MACD;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA,EAGA,OAAO,UAAU,YAAY;AAC3B,UAAM,QAAQ,MAAM,MAAM,QAAA;AAC1B,UAAM,SAAS,IAAI,eAAe,KAAK;AACvC,UAAM,KAAK,IAAI,OAAO,MAAM;AAC5B,UAAM,GAAG,KAAA;AACT,WAAO;AAAA,EACT;AACF;AC1VO,MAAM,QAAsB;AAAA,EAGjC,YAAoB,MAAwB;AAAxB,SAAA,OAAA;AAAA,EAAyB;AAAA,EAF7C,SAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUlB,MAAM,OAAsB;AAC1B,aAAS,MAAM,GAAG,MAAM,KAAK,KAAK,QAAQ,OAAO;AAC/C,YAAM,EAAE,GAAA,IAAO,KAAK,KAAK,GAAG;AAC5B,UAAI,GAAG,WAAW,OAAO;AACvB,cAAM,IAAI;AAAA,UACR;AAAA,QAAA;AAAA,MAEJ;AAEA,WAAK,KAAK,GAAG,IAAI,EAAE,GAAG,KAAK,KAAK,GAAG,GAAG,IAAI,MAAM,GAAG,GAAA;AAAA,IACrD;AAEA,SAAK,SAAS;AACd,WAAO,QAAQ,QAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAuB;AAC3B,UAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC,cAAc,UAAU,GAAG,MAAA,CAAO,CAAC;AAEpE,SAAK,SAAS;AAEd,WAAO,QAAQ,QAAA;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAyB;AACvB,WAAO,QAAQ;AAAA,MACb,KAAK,KAAK,IAAI,CAAC,cAAc,UAAU,GAAG,SAAS;AAAA,IAAA,EACnD,KAAK,MAAM,QAAQ,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAwB;AAE5B,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,QAAQ,MAAM,QAAQ;AAAA,MAC1B,KAAK,UAAU,IAAI,CAAC,EAAE,IAAI,SAAA,MAAe,SAAS,KAAA,CAAM;AAAA,IAAA;AAG1D,WAAO,MAAM,GAAG,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,SAA6C;AAE3D,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,QAAkB,CAAA;AAExB,eAAW,EAAE,IAAI,SAAA,KAAc,KAAK,WAAW;AAC7C,UAAI;AACF,cAAM,OAAO,MAAM,SAAS,UAAU,OAAO;AAC7C,cAAM,KAAK,IAAI;AAAA,MACjB,QAAQ;AACN;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,IAAI,MAAM,UAAU,QAAQ,KAAK,aAAa;AAAA,IACtD;AAEA,WAAO,MAAM,GAAG,KAAK;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,YAAY,SAAkD;AAElE,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,eAAW,EAAE,IAAI,SAAA,KAAc,KAAK,WAAW;AAC7C,aAAO,SAAS,YAAY,OAAO;AAAA,IACrC;AAEA,UAAM,IAAI,MAAM,UAAU,QAAQ,KAAK,aAAa;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,YAAY,UAAsC;AAEtD,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,SAAS,QAAQ,iBAAiB,KAAK,SAAS;AACtD,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,WAAW,GAAG;AACtB,cAAM,SAAS,MAAM,MAAM,CAAC,EAAE,GAAG,YAAY,QAAQ;AACrD,YAAI,OAAQ,QAAO;AAAA,MACrB,OAAO;AACL,cAAM,UAAU,MAAM,QAAQ;AAAA,UAC5B,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,QAAQ,CAAC;AAAA,QAAA;AAE7C,mBAAW,UAAU,SAAS;AAC5B,cAAI,OAAO,WAAW,eAAe,OAAO,MAAO,QAAO;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,oBAAoB,SAAgD;AAElE,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,YAAY,KAAK,UAAU;AAAA,MAAI,CAAC,EAAE,IAAI,eAC1C,SAAS,oBAAoB,OAAO;AAAA,IAAA;AAEtC,WAAO,QAAQ,IAAI,SAAS,EAAE,KAAK,MAAM,QAAQ,SAAS;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,eAAoC;AAExC,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,mCAA0C,IAAA;AAChD,eAAW,EAAE,IAAI,SAAA,KAAc,KAAK,WAAW;AAC7C,YAAM,OAAO,MAAM,SAAS,aAAA;AAE5B,UAAI,KAAK,SAAS,GAAG;AACnB,mBAAW,YAAY,MAAM;AAC3B,cAAI,CAAC,aAAa,IAAI,SAAS,GAAG,GAAG;AACnC,yBAAa,IAAI,SAAS,KAAK,QAAQ;AAAA,UACzC;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AACA,WAAO,MAAM,KAAK,aAAa,OAAA,CAAQ;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAA0C;AAE9C,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAGA,UAAM,SAAS,KAAK,UAAU;AAAA,MAAI,CAAC,EAAE,IAAI,eACvC,SAAS,MAAM,OAAO;AAAA,IAAA;AAExB,WAAO,QAAQ,IAAI,MAAM,EAAE,KAAK,MAAM,QAAQ,SAAS;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,SAAS,SAGK;AAElB,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,QAAI,iBAAiB;AACrB,UAAM,2BAA8B,IAAA;AACpC,QAAI,OAAgC;AACpC,QAAI,WAAmB;AAEvB,UAAM,SAAkB,CAAA;AAGxB,UAAM,SAAS,QAAQ,iBAAiB,KAAK,SAAS;AAEtD,eAAW,SAAS,QAAQ;AAC1B,UAAI,MAAM,WAAW,GAAG;AAEtB,cAAM,WAAW,MAAM,CAAC;AACxB,YAAI;AACF,gBAAM,EAAE,CAAC,QAAQ,KAAK,GAAG,UAAA,IAAc,MAAM,SAAS,GAAG;AAAA,YACvD;AAAA,UAAA;AAEF,gBAAM,YAAa,UAChB;AACH,gBAAM,YAAa,UAChB;AACH,2BAAiB;AACjB,mBAAS;AAET,cAAI,UAAU,SAAS,GAAG;AAExB,uBAAW,SAAS,MAAM;AAE1B,uBAAW,YAAY,WAAW;AAChC,oBAAM,MAAM,SAAS;AACrB,mBAAK,IAAI,KAAK,QAAQ;AAAA,YACxB;AACA;AAAA,UACF;AAAA,QACF,SAAS,GAAG;AACV,iBAAO,KAAK,CAAU;AAAA,QACxB;AAAA,MACF,OAAO;AAGL,cAAM,UAAU,MAAM,QAAQ;AAAA,UAC5B,MAAM,IAAI,OAAO,aAAa;AAC5B,kBAAM,EAAE,CAAC,QAAQ,KAAK,GAAG,UAAA,IAAc,MAAM,SAAS,GAAG;AAAA,cACvD;AAAA,YAAA;AAEF,mBAAO;AAAA,cACL;AAAA,cACA,WAAY,UAA6C;AAAA,cACzD,WAAY,UAA6C;AAAA,YAAA;AAAA,UAE7D,CAAC;AAAA,QAAA;AAGH,YAAI,YAAY;AAChB,mBAAW,UAAU,SAAS;AAC5B,cAAI,OAAO,WAAW,YAAY;AAChC,mBAAO,KAAK,OAAO,MAAe;AAClC;AAAA,UACF;AACA,2BAAiB;AACjB,gBAAM,EAAE,UAAU,WAAW,UAAA,IAAc,OAAO;AAClD,mBAAS;AACT,cAAI,UAAU,SAAS,KAAK,CAAC,WAAW;AACtC,wBAAY;AACZ,uBAAW,SAAS,MAAM;AAE1B,uBAAW,YAAY,WAAW;AAChC,oBAAM,MAAM,SAAS;AACrB,mBAAK,IAAI,KAAK,QAAQ;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAEA,YAAI,UAAW;AAAA,MACjB;AAAA,IACF;AAEA,QAAI,CAAC,gBAAgB;AAEnB,UAAI,OAAO,WAAW,GAAG;AACvB,cAAM,IAAI,MAAM,UAAU,QAAQ,KAAK,aAAa;AAAA,MACtD,OAAO;AACL,cAAM,gBAAgB,OAAO;AAAA,UAC3B,CAAC,QAAQ,CAAC,IAAI,QAAQ,SAAS,UAAU,QAAQ,KAAK,aAAa;AAAA,QAAA;AAErE,YAAI,cAAc,SAAS,GAAG;AAC5B,gBAAM,cAAc,CAAC;AAAA,QACvB,OAAO;AACL,gBAAM,OAAO,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,SAAS;AAAA,QACb,CAAC,QAAQ,KAAK,GAAG,IAAI,EAAE,OAAO,MAAM,KAAK,KAAK,OAAA,CAAQ,GAAG,OAAO,MAAM;AAAA,MAAA;AAIxE,UAAI,KAAK,UAAU,SAAS,KAAK,KAAK,OAAO,GAAG;AAC9C,mBAAW,aAAa,KAAK,WAAW;AACtC,cAAI,UAAU,OAAO,UAAU;AAC7B;AAAA,UACF;AAEA,cAAI;AACF,kBAAM,UAAU,GAAG,MAAM;AAAA,cACvB,MAAM;AAAA,YAAA,CACP;AAAA,UACH,QAAQ;AACN;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,SAAS,OAAgC;AAE7C,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,UAAM,YAAY,MAAM,KAAK,UAAU,EAAE,OAAO;AAChD,UAAM,YAAuB,UAAU,KAAK;AAE5C,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,UAAU,KAAK,aAAa;AAAA,IAC9C;AACA,WAAO,QAAQ,QAAQ,UAAU,MAAM,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBAAiB,SAGH;AAElB,QAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAEA,QAAI,iBAAiB;AACrB,UAAM,2BAA8B,IAAA;AACpC,QAAI,OAAgC;AACpC,QAAI,WAAmB;AACvB,UAAM,SAAkB,CAAA;AAExB,QAAI,YAAY,MAAM,KAAK,IAAI,IAAI,QAAQ,MAAM,CAAC;AAElD,eAAW,YAAY,KAAK,WAAW;AACrC,UAAI,UAAU,WAAW,EAAG;AAE5B,UAAI;AACF,YAAI;AACJ,YAAI,SAAS,GAAG,kBAAkB;AAChC,mBAAS,MAAM,SAAS,GAAG,iBAAiB;AAAA,YAC1C,OAAO,QAAQ;AAAA,YACf,QAAQ;AAAA,UAAA,CACT;AAAA,QACH,OAAO;AACL,mBAAS,MAAM,QAAQ;AAAA,YACrB,SAAS;AAAA,YACT,QAAQ;AAAA,YACR;AAAA,UAAA;AAAA,QAEJ;AAEA,cAAM,YAAY,OAAO,QAAQ,KAAK;AAItC,yBAAiB;AAEjB,eAAO,UAAU;AAEjB,YAAI,UAAU,MAAM,SAAS,GAAG;AAI9B,qBAAW,SAAS,MAAM;AAC1B,qBAAW,YAAY,UAAU,OAAO;AACtC,iBAAK,IAAI,SAAS,OAAiB,QAAQ;AAAA,UAC7C;AACA,sBAAY,UAAU,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC;AAAA,QACxD;AAAA,MACF,SAAS,GAAG;AACV,eAAO,KAAK,CAAU;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,CAAC,gBAAgB;AAEnB,UAAI,OAAO,WAAW,GAAG;AACvB,cAAM,IAAI,MAAM,UAAU,QAAQ,KAAK,aAAa;AAAA,MACtD,OAAO;AACL,cAAM,gBAAgB,OAAO;AAAA,UAC3B,CAAC,QAAQ,CAAC,IAAI,QAAQ,SAAS,UAAU,QAAQ,KAAK,aAAa;AAAA,QAAA;AAGrE,YAAI,cAAc,SAAS,GAAG;AAC5B,gBAAM,cAAc,CAAC;AAAA,QACvB,OAAO;AACL,gBAAM,OAAO,CAAC;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb,CAAC,QAAQ,KAAK,GAAG,IAAI,EAAE,OAAO,MAAM,KAAK,KAAK,OAAA,CAAQ,GAAG,OAAO,MAAM;AAAA,IAAA;AAKxE,QAAI,KAAK,UAAU,SAAS,KAAK,KAAK,OAAO,GAAG;AAC9C,iBAAW,aAAa,KAAK,WAAW;AACtC,YAAI,UAAU,OAAO,UAAU;AAC7B;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,UAAU,GAAG,MAAM,EAAE,MAAM,QAAQ;AAAA,QAC3C,QAAQ;AACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAqB,uBACnB,IACA,OACA,QACiB;AACjB,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,OAAO,IAAI,CAAC,SAAS,GAAG,SAAS,EAAE,OAAO,OAAO,EAAE,OAAO,KAAA,EAAK,CAAG,CAAC;AAAA,IAAA;AAGrE,QAAI,OAAgC;AACpC,UAAM,OAAe,CAAA;AACrB,eAAW,UAAU,SAAS;AAC5B,YAAM,YAAY,OAAO,KAAK;AAC9B,eAAS,UAAU;AACnB,WAAK,KAAK,GAAG,UAAU,KAAK;AAAA,IAC9B;AAEA,WAAO,EAAE,CAAC,KAAK,GAAG,EAAE,OAAO,MAAM,OAAO,OAAK;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAA8B;AAChC,WAAO,KAAK,KACT,OAAO,CAAC,cAAc,UAAU,IAAI,EACpC,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAA8B;AAChC,WAAO,KAAK,KACT,OAAO,CAAC,cAAc,UAAU,KAAK,EACrC,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,IAAI,YAA8B;AAChC,WAAO,KAAK,KACT,OAAO,CAAC,cAAc,UAAU,IAAI,EACpC,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,QAAQ;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,iBAAiB,KAAgD;AACtE,UAAM,SAAkC,CAAA;AACxC,QAAI,UAA4B,CAAA;AAChC,QAAI,kBAAiC;AAErC,eAAW,MAAM,KAAK;AACpB,UAAI,GAAG,aAAa,iBAAiB;AACnC,YAAI,QAAQ,SAAS,EAAG,QAAO,KAAK,OAAO;AAC3C,kBAAU,CAAC,EAAE;AACb,0BAAkB,GAAG;AAAA,MACvB,OAAO;AACL,gBAAQ,KAAK,EAAE;AAAA,MACjB;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,EAAG,QAAO,KAAK,OAAO;AAE3C,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,OAAO,UAAU,YAAY;AAC3B,UAAM,YAAY,MAAM,MAAM,QAAA;AAC9B,UAAM,UAAU,KAAA;AAEhB,UAAM,eAAe,IAAI,eAAe,SAAS;AACjD,UAAM,SAAS,IAAI,OAAO,YAAY;AACtC,UAAM,OAAO,KAAA;AAEb,UAAM,QAAQ,MAAM,MAAM,QAAA;AAC1B,UAAM,MAAM,KAAA;AAEZ,UAAM,MAAwB;AAAA,MAC5B,EAAE,IAAI,QAAQ,UAAU,GAAG,MAAM,MAAM,OAAO,OAAO,MAAM,MAAA;AAAA,MAC3D,EAAE,IAAI,OAAO,UAAU,GAAG,MAAM,MAAM,OAAO,MAAM,MAAM,KAAA;AAAA,IAAK;AAGhE,UAAM,UAAU,IAAI,QAAQ,GAAG;AAC/B,UAAM,QAAQ,KAAA;AAEd,WAAO;AAAA,EACT;AACF;AC5lBO,MAAM,aAAa;AAAA,EAIxB,YAAoB,KAAiB,SAAiB;AAAlC,SAAA,MAAA;AAAiB,SAAA,UAAA;AAAA,EAAkB;AAAA,EAH/C,qCACF,IAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQN,QAAc;AACZ,SAAK,QAAQ,GAAG,WAAW,MAAM,KAAK,gBAAgB;AACtD,SAAK,QAAQ,GAAG,cAAc,MAAM,KAAK,mBAAmB;AAG5D,SAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,OAAa;AAEX,SAAK,QAAQ,IAAI,WAAW,MAAM,KAAK,gBAAgB;AAEvD,SAAK,QAAQ,IAAI,cAAc,MAAM,KAAK,mBAAmB;AAE7D,eAAW,CAAC,WAAW,OAAO,KAAK,KAAK,gBAAgB;AACtD,WAAK,QAAQ,IAAI,WAAW,OAAO;AAAA,IACrC;AACA,SAAK,eAAe,MAAA;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AAEjC,UAAM,YAAY;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAGF,eAAW,cAAc,WAAW;AAClC,WAAK,cAAc,UAAU;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,cAAc,WAAmB,cAA6B;AAC5D,UAAM,aAAa,gBAAgB;AAGnC,UAAM,UAAU,IAAI,SAAgB;AAElC,YAAM,WAAW,KAAK,KAAK,SAAS,CAAC;AACrC,YAAM,aAAa,KAAK,MAAM,GAAG,EAAE;AAGnC,YAAM,WAAY,KAAK,IAAY,UAAU;AAG7C,UAAI,OAAO,aAAa,YAAY;AAClC,cAAM,QAAQ,IAAI;AAAA,UAChB,WAAW,UAAU;AAAA,QAAA;AAEvB,YAAI,OAAO,aAAa,YAAY;AAClC,mBAAS,MAAM,KAAK;AAAA,QACtB;AACA;AAAA,MACF;AAIA,eACG,MAAM,KAAK,KAAK,UAAU,EAC1B,KAAK,CAAC,WAAgB;AACrB,YAAI,OAAO,aAAa,YAAY;AAElC,mBAAS,QAAQ,IAAI;AAAA,QACvB;AAAA,MACF,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,YAAI,OAAO,aAAa,YAAY;AAElC,mBAAS,MAAM,KAAK;AAAA,QACtB;AAAA,MACF,CAAC;AAAA,IACL;AAEA,SAAK,eAAe,IAAI,WAAW,OAAO;AAC1C,SAAK,QAAQ,GAAG,WAAW,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,YAA4B;AACzC,eAAW,aAAa,YAAY;AAClC,WAAK,cAAc,SAAS;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,WAAkC;AAChD,UAAM,UAAU,KAAK,eAAe,IAAI,SAAS;AACjD,QAAI,SAAS;AACX,WAAK,QAAQ,IAAI,WAAW,OAAO;AACnC,WAAK,eAAe,OAAO,SAAS;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,cAA+B,MAAmB;AAC7D,SAAK,QAAQ,KAAK,WAAW,GAAG,IAAI;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACJ,cACA,oBACG,MACY;AACf,QAAI;AACF,YAAM,WAAY,KAAK,IAAY,YAAY;AAE/C,UAAI,OAAO,aAAa,YAAY;AAClC,cAAM,IAAI,MAAM,WAAW,YAAY,4BAA4B;AAAA,MACrE;AAEA,YAAM,SAAS,MAAM,SAAS,MAAM,KAAK,KAAK,IAAI;AAClD,WAAK,QAAQ,KAAK,iBAAiB,QAAQ,IAAI;AAAA,IACjD,SAAS,OAAO;AACd,WAAK,QAAQ,KAAK,iBAAiB,MAAM,KAAK;AAAA,IAChD;AAAA,EACF;AAAA;AAAA,EAGQ,iBAAuB;AAAA,EAE/B;AAAA;AAAA,EAGQ,oBAA0B;AAAA,EAElC;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,KAAS;AACX,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,cAAuB;AACzB,WAAO,KAAK,QAAQ;AAAA,EACtB;AACF;AC3MO,MAAM,SAAS;AAAA,EAGpB,YAAoB,KAAS;AAAT,SAAA,MAAA;AAAA,EAAU;AAAA,EAFtB,WAAqB,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS7B,MAAM,UAAU,QAA+B;AAE7C,UAAM,KAAK,mBAAmB,MAAM;AAGpC,SAAK,SAAS,KAAK,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,QAAsB;AACjC,SAAK,WAAW,KAAK,SAAS,OAAO,CAAC,MAAM,MAAM,MAAM;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,mBAAmB,QAA+B;AAI9D,UAAM,OAAO,KAAK,4BAAA;AAClB,eAAW,CAAC,KAAK,EAAE,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC5C,aAAO,GAAG,KAAK,IAAI,SAAgB;AACjC,cAAM,KAAK,KAAK,KAAK,SAAS,CAAC;AAE/B,WAAG,MAAM,MAAM,KAAK,MAAM,GAAG,EAAE,CAAC,EAC7B,KAAK,CAAC,WAAW;AAChB,aAAG,QAAQ,IAAI;AAAA,QACjB,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,aAAG,MAAM,GAAG;AAAA,QACd,CAAC;AAAA,MACL,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBAAoB,SAEhB;AAChB,WAAO,KAAK,IAAI,oBAAoB,OAAO;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,8BAA8B,OACnC;AAAA,IACC,MAAM,MAAM,KAAK,IAAI,KAAA;AAAA,IACrB,OAAO,MAAM,KAAK,IAAI,MAAA;AAAA,IACtB,QAAQ,MACN,IAAI,QAAQ,CAAC,YAAY,QAAQ,KAAK,IAAI,MAAM,CAAC;AAAA,IACnD,SAAS,MAAM,KAAK,IAAI,QAAA;AAAA,IACxB,MAAM,MAAM,KAAK,IAAI,KAAA;AAAA,IACrB,WAAW,CAAC,YAA+B,KAAK,IAAI,UAAU,OAAO;AAAA,IACrE,aAAa,CAAC,YACZ,KAAK,IAAI,YAAY,OAAO;AAAA,IAC9B,aAAa,CAAC,aAAuB,KAAK,IAAI,YAAY,QAAQ;AAAA,IAClE,qBAAqB,CAAC,YACpB,KAAK,oBAAoB,OAAO;AAAA,IAClC,cAAc,MAAM,KAAK,IAAI,aAAA;AAAA,IAC7B,OAAO,CAAC,YAA8B,KAAK,IAAI,MAAM,OAAO;AAAA,IAC5D,UAAU,CAAC,YAGL,KAAK,IAAI,SAAS,OAAO;AAAA,IAC/B,kBAAkB,CAAC,YACjB,KAAK,IAAI,mBACL,KAAK,IAAI,iBAAiB,OAAO,IACjC,QAAQ;AAAA,MACN,IAAI;AAAA,QACF;AAAA,MAAA;AAAA,IACF;AAAA,IAER,UAAU,CAAC,UAAkB,KAAK,IAAI,SAAS,KAAK;AAAA,EAAA;AAE1D;ACzEO,MAAM,mBAAmB,MAAmB;AACjD,SAAO;AAAA,IACL,IAAI,IAAI,MAAA;AAAA,IACR,WAAW,YAAY;AAAA,IAGvB;AAAA,IAEA,YAAY,YAAY;AAAA,IAExB;AAAA,IACA,WAAW,YAAY;AAAA,IAEvB;AAAA,IAEA,UAAU,YAAY;AAAA,IAEtB;AAAA,EAAA;AAEJ;ACsCO,MAAM,YACX;ACrCK,MAAM,kBAAkB,CAAC,WAAgC;AAC9D,QAAM,SAAsB,CAAA;AAI5B,oBAAkB,QAAQ,CAAC,eAAe,UAAU;AAClD,UAAM,aAAoD,CAAA;AAC1D,WAAO,aAAa,IAAI;AACxB,eAAW,YAAY,MAAM,OAAO;AAClC,iBAAW,SAAS,KAAK,IAAI,CAAA;AAAA,IAC/B;AAAA,EACF,CAAC;AAID,oBAAkB,QAAQ,CAAC,gBAAgB,gBAAgB;AAEzD,eAAW,kBAAkB,YAAY,OAAO;AAG9C,cAAQ,YAAY,OAAA;AAAA,QAClB,KAAK;AACH,8BAAoB,gBAAgB,gBAAgB,MAAM;AAC1D;AAAA,QAEF,KAAK,UAAU;AACb,0BAAgB,gBAAgB,gBAAgB,MAAM;AACtD;AAAA,QACF;AAAA,QAEA,KAAK,YAAY;AAEf;AAAA,QACF;AAAA,QAEA,KAAK,SAAS;AACZ,yBAAe,gBAAgB,gBAAgB,MAAM;AACrD;AAAA,QACF;AAAA,QAEA,KAAK,WAAW;AACd,2BAAiB,gBAAgB,gBAAgB,MAAM;AACvD;AAAA,QACF;AAAA,MAAA;AAAA,IAEJ;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAKA,MAAM,sBAAsB,CAC1B,iBACA,WACA,WACG;AACH,QAAM,gBAAgB,UAAU;AAEhC,aAAW,oBAAoB,WAAW;AACxC,QAAI,iBAAiB,WAAW,GAAG,GAAG;AACpC;AAAA,IACF;AAEA,QAAI,CAAC,iBAAiB,SAAS,KAAK,GAAG;AACrC;AAAA,IACF;AAEA,UAAM,iBAAiB,iBAAiB,MAAM,GAAG,EAAE;AACnD,UAAM,eAAe,UAAU,gBAAgB;AAE/C;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AAGA,MAAM,kBAAkB,CACtB,iBACA,WACA,WACG;AACH,QAAM,iBAAiB,UAAU;AACjC,QAAM,gBAAgB,UAAU;AAEhC,aAAW,WAAW,UAAU,KAAK;AACnC,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B;AAAA,IACF;AAEA,UAAM,YAAY,UAAU,IAAI,OAAO;AAEvC,WAAO,QAAQ,gBAAgB,WAAW,iBAAiB,aAAa;AAAA,EAC1E;AACF;AAGA,MAAM,iBAAiB,CACrB,iBACA,WACA,WACG;AACH,QAAM,gBAAgB,UAAU;AAEhC,aAAW,SAAS,UAAU,QAAQ;AACpC,UAAM,iBAAiB;AACvB,UAAM,eAAe,UAAU,OAAO,KAAK;AAC3C;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AAGA,MAAM,mBAAmB,CACvB,iBACA,WACA,WACG;AACH,QAAM,gBAAgB,UAAU;AAEhC,aAAW,QAAQ,UAAU,OAAO;AAClC,UAAM,iBAAiB,KAAK;AAC5B,UAAM,eAAe,KAAK;AAC1B;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AAGA,MAAM,SAAS,CACb,QACA,gBACA,cACA,iBACA,kBACG;AACH,QAAM,0BAA2B,OAAO,cAAc,MAAM,CAAA;AAC5D,QAAM,6BAA8B,wBAAwB,YAAY,MACtE,CAAA;AAEF,6BAA2B,eAAe,MAAM,CAAA;AAChD,6BAA2B,eAAe,EAAE,aAAa,MAAM,CAAA;AACjE;ACpNO,MAAM,WAA6B;AAAA,EACjC,YAAqB;AAAA,EACrB,eAAwB;AAAA,EAEvB,iCACF,IAAA;AAAA,EACE,qCAGA,IAAA;AAAA,EAER,UAAgB;AACd,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY;AACjB,WAAK,eAAe;AACpB,WAAK,KAAK,SAAS;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,aAAmB;AACjB,QAAI,KAAK,WAAW;AAClB,WAAK,YAAY;AACjB,WAAK,eAAe;AACpB,WAAK,KAAK,YAAY;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,GAAG,WAA4B,UAA0C;AACvE,QAAI,CAAC,KAAK,WAAW,IAAI,SAAS,GAAG;AACnC,WAAK,WAAW,IAAI,WAAW,CAAA,CAAE;AAAA,IACnC;AACA,SAAK,WAAW,IAAI,SAAS,EAAG,KAAK,QAAQ;AAC7C,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,WAA4B,UAA0C;AACzE,QAAI,CAAC,KAAK,eAAe,IAAI,SAAS,GAAG;AACvC,WAAK,eAAe,IAAI,WAAW,CAAA,CAAE;AAAA,IACvC;AACA,SAAK,eAAe,IAAI,SAAS,EAAG,KAAK,QAAQ;AACjD,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,WAA4B,UAA2C;AACzE,QAAI,UAAU;AAEZ,YAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS;AACtD,UAAI,kBAAkB;AACpB,cAAM,QAAQ,iBAAiB,QAAQ,QAAQ;AAC/C,YAAI,QAAQ,IAAI;AACd,2BAAiB,OAAO,OAAO,CAAC;AAAA,QAClC;AAAA,MACF;AAEA,YAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS;AACvD,UAAI,eAAe;AACjB,cAAM,QAAQ,cAAc,QAAQ,QAAQ;AAC5C,YAAI,QAAQ,IAAI;AACd,wBAAc,OAAO,OAAO,CAAC;AAAA,QAC/B;AAAA,MACF;AAAA,IACF,OAAO;AAEL,WAAK,WAAW,OAAO,SAAS;AAChC,WAAK,eAAe,OAAO,SAAS;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,cAA+B,MAAsB;AACxD,QAAI,eAAe;AAGnB,UAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS;AACtD,QAAI,oBAAoB,iBAAiB,SAAS,GAAG;AACnD,qBAAe;AAEf,OAAC,GAAG,gBAAgB,EAAE,QAAQ,CAAC,aAAa;AAC1C,YAAI;AACF,mBAAS,GAAG,IAAI;AAAA,QAClB,SAAS,OAAO;AAEd,kBAAQ;AAAA,YACN,+BAA+B,OAAO,SAAS,CAAC;AAAA,YAChD;AAAA,UAAA;AAAA,QAEJ;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS;AACvD,QAAI,iBAAiB,cAAc,SAAS,GAAG;AAC7C,qBAAe;AAEf,YAAM,kBAAkB,CAAC,GAAG,aAAa;AACzC,WAAK,eAAe,OAAO,SAAS;AAEpC,sBAAgB,QAAQ,CAAC,aAAa;AACpC,YAAI;AACF,mBAAS,GAAG,IAAI;AAAA,QAClB,SAAS,OAAO;AACd,kBAAQ;AAAA,YACN,oCAAoC,OAAO,SAAS,CAAC;AAAA,YACrD;AAAA,UAAA;AAAA,QAEJ;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,mBAAmB,WAAmC;AACpD,QAAI,cAAc,QAAW;AAC3B,WAAK,WAAW,OAAO,SAAS;AAChC,WAAK,eAAe,OAAO,SAAS;AAAA,IACtC,OAAO;AACL,WAAK,WAAW,MAAA;AAChB,WAAK,eAAe,MAAA;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,WAAoC;AAChD,UAAM,eAAe,KAAK,WAAW,IAAI,SAAS,GAAG,UAAU;AAC/D,UAAM,YAAY,KAAK,eAAe,IAAI,SAAS,GAAG,UAAU;AAChE,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,UAAU,WAA6D;AACrE,UAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS,KAAK,CAAA;AAC3D,UAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS,KAAK,CAAA;AAC5D,WAAO,CAAC,GAAG,kBAAkB,GAAG,aAAa;AAAA,EAC/C;AAAA,EAEA,aAAqC;AACnC,UAAM,gCAAgB,IAAI;AAAA,MACxB,GAAG,KAAK,WAAW,KAAA;AAAA,MACnB,GAAG,KAAK,eAAe,KAAA;AAAA,IAAK,CAC7B;AACD,WAAO,MAAM,KAAK,SAAS;AAAA,EAC7B;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,mBAAA;AAAA,EACP;AAAA,EAEA,cAAc,OAAoB;AAChC,SAAK,KAAK,SAAS,KAAK;AAAA,EAC1B;AAAA,EAEA,gBAAgB,SAAoB;AAClC,SAAK,KAAK,WAAW,OAAO;AAAA,EAC9B;AAAA;AAAA,EAGA,eAAsE;AACpE,WAAO,IAAI,IAAI,KAAK,UAAU;AAAA,EAChC;AAAA,EAEA,mBAA0E;AACxE,WAAO,IAAI,IAAI,KAAK,cAAc;AAAA,EACpC;AACF;AC9JO,SAAS,mBAGd;AACA,QAAM,UAAU,IAAI,sBAAA;AACpB,QAAM,UAAU,IAAI,sBAAA;AAGpB,UAAQ,SAAS,OAAO;AACxB,UAAQ,SAAS,OAAO;AAExB,SAAO,CAAC,SAAS,OAAO;AAC1B;AAEO,MAAM,sBAAwC;AAAA,EAC5C,YAAqB;AAAA,EACrB,eAAwB;AAAA,EAEvB;AAAA,EACA,iCACF,IAAA;AAAA,EACE,qCAGA,IAAA;AAAA,EAER,SAAS,MAAmC;AAC1C,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,UAAgB;AACd,QAAI,CAAC,KAAK,WAAW;AACnB,WAAK,YAAY;AACjB,WAAK,eAAe;AAEpB,WAAK,cAAc,SAAS;AAE5B,UAAI,KAAK,OAAO;AACd,aAAK,MAAM,cAAc,SAAS;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAmB;AACjB,QAAI,KAAK,WAAW;AAClB,WAAK,YAAY;AACjB,WAAK,eAAe;AACpB,WAAK,cAAc,YAAY;AAC/B,UAAI,KAAK,OAAO;AACd,aAAK,MAAM,cAAc,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,GAAG,WAA4B,UAA0C;AACvE,QAAI,CAAC,KAAK,WAAW,IAAI,SAAS,GAAG;AACnC,WAAK,WAAW,IAAI,WAAW,CAAA,CAAE;AAAA,IACnC;AACA,SAAK,WAAW,IAAI,SAAS,EAAG,KAAK,QAAQ;AAC7C,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,WAA4B,UAA0C;AACzE,QAAI,CAAC,KAAK,eAAe,IAAI,SAAS,GAAG;AACvC,WAAK,eAAe,IAAI,WAAW,CAAA,CAAE;AAAA,IACvC;AACA,SAAK,eAAe,IAAI,SAAS,EAAG,KAAK,QAAQ;AACjD,WAAO;AAAA,EACT;AAAA,EAEA,IAAI,WAA4B,UAA2C;AACzE,QAAI,UAAU;AACZ,YAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS;AACtD,UAAI,kBAAkB;AACpB,cAAM,QAAQ,iBAAiB,QAAQ,QAAQ;AAC/C,YAAI,QAAQ,GAAI,kBAAiB,OAAO,OAAO,CAAC;AAAA,MAClD;AACA,YAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS;AACvD,UAAI,eAAe;AACjB,cAAM,QAAQ,cAAc,QAAQ,QAAQ;AAC5C,YAAI,QAAQ,GAAI,eAAc,OAAO,OAAO,CAAC;AAAA,MAC/C;AAAA,IACF,OAAO;AACL,WAAK,WAAW,OAAO,SAAS;AAChC,WAAK,eAAe,OAAO,SAAS;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KAAK,cAA+B,MAAsB;AACxD,QAAI,CAAC,KAAK,OAAO;AACf,cAAQ;AAAA,QACN,2DAA2D,OAAO,SAAS,CAAC;AAAA,MAAA;AAE9E,aAAO;AAAA,IACT;AAGA,SAAK,MAAM,cAAc,WAAW,GAAG,IAAI;AAC3C,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAc,cAA+B,MAAmB;AAEtE,UAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS;AACtD,QAAI,kBAAkB;AACpB,OAAC,GAAG,gBAAgB,EAAE,QAAQ,CAAC,aAAa;AAC1C,YAAI;AACF,mBAAS,GAAG,IAAI;AAAA,QAClB,SAAS,OAAO;AACd,kBAAQ,MAAM,yBAAyB,OAAO,SAAS,CAAC,KAAK,KAAK;AAAA,QACpE;AAAA,MACF,CAAC;AAAA,IACH;AAGA,UAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS;AACvD,QAAI,eAAe;AACjB,YAAM,kBAAkB,CAAC,GAAG,aAAa;AACzC,WAAK,eAAe,OAAO,SAAS;AACpC,sBAAgB,QAAQ,CAAC,aAAa;AACpC,YAAI;AACF,mBAAS,GAAG,IAAI;AAAA,QAClB,SAAS,OAAO;AACd,kBAAQ;AAAA,YACN,8BAA8B,OAAO,SAAS,CAAC;AAAA,YAC/C;AAAA,UAAA;AAAA,QAEJ;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,mBAAmB,WAAmC;AACpD,QAAI,cAAc,QAAW;AAC3B,WAAK,WAAW,OAAO,SAAS;AAChC,WAAK,eAAe,OAAO,SAAS;AAAA,IACtC,OAAO;AACL,WAAK,WAAW,MAAA;AAChB,WAAK,eAAe,MAAA;AAAA,IACtB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,WAAoC;AAChD,UAAM,eAAe,KAAK,WAAW,IAAI,SAAS,GAAG,UAAU;AAC/D,UAAM,YAAY,KAAK,eAAe,IAAI,SAAS,GAAG,UAAU;AAChE,WAAO,eAAe;AAAA,EACxB;AAAA,EAEA,UAAU,WAA6D;AACrE,UAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS,KAAK,CAAA;AAC3D,UAAM,gBAAgB,KAAK,eAAe,IAAI,SAAS,KAAK,CAAA;AAC5D,WAAO,CAAC,GAAG,kBAAkB,GAAG,aAAa;AAAA,EAC/C;AAAA,EAEA,aAAqC;AACnC,UAAM,gCAAgB,IAAI;AAAA,MACxB,GAAG,KAAK,WAAW,KAAA;AAAA,MACnB,GAAG,KAAK,eAAe,KAAA;AAAA,IAAK,CAC7B;AACD,WAAO,MAAM,KAAK,SAAS;AAAA,EAC7B;AACF;AC7KO,MAAM,gBAAgB,OAAe;AAAA,EAC1C,WAAW;AAAA,EACX,cAAc;AAAA,EACd,UAAU;AACR,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,KAAK,SAAS;AAAA,EACrB;AAAA,EACA,aAAa;AACX,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,KAAK,YAAY;AAAA,EACxB;AAAA;AAAA,EAEA,KAAK;AAEH,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,OAAO;AAEL,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,MAAM;AAEJ,WAAO;AAAA,EACT;AAAA;AAAA,EAEA,qBAAqB;AAEnB,WAAO;AAAA,EACT;AACF;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rljson/io",
3
- "version": "0.0.70",
3
+ "version": "0.0.71",
4
4
  "description": "Low level interface for reading and writing RLJSON data",
5
5
  "homepage": "https://github.com/rljson/io",
6
6
  "bugs": "https://github.com/rljson/io/issues",