@delali/sirannon-db 0.1.7 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +117 -969
  2. package/dist/backup-scheduler/index.d.ts +1 -1
  3. package/dist/backup-scheduler/index.mjs +2 -2
  4. package/dist/baseline-Br77Fnhb.d.ts +6 -0
  5. package/dist/{change-tracker-CbmaMO-N.d.ts → change-tracker-DKRVUC3l.d.ts} +5 -8
  6. package/dist/{chunk-DJLX6CAE.mjs → chunk-4ISB7XMA.mjs} +2 -1
  7. package/dist/chunk-5NOIGN5Y.mjs +18 -0
  8. package/dist/chunk-67M7KAH6.mjs +90 -0
  9. package/dist/{chunk-GEZUUIKV.mjs → chunk-D7LAYTKN.mjs} +5 -2
  10. package/dist/{chunk-4IGMIJQK.mjs → chunk-EBJXPQQO.mjs} +59 -20
  11. package/dist/{chunk-BNUTBHHH.mjs → chunk-FHWTZFI4.mjs} +1 -1
  12. package/dist/chunk-GVCNMPOS.mjs +130 -0
  13. package/dist/chunk-H237TXZW.mjs +1407 -0
  14. package/dist/{chunk-HHRMRFFR.mjs → chunk-H6PIVVDN.mjs} +353 -142
  15. package/dist/chunk-HR5CWTLC.mjs +661 -0
  16. package/dist/chunk-JU64Y7HM.mjs +299 -0
  17. package/dist/{chunk-CW6S3WL5.mjs → chunk-JZGINXTN.mjs} +7 -5
  18. package/dist/{chunk-CJLYFDP5.mjs → chunk-LFZ37BSX.mjs} +1 -1
  19. package/dist/chunk-LNY2VVHE.mjs +18 -0
  20. package/dist/chunk-NVQS53NT.mjs +665 -0
  21. package/dist/{chunk-H5AB6NIR.mjs → chunk-O7SLN3GI.mjs} +2 -15
  22. package/dist/chunk-OQVZBEBY.mjs +283 -0
  23. package/dist/{chunk-VLTICJOD.mjs → chunk-PIKHN33N.mjs} +1 -1
  24. package/dist/chunk-TJF5GZSV.mjs +187 -0
  25. package/dist/chunk-TUD5CJ76.mjs +126 -0
  26. package/dist/{chunk-YPYVQJ4C.mjs → chunk-UC3SCMIN.mjs} +9 -1
  27. package/dist/client/index.d.ts +216 -321
  28. package/dist/client/index.mjs +1192 -1342
  29. package/dist/client/topology.d.ts +61 -0
  30. package/dist/client/topology.mjs +682 -0
  31. package/dist/client-base-CLWmH5Ln.d.ts +234 -0
  32. package/dist/codegen/cli.d.ts +2 -0
  33. package/dist/codegen/cli.mjs +11 -0
  34. package/dist/codegen/index.d.ts +30 -0
  35. package/dist/codegen/index.mjs +5 -0
  36. package/dist/core/index.d.ts +37 -16
  37. package/dist/core/index.mjs +2322 -298
  38. package/dist/core/writer-worker.mjs +28 -6
  39. package/dist/{database-DuGp0Rtr.d.ts → database-BY0L5Q2n.d.ts} +59 -14
  40. package/dist/driver/better-sqlite3.d.ts +1 -1
  41. package/dist/driver/better-sqlite3.mjs +6 -6
  42. package/dist/driver/node.d.ts +1 -1
  43. package/dist/driver/node.mjs +6 -6
  44. package/dist/driver/wa-sqlite.d.ts +1 -136
  45. package/dist/{errors-5Nf5ZAEC.d.ts → errors-Bw5MdNCu.d.ts} +5 -1
  46. package/dist/file-migrations/index.d.ts +7 -5
  47. package/dist/file-migrations/index.mjs +42 -37
  48. package/dist/operation-registry-9DcvxcE5.d.ts +45 -0
  49. package/dist/primary-wins-DPAm2AKG.d.ts +61 -0
  50. package/dist/protocol-6KrSq2Hy.d.ts +66 -0
  51. package/dist/react/index.d.ts +20 -0
  52. package/dist/react/index.mjs +137 -0
  53. package/dist/replication/coordinator/etcd.d.ts +5 -3
  54. package/dist/replication/coordinator/etcd.mjs +554 -462
  55. package/dist/replication/index.d.ts +51 -105
  56. package/dist/replication/index.mjs +1415 -2061
  57. package/dist/server/index.d.ts +111 -87
  58. package/dist/server/index.mjs +1917 -489
  59. package/dist/server-options-1JHu8pid.d.ts +191 -0
  60. package/dist/{sirannon-4SspRvP5.d.ts → sirannon-DaQSyhbJ.d.ts} +7 -2
  61. package/dist/transport/grpc.d.ts +7 -4
  62. package/dist/transport/grpc.mjs +191 -97
  63. package/dist/transport/memory.d.ts +5 -134
  64. package/dist/transport/memory.mjs +3 -1
  65. package/dist/{types-BsjobKbl.d.ts → types-B7gmEsZW.d.ts} +8 -61
  66. package/dist/{types-BEu1I_9_.d.ts → types-BsVabqSI.d.ts} +1 -1
  67. package/dist/types-CL6piSnD.d.ts +43 -0
  68. package/dist/types-C_D8IhpO.d.ts +60 -0
  69. package/dist/{types-D_hQW1hr.d.ts → types-zhnRXrsb.d.ts} +55 -165
  70. package/package.json +44 -6
  71. package/dist/chunk-TKGHYWQ6.mjs +0 -35
  72. package/dist/types-D4p4UyDK.d.ts +0 -26
@@ -1,344 +1,217 @@
1
- /** Query parameter types: named (object) or positional (array). */
2
- type Params = Record<string, unknown> | unknown[];
3
- type WriteConcernLevel = 'local' | 'majority' | 'all';
4
- interface WriteConcern {
5
- level: WriteConcernLevel;
6
- timeoutMs?: number;
7
- }
8
- type ReadConcernLevel = 'local' | 'majority' | 'linearizable';
9
- interface ReadConcern {
10
- level: ReadConcernLevel;
1
+ export { F as FieldMergeResolver, L as LWWResolver, P as PrimaryWinsResolver } from '../primary-wins-DPAm2AKG.js';
2
+ import { C as ConflictResolver, R as ReplicationBatch } from '../types-C_D8IhpO.js';
3
+ export { a as ConflictContext, b as ConflictResolution } from '../types-C_D8IhpO.js';
4
+ import { C as ClientOptions, B as BulkLoadDurability } from '../server-options-1JHu8pid.js';
5
+ import { D as DatabaseClient, T as Transport, L as LiveHandlers, R as RemoteSubscription, a as RemoteSubscriptionBuilder, S as SubscribeOptions, b as RegistryDigestSource } from '../client-base-CLWmH5Ln.js';
6
+ export { c as LoadAllOptions, d as RemoteDatabase, e as RemoteError, f as SQL_REFUSED_MESSAGE, g as ServerCapabilities, h as ServerCapabilityCheck } from '../client-base-CLWmH5Ln.js';
7
+ import { a as LiveQuery, b as LiveQueryState, c as LiveUpdate } from '../types-CL6piSnD.js';
8
+ import { e as DeviceSyncPort, D as Database } from '../database-BY0L5Q2n.js';
9
+ import { h as ChangeEvent, P as Params, R as ReadConcern, W as WriteConcern } from '../types-zhnRXrsb.js';
10
+ import { Q as QueryResponse, E as ExecuteResponse, a as TransactionResponse, B as BatchResponse, L as LoadResponse, A as AckResponse } from '../protocol-6KrSq2Hy.js';
11
+ import '../operation-registry-9DcvxcE5.js';
12
+
13
+ declare class SirannonClient extends DatabaseClient {
14
+ private readonly baseUrl;
15
+ constructor(url: string, options?: ClientOptions);
16
+ protected createTransport(databaseId: string): Transport;
17
+ protected resolveServerUrl(): string;
11
18
  }
12
- interface QueryOptions {
13
- writeConcern?: WriteConcern;
14
- readConcern?: ReadConcern;
19
+
20
+ declare class RemoteLiveQuery<T> implements LiveQuery<T> {
21
+ private state;
22
+ private rows;
23
+ private readonly listeners;
24
+ private subscription;
25
+ private closed;
26
+ static open<T>(subscribe: (handlers: LiveHandlers) => Promise<RemoteSubscription>): Promise<RemoteLiveQuery<T>>;
27
+ getState(): LiveQueryState<T>;
28
+ subscribe(listener: (update: LiveUpdate<T>) => void): () => void;
29
+ close(): Promise<void>;
30
+ private handlers;
31
+ private replace;
32
+ private apply;
33
+ private markRevalidating;
34
+ private fail;
35
+ private publish;
15
36
  }
16
- /** CDC operation type. */
17
- type ChangeOperation = 'insert' | 'update' | 'delete';
18
- /** Event emitted when a watched table row changes. */
19
- interface ChangeEvent<T = Record<string, unknown>> {
20
- type: ChangeOperation;
37
+
38
+ interface SnapshotProgress {
21
39
  table: string;
22
- row: T;
23
- oldRow?: T;
24
- seq: bigint;
25
- timestamp: number;
40
+ tableLoadedRows: number;
41
+ tableTotalRows: number;
42
+ loadedRows: number;
43
+ totalRows: number;
26
44
  }
27
- /**
28
- * Durability level in force while a bulk load runs. SQLite sanctions 'off' for
29
- * a from-scratch load that the operator can re-run after a power loss; 'off'
30
- * gives up corruption safety, so it fits only a load that starts from nothing.
31
- * 'normal' keeps WAL-mode corruption safety and suits loads into a database
32
- * that already holds data the operator cannot afford to lose.
33
- */
34
- type BulkLoadDurability = 'off' | 'normal';
35
- /** Aggregate outcome of a bulk load. Summed rather than per-row so a
36
- * million-row load never holds a million result objects in memory. */
37
- interface BulkLoadResult {
38
- rowsLoaded: number;
39
- changes: number;
40
- }
41
- /** Options for the client SDK. */
42
- interface ClientOptions {
43
- /** Transport to use. Default: 'websocket'. */
44
- transport?: 'websocket' | 'http';
45
- /** Custom headers for HTTP requests. */
45
+ interface SnapshotDownloadOptions {
46
+ url: string;
47
+ databaseId: string;
46
48
  headers?: Record<string, string>;
47
- /** WebSocket subprotocols sent during the browser-compatible handshake. */
48
- webSocketProtocols?: string | string[];
49
- /** Reconnect on WebSocket disconnect. Default: true. */
50
- autoReconnect?: boolean;
51
- /** Reconnect interval in ms. Default: 1000. */
52
- reconnectInterval?: number;
53
- /**
54
- * Per-request timeout in milliseconds for the WebSocket transport. A bulk
55
- * load or batch of tens of millions of rows can legitimately run longer than
56
- * the default, so raise this for large writes. Set to 0 to wait indefinitely.
57
- * Default: 30000.
58
- */
59
- requestTimeout?: number;
60
- }
61
-
62
- interface QueryResponse {
63
- rows: Record<string, unknown>[];
64
- }
65
- interface ExecuteResponse {
66
- changes: number;
67
- lastInsertRowId: number | string;
49
+ pageSize?: number;
50
+ requestTimeoutMs?: number;
51
+ onProgress?: (progress: SnapshotProgress) => void;
68
52
  }
69
- interface TransactionResponse {
70
- results: ExecuteResponse[];
53
+ interface SnapshotDownloadResult {
54
+ startSeq: bigint;
55
+ epoch: string;
56
+ tables: string[];
57
+ loadedRows: number;
71
58
  }
72
- interface BatchResponse {
73
- results: ExecuteResponse[];
74
- }
75
- type LoadResponse = BulkLoadResult;
59
+ declare function downloadDatabaseSnapshot(port: DeviceSyncPort, options: SnapshotDownloadOptions): Promise<SnapshotDownloadResult>;
76
60
 
77
- /** Optional behaviours for a CDC subscription. */
78
- interface SubscribeOptions {
79
- /**
80
- * Invoked when a reconnect cannot replay missed changes because they fell
81
- * outside the server's retained history. The subscription continues live
82
- * from the current moment; treat any prior state as stale and re-read.
83
- */
84
- onReset?: () => void;
85
- }
86
61
  /**
87
- * Transport layer for communicating with a sirannon-db server.
88
- * Each transport instance is bound to a specific database.
62
+ * Builds a remote CDC subscription with optional row-level filters.
63
+ * Mirrors the core {@link SubscriptionBuilder} interface but returns
64
+ * a promise from `subscribe()` since confirming the subscription
65
+ * requires a server round-trip.
89
66
  */
90
- interface Transport {
91
- query(sql: string, params?: Params, readConcern?: ReadConcern): Promise<QueryResponse>;
92
- execute(sql: string, params?: Params): Promise<ExecuteResponse>;
93
- transaction(statements: Array<{
94
- sql: string;
95
- params?: Params;
96
- }>): Promise<TransactionResponse>;
97
- batch(sql: string, paramsBatch: Params[], writeConcern?: WriteConcern): Promise<BatchResponse>;
98
- load(sql: string, paramsBatch: Params[], durability?: BulkLoadDurability, checkpoint?: boolean): Promise<LoadResponse>;
99
- subscribe(table: string, filter: Record<string, unknown> | undefined, callback: (event: ChangeEvent) => void, options?: SubscribeOptions): Promise<RemoteSubscription>;
100
- close(): void;
101
- }
102
- /** Handle for an active remote subscription. */
103
- interface RemoteSubscription {
104
- unsubscribe(): void;
105
- }
106
- /** Builder for creating remote CDC subscriptions with optional filters. */
107
- interface RemoteSubscriptionBuilder {
67
+ declare class RemoteSubscriptionBuilderImpl implements RemoteSubscriptionBuilder {
68
+ private readonly table;
69
+ private readonly transport;
70
+ private conditions;
71
+ constructor(table: string, transport: Transport);
108
72
  filter(conditions: Record<string, unknown>): RemoteSubscriptionBuilder;
109
73
  subscribe(callback: (event: ChangeEvent) => void, options?: SubscribeOptions): Promise<RemoteSubscription>;
110
74
  }
111
- /**
112
- * Error originating from a remote sirannon-db server.
113
- * Carries the machine-readable error code from the server's error response.
114
- */
115
- declare class RemoteError extends Error {
116
- readonly code: string;
117
- constructor(code: string, message: string);
118
- }
119
75
 
120
- /** Options for {@link RemoteDatabase.loadAll}. */
121
- interface LoadAllOptions {
122
- /**
123
- * Rows per batch sent to the server. Each batch is one request, so it must
124
- * fit under the server's `maxBodyBytes`; widen that cap or lower this for
125
- * wide rows. Default: 1000.
126
- */
76
+ interface SyncControllerOptions {
77
+ url: string;
78
+ databaseId: string;
79
+ tables: readonly string[];
80
+ headers?: Record<string, string>;
127
81
  batchSize?: number;
128
- /** Durability during the load. Default: 'off'. */
129
- durability?: BulkLoadDurability;
82
+ pushIntervalMs?: number;
83
+ ackIntervalMs?: number;
84
+ maxPushRetryDelayMs?: number;
85
+ requestTimeout?: number;
86
+ autoResync?: boolean;
87
+ snapshotRetryDelayMs?: number;
88
+ maxSnapshotRetryDelayMs?: number;
89
+ snapshotPageSize?: number;
90
+ immediateAckAfterChanges?: number;
91
+ resolver?: ConflictResolver | ((table: string) => ConflictResolver);
92
+ onChange?: (event: ChangeEvent) => void;
93
+ onResyncRequired?: () => void;
94
+ onSnapshotProgress?: (progress: SnapshotProgress) => void;
95
+ onSnapshotComplete?: (outcome: SnapshotOutcome) => void;
130
96
  }
131
- /**
132
- * Proxy for a remote sirannon-db database. Mirrors the core
133
- * {@link Database} query interface with async methods that send
134
- * requests to the server via the configured transport.
135
- */
136
- declare class RemoteDatabase {
137
- readonly id: string;
138
- private readonly transport;
139
- private readonly onDispose?;
140
- constructor(id: string, transport: Transport, onDispose?: (() => void) | undefined);
141
- /**
142
- * Execute a SELECT and return all matching rows.
143
- *
144
- * ```ts
145
- * const users = await db.query<{ id: number; name: string }>(
146
- * 'SELECT * FROM users WHERE age > ?',
147
- * [21],
148
- * )
149
- * ```
150
- */
151
- query<T = Record<string, unknown>>(sql: string, params?: Params, options?: QueryOptions): Promise<T[]>;
152
- /**
153
- * Execute a mutation (INSERT, UPDATE, DELETE) and return
154
- * the number of affected rows and last insert row ID.
155
- */
156
- execute(sql: string, params?: Params): Promise<ExecuteResponse>;
157
- /**
158
- * Execute multiple statements as a single atomic transaction.
159
- * Returns an array of results, one per statement.
160
- *
161
- * The whole list travels in one request and commits or rolls back as a
162
- * unit, so the client is never in the loop between statements.
163
- */
164
- transaction(statements: Array<{
165
- sql: string;
166
- params?: Params;
167
- }>): Promise<ExecuteResponse[]>;
168
- /**
169
- * Run the same statement once per parameter set as a single atomic
170
- * transaction that commits with one fsync. Returns one result per
171
- * parameter set, in order. Use this for a burst of same-shape writes
172
- * (an import, a bulk insert) that must all commit or all roll back.
173
- */
174
- batch(sql: string, paramsBatch: Params[], writeConcern?: WriteConcern): Promise<ExecuteResponse[]>;
175
- /**
176
- * Load a whole dataset through the same statement, batching it into requests
177
- * for you and paying the one fsyncing WAL checkpoint once, after the final
178
- * batch. The configured durability is restored after every batch, so an
179
- * import that stops partway never leaves the writer at the relaxed level.
180
- * Prefer this over {@link load} for anything larger than a single request:
181
- * it runs the finalize itself, so there is no checkpoint flag to forget.
182
- *
183
- * Accepts a synchronous or asynchronous iterable of parameter sets, so rows
184
- * can stream from a file or the network without being held in memory at
185
- * once. Returns the total rows loaded and changes applied.
186
- *
187
- * ```ts
188
- * const summary = await db.loadAll(
189
- * 'INSERT INTO events (id, payload) VALUES (?, ?)',
190
- * rowStream,
191
- * { batchSize: 5000, durability: 'off' },
192
- * )
193
- * ```
194
- */
195
- loadAll(sql: string, rows: Iterable<Params> | AsyncIterable<Params>, options?: LoadAllOptions): Promise<BulkLoadResult>;
196
- /**
197
- * Load one batch of rows through the same statement with writer durability
198
- * relaxed for the duration, then restored before this resolves. This is the
199
- * low-level primitive; prefer {@link loadAll} for a dataset that spans more
200
- * than one request, since it runs the finalize itself rather than relying on
201
- * a `checkpoint` flag.
202
- *
203
- * Returns the total rows loaded and changes applied. When splitting a dataset
204
- * across many `load` calls by hand, pass `checkpoint: false` on every call
205
- * but the last so the one fsyncing WAL checkpoint runs once at the end; the
206
- * configured durability is restored after each call regardless.
207
- */
208
- load(sql: string, paramsBatch: Params[], durability?: BulkLoadDurability, checkpoint?: boolean): Promise<BulkLoadResult>;
97
+ type SnapshotOutcome = {
98
+ ok: true;
99
+ error: null;
100
+ databaseUsable: true;
101
+ retrying: false;
102
+ } | {
103
+ ok: false;
104
+ error: {
105
+ code: string;
106
+ message: string;
107
+ };
108
+ databaseUsable: boolean;
109
+ retrying: boolean;
110
+ };
111
+ type SyncState = 'stopped' | 'starting' | 'running' | 'paused' | 'snapshotting';
112
+ interface SnapshotOptions {
113
+ pageSize?: number;
114
+ onProgress?: (progress: SnapshotProgress) => void;
115
+ }
116
+ interface SyncStatus {
117
+ state: SyncState;
118
+ deviceId: string | null;
119
+ serverCapabilities: string[] | null;
120
+ schemaVersion: number | null;
121
+ pendingPushCount: number;
122
+ lastPushedSeq: bigint;
123
+ lastPulledSeq: bigint | null;
124
+ pushCaughtUp: boolean;
125
+ resyncRequired: boolean;
126
+ lastError: {
127
+ code: string;
128
+ message: string;
129
+ } | null;
130
+ }
131
+
132
+ declare class SyncController {
133
+ private readonly db;
134
+ private readonly options;
135
+ private readonly baseUrl;
136
+ private readonly pushIntervalMs;
137
+ private readonly maxPushRetryDelayMs;
138
+ private readonly pull;
139
+ private readonly push;
140
+ private readonly resync;
141
+ private port;
142
+ private deviceId;
143
+ private capabilities;
144
+ private schemaVersion;
145
+ private state;
146
+ private pullRetryTimer;
147
+ private consecutivePullFailures;
148
+ private lastError;
149
+ constructor(db: Database, options: SyncControllerOptions);
150
+ start(): Promise<void>;
151
+ pause(): void;
152
+ resume(): Promise<void>;
153
+ stop(): Promise<void>;
154
+ status(): Promise<SyncStatus>;
155
+ triggerPush(): void;
156
+ private verifyCapabilities;
157
+ private localSchemaVersion;
158
+ private reconcileSchema;
159
+ private markResyncRequired;
160
+ downloadSnapshot(options?: SnapshotOptions): Promise<void>;
209
161
  /**
210
- * Start building a CDC subscription for the given table.
211
- * Chain `.filter()` to narrow the events, then call `.subscribe()`
212
- * with a callback to begin receiving real-time change events.
213
- *
214
- * ```ts
215
- * const sub = await db
216
- * .on('orders')
217
- * .filter({ status: 'pending' })
218
- * .subscribe(event => console.log(event))
219
- *
220
- * // Later:
221
- * sub.unsubscribe()
222
- * ```
162
+ * Answers whether the local database serves reads and writes again. A failure
163
+ * before the wipe begins leaves it intact, while one after it leaves every
164
+ * statement refused with `SNAPSHOT_IN_PROGRESS` until a later copy succeeds,
165
+ * so the application learns which of the two it is rather than assuming.
223
166
  */
224
- on(table: string): RemoteSubscriptionBuilder;
167
+ private snapshotGateOpen;
168
+ private recordError;
169
+ private handleApplyFailure;
170
+ private reopenPull;
225
171
  /**
226
- * Close the transport for this database. After calling `close()`,
227
- * all pending requests are rejected and new calls will throw.
172
+ * Opens the pull subscription, reconciling migrations when the server refuses
173
+ * it because this device is behind. A device that only reads never pushes, so
174
+ * the subscribe refusal is the sole point at which it can learn that the
175
+ * server has migrated; without this it would retry the same refused
176
+ * subscription forever and silently receive nothing.
228
177
  */
229
- close(): void;
178
+ private openPull;
179
+ private teardownStream;
230
180
  }
231
181
 
232
- interface TopologyAwareClientOptions extends ClientOptions {
233
- endpoints?: string[];
234
- primary?: string;
235
- replicas?: string[];
236
- readPreference?: 'primary' | 'replica' | 'nearest';
237
- discovery?: 'static' | 'coordinator';
238
- readConcern?: ReadConcernLevel;
239
- }
240
- declare class SirannonClient {
241
- private readonly baseUrl;
242
- private readonly wsBaseUrl;
243
- private readonly transport;
244
- private readonly headers;
245
- private readonly webSocketProtocols;
246
- private readonly autoReconnect;
247
- private readonly reconnectInterval;
248
- private readonly requestTimeout;
249
- private readonly databases;
250
- private closed;
251
- private readonly topologyEnabled;
252
- private readonly primaryUrl;
253
- private readonly replicaUrls;
254
- private readonly readPreference;
255
- private readonly discovery;
256
- private readonly readConcern;
257
- private readonly starterEndpoints;
258
- private readonly clusterRouting;
259
- private readonly topologyTransports;
260
- private latencies;
261
- private latencyMeasuredAt;
262
- private latencyMeasuring;
263
- private readonly LATENCY_TTL_MS;
264
- private removedReplicas;
265
- constructor(url: string, options?: ClientOptions);
266
- constructor(options: TopologyAwareClientOptions);
267
- database(id: string): RemoteDatabase;
268
- close(): void;
269
- private createTransport;
270
- private createTransportForUrl;
271
- _createTransportForEndpoint(url: string, databaseId: string): Transport;
272
- _getReadEndpoint(databaseId?: string, readConcern?: ReadConcernLevel): Promise<string>;
273
- _getWriteEndpoint(databaseId?: string): Promise<string>;
274
- _getReadConcern(): ReadConcernLevel | undefined;
275
- _usesCoordinatorDiscovery(): boolean;
276
- _removeReplica(url: string): void;
277
- private ensureLatencyMeasured;
278
- private measureLatencies;
279
- _refreshClusterRouting(databaseId: string): Promise<void>;
280
- private ensureClusterRouting;
281
- private clusterDiscoveryCandidates;
282
- _unregisterTopologyTransport(databaseId: string, transport: TopologyAwareTransport): void;
283
- private notifyClusterRoutingChanged;
182
+ interface ChangesRequest {
183
+ schemaVersion?: number;
184
+ batch: {
185
+ sourceNodeId: string;
186
+ batchId: string;
187
+ fromSeq: string;
188
+ toSeq: string;
189
+ hlcRange: {
190
+ min: string;
191
+ max: string;
192
+ };
193
+ changes: {
194
+ table: string;
195
+ operation: string;
196
+ rowId: string;
197
+ primaryKey: Record<string, unknown>;
198
+ hlc: string;
199
+ txId: string;
200
+ nodeId: string;
201
+ newData: Record<string, unknown> | null;
202
+ oldData: Record<string, unknown> | null;
203
+ }[];
204
+ checksum: string;
205
+ };
284
206
  }
285
-
286
- declare class TopologyAwareTransport implements Transport {
287
- private readonly databaseId;
288
- private readonly client;
289
- private closed;
290
- private readTransport;
291
- private writeTransport;
292
- private subscriptionTransport;
293
- private readTransportRequest;
294
- private writeTransportRequest;
295
- private subscriptionTransportRequest;
296
- private subscriptionOperation;
297
- private activeSubscriptions;
298
- private nextSubscriptionId;
299
- private currentReadUrl;
300
- private currentWriteUrl;
301
- private currentSubscriptionUrl;
302
- constructor(databaseId: string, client: SirannonClient);
303
- query(sql: string, params?: Params): Promise<QueryResponse>;
304
- execute(sql: string, params?: Params): Promise<ExecuteResponse>;
305
- transaction(statements: Array<{
306
- sql: string;
307
- params?: Params;
308
- }>): Promise<TransactionResponse>;
309
- batch(sql: string, paramsBatch: Params[], writeConcern?: WriteConcern): Promise<BatchResponse>;
310
- load(sql: string, paramsBatch: Params[], durability?: BulkLoadDurability, checkpoint?: boolean): Promise<LoadResponse>;
311
- subscribe(table: string, filter: Record<string, unknown> | undefined, callback: (event: ChangeEvent) => void, options?: SubscribeOptions): Promise<RemoteSubscription>;
312
- _handleClusterRoutingChanged(): Promise<void>;
313
- close(): void;
314
- private subscribeOnCurrentEndpoint;
315
- private createSubscriptionHandle;
316
- private migrateSubscriptionsToCurrentEndpoint;
317
- private getReadTransport;
318
- private resolveReadTransport;
319
- private getWriteTransport;
320
- private resolveWriteTransport;
321
- private getSubscriptionTransport;
322
- private resolveSubscriptionTransport;
323
- private closeSubscriptionTransport;
324
- private withSubscriptionOperation;
325
- private assertOpen;
207
+ interface ChangesResponse {
208
+ applied: number;
209
+ skipped: number;
210
+ conflicts: number;
326
211
  }
327
212
 
328
- /**
329
- * Builds a remote CDC subscription with optional row-level filters.
330
- * Mirrors the core {@link SubscriptionBuilder} interface but returns
331
- * a promise from `subscribe()` since confirming the subscription
332
- * requires a server round-trip.
333
- */
334
- declare class RemoteSubscriptionBuilderImpl implements RemoteSubscriptionBuilder {
335
- private readonly table;
336
- private readonly transport;
337
- private conditions;
338
- constructor(table: string, transport: Transport);
339
- filter(conditions: Record<string, unknown>): RemoteSubscriptionBuilder;
340
- subscribe(callback: (event: ChangeEvent) => void, options?: SubscribeOptions): Promise<RemoteSubscription>;
341
- }
213
+ declare function encodeSyncBatch(batch: ReplicationBatch): ChangesRequest['batch'];
214
+ declare function pushSyncBatch(baseUrl: string, databaseId: string, batch: ReplicationBatch, headers?: Record<string, string>, timeoutMs?: number, schemaVersion?: number): Promise<ChangesResponse>;
342
215
 
343
216
  /**
344
217
  * HTTP transport for sirannon-db. Sends requests via `fetch` to the
@@ -347,6 +220,7 @@ declare class RemoteSubscriptionBuilderImpl implements RemoteSubscriptionBuilder
347
220
  * HTTP; use {@link WebSocketTransport} for CDC subscriptions.
348
221
  */
349
222
  declare class HttpTransport implements Transport {
223
+ readonly carriesReadConcern = true;
350
224
  private readonly baseUrl;
351
225
  private readonly headers;
352
226
  private closed;
@@ -359,20 +233,37 @@ declare class HttpTransport implements Transport {
359
233
  }>): Promise<TransactionResponse>;
360
234
  batch(sql: string, paramsBatch: Params[], writeConcern?: WriteConcern): Promise<BatchResponse>;
361
235
  load(sql: string, paramsBatch: Params[], durability?: BulkLoadDurability, checkpoint?: boolean): Promise<LoadResponse>;
236
+ queryNamed(name: string, args?: Record<string, unknown>, readConcern?: ReadConcern): Promise<QueryResponse>;
237
+ executeNamed(name: string, args?: Record<string, unknown>, writeConcern?: WriteConcern): Promise<TransactionResponse>;
238
+ liveSubscribe(): Promise<RemoteSubscription>;
362
239
  subscribe(_table: string, _filter: Record<string, unknown> | undefined, _callback: (event: ChangeEvent) => void): Promise<RemoteSubscription>;
363
240
  close(): void;
364
241
  private post;
365
242
  }
366
243
 
244
+ /**
245
+ * WebSocket transport for sirannon-db. Connects to
246
+ * `ws(s)://host:port/db/{id}` and supports query, execute, transaction,
247
+ * batch, load, and real-time CDC subscriptions over a single persistent
248
+ * connection.
249
+ *
250
+ * Connections are established lazily on first use and will
251
+ * auto-reconnect (with subscription restoration) when
252
+ * `autoReconnect` is enabled.
253
+ */
367
254
  declare class WebSocketTransport implements Transport {
255
+ readonly carriesReadConcern = true;
368
256
  private ws;
369
257
  private readonly url;
370
258
  private readonly autoReconnect;
371
259
  private readonly reconnectInterval;
372
260
  private readonly requestTimeout;
373
261
  private readonly protocols;
374
- private pendingRequests;
262
+ private readonly headers;
263
+ private refusal;
264
+ private readonly pending;
375
265
  private activeSubscriptions;
266
+ private readonly liveQueries;
376
267
  private idCounter;
377
268
  private closed;
378
269
  private connectPromise;
@@ -382,8 +273,9 @@ declare class WebSocketTransport implements Transport {
382
273
  reconnectInterval?: number;
383
274
  requestTimeout?: number;
384
275
  protocols?: string | string[];
276
+ headers?: Record<string, string>;
385
277
  });
386
- query(sql: string, params?: Params): Promise<QueryResponse>;
278
+ query(sql: string, params?: Params, readConcern?: ReadConcern): Promise<QueryResponse>;
387
279
  execute(sql: string, params?: Params): Promise<ExecuteResponse>;
388
280
  transaction(statements: Array<{
389
281
  sql: string;
@@ -391,18 +283,21 @@ declare class WebSocketTransport implements Transport {
391
283
  }>): Promise<TransactionResponse>;
392
284
  batch(sql: string, paramsBatch: Params[], writeConcern?: WriteConcern): Promise<BatchResponse>;
393
285
  load(sql: string, paramsBatch: Params[], durability?: BulkLoadDurability, checkpoint?: boolean): Promise<LoadResponse>;
286
+ queryNamed(name: string, args?: Record<string, unknown>, readConcern?: ReadConcern): Promise<QueryResponse>;
287
+ executeNamed(name: string, args?: Record<string, unknown>, writeConcern?: WriteConcern): Promise<TransactionResponse>;
288
+ liveSubscribe(name: string, args: Record<string, unknown> | undefined, handlers: LiveHandlers, registryDigest?: RegistryDigestSource): Promise<RemoteSubscription>;
394
289
  subscribe(table: string, filter: Record<string, unknown> | undefined, callback: (event: ChangeEvent) => void, options?: SubscribeOptions): Promise<RemoteSubscription>;
290
+ private sendUnsubscribe;
291
+ ack(deviceId: string, seq: bigint): Promise<AckResponse>;
395
292
  close(): void;
396
293
  private nextId;
397
294
  private ensureConnected;
398
295
  private connect;
399
- private handleMessage;
400
296
  private handleDisconnect;
401
297
  private scheduleReconnect;
402
298
  private resubscribeAll;
403
299
  private request;
404
- private rejectAllPending;
405
300
  private cancelReconnect;
406
301
  }
407
302
 
408
- export { HttpTransport, type LoadAllOptions, RemoteDatabase, RemoteError, type RemoteSubscription, type RemoteSubscriptionBuilder, RemoteSubscriptionBuilderImpl, SirannonClient, type TopologyAwareClientOptions, type Transport, WebSocketTransport };
303
+ export { ConflictResolver, HttpTransport, LiveHandlers, RegistryDigestSource, RemoteLiveQuery, RemoteSubscription, RemoteSubscriptionBuilder, RemoteSubscriptionBuilderImpl, SirannonClient, type SnapshotDownloadOptions, type SnapshotDownloadResult, type SnapshotOptions, type SnapshotOutcome, type SnapshotProgress, SyncController, type SyncControllerOptions, type SyncState, type SyncStatus, Transport, WebSocketTransport, downloadDatabaseSnapshot, encodeSyncBatch, pushSyncBatch };