@delali/sirannon-db 0.3.5-next.69 → 0.3.5-next.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.
Files changed (91) hide show
  1. package/README.md +2 -0
  2. package/dist/backup/index.d.ts +5 -5
  3. package/dist/backup/index.mjs +4 -3
  4. package/dist/backup-scheduler/index.d.ts +2 -2
  5. package/dist/backup-scheduler/index.mjs +5 -4
  6. package/dist/{change-tracker-DqCdeEyx.d.ts → change-tracker-Dpo99EI-.d.ts} +24 -7
  7. package/dist/{chunk-ADNWEHGZ.mjs → chunk-3VTT3VU6.mjs} +15 -7
  8. package/dist/chunk-54MAOILS.mjs +149 -0
  9. package/dist/{chunk-ESTZZPT5.mjs → chunk-56HOLQKD.mjs} +391 -33
  10. package/dist/chunk-75IBRE73.mjs +55 -0
  11. package/dist/chunk-BGJ5JVYL.mjs +62 -0
  12. package/dist/{chunk-R7GBXNTO.mjs → chunk-BUWJH3D3.mjs} +2 -55
  13. package/dist/{chunk-NVSQ2T5Q.mjs → chunk-C53DPOR5.mjs} +16 -5
  14. package/dist/chunk-D3YF2G7X.mjs +147 -0
  15. package/dist/chunk-E2GRX4ZD.mjs +30 -0
  16. package/dist/{chunk-2O3PP4CF.mjs → chunk-EUNHTFR7.mjs} +42 -16
  17. package/dist/{chunk-QBBLSQHQ.mjs → chunk-HO2XTXVX.mjs} +1 -8
  18. package/dist/{chunk-KJLNYOOL.mjs → chunk-IWS4PJIO.mjs} +1 -1
  19. package/dist/{chunk-IEKIYO4V.mjs → chunk-JAQ2I4OT.mjs} +5 -5
  20. package/dist/{chunk-2ES3DT4A.mjs → chunk-JZL64CZZ.mjs} +66 -6
  21. package/dist/chunk-K43WJORM.mjs +23 -0
  22. package/dist/{chunk-55YRLSM2.mjs → chunk-KOTBP4AW.mjs} +27 -4
  23. package/dist/{chunk-3BZLZ47R.mjs → chunk-L6EX6K27.mjs} +2 -2
  24. package/dist/chunk-LHH4PMRV.mjs +197 -0
  25. package/dist/{chunk-6AOJCNRU.mjs → chunk-LRUC2GSU.mjs} +3 -3
  26. package/dist/chunk-N4EXO2VH.mjs +117 -0
  27. package/dist/{chunk-NZGSDALX.mjs → chunk-NBPLGMPP.mjs} +217 -76
  28. package/dist/chunk-PJRCMG7L.mjs +232 -0
  29. package/dist/{chunk-VO3ZWA2G.mjs → chunk-RASMCXBN.mjs} +208 -41
  30. package/dist/{chunk-HR7K3GZW.mjs → chunk-RLBKZZ24.mjs} +5 -1
  31. package/dist/chunk-SEL4A4WT.mjs +156 -0
  32. package/dist/chunk-UGGWPZIP.mjs +1374 -0
  33. package/dist/{chunk-4KASJKKK.mjs → chunk-UIDQGPJY.mjs} +147 -6
  34. package/dist/{chunk-FJPR2CJX.mjs → chunk-YGFNJBF3.mjs} +2 -2
  35. package/dist/chunk-YRNLEOSU.mjs +1080 -0
  36. package/dist/chunk-ZFFUVYYE.mjs +439 -0
  37. package/dist/client/index.d.ts +26 -18
  38. package/dist/client/index.mjs +105 -17
  39. package/dist/client/topology.d.ts +12 -10
  40. package/dist/client/topology.mjs +17 -7
  41. package/dist/{client-base-BxTocU1x.d.ts → client-base-CCY9go0g.d.ts} +22 -9
  42. package/dist/{client-streams-YKANXMWO.mjs → client-streams-MKPE4MXW.mjs} +6 -6
  43. package/dist/codegen/cli.mjs +3 -2
  44. package/dist/codegen/index.mjs +3 -2
  45. package/dist/core/index.d.ts +59 -16
  46. package/dist/core/index.mjs +1141 -435
  47. package/dist/core/writer-worker.mjs +57 -9
  48. package/dist/{database-CGDsXW1K.d.ts → database-D4oNUy_2.d.ts} +355 -89
  49. package/dist/{database-backup-DcLhxoa1.d.ts → database-backup-BwTNiBm2.d.ts} +1 -1
  50. package/dist/driver/better-sqlite3.d.ts +20 -2
  51. package/dist/driver/better-sqlite3.mjs +212 -36
  52. package/dist/driver/bun.d.ts +1 -1
  53. package/dist/driver/bun.mjs +20 -33
  54. package/dist/driver/expo.d.ts +1 -1
  55. package/dist/driver/expo.mjs +34 -5
  56. package/dist/driver/node.d.ts +1 -1
  57. package/dist/driver/node.mjs +26 -16
  58. package/dist/driver/wa-sqlite.d.ts +1 -1
  59. package/dist/driver/wa-sqlite.mjs +160 -13
  60. package/dist/file-migrations/index.d.ts +1 -1
  61. package/dist/file-migrations/index.mjs +13 -8
  62. package/dist/{forward-rpc-VRWFZXHN.mjs → forward-rpc-S7NMLBX7.mjs} +1 -1
  63. package/dist/{primary-wins-CHNOYuN7.d.ts → primary-wins-BnNAEjwB.d.ts} +7 -6
  64. package/dist/{protocol-DFpNNsIT.d.ts → protocol-DZSYSv0S.d.ts} +1 -1
  65. package/dist/replication/coordinator/etcd.d.ts +22 -5
  66. package/dist/replication/coordinator/etcd.mjs +349 -271
  67. package/dist/replication/index.d.ts +269 -41
  68. package/dist/replication/index.mjs +2197 -1155
  69. package/dist/{restore-options-CH8mE-Tb.d.ts → restore-options-CcMukOLO.d.ts} +1 -1
  70. package/dist/server/index.d.ts +55 -19
  71. package/dist/server/index.mjs +858 -307
  72. package/dist/{server-options-aYtCkefX.d.ts → server-options-B9CsAZp5.d.ts} +9 -7
  73. package/dist/{server-streams-24XL4T43.mjs → server-streams-SBYCHWWM.mjs} +36 -59
  74. package/dist/{sirannon-J3EgPVD7.d.ts → sirannon-B6sPKDye.d.ts} +2 -2
  75. package/dist/transport/grpc.d.ts +26 -7
  76. package/dist/transport/grpc.mjs +45 -23
  77. package/dist/transport/memory.d.ts +5 -5
  78. package/dist/transport/memory.mjs +9 -3
  79. package/dist/{types-DqODKeOq.d.ts → types-BG31TtrQ.d.ts} +17 -0
  80. package/dist/{types-BrAiDGOb.d.ts → types-BlZ9GG1a.d.ts} +33 -8
  81. package/dist/{types-Dc8oWlxj.d.ts → types-DTmi7pXp.d.ts} +198 -15
  82. package/dist/{types-guEKSzMr.d.ts → types-MczwKtul.d.ts} +214 -135
  83. package/package.json +18 -7
  84. package/dist/chunk-52XW3Z76.mjs +0 -256
  85. package/dist/chunk-A3PHCO6W.mjs +0 -645
  86. package/dist/chunk-ER7ODTDA.mjs +0 -23
  87. package/dist/chunk-GVYLZVUZ.mjs +0 -58
  88. package/dist/chunk-MVSES6MS.mjs +0 -22
  89. package/dist/chunk-ZN4HI5FK.mjs +0 -907
  90. package/dist/chunk-ZYWI45EN.mjs +0 -299
  91. package/dist/errors-CJUkQ-KL.d.ts +0 -199
@@ -1,5 +1,5 @@
1
- import { ReplicationError } from './chunk-BLMRNSUG.mjs';
2
- import { META_TABLE, CHANGES_TABLE, MIGRATIONS_TABLE, APPLIED_CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, PEER_STATE_TABLE, SYNC_STATE_TABLE, STAGED_CHANGES_TABLE, isReservedIdentifier } from './chunk-2O3PP4CF.mjs';
1
+ import { ReplicationError, BatchValidationError } from './chunk-BLMRNSUG.mjs';
2
+ import { CHANGES_TABLE, META_TABLE, MIGRATIONS_TABLE, REPLACED_ROWS_TABLE, APPLIED_CHANGES_TABLE, STAGED_PUSH_CHANGES_TABLE, COLUMN_VERSIONS_TABLE, DEVICE_CURSORS_TABLE, PEER_STATE_TABLE, SYNC_STATE_TABLE, STAGED_CHANGES_TABLE, isReservedIdentifier } from './chunk-EUNHTFR7.mjs';
3
3
  import { SirannonError } from './chunk-KINDFBQP.mjs';
4
4
 
5
5
  // src/core/sync/hlc.ts
@@ -89,6 +89,12 @@ var HLC = class _HLC {
89
89
  };
90
90
 
91
91
  // src/core/system-catalog/sqlite-catalog.ts
92
+ var TABLE_XINFO_HIDDEN = {
93
+ ordinary: 0,
94
+ virtualTableColumn: 1,
95
+ generatedVirtual: 2,
96
+ generatedStored: 3
97
+ };
92
98
  async function selectTableExists(conn, table) {
93
99
  const stmt = await conn.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?");
94
100
  return Boolean(await stmt.get(table));
@@ -97,17 +103,29 @@ async function tableInfoRows(conn, table) {
97
103
  const stmt = await conn.prepare(`PRAGMA table_info("${table}")`);
98
104
  return await stmt.all();
99
105
  }
106
+ async function tableColumnsWithGenerated(conn, table) {
107
+ const stmt = await conn.prepare(`PRAGMA table_xinfo("${table}")`);
108
+ return (await stmt.all()).map((row) => ({ ...row, hidden: Number(row.hidden) }));
109
+ }
100
110
  async function tableColumnNames(conn, table) {
101
111
  return (await tableInfoRows(conn, table)).map((col) => col.name);
102
112
  }
113
+ function primaryKeyColumns(columns) {
114
+ return columns.filter((column) => column.pk > 0).sort((a, b) => a.pk - b.pk).map((column) => column.name);
115
+ }
103
116
  async function tablePkColumns(conn, table) {
104
- return (await tableInfoRows(conn, table)).filter((col) => col.pk > 0).sort((a, b) => a.pk - b.pk).map((col) => col.name);
117
+ return primaryKeyColumns(await tableInfoRows(conn, table));
105
118
  }
106
119
  async function selectTableSql(conn, table) {
107
120
  const stmt = await conn.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?");
108
121
  const row = await stmt.get(table);
109
122
  return row?.sql ?? null;
110
123
  }
124
+ async function selectTriggerSql(conn, trigger) {
125
+ const stmt = await conn.prepare("SELECT sql FROM sqlite_master WHERE type = 'trigger' AND name = ?");
126
+ const row = await stmt.get(trigger);
127
+ return row?.sql ?? null;
128
+ }
111
129
  async function selectCountTableRows(conn, table) {
112
130
  const stmt = await conn.prepare(`SELECT COUNT(*) AS cnt FROM "${table}"`);
113
131
  const row = await stmt.get();
@@ -135,6 +153,34 @@ async function selectUserTableNames(conn, excludePrefix) {
135
153
  const rows = await stmt.all(`${excludePrefix}%`);
136
154
  return rows.map((row) => row.name);
137
155
  }
156
+ async function selectOrdinaryTableName(conn, table) {
157
+ const stmt = await conn.prepare(
158
+ `SELECT name FROM sqlite_master
159
+ WHERE type = 'table' AND name = ? COLLATE NOCASE AND sql NOT LIKE 'CREATE VIRTUAL TABLE%'`
160
+ );
161
+ const row = await stmt.get(table);
162
+ return typeof row?.name === "string" ? row.name : null;
163
+ }
164
+ async function selectIndexSql(conn, index) {
165
+ const stmt = await conn.prepare("SELECT sql FROM sqlite_master WHERE type = 'index' AND name = ?");
166
+ const row = await stmt.get(index);
167
+ return row?.sql ?? null;
168
+ }
169
+ async function tableIndexList(conn, table) {
170
+ const stmt = await conn.prepare('SELECT name, "unique", origin, partial FROM pragma_index_list(?) ORDER BY seq');
171
+ const rows = await stmt.all(table);
172
+ return rows.map((row) => ({
173
+ name: row.name,
174
+ unique: Number(row.unique),
175
+ origin: row.origin,
176
+ partial: Number(row.partial)
177
+ }));
178
+ }
179
+ async function indexColumns(conn, index) {
180
+ const stmt = await conn.prepare('SELECT cid, name, coll, "key" FROM pragma_index_xinfo(?) ORDER BY seqno');
181
+ const rows = await stmt.all(index);
182
+ return rows.map((row) => ({ cid: Number(row.cid), name: row.name, collation: row.coll, key: Number(row.key) }));
183
+ }
138
184
 
139
185
  // src/core/system-catalog/columns.ts
140
186
  var SAFE_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/;
@@ -192,14 +238,29 @@ async function deleteMetaValue(conn, key) {
192
238
  }
193
239
  var UPSERT_META_VALUE_SQL = `INSERT INTO "${META_TABLE}" (key, value) VALUES (?, ?)
194
240
  ON CONFLICT(key) DO UPDATE SET value = excluded.value`;
241
+ function upsertMetaMaxChangeSeqSql(changesTable) {
242
+ return `INSERT INTO "${META_TABLE}" (key, value)
243
+ VALUES (?, (SELECT CAST(COALESCE(MAX(seq), 0) AS TEXT) FROM "${changesTable}"))
244
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`;
245
+ }
246
+ function upsertMetaValueAndMaxChangeSeqSql(changesTable) {
247
+ return `INSERT INTO "${META_TABLE}" (key, value)
248
+ VALUES (?, ?), (?, (SELECT CAST(COALESCE(MAX(seq), 0) AS TEXT) FROM "${changesTable}"))
249
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`;
250
+ }
195
251
  async function upsertMetaValue(conn, key, value) {
196
252
  const stmt = await conn.prepare(UPSERT_META_VALUE_SQL);
197
253
  await stmt.run(key, value);
198
254
  }
199
255
 
200
256
  // src/core/system-catalog/changes-table.ts
201
- var CHANGE_LOG_COLUMNS = "seq, table_name, operation, row_id, changed_at, old_data, new_data, node_id, tx_id, hlc";
257
+ var SQLITE_SEQUENCE_TABLE = "sqlite_sequence";
202
258
  var DDL_CHANGE_ROW_TABLE = "__ddl__";
259
+ var CHANGE_LOG_COLUMNS = "seq, table_name, operation, row_id, changed_at, old_data, new_data, node_id, tx_id, hlc";
260
+ function seqFromColumn(value) {
261
+ if (value === void 0 || value === null) return 0n;
262
+ return typeof value === "bigint" ? value : BigInt(String(value));
263
+ }
203
264
  function selectChangesAfterSeqSql(tableName) {
204
265
  return `SELECT ${CHANGE_LOG_COLUMNS} FROM "${tableName}" WHERE seq > ? ORDER BY seq ASC LIMIT ?`;
205
266
  }
@@ -237,15 +298,13 @@ async function insertDdlChange(conn, tableName, entry) {
237
298
  function updateChangeStampsAfterSeqSql(tableName) {
238
299
  return `UPDATE "${tableName}" SET node_id = ?, tx_id = ?, hlc = ? WHERE seq > ? AND node_id = ''`;
239
300
  }
240
- function updateUnstampedChangeStampsSql(tableName) {
241
- return `UPDATE "${tableName}" SET node_id = ?, tx_id = ?, hlc = ? WHERE node_id = ''`;
301
+ function updateChangeStampsAboveMetaSeqSql(tableName) {
302
+ return `UPDATE "${tableName}" SET node_id = ?, tx_id = ?, hlc = ?
303
+ WHERE node_id = '' AND seq > COALESCE((SELECT CAST(value AS INTEGER) FROM "${META_TABLE}" WHERE key = ?), 0)`;
242
304
  }
243
305
  function selectMinChangeSeqSql(tableName) {
244
306
  return `SELECT MIN(seq) AS seq FROM "${tableName}"`;
245
307
  }
246
- function deleteChangesBeforeSql(tableName) {
247
- return `DELETE FROM "${tableName}" WHERE changed_at < ?`;
248
- }
249
308
  function deleteChangesBeforeUpToSeqSql(tableName) {
250
309
  return `DELETE FROM "${tableName}" WHERE changed_at < ? AND seq <= ?`;
251
310
  }
@@ -259,9 +318,20 @@ async function selectMaxRowChangeHlc(conn, tableName, rowTable, rowId) {
259
318
  async function selectMaxChangeSeq(conn, tableName = CHANGES_TABLE) {
260
319
  const stmt = await conn.prepare(`SELECT COALESCE(MAX(seq), 0) AS seq FROM "${tableName}"`);
261
320
  const row = await stmt.get();
262
- const seq = row?.seq;
263
- if (seq === void 0 || seq === null) return 0n;
264
- return typeof seq === "bigint" ? seq : BigInt(String(seq));
321
+ return seqFromColumn(row?.seq);
322
+ }
323
+ async function selectMaxAssignedChangeSeq(conn, tableName = CHANGES_TABLE) {
324
+ const logged = await selectMaxChangeSeq(conn, tableName);
325
+ if (!await selectTableExists(conn, SQLITE_SEQUENCE_TABLE)) return logged;
326
+ const stmt = await conn.prepare(`SELECT seq FROM ${SQLITE_SEQUENCE_TABLE} WHERE name = ?`);
327
+ const row = await stmt.get(tableName);
328
+ const assigned = seqFromColumn(row?.seq);
329
+ return assigned > logged ? assigned : logged;
330
+ }
331
+ async function selectMaxNodeChangeSeq(conn, tableName, nodeId) {
332
+ const stmt = await conn.prepare(`SELECT COALESCE(MAX(seq), 0) AS seq FROM "${tableName}" WHERE node_id = ?`);
333
+ const row = await stmt.get(nodeId);
334
+ return seqFromColumn(row?.seq);
265
335
  }
266
336
  async function selectMaxChangeHlc(conn, tableName = CHANGES_TABLE) {
267
337
  const stmt = await conn.prepare(`SELECT MAX(hlc) AS hlc FROM "${tableName}" WHERE hlc != ''`);
@@ -340,11 +410,31 @@ function highestMigrationVersion(rows) {
340
410
  return highest;
341
411
  }
342
412
 
343
- // src/core/system-catalog/applied-changes-table.ts
344
- function toSeq(value) {
345
- if (value === null || value === void 0) return 0n;
346
- return typeof value === "bigint" ? value : BigInt(String(value));
413
+ // src/core/system-catalog/replaced-rows-table.ts
414
+ async function ensureReplacedRowsTable(conn) {
415
+ await conn.exec(
416
+ `CREATE TABLE IF NOT EXISTS "${REPLACED_ROWS_TABLE}" (
417
+ table_name TEXT NOT NULL,
418
+ row_key NOT NULL,
419
+ match_key TEXT NOT NULL,
420
+ row_id NOT NULL,
421
+ old_data TEXT,
422
+ UNIQUE (table_name, row_key)
423
+ )`
424
+ );
425
+ await conn.exec(
426
+ `CREATE INDEX IF NOT EXISTS "${REPLACED_ROWS_TABLE}_by_match" ON "${REPLACED_ROWS_TABLE}" (table_name, match_key)`
427
+ );
347
428
  }
429
+ async function deleteReplacedRowsOfTable(conn, table) {
430
+ const stmt = await conn.prepare(`DELETE FROM "${REPLACED_ROWS_TABLE}" WHERE table_name = ?`);
431
+ await stmt.run(table);
432
+ }
433
+ async function deleteAllReplacedRows(conn) {
434
+ await conn.exec(`DELETE FROM "${REPLACED_ROWS_TABLE}"`);
435
+ }
436
+
437
+ // src/core/system-catalog/applied-changes-table.ts
348
438
  async function ensureAppliedChangesTable(conn) {
349
439
  await conn.exec(`
350
440
  CREATE TABLE IF NOT EXISTS "${APPLIED_CHANGES_TABLE}" (
@@ -359,12 +449,23 @@ function prepareInsertAppliedChange(conn) {
359
449
  `INSERT OR IGNORE INTO ${APPLIED_CHANGES_TABLE} (source_node_id, source_seq, applied_at) VALUES (?, ?, ?)`
360
450
  );
361
451
  }
452
+ async function insertAppliedChangesFromStagedPush(conn, sourceNodeId, appliedAt) {
453
+ const stmt = await conn.prepare(
454
+ `INSERT OR IGNORE INTO "${APPLIED_CHANGES_TABLE}" (source_node_id, source_seq, applied_at)
455
+ SELECT source_node_id, source_seq, ? FROM "${STAGED_PUSH_CHANGES_TABLE}" WHERE source_node_id = ?`
456
+ );
457
+ await stmt.run(appliedAt, sourceNodeId);
458
+ }
459
+ async function deleteAppliedChangesAfterSeq(conn, sourceNodeId, seq) {
460
+ const stmt = await conn.prepare(`DELETE FROM ${APPLIED_CHANGES_TABLE} WHERE source_node_id = ? AND source_seq > ?`);
461
+ await stmt.run(sourceNodeId, seq.toString());
462
+ }
362
463
  async function selectMaxAppliedSourceSeq(conn, sourceNodeId) {
363
464
  const stmt = await conn.prepare(
364
465
  `SELECT MAX(source_seq) AS max_seq FROM ${APPLIED_CHANGES_TABLE} WHERE source_node_id = ?`
365
466
  );
366
467
  const row = await stmt.get(sourceNodeId);
367
- return toSeq(row?.max_seq);
468
+ return seqFromColumn(row?.max_seq);
368
469
  }
369
470
  async function selectMaxAppliedSourceSeqByNode(conn) {
370
471
  const stmt = await conn.prepare(
@@ -374,7 +475,7 @@ async function selectMaxAppliedSourceSeqByNode(conn) {
374
475
  const byNode = /* @__PURE__ */ new Map();
375
476
  for (const row of rows) {
376
477
  if (row.max_seq === null || row.max_seq === void 0) continue;
377
- byNode.set(row.source_node_id, toSeq(row.max_seq));
478
+ byNode.set(row.source_node_id, seqFromColumn(row.max_seq));
378
479
  }
379
480
  return byNode;
380
481
  }
@@ -390,6 +491,73 @@ async function selectAppliedSourceSeqsInRange(conn, sourceNodeId, fromSeq, toSeq
390
491
  return seqs;
391
492
  }
392
493
 
494
+ // src/core/system-catalog/changes-history.ts
495
+ function originPlaceholders(originCount) {
496
+ return Array.from({ length: originCount }, () => "?").join(", ");
497
+ }
498
+ function selectOutboundHistoryChangesSql(tableName, originCount) {
499
+ return `SELECT ${CHANGE_LOG_COLUMNS} FROM "${tableName}"
500
+ WHERE seq > ? AND hlc != '' AND node_id IN (${originPlaceholders(originCount)})
501
+ ORDER BY seq ASC LIMIT ?`;
502
+ }
503
+ async function selectNewestHistoryChange(conn, tableName, origins, bounds = {}) {
504
+ if (origins.length === 0) return null;
505
+ const seqFilter = bounds.maxSeq === void 0 ? "" : "AND seq <= ?";
506
+ const hlcFilter = bounds.beforeHlc === void 0 ? "" : "AND hlc < ?";
507
+ const stmt = await conn.prepare(
508
+ `SELECT seq, hlc, tx_id FROM "${tableName}"
509
+ WHERE hlc != '' AND node_id IN (${originPlaceholders(origins.length)}) ${seqFilter} ${hlcFilter}
510
+ ORDER BY hlc DESC, seq DESC LIMIT 1`
511
+ );
512
+ const params = [...origins];
513
+ if (bounds.maxSeq !== void 0) params.push(bounds.maxSeq.toString());
514
+ if (bounds.beforeHlc !== void 0) params.push(bounds.beforeHlc);
515
+ const row = await stmt.get(...params);
516
+ if (!row) return null;
517
+ return await selectHistoryTransaction(conn, tableName, row.tx_id) ?? {
518
+ seq: seqFromColumn(row.seq),
519
+ hlc: row.hlc,
520
+ txId: row.tx_id
521
+ };
522
+ }
523
+ async function selectMaxHistoryChangeSeq(conn, tableName, origins) {
524
+ if (origins.length === 0) return 0n;
525
+ const stmt = await conn.prepare(
526
+ `SELECT COALESCE(MAX(seq), 0) AS seq FROM "${tableName}"
527
+ WHERE hlc != '' AND node_id IN (${originPlaceholders(origins.length)})`
528
+ );
529
+ const row = await stmt.get(...origins);
530
+ return seqFromColumn(row?.seq);
531
+ }
532
+ async function selectHistoryTransaction(conn, tableName, txId) {
533
+ const stmt = await conn.prepare(
534
+ `SELECT MAX(seq) AS seq, MAX(hlc) AS hlc FROM "${tableName}" WHERE tx_id = ? AND hlc != ''`
535
+ );
536
+ const row = await stmt.get(txId);
537
+ if (row?.seq === void 0 || row.seq === null || typeof row.hlc !== "string") return null;
538
+ return { seq: seqFromColumn(row.seq), hlc: row.hlc, txId };
539
+ }
540
+ async function selectHistoryChangesAfterHlc(conn, tableName, origins, hlc) {
541
+ if (origins.length === 0) return [];
542
+ const stmt = await conn.prepare(
543
+ `SELECT seq, table_name, operation, row_id, old_data, new_data FROM "${tableName}"
544
+ WHERE hlc > ? AND node_id IN (${originPlaceholders(origins.length)})
545
+ ORDER BY seq DESC`
546
+ );
547
+ return await stmt.all(hlc, ...origins);
548
+ }
549
+ async function deleteHistoryChangesAfterHlc(conn, tableName, origins, hlc) {
550
+ if (origins.length === 0) return;
551
+ const stmt = await conn.prepare(
552
+ `DELETE FROM "${tableName}" WHERE hlc > ? AND node_id IN (${originPlaceholders(origins.length)})`
553
+ );
554
+ await stmt.run(hlc, ...origins);
555
+ }
556
+ async function deleteStampedChangesUpToSeq(conn, tableName, seq) {
557
+ const stmt = await conn.prepare(`DELETE FROM "${tableName}" WHERE seq <= ? AND hlc != ''`);
558
+ await stmt.run(seq.toString());
559
+ }
560
+
393
561
  // src/core/system-catalog/column-versions-table.ts
394
562
  var UPSERT_COLUMN_VERSION = `INSERT INTO ${COLUMN_VERSIONS_TABLE} (table_name, row_id, column_name, hlc, node_id)
395
563
  VALUES (?, ?, ?, ?, ?)
@@ -418,6 +586,13 @@ async function selectMaxColumnVersionHlcForRow(conn, tableName, rowId) {
418
586
  const row = await stmt.get(tableName, rowId);
419
587
  return row?.max_hlc ?? null;
420
588
  }
589
+ async function deleteColumnVersionsAfterHlc(conn, hlc) {
590
+ const stmt = await conn.prepare(`DELETE FROM ${COLUMN_VERSIONS_TABLE} WHERE hlc > ?`);
591
+ await stmt.run(hlc);
592
+ }
593
+ async function deleteColumnVersions(conn) {
594
+ await conn.exec(`DELETE FROM ${COLUMN_VERSIONS_TABLE}`);
595
+ }
421
596
  function prepareUpsertColumnVersion(conn) {
422
597
  return conn.prepare(UPSERT_COLUMN_VERSION);
423
598
  }
@@ -428,9 +603,6 @@ function prepareUpsertNewerColumnVersion(conn) {
428
603
  function prepareDeleteRowColumnVersions(conn) {
429
604
  return conn.prepare(`DELETE FROM ${COLUMN_VERSIONS_TABLE} WHERE table_name = ? AND row_id = ?`);
430
605
  }
431
- function prepareDeleteRowColumnVersionsUpToHlc(conn) {
432
- return conn.prepare(`DELETE FROM ${COLUMN_VERSIONS_TABLE} WHERE table_name = ? AND row_id = ? AND hlc <= ?`);
433
- }
434
606
 
435
607
  // src/core/system-catalog/device-cursors-table.ts
436
608
  async function ensureDeviceCursorsTable(conn) {
@@ -451,6 +623,19 @@ async function upsertDeviceCursor(conn, deviceId, ackedSeq, updatedAt) {
451
623
  );
452
624
  await stmt.run(deviceId, ackedSeq.toString(), updatedAt);
453
625
  }
626
+ async function updateDeviceCursor(conn, deviceId, ackedSeq, updatedAt) {
627
+ const stmt = await conn.prepare(
628
+ `UPDATE "${DEVICE_CURSORS_TABLE}"
629
+ SET acked_seq = max(acked_seq, CAST(? AS INTEGER)), updated_at = ?
630
+ WHERE device_id = ?`
631
+ );
632
+ const result = await stmt.run(ackedSeq.toString(), updatedAt, deviceId);
633
+ return result.changes;
634
+ }
635
+ async function selectDeviceCursorExists(conn, deviceId) {
636
+ const stmt = await conn.prepare(`SELECT 1 AS present FROM "${DEVICE_CURSORS_TABLE}" WHERE device_id = ?`);
637
+ return await stmt.get(deviceId) !== void 0;
638
+ }
454
639
  async function deleteExpiredDeviceCursors(conn, changesTable, bounds) {
455
640
  assertSafeIdentifier(changesTable);
456
641
  const stmt = await conn.prepare(
@@ -521,20 +706,98 @@ async function upsertPeerAckedSeq(conn, peerNodeId, seq, updatedAt) {
521
706
  );
522
707
  await stmt.run(peerNodeId, seq.toString(), updatedAt);
523
708
  }
709
+ async function deletePeerStates(conn) {
710
+ await conn.exec(`DELETE FROM ${PEER_STATE_TABLE}`);
711
+ }
712
+ async function deletePeerState(conn, peerNodeId) {
713
+ const stmt = await conn.prepare(`DELETE FROM ${PEER_STATE_TABLE} WHERE peer_node_id = ?`);
714
+ await stmt.run(peerNodeId);
715
+ }
524
716
  async function selectPeerAckedSeq(conn, peerNodeId) {
525
717
  const stmt = await conn.prepare(`SELECT last_acked_seq FROM ${PEER_STATE_TABLE} WHERE peer_node_id = ?`);
526
718
  const row = await stmt.get(peerNodeId);
527
- const seq = row?.last_acked_seq;
528
- if (seq === null || seq === void 0) return 0n;
529
- return typeof seq === "bigint" ? seq : BigInt(String(seq));
719
+ return seqFromColumn(row?.last_acked_seq);
530
720
  }
531
721
  async function selectMinPeerAckedSeq(conn) {
532
722
  const stmt = await conn.prepare(`SELECT MIN(last_acked_seq) AS min_seq, COUNT(*) AS cnt FROM ${PEER_STATE_TABLE}`);
533
723
  const row = await stmt.get();
534
724
  if (row === void 0 || Number(row.cnt ?? 0) === 0) return null;
535
- const min = row.min_seq;
536
- if (min === null || min === void 0) return 0n;
537
- return typeof min === "bigint" ? min : BigInt(String(min));
725
+ return seqFromColumn(row.min_seq);
726
+ }
727
+
728
+ // src/core/system-catalog/replication-history-meta.ts
729
+ var PRIMARY_TERM_START_META_KEY = "replication_primary_term_start";
730
+ var ANCHORED_TERM_META_KEY = "replication_anchored_term";
731
+ var HISTORY_BASE_META_KEY = "replication_history_base";
732
+ var QUARANTINED_META_KEY = "replication_quarantined";
733
+ var DECIMAL_DIGITS = /^\d+$/;
734
+ function parseTermStart(raw) {
735
+ if (raw === null) return null;
736
+ try {
737
+ const parsed = JSON.parse(raw);
738
+ if (typeof parsed !== "object" || parsed === null) return null;
739
+ const term = Reflect.get(parsed, "term");
740
+ const seq = Reflect.get(parsed, "seq");
741
+ if (typeof term !== "string" || typeof seq !== "string") return null;
742
+ if (!DECIMAL_DIGITS.test(term) || !DECIMAL_DIGITS.test(seq)) return null;
743
+ return { term: BigInt(term), seq: BigInt(seq) };
744
+ } catch {
745
+ return null;
746
+ }
747
+ }
748
+ function parseHistoryPoint(raw) {
749
+ if (raw === null) return null;
750
+ try {
751
+ const parsed = JSON.parse(raw);
752
+ if (typeof parsed !== "object" || parsed === null) return null;
753
+ const hlc = Reflect.get(parsed, "hlc");
754
+ const txId = Reflect.get(parsed, "txId");
755
+ if (typeof hlc !== "string" || typeof txId !== "string" || hlc === "") return null;
756
+ return { hlc, txId };
757
+ } catch {
758
+ return null;
759
+ }
760
+ }
761
+ async function selectPrimaryTermStart(conn) {
762
+ await ensureMetaTable(conn);
763
+ return parseTermStart(await selectMetaValue(conn, PRIMARY_TERM_START_META_KEY));
764
+ }
765
+ async function upsertPrimaryTermStart(conn, termStart) {
766
+ await ensureMetaTable(conn);
767
+ await upsertMetaValue(
768
+ conn,
769
+ PRIMARY_TERM_START_META_KEY,
770
+ JSON.stringify({ term: termStart.term.toString(), seq: termStart.seq.toString() })
771
+ );
772
+ }
773
+ async function deletePrimaryTermStart(conn) {
774
+ await ensureMetaTable(conn);
775
+ await deleteMetaValue(conn, PRIMARY_TERM_START_META_KEY);
776
+ }
777
+ async function selectAnchoredTerm(conn) {
778
+ await ensureMetaTable(conn);
779
+ const raw = await selectMetaValue(conn, ANCHORED_TERM_META_KEY);
780
+ return raw !== null && DECIMAL_DIGITS.test(raw) ? BigInt(raw) : null;
781
+ }
782
+ async function upsertAnchoredTerm(conn, term) {
783
+ await ensureMetaTable(conn);
784
+ await upsertMetaValue(conn, ANCHORED_TERM_META_KEY, term.toString());
785
+ }
786
+ async function selectHistoryBase(conn) {
787
+ await ensureMetaTable(conn);
788
+ return parseHistoryPoint(await selectMetaValue(conn, HISTORY_BASE_META_KEY));
789
+ }
790
+ async function upsertHistoryBase(conn, point) {
791
+ await ensureMetaTable(conn);
792
+ await upsertMetaValue(conn, HISTORY_BASE_META_KEY, point ? JSON.stringify({ hlc: point.hlc, txId: point.txId }) : "");
793
+ }
794
+ async function selectQuarantined(conn) {
795
+ await ensureMetaTable(conn);
796
+ return await selectMetaValue(conn, QUARANTINED_META_KEY) === "true";
797
+ }
798
+ async function upsertQuarantined(conn, quarantined) {
799
+ await ensureMetaTable(conn);
800
+ await upsertMetaValue(conn, QUARANTINED_META_KEY, quarantined ? "true" : "false");
538
801
  }
539
802
 
540
803
  // src/core/system-catalog/sync-state-table.ts
@@ -620,7 +883,7 @@ async function ensureReplicationStateTables(conn) {
620
883
  }
621
884
 
622
885
  // src/core/system-catalog/staged-changes-table.ts
623
- function toSeq2(value) {
886
+ function toSeq(value) {
624
887
  if (value === null || value === void 0) return null;
625
888
  return typeof value === "bigint" ? value : BigInt(String(value));
626
889
  }
@@ -662,14 +925,14 @@ function upsertStagedChangeSql() {
662
925
  async function selectMaxStagedSeq(conn) {
663
926
  const stmt = await conn.prepare(`SELECT MAX(seq) AS seq FROM "${STAGED_CHANGES_TABLE}"`);
664
927
  const row = await stmt.get();
665
- return toSeq2(row?.seq);
928
+ return toSeq(row?.seq);
666
929
  }
667
930
  async function selectFirstStagedTransactionEnd(conn) {
668
931
  const stmt = await conn.prepare(
669
932
  `SELECT seq, tx_id FROM "${STAGED_CHANGES_TABLE}" WHERE tx_end = 1 ORDER BY seq ASC LIMIT 1`
670
933
  );
671
934
  const row = await stmt.get();
672
- const seq = toSeq2(row?.seq);
935
+ const seq = toSeq(row?.seq);
673
936
  if (seq === null) return null;
674
937
  return { seq, txId: row?.tx_id ?? "" };
675
938
  }
@@ -688,6 +951,51 @@ async function deleteAllStagedChanges(conn) {
688
951
  await conn.exec(`DELETE FROM "${STAGED_CHANGES_TABLE}"`);
689
952
  }
690
953
 
954
+ // src/core/system-catalog/staged-push-changes-table.ts
955
+ async function ensureStagedPushChangesTable(conn) {
956
+ await conn.exec(`
957
+ CREATE TABLE IF NOT EXISTS "${STAGED_PUSH_CHANGES_TABLE}" (
958
+ source_node_id TEXT NOT NULL,
959
+ source_seq INTEGER NOT NULL,
960
+ tx_id TEXT NOT NULL,
961
+ change TEXT NOT NULL,
962
+ PRIMARY KEY (source_node_id, source_seq)
963
+ )`);
964
+ }
965
+ function prepareInsertStagedPushChange(conn) {
966
+ return conn.prepare(
967
+ `INSERT OR IGNORE INTO "${STAGED_PUSH_CHANGES_TABLE}" (source_node_id, source_seq, tx_id, change) VALUES (?, ?, ?, ?)`
968
+ );
969
+ }
970
+ async function selectStagedPushTail(conn, sourceNodeId) {
971
+ const stmt = await conn.prepare(
972
+ `SELECT tx_id, source_seq FROM "${STAGED_PUSH_CHANGES_TABLE}"
973
+ WHERE source_node_id = ? ORDER BY source_seq DESC LIMIT 1`
974
+ );
975
+ const row = await stmt.get(sourceNodeId);
976
+ if (row === void 0 || row.source_seq === null || row.source_seq === void 0) return null;
977
+ return { txId: row.tx_id, maxSeq: BigInt(String(row.source_seq)) };
978
+ }
979
+ async function selectStagedPushSeqsInRange(conn, sourceNodeId, fromSeq, toSeq2) {
980
+ const stmt = await conn.prepare(
981
+ `SELECT source_seq FROM "${STAGED_PUSH_CHANGES_TABLE}"
982
+ WHERE source_node_id = ? AND source_seq >= ? AND source_seq <= ?`
983
+ );
984
+ const rows = await stmt.all(sourceNodeId, fromSeq.toString(), toSeq2.toString());
985
+ return new Set(rows.map((row) => String(row.source_seq)));
986
+ }
987
+ async function selectStagedPushChangesAfter(conn, sourceNodeId, afterSeq, limit) {
988
+ const stmt = await conn.prepare(
989
+ `SELECT source_seq, change FROM "${STAGED_PUSH_CHANGES_TABLE}"
990
+ WHERE source_node_id = ? AND source_seq > ? ORDER BY source_seq ASC LIMIT ?`
991
+ );
992
+ return await stmt.all(sourceNodeId, afterSeq.toString(), limit);
993
+ }
994
+ async function deleteStagedPushChanges(conn, sourceNodeId) {
995
+ const stmt = await conn.prepare(`DELETE FROM "${STAGED_PUSH_CHANGES_TABLE}" WHERE source_node_id = ?`);
996
+ await stmt.run(sourceNodeId);
997
+ }
998
+
691
999
  // src/core/sync/canonicalise.ts
692
1000
  function canonicaliseForChecksum(value) {
693
1001
  return canonicaliseValue(value);
@@ -750,12 +1058,12 @@ var PkResolver = class {
750
1058
  // src/core/sync/validators.ts
751
1059
  var IDENTIFIER_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
752
1060
  var SEQ_STRING_RE = /^\d{1,19}$/;
753
- var SAFE_DDL_RE = /^\s*(CREATE\s+TABLE|ALTER\s+TABLE\s+\S+\s+ADD\s+COLUMN|DROP\s+TABLE|CREATE\s+INDEX|DROP\s+INDEX)\b/i;
1061
+ var SAFE_DDL_RE = /^\s*(CREATE\s+TABLE|ALTER\s+TABLE\s+\S+\s+ADD\s+COLUMN|DROP\s+TABLE|CREATE\s+(?:UNIQUE\s+)?INDEX|DROP\s+INDEX)\b/i;
754
1062
  var DDL_DENY_RE = /\b(load_extension|ATTACH|randomblob|zeroblob|writefile|readfile|fts3_tokenizer)\b/i;
755
1063
  function validateIdentifier(name) {
756
1064
  return IDENTIFIER_RE.test(name);
757
1065
  }
758
- var CREATE_INDEX_TARGETS_RE = /^\s*CREATE\s+INDEX(?:\s+IF\s+NOT\s+EXISTS)?\s+(?:["`[]?[A-Za-z_][A-Za-z0-9_]*["`\]]?\s*\.\s*)?["`[]?([A-Za-z_][A-Za-z0-9_]*)["`\]]?\s+ON\s+(?:["`[]?[A-Za-z_][A-Za-z0-9_]*["`\]]?\s*\.\s*)?["`[]?([A-Za-z_][A-Za-z0-9_]*)/i;
1066
+ var CREATE_INDEX_TARGETS_RE = /^\s*CREATE\s+(?:UNIQUE\s+)?INDEX(?:\s+IF\s+NOT\s+EXISTS)?\s+(?:["`[]?[A-Za-z_][A-Za-z0-9_]*["`\]]?\s*\.\s*)?["`[]?([A-Za-z_][A-Za-z0-9_]*)["`\]]?\s+ON\s+(?:["`[]?[A-Za-z_][A-Za-z0-9_]*["`\]]?\s*\.\s*)?["`[]?([A-Za-z_][A-Za-z0-9_]*)/i;
759
1067
  var DDL_TARGET_RE = /^\s*(?:CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|ALTER\s+TABLE|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|DROP\s+INDEX(?:\s+IF\s+EXISTS)?)\s+(?:["`[]?[A-Za-z_][A-Za-z0-9_]*["`\]]?\s*\.\s*)?["`[]?([A-Za-z_][A-Za-z0-9_]*)/i;
760
1068
  function ddlTargetsReservedIdentifier(sql) {
761
1069
  const indexTargets = CREATE_INDEX_TARGETS_RE.exec(sql);
@@ -782,4 +1090,54 @@ function extractDroppedTable(sql) {
782
1090
  return m?.[1] ?? null;
783
1091
  }
784
1092
 
785
- export { HLC, IDENTIFIER_RE, PkResolver, SEQ_STRING_RE, UPSERT_META_VALUE_SQL, assertSafeIdentifier, canonicaliseForChecksum, deleteAllStagedChanges, deleteChangesBeforeSql, deleteChangesBeforeUpToSeqSql, deleteExpiredDeviceCursors, deleteMetaValue, deleteStagedChangesUpToSeq, deleteSyncTableStates, ensureBatchApplyTables, ensureChangesTable, ensureDeviceCursorsTable, ensureMetaTable, ensureMigrationsTable, ensureReplicationStateTables, ensureStagedChangesTable, extractDroppedTable, highestMigrationVersion, insertDdlChange, insertMetaValueIfAbsent, prepareDeleteMigration, prepareDeleteRowColumnVersions, prepareDeleteRowColumnVersionsUpToHlc, prepareInsertAppliedChange, prepareInsertMigration, prepareUpdateMigrationChecksum, prepareUpsertColumnVersion, prepareUpsertNewerColumnVersion, referencedTables, replaceMigrationHistory, selectAppliedMigrations, selectAppliedMigrationsNewestFirst, selectAppliedSourceSeqsInRange, selectChangesAfterSeqSql, selectCompletedSyncTableNames, selectCountOutboundChanges, selectCountTableRows, selectFirstStagedTransactionEnd, selectMaxAppliedSourceSeq, selectMaxAppliedSourceSeqByNode, selectMaxChangeHlc, selectMaxChangeSeq, selectMaxColumnVersionHlc, selectMaxColumnVersionHlcForRow, selectMaxRowChangeHlc, selectMaxStagedSeq, selectMetaValue, selectMinChangeSeqSql, selectMinDeviceCursorBoundary, selectMinPeerAckedSeq, selectNodeChangesAfterSeqSql, selectOutboundChangesSql, selectPeerAckedSeq, selectStagedChangesInRange, selectSyncMetaRow, selectTableExists, selectTableSql, selectTablesChangesInRangeSql, selectUserSchemaObjects, selectUserTableNames, setForeignKeysEnabled, tableColumnNames, tableInfoRows, tablePkColumns, updateChangeStampsAfterSeqSql, updateUnstampedChangeStampsSql, upsertDeviceCursor, upsertMetaValue, upsertPeerAckedSeq, upsertStagedChangeSql, upsertSyncMeta, upsertSyncTableStatus, validateDdlSafety, validateIdentifier };
1093
+ // src/core/sync/change-seqs.ts
1094
+ var MAX_CHANGE_SEQ = 9223372036854775807n;
1095
+ function assertSeqInRange(seq, label) {
1096
+ if (seq < 0n || seq > MAX_CHANGE_SEQ) {
1097
+ throw new BatchValidationError(`${label} must be a sequence from 0 to ${MAX_CHANGE_SEQ}`);
1098
+ }
1099
+ }
1100
+ function explicitSeqs(batch, changeSeqs) {
1101
+ if (changeSeqs.length !== batch.changes.length) {
1102
+ throw new BatchValidationError("changeSeqs must hold one sequence for each change");
1103
+ }
1104
+ const seqs = [];
1105
+ let previous = null;
1106
+ for (const [index, seq] of changeSeqs.entries()) {
1107
+ assertSeqInRange(seq, `changeSeqs[${index}]`);
1108
+ if (previous !== null && seq <= previous) {
1109
+ throw new BatchValidationError("changeSeqs must rise strictly");
1110
+ }
1111
+ previous = seq;
1112
+ seqs.push([seq]);
1113
+ }
1114
+ if (changeSeqs[0] !== batch.fromSeq || previous !== batch.toSeq) {
1115
+ throw new BatchValidationError("changeSeqs must start at fromSeq and end at toSeq");
1116
+ }
1117
+ return seqs;
1118
+ }
1119
+ function attributeChangeSeqs(batch) {
1120
+ assertSeqInRange(batch.fromSeq, "fromSeq");
1121
+ assertSeqInRange(batch.toSeq, "toSeq");
1122
+ if (batch.fromSeq > batch.toSeq) {
1123
+ throw new BatchValidationError("fromSeq must not exceed toSeq");
1124
+ }
1125
+ if (batch.changeSeqs !== void 0) {
1126
+ return explicitSeqs(batch, batch.changeSeqs);
1127
+ }
1128
+ if (batch.txContinues === true) {
1129
+ throw new BatchValidationError("txContinues requires changeSeqs");
1130
+ }
1131
+ const count = batch.changes.length;
1132
+ if (batch.toSeq - batch.fromSeq + 1n === BigInt(count)) {
1133
+ return batch.changes.map((_, index) => [batch.fromSeq + BigInt(index)]);
1134
+ }
1135
+ return batch.changes.map((_, index) => {
1136
+ const seqs = [];
1137
+ if (index === 0) seqs.push(batch.fromSeq);
1138
+ if (index === count - 1 && (index !== 0 || batch.toSeq !== batch.fromSeq)) seqs.push(batch.toSeq);
1139
+ return seqs;
1140
+ });
1141
+ }
1142
+
1143
+ export { HLC, IDENTIFIER_RE, MAX_CHANGE_SEQ, PkResolver, SEQ_STRING_RE, TABLE_XINFO_HIDDEN, assertSafeIdentifier, attributeChangeSeqs, canonicaliseForChecksum, deleteAllReplacedRows, deleteAllStagedChanges, deleteAppliedChangesAfterSeq, deleteChangesBeforeUpToSeqSql, deleteColumnVersions, deleteColumnVersionsAfterHlc, deleteExpiredDeviceCursors, deleteHistoryChangesAfterHlc, deleteMetaValue, deletePeerState, deletePeerStates, deletePrimaryTermStart, deleteReplacedRowsOfTable, deleteStagedChangesUpToSeq, deleteStagedPushChanges, deleteStampedChangesUpToSeq, deleteSyncTableStates, ensureBatchApplyTables, ensureChangesTable, ensureDeviceCursorsTable, ensureMetaTable, ensureMigrationsTable, ensureReplacedRowsTable, ensureReplicationStateTables, ensureStagedChangesTable, ensureStagedPushChangesTable, extractDroppedTable, highestMigrationVersion, indexColumns, insertAppliedChangesFromStagedPush, insertDdlChange, insertMetaValueIfAbsent, prepareDeleteMigration, prepareDeleteRowColumnVersions, prepareInsertAppliedChange, prepareInsertMigration, prepareInsertStagedPushChange, prepareUpdateMigrationChecksum, prepareUpsertColumnVersion, prepareUpsertNewerColumnVersion, primaryKeyColumns, referencedTables, replaceMigrationHistory, selectAnchoredTerm, selectAppliedMigrations, selectAppliedMigrationsNewestFirst, selectAppliedSourceSeqsInRange, selectChangesAfterSeqSql, selectCompletedSyncTableNames, selectCountOutboundChanges, selectCountTableRows, selectDeviceCursorExists, selectFirstStagedTransactionEnd, selectHistoryBase, selectHistoryChangesAfterHlc, selectHistoryTransaction, selectIndexSql, selectMaxAppliedSourceSeq, selectMaxAppliedSourceSeqByNode, selectMaxAssignedChangeSeq, selectMaxChangeHlc, selectMaxChangeSeq, selectMaxColumnVersionHlc, selectMaxColumnVersionHlcForRow, selectMaxHistoryChangeSeq, selectMaxNodeChangeSeq, selectMaxRowChangeHlc, selectMaxStagedSeq, selectMetaValue, selectMinChangeSeqSql, selectMinDeviceCursorBoundary, selectMinPeerAckedSeq, selectNewestHistoryChange, selectNodeChangesAfterSeqSql, selectOrdinaryTableName, selectOutboundChangesSql, selectOutboundHistoryChangesSql, selectPeerAckedSeq, selectPrimaryTermStart, selectQuarantined, selectStagedChangesInRange, selectStagedPushChangesAfter, selectStagedPushSeqsInRange, selectStagedPushTail, selectSyncMetaRow, selectTableExists, selectTableSql, selectTablesChangesInRangeSql, selectTriggerSql, selectUserSchemaObjects, selectUserTableNames, setForeignKeysEnabled, tableColumnsWithGenerated, tableIndexList, tableInfoRows, tablePkColumns, updateChangeStampsAboveMetaSeqSql, updateChangeStampsAfterSeqSql, updateDeviceCursor, upsertAnchoredTerm, upsertDeviceCursor, upsertHistoryBase, upsertMetaMaxChangeSeqSql, upsertMetaValue, upsertMetaValueAndMaxChangeSeqSql, upsertPeerAckedSeq, upsertPrimaryTermStart, upsertQuarantined, upsertStagedChangeSql, upsertSyncMeta, upsertSyncTableStatus, validateDdlSafety, validateIdentifier };
@@ -0,0 +1,55 @@
1
+ import { withRowCounts, rowCountsOf } from './chunk-E2GRX4ZD.mjs';
2
+ import { SirannonError } from './chunk-KINDFBQP.mjs';
3
+
4
+ // src/core/worker/protocol.ts
5
+ function toWorkerGroupStatement(statement) {
6
+ return {
7
+ sql: statement.sql,
8
+ params: statement.params ? [...statement.params] : [],
9
+ ...statement.trusted === true ? { trusted: true } : {}
10
+ };
11
+ }
12
+ var WORKER_CANCELLED_CODE = "WRITER_WORKER_CANCELLED";
13
+ var WORKER_BEGIN_FAILED_CODE = "WRITER_WORKER_BEGIN_FAILED";
14
+ var KINDS_THAT_CARRY_BEGIN = /* @__PURE__ */ new Set([
15
+ "exec",
16
+ "run",
17
+ "get",
18
+ "all",
19
+ "allRaw",
20
+ "allCounted",
21
+ "getCounted",
22
+ "allRawCounted",
23
+ "runBatch",
24
+ "runBatchSummary"
25
+ ]);
26
+ function canCarryBegin(kind) {
27
+ return KINDS_THAT_CARRY_BEGIN.has(kind);
28
+ }
29
+ function leftTransactionUnbegun(error) {
30
+ return error.code === WORKER_BEGIN_FAILED_CODE || error.code === WORKER_CANCELLED_CODE;
31
+ }
32
+ var WORKER_COPY_STOPPED_CODE = "WRITER_WORKER_COPY_STOPPED";
33
+ function serializeError(err) {
34
+ if (err instanceof Error) {
35
+ const { code, sql } = err;
36
+ return withRowCounts(
37
+ {
38
+ message: err.message,
39
+ name: err.name,
40
+ ...typeof code === "string" ? { code } : {},
41
+ ...typeof sql === "string" ? { sql } : {},
42
+ ...err instanceof SirannonError ? { sirannonError: true } : {}
43
+ },
44
+ rowCountsOf(err)
45
+ );
46
+ }
47
+ return { message: String(err) };
48
+ }
49
+ function deserializeError(error) {
50
+ const err = error.sirannonError === true && error.code !== void 0 ? new SirannonError(error.message, error.code) : Object.assign(new Error(error.message), error.code === void 0 ? {} : { code: error.code });
51
+ if (error.name) err.name = error.name;
52
+ return withRowCounts(err, rowCountsOf(error));
53
+ }
54
+
55
+ export { WORKER_BEGIN_FAILED_CODE, WORKER_CANCELLED_CODE, WORKER_COPY_STOPPED_CODE, canCarryBegin, deserializeError, leftTransactionUnbegun, serializeError, toWorkerGroupStatement };