@delali/sirannon-db 0.2.0 → 0.2.1

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 (75) hide show
  1. package/dist/backup-scheduler/index.d.ts +15 -1
  2. package/dist/backup-scheduler/index.mjs +2 -2
  3. package/dist/baseline-D93hcIEE.d.ts +17 -0
  4. package/dist/{change-tracker-DKRVUC3l.d.ts → change-tracker-DDmXB754.d.ts} +56 -8
  5. package/dist/{chunk-5NOIGN5Y.mjs → chunk-2QLXDHAP.mjs} +1 -1
  6. package/dist/{chunk-LNY2VVHE.mjs → chunk-7C36BCSN.mjs} +1 -1
  7. package/dist/{chunk-NVQS53NT.mjs → chunk-7FQRQH5Z.mjs} +53 -64
  8. package/dist/{chunk-D7LAYTKN.mjs → chunk-7R4ER4FB.mjs} +1 -1
  9. package/dist/{chunk-FHWTZFI4.mjs → chunk-BQFQ65OL.mjs} +1 -1
  10. package/dist/{chunk-O7SLN3GI.mjs → chunk-BTTFW4Z4.mjs} +1 -1
  11. package/dist/{chunk-H6PIVVDN.mjs → chunk-CCZK6LCB.mjs} +38 -25
  12. package/dist/{chunk-JZGINXTN.mjs → chunk-HCCGEIZ2.mjs} +2 -2
  13. package/dist/{chunk-67M7KAH6.mjs → chunk-IWGIYDMZ.mjs} +1 -1
  14. package/dist/{chunk-LFZ37BSX.mjs → chunk-OUSWVNWT.mjs} +1 -1
  15. package/dist/{chunk-HR5CWTLC.mjs → chunk-P2VJYRVY.mjs} +60 -7
  16. package/dist/{chunk-UC3SCMIN.mjs → chunk-PBRXXISQ.mjs} +3 -0
  17. package/dist/{chunk-JU64Y7HM.mjs → chunk-SBL6GN43.mjs} +1 -1
  18. package/dist/{chunk-EBJXPQQO.mjs → chunk-UPKKSUPA.mjs} +2 -2
  19. package/dist/{chunk-TJF5GZSV.mjs → chunk-VOSJBZ6Q.mjs} +1 -1
  20. package/dist/{chunk-PIKHN33N.mjs → chunk-VOYGMAU7.mjs} +9 -1
  21. package/dist/{chunk-H237TXZW.mjs → chunk-WJ67DTD6.mjs} +48 -6
  22. package/dist/{chunk-OQVZBEBY.mjs → chunk-XF2HH5E6.mjs} +4 -61
  23. package/dist/client/index.d.ts +211 -12
  24. package/dist/client/index.mjs +155 -67
  25. package/dist/client/topology.d.ts +55 -7
  26. package/dist/client/topology.mjs +20 -1
  27. package/dist/{client-base-CLWmH5Ln.d.ts → client-base-CmZO0v3m.d.ts} +133 -24
  28. package/dist/codegen/cli.mjs +3 -3
  29. package/dist/codegen/index.d.ts +92 -2
  30. package/dist/codegen/index.mjs +3 -3
  31. package/dist/core/index.d.ts +177 -15
  32. package/dist/core/index.mjs +2481 -2226
  33. package/dist/core/writer-worker.mjs +3 -3
  34. package/dist/database-B5Qv1-cU.d.ts +380 -0
  35. package/dist/driver/better-sqlite3.d.ts +18 -1
  36. package/dist/driver/better-sqlite3.mjs +5 -5
  37. package/dist/driver/bun.d.ts +28 -0
  38. package/dist/driver/expo.d.ts +17 -0
  39. package/dist/driver/node.d.ts +18 -1
  40. package/dist/driver/node.mjs +5 -5
  41. package/dist/driver/wa-sqlite.d.ts +18 -1
  42. package/dist/{errors-Bw5MdNCu.d.ts → errors-Dei4GdBb.d.ts} +80 -7
  43. package/dist/file-migrations/index.d.ts +54 -2
  44. package/dist/file-migrations/index.mjs +3 -3
  45. package/dist/{operation-registry-9DcvxcE5.d.ts → operation-registry-hlbhqu7q.d.ts} +50 -1
  46. package/dist/{primary-wins-DPAm2AKG.d.ts → primary-wins-B0np8JS3.d.ts} +25 -1
  47. package/dist/protocol-rqANt-9Q.d.ts +152 -0
  48. package/dist/query-types-DL3LtPvY.d.ts +95 -0
  49. package/dist/react/index.d.ts +58 -3
  50. package/dist/replication/coordinator/etcd.d.ts +63 -3
  51. package/dist/replication/coordinator/etcd.mjs +82 -46
  52. package/dist/replication/index.d.ts +329 -95
  53. package/dist/replication/index.mjs +256 -141
  54. package/dist/server/index.d.ts +230 -12
  55. package/dist/server/index.mjs +63 -50
  56. package/dist/{server-options-1JHu8pid.d.ts → server-options-Dab_Jvd_.d.ts} +96 -12
  57. package/dist/sirannon-CMhiJa5Y.d.ts +111 -0
  58. package/dist/transport/grpc.d.ts +93 -9
  59. package/dist/transport/grpc.mjs +63 -20
  60. package/dist/transport/memory.d.ts +50 -20
  61. package/dist/transport/memory.mjs +25 -0
  62. package/dist/{types-CL6piSnD.d.ts → types-BCejqzNA.d.ts} +20 -0
  63. package/dist/types-CMBcFPhb.d.ts +336 -0
  64. package/dist/types-CjhxcjhA.d.ts +123 -0
  65. package/dist/types-DyrCiWuc.d.ts +499 -0
  66. package/dist/types-rVZKnKN-.d.ts +591 -0
  67. package/package.json +7 -1
  68. package/dist/baseline-Br77Fnhb.d.ts +0 -6
  69. package/dist/database-BY0L5Q2n.d.ts +0 -172
  70. package/dist/protocol-6KrSq2Hy.d.ts +0 -66
  71. package/dist/sirannon-DaQSyhbJ.d.ts +0 -36
  72. package/dist/types-B7gmEsZW.d.ts +0 -221
  73. package/dist/types-BsVabqSI.d.ts +0 -139
  74. package/dist/types-C_D8IhpO.d.ts +0 -60
  75. package/dist/types-zhnRXrsb.d.ts +0 -384
@@ -1,27 +1,47 @@
1
- import { T as TransactionStatement, Q as QueryResponse, E as ExecuteResponse, a as TransactionResponse, B as BatchResponse, L as LoadResponse, A as AckResponse } from '../protocol-6KrSq2Hy.js';
2
- export { b as BatchRequest, c as ErrorResponse, d as ExecuteRequest, e as LoadRequest, f as QueryRequest, g as TransactionRequest, t as toExecuteResponse } from '../protocol-6KrSq2Hy.js';
3
- import { S as Sirannon } from '../sirannon-DaQSyhbJ.js';
4
- import { B as BulkLoadDurability, S as ServerOptions, W as WSHandlerOptions } from '../server-options-1JHu8pid.js';
5
- import { W as WriteConcern, R as ReadConcern } from '../types-zhnRXrsb.js';
6
- import '../database-BY0L5Q2n.js';
7
- import '../types-C_D8IhpO.js';
8
- import '../types-CL6piSnD.js';
9
- import '../operation-registry-9DcvxcE5.js';
1
+ import { T as TransactionStatement, Q as QueryResponse, E as ExecuteResponse, a as TransactionResponse, B as BatchResponse, L as LoadResponse, A as AckResponse } from '../protocol-rqANt-9Q.js';
2
+ export { b as BatchRequest, c as ErrorResponse, d as ExecuteRequest, e as LoadRequest, f as QueryRequest, g as TransactionRequest, t as toExecuteResponse } from '../protocol-rqANt-9Q.js';
3
+ import { S as Sirannon } from '../sirannon-CMhiJa5Y.js';
4
+ import { B as BulkLoadDurability, S as ServerOptions, W as WSHandlerOptions } from '../server-options-Dab_Jvd_.js';
5
+ import { W as WriteConcern, R as ReadConcern } from '../query-types-DL3LtPvY.js';
6
+ import '../database-B5Qv1-cU.js';
7
+ import '../types-rVZKnKN-.js';
8
+ import '../types-CjhxcjhA.js';
9
+ import '../types-BCejqzNA.js';
10
+ import '../operation-registry-hlbhqu7q.js';
10
11
 
12
+ /**
13
+ * Every message a client sends over the WebSocket. Each carries a `type` and a
14
+ * client-chosen `id` the reply echoes.
15
+ *
16
+ * @public
17
+ */
11
18
  type WSClientMessage = WSSubscribeMessage | WSUnsubscribeMessage | WSAckMessage | WSQueryMessage | WSExecuteMessage | WSTransactionMessage | WSBatchMessage | WSLoadMessage;
19
+ /**
20
+ * Opens a change subscription on one or more tables, or a live query on a registered read.
21
+ *
22
+ * @public
23
+ */
12
24
  interface WSSubscribeMessage {
25
+ /** Names this message as a subscribe. */
13
26
  type: 'subscribe';
27
+ /** Client-chosen identifier the replies and change events echo. */
14
28
  id: string;
29
+ /** Table to subscribe to. */
15
30
  table?: string;
31
+ /** Several tables to subscribe to at once. */
16
32
  tables?: string[];
33
+ /** Narrows the subscription to rows whose columns equal these values. */
17
34
  filter?: Record<string, unknown>;
35
+ /** Name of a registered read, which opens a live query instead of a change subscription. */
18
36
  name?: string;
37
+ /** Arguments that registered read takes. */
19
38
  args?: Record<string, unknown>;
39
+ /** Digest of the operation registry the client built its live query against. */
20
40
  registryDigest?: string;
21
41
  /**
22
42
  * Highest `seq` the client has already processed. When present, the server
23
43
  * replays every retained change with a greater seq before delivering live
24
- * events, so a reconnecting subscriber does not miss changes. Sent as a
44
+ * events so that a reconnecting subscriber does not miss changes. Sent as a
25
45
  * decimal string to preserve values beyond `Number.MAX_SAFE_INTEGER`.
26
46
  */
27
47
  sinceSeq?: string;
@@ -32,7 +52,9 @@ interface WSSubscribeMessage {
32
52
  * resync rather than replay foreign rows against it.
33
53
  */
34
54
  epoch?: string;
55
+ /** Identifies the device, which turns this into a device-sync subscription. */
35
56
  deviceId?: string;
57
+ /** Schema version the device's local database is at, which the server gates the stream on. */
36
58
  schemaVersion?: number;
37
59
  /**
38
60
  * Declares that this device stages pulled changes durably and
@@ -42,61 +64,138 @@ interface WSSubscribeMessage {
42
64
  */
43
65
  stagedStream?: boolean;
44
66
  }
67
+ /**
68
+ * Ends a subscription.
69
+ *
70
+ * @public
71
+ */
45
72
  interface WSUnsubscribeMessage {
73
+ /** Names this message as an unsubscribe. */
46
74
  type: 'unsubscribe';
75
+ /** Identifier of the subscription to end. */
47
76
  id: string;
48
77
  }
78
+ /**
79
+ * Acknowledges every change a device has stored up to a sequence.
80
+ *
81
+ * @public
82
+ */
49
83
  interface WSAckMessage {
84
+ /** Names this message as an acknowledgement. */
50
85
  type: 'ack';
86
+ /** Client-chosen identifier the reply echoes. */
51
87
  id: string;
88
+ /** Identifies the device acknowledging. */
52
89
  deviceId: string;
90
+ /** Highest sequence the device has stored, as a decimal string. */
53
91
  seq: string;
54
92
  }
93
+ /**
94
+ * Runs a read, either as SQL or by the name of a registered read.
95
+ *
96
+ * @public
97
+ */
55
98
  interface WSQueryMessage {
99
+ /** Names this message as a read. */
56
100
  type: 'query';
101
+ /** Client-chosen identifier the reply echoes. */
57
102
  id: string;
103
+ /** The statement to run. The server refuses it unless it accepts SQL. */
58
104
  sql?: string;
105
+ /** Values bound to that statement, named or positional. */
59
106
  params?: Record<string, unknown> | unknown[];
107
+ /** Name of a registered read to run instead, which carries no SQL. */
60
108
  name?: string;
109
+ /** Arguments that registered read takes. */
61
110
  args?: Record<string, unknown>;
111
+ /** Currency this read requires. */
62
112
  readConcern?: ReadConcern;
63
113
  }
114
+ /**
115
+ * Runs a write, either as SQL or by the name of a registered write.
116
+ *
117
+ * @public
118
+ */
64
119
  interface WSExecuteMessage {
120
+ /** Names this message as a write. */
65
121
  type: 'execute';
122
+ /** Client-chosen identifier the reply echoes. */
66
123
  id: string;
124
+ /** The statement to run. The server refuses it unless it accepts SQL. */
67
125
  sql?: string;
126
+ /** Values bound to that statement, named or positional. */
68
127
  params?: Record<string, unknown> | unknown[];
128
+ /** Name of a registered write to run instead, which carries no SQL. */
69
129
  name?: string;
130
+ /** Arguments that registered write takes. */
70
131
  args?: Record<string, unknown>;
132
+ /** Acknowledgements this write waits for. */
71
133
  writeConcern?: WriteConcern;
72
134
  }
73
135
  /**
74
136
  * Runs every statement in one server-side transaction and replies once with
75
137
  * all results. The client is never in the loop between statements, so the
76
138
  * single writer lock is held only for the duration of local execution.
139
+ *
140
+ * @public
77
141
  */
78
142
  interface WSTransactionMessage {
143
+ /** Names this message as a transaction. */
79
144
  type: 'transaction';
145
+ /** Client-chosen identifier the reply echoes. */
80
146
  id: string;
147
+ /** The statements to run, in order. */
81
148
  statements: TransactionStatement[];
149
+ /** Acknowledgements the transaction waits for. */
82
150
  writeConcern?: WriteConcern;
83
151
  }
152
+ /**
153
+ * Applies one statement over many parameter sets in a single server-side transaction.
154
+ *
155
+ * @public
156
+ */
84
157
  interface WSBatchMessage {
158
+ /** Names this message as a batch. */
85
159
  type: 'batch';
160
+ /** Client-chosen identifier the reply echoes. */
86
161
  id: string;
162
+ /** The statement to run for each parameter set. */
87
163
  sql: string;
164
+ /** One parameter set per run. */
88
165
  paramsBatch: (Record<string, unknown> | unknown[])[];
166
+ /** Acknowledgements the batch waits for. */
89
167
  writeConcern?: WriteConcern;
90
168
  }
169
+ /**
170
+ * Imports many rows at relaxed durability, which the server restores before it replies.
171
+ *
172
+ * @public
173
+ */
91
174
  interface WSLoadMessage {
175
+ /** Names this message as a load. */
92
176
  type: 'load';
177
+ /** Client-chosen identifier the reply echoes. */
93
178
  id: string;
179
+ /** The statement to run for each parameter set. */
94
180
  sql: string;
181
+ /** One parameter set per row. */
95
182
  paramsBatch: (Record<string, unknown> | unknown[])[];
183
+ /** Durability in force while the load runs. Default: 'off'. */
96
184
  durability?: BulkLoadDurability;
185
+ /** Whether this load ends with a checkpoint. */
97
186
  checkpoint?: boolean;
98
187
  }
188
+ /**
189
+ * Every message the server sends over the WebSocket.
190
+ *
191
+ * @public
192
+ */
99
193
  type WSServerMessage = WSSubscribedMessage | WSUnsubscribedMessage | WSChangeMessage | WSChangesMessage | WSLiveMessage | WSResultMessage | WSErrorMessage;
194
+ /**
195
+ * One edit to a live query's result set, as a position and the row at it.
196
+ *
197
+ * @public
198
+ */
100
199
  type WSLiveOp = {
101
200
  op: 'insert';
102
201
  index: number;
@@ -109,15 +208,32 @@ type WSLiveOp = {
109
208
  op: 'delete';
110
209
  index: number;
111
210
  };
211
+ /**
212
+ * Carries a live query's new state: the edits that move it, a full replacement, or notice that a re-read has started.
213
+ *
214
+ * @public
215
+ */
112
216
  interface WSLiveMessage {
217
+ /** Names this message as a live-query update. */
113
218
  type: 'live';
219
+ /** Identifier of the subscription this update belongs to. */
114
220
  id: string;
221
+ /** The edits that move the result set to its new state. */
115
222
  ops?: WSLiveOp[];
223
+ /** A complete replacement result set. */
116
224
  rows?: unknown[];
225
+ /** Set while the server re-reads the query. */
117
226
  revalidating?: boolean;
118
227
  }
228
+ /**
229
+ * Confirms a subscription opened, and states the cursor and sequence space it streams from.
230
+ *
231
+ * @public
232
+ */
119
233
  interface WSSubscribedMessage {
234
+ /** Names this message as a subscription confirmation. */
120
235
  type: 'subscribed';
236
+ /** Identifier of the subscription that opened. */
121
237
  id: string;
122
238
  /**
123
239
  * How far a device may run ahead of its acknowledged cursor before the
@@ -126,7 +242,7 @@ interface WSSubscribedMessage {
126
242
  maxUnacknowledgedChanges?: number;
127
243
  /**
128
244
  * The seq the subscription is live from. A client that has not yet seen any
129
- * change adopts this as its resume cursor, so a reconnect during an idle
245
+ * change adopts this as its resume cursor so that a reconnect during an idle
130
246
  * spell still replays what it missed instead of silently skipping it.
131
247
  */
132
248
  seq?: string;
@@ -138,58 +254,119 @@ interface WSSubscribedMessage {
138
254
  resync?: boolean;
139
255
  /**
140
256
  * Identifies the sequence space this subscription streams from. The client
141
- * stores it and echoes it when resuming, so a cursor carried to a different
257
+ * stores it and echoes it when resuming so that a cursor carried to a different
142
258
  * database forces a resync instead of a silent replay of unrelated rows.
143
259
  */
144
260
  epoch?: string;
261
+ /** First result set of a live query, sent when the subscription named a registered read. */
145
262
  rows?: unknown[];
146
263
  }
264
+ /**
265
+ * Confirms a subscription ended.
266
+ *
267
+ * @public
268
+ */
147
269
  interface WSUnsubscribedMessage {
270
+ /** Names this message as an unsubscribe confirmation. */
148
271
  type: 'unsubscribed';
272
+ /** Identifier of the subscription that ended. */
149
273
  id: string;
150
274
  }
275
+ /**
276
+ * One change event as it crosses the wire, with sequences as decimal strings
277
+ * so a value beyond the safe integer range survives JSON.
278
+ *
279
+ * @public
280
+ */
151
281
  interface WSWireChangeEvent {
282
+ /** Whether the row was inserted, updated, or deleted. */
152
283
  type: 'insert' | 'update' | 'delete';
284
+ /** Table the row belongs to. */
153
285
  table: string;
286
+ /** The row as it stands after the change. */
154
287
  row: Record<string, unknown>;
288
+ /** The row as it stood before an update or a delete. */
155
289
  oldRow?: Record<string, unknown>;
290
+ /** Position of this change in the database's change log, as a decimal string. */
156
291
  seq: string;
292
+ /** Milliseconds since the Unix epoch, taken when the change was recorded. */
157
293
  timestamp: number;
294
+ /** Hybrid logical clock stamp the writing node gave this change. */
158
295
  hlc?: string;
296
+ /** Identifier of the node that authored the change. */
159
297
  origin?: string;
298
+ /** Primary key of the changed row, encoded as a string. */
160
299
  rowId?: string;
300
+ /** Identifier of the transaction that produced this change. */
161
301
  txId?: string;
302
+ /** Set on the last change of a transaction. */
162
303
  txEnd?: boolean;
163
304
  }
305
+ /**
306
+ * Carries one change event to a subscriber.
307
+ *
308
+ * @public
309
+ */
164
310
  interface WSChangeMessage {
311
+ /** Names this message as a single change event. */
165
312
  type: 'change';
313
+ /** Identifier of the subscription this change belongs to. */
166
314
  id: string;
315
+ /** The change itself. */
167
316
  event: WSWireChangeEvent;
168
317
  }
169
318
  /**
170
319
  * Several change events in one frame, in ascending seq order. Sent only on
171
320
  * a device subscription that requested `stagedStream`; the events carry the
172
321
  * same fields as a `change` frame's event.
322
+ *
323
+ * @public
173
324
  */
174
325
  interface WSChangesMessage {
326
+ /** Names this message as a run of change events. */
175
327
  type: 'changes';
328
+ /** Identifier of the subscription these changes belong to. */
176
329
  id: string;
330
+ /** The changes, in ascending sequence order. */
177
331
  events: WSWireChangeEvent[];
178
332
  }
333
+ /**
334
+ * Replies to a read, write, transaction, batch, load, or acknowledgement.
335
+ *
336
+ * @public
337
+ */
179
338
  interface WSResultMessage {
339
+ /** Names this message as a reply to a read, write, transaction, batch, load, or acknowledgement. */
180
340
  type: 'result';
341
+ /** Identifier the request carried. */
181
342
  id: string;
343
+ /** The reply body, whose shape follows the request that produced it. */
182
344
  data: QueryResponse | ExecuteResponse | TransactionResponse | BatchResponse | LoadResponse | AckResponse;
183
345
  }
346
+ /**
347
+ * Reports that a request failed.
348
+ *
349
+ * @public
350
+ */
184
351
  interface WSErrorMessage {
352
+ /** Names this message as a failure. */
185
353
  type: 'error';
354
+ /** Identifier the request carried. */
186
355
  id: string;
356
+ /** Machine-readable code and human-readable message. */
187
357
  error: {
188
358
  code: string;
189
359
  message: string;
190
360
  };
191
361
  }
192
362
 
363
+ /**
364
+ * @public
365
+ *
366
+ * Serves a `Sirannon` database registry over HTTP and WebSocket.
367
+ *
368
+ * Build one with {@link createServer}, then call {@link SirannonServer.listen}.
369
+ */
193
370
  declare class SirannonServer<Identity = unknown> {
194
371
  private app;
195
372
  private listenSocket;
@@ -209,8 +386,19 @@ declare class SirannonServer<Identity = unknown> {
209
386
  private readonly maxBodyBytes;
210
387
  private readonly maxWsBackpressureBytes;
211
388
  constructor(sirannon: Sirannon, options?: ServerOptions<Identity>);
389
+ /**
390
+ * Binds the configured host and port and starts serving.
391
+ *
392
+ * @throws When the port is already in use.
393
+ */
212
394
  listen(): Promise<void>;
395
+ /**
396
+ * Stops serving and closes every open connection.
397
+ */
213
398
  close(): Promise<void>;
399
+ /**
400
+ * Port the server bound to, which is the resolved port when you asked for 0.
401
+ */
214
402
  get listeningPort(): number;
215
403
  private registerRoutes;
216
404
  private registerWebSocketRoute;
@@ -219,6 +407,15 @@ declare class SirannonServer<Identity = unknown> {
219
407
  private wrapOperationRoute;
220
408
  private wrapDbGetRoute;
221
409
  }
410
+ /**
411
+ * @public
412
+ *
413
+ * Builds a server over a database registry.
414
+ *
415
+ * @param sirannon - The registry whose databases the server exposes.
416
+ * @param options - Address, cross-origin rules, size limits, authentication, registered operations, and whether the server accepts SQL.
417
+ * @returns The server, ready to listen.
418
+ */
222
419
  declare function createServer<Identity = unknown>(sirannon: Sirannon, options?: ServerOptions<Identity>): SirannonServer<Identity>;
223
420
 
224
421
  /**
@@ -232,11 +429,27 @@ declare function createServer<Identity = unknown>(sirannon: Sirannon, options?:
232
429
  * the request as answered.
233
430
  */
234
431
  type WSSendOutcome = 'sent' | 'buffered' | 'dropped';
432
+ /**
433
+ * One open WebSocket, as the handler sends over it.
434
+ *
435
+ * @internal
436
+ */
235
437
  interface WSConnection {
438
+ /**
439
+ * Sends one frame and reports whether it went out, was buffered, or was dropped.
440
+ */
236
441
  send(data: string): WSSendOutcome;
442
+ /**
443
+ * Closes the connection with a code and reason.
444
+ */
237
445
  close(code?: number, reason?: string): void;
238
446
  }
239
447
 
448
+ /**
449
+ * Serves the WebSocket protocol for one server: queries, writes, change subscriptions, and live queries.
450
+ *
451
+ * @internal
452
+ */
240
453
  declare class WSHandler<Identity = unknown> {
241
454
  private readonly sirannon;
242
455
  private readonly maxPayloadLength;
@@ -272,6 +485,11 @@ declare class WSHandler<Identity = unknown> {
272
485
  private sendChange;
273
486
  private sendText;
274
487
  }
488
+ /**
489
+ * Builds the WebSocket handler a server routes its upgrades and messages through.
490
+ *
491
+ * @internal
492
+ */
275
493
  declare function createWSHandler<Identity = unknown>(sirannon: Sirannon, options?: WSHandlerOptions<Identity>): WSHandler<Identity>;
276
494
 
277
495
  export { BatchResponse, ExecuteResponse, LoadResponse, QueryResponse, SirannonServer, TransactionResponse, TransactionStatement, type WSBatchMessage, type WSChangeMessage, type WSClientMessage, type WSConnection, type WSErrorMessage, type WSExecuteMessage, WSHandler, type WSLoadMessage, type WSQueryMessage, type WSResultMessage, type WSServerMessage, type WSSubscribeMessage, type WSSubscribedMessage, type WSTransactionMessage, type WSUnsubscribeMessage, type WSUnsubscribedMessage, createServer, createWSHandler };
@@ -1,13 +1,13 @@
1
- import { dumpSchema, tablesInFkOrder, dumpTablePages } from '../chunk-OQVZBEBY.mjs';
2
- import { ChangeTracker, SubscriptionManager, ensureCdcEpoch, migrationChecksum, needsResync, filteredChange, TransactionGrouper, isBulkLoadDurability, PrimedSubscription } from '../chunk-H6PIVVDN.mjs';
3
- import { SEQ_STRING_RE, highestMigrationVersion, selectCountTableRows, selectTableExists, selectAppliedMigrations, PkResolver, ensureDeviceCursorsTable, upsertDeviceCursor, selectMaxChangeSeq, canonicaliseForChecksum, selectDeviceCursors, selectMinForeignChangeSeqSql, IDENTIFIER_RE, deleteDeviceCursorsUpdatedBefore } from '../chunk-NVQS53NT.mjs';
4
- import '../chunk-5NOIGN5Y.mjs';
5
- import { encodeTaggedValues, MIGRATIONS_TABLE, decodeTaggedValues, encodeWireRowsInPlace, CHANGES_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX } from '../chunk-D7LAYTKN.mjs';
1
+ import { dumpSchema, tablesInFkOrder, dumpTablePages } from '../chunk-XF2HH5E6.mjs';
2
+ import { ChangeTracker, SubscriptionManager, ensureCdcEpoch, migrationChecksum, needsResync, filteredChange, TransactionGrouper, isBulkLoadDurability, PrimedSubscription } from '../chunk-CCZK6LCB.mjs';
3
+ import { SEQ_STRING_RE, highestMigrationVersion, selectCountTableRows, selectTableExists, selectAppliedMigrations, PkResolver, ensureDeviceCursorsTable, upsertDeviceCursor, selectMaxChangeSeq, canonicaliseForChecksum, selectDeviceCursors, selectMinForeignChangeSeqSql, IDENTIFIER_RE, deleteDeviceCursorsUpdatedBefore } from '../chunk-7FQRQH5Z.mjs';
4
+ import '../chunk-2QLXDHAP.mjs';
5
+ import { encodeTaggedValues, MIGRATIONS_TABLE, decodeTaggedValues, encodeWireRowsInPlace, CHANGES_TABLE, DEVICE_CURSORS_TABLE, INTERNAL_TABLE_PREFIX } from '../chunk-7R4ER4FB.mjs';
6
6
  import { createOperationSource, operationRegistryDigest, findRead, isRefusal, resolveArguments, findWrite } from '../chunk-TUD5CJ76.mjs';
7
7
  import '../chunk-GVCNMPOS.mjs';
8
- import '../chunk-LFZ37BSX.mjs';
9
- import { SQLITE_USER_VERSION_MAX } from '../chunk-67M7KAH6.mjs';
10
- import { SirannonError, WriteOverloadError } from '../chunk-UC3SCMIN.mjs';
8
+ import '../chunk-OUSWVNWT.mjs';
9
+ import { SQLITE_USER_VERSION_MAX } from '../chunk-IWGIYDMZ.mjs';
10
+ import { SirannonError, WriteOverloadError } from '../chunk-PBRXXISQ.mjs';
11
11
  import uWS from 'uWebSockets.js';
12
12
  import { createHash } from 'crypto';
13
13
 
@@ -1165,6 +1165,49 @@ function handleSnapshotPage(sirannon) {
1165
1165
  };
1166
1166
  }
1167
1167
 
1168
+ // src/server/limits.ts
1169
+ var DEFAULT_MAX_BODY_BYTES = 1048576;
1170
+ var DEFAULT_WS_BACKPRESSURE_BYTES = 16 * 1048576;
1171
+ var UWS_MAX_LIMIT_BYTES = 4294967295;
1172
+ function resolveMaxBodyBytes(value) {
1173
+ if (value === void 0) return DEFAULT_MAX_BODY_BYTES;
1174
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
1175
+ throw new SirannonError(
1176
+ "ServerOptions.maxBodyBytes must be a positive integer number of bytes",
1177
+ "INVALID_MAX_BODY_BYTES"
1178
+ );
1179
+ }
1180
+ if (value > UWS_MAX_LIMIT_BYTES) {
1181
+ throw new SirannonError(
1182
+ `ServerOptions.maxBodyBytes must be at most ${UWS_MAX_LIMIT_BYTES} bytes; uWebSockets.js stores the limit as an unsigned 32-bit integer and would silently wrap a larger value modulo 2^32`,
1183
+ "INVALID_MAX_BODY_BYTES"
1184
+ );
1185
+ }
1186
+ return value;
1187
+ }
1188
+ function resolveWsBackpressure(value, maxBodyBytes) {
1189
+ const resolved = value ?? Math.max(DEFAULT_WS_BACKPRESSURE_BYTES, maxBodyBytes);
1190
+ if (typeof resolved !== "number" || !Number.isInteger(resolved) || resolved <= 0) {
1191
+ throw new SirannonError(
1192
+ "ServerOptions.maxWebSocketBackpressureBytes must be a positive integer number of bytes",
1193
+ "INVALID_WS_BACKPRESSURE"
1194
+ );
1195
+ }
1196
+ if (resolved > UWS_MAX_LIMIT_BYTES) {
1197
+ throw new SirannonError(
1198
+ `ServerOptions.maxWebSocketBackpressureBytes must be at most ${UWS_MAX_LIMIT_BYTES} bytes; uWebSockets.js stores the limit as an unsigned 32-bit integer and would silently wrap a larger value modulo 2^32`,
1199
+ "INVALID_WS_BACKPRESSURE"
1200
+ );
1201
+ }
1202
+ if (resolved < maxBodyBytes) {
1203
+ throw new SirannonError(
1204
+ "ServerOptions.maxWebSocketBackpressureBytes must be at least maxBodyBytes so a single frame fits",
1205
+ "INVALID_WS_BACKPRESSURE"
1206
+ );
1207
+ }
1208
+ return resolved;
1209
+ }
1210
+
1168
1211
  // src/core/ws-handshake.ts
1169
1212
  var SIRANNON_WS_SUBPROTOCOL = "sirannon.v1";
1170
1213
  var WS_CLOSE_UNAUTHENTICATED = 4401;
@@ -1736,7 +1779,7 @@ var DeviceChangeStream = class {
1736
1779
  }
1737
1780
  }
1738
1781
  /**
1739
- * Rejoins the live feed. Runs synchronously right after a log read, so no
1782
+ * Rejoins the live feed. Runs synchronously right after a log read so that no
1740
1783
  * poller tick can dispatch between the caught-up check and the mode flip.
1741
1784
  * The grouper survives the transition: the event it holds is released by
1742
1785
  * the boundary flush when the poller stopped at a transaction boundary,
@@ -2811,47 +2854,6 @@ var SQL_ROUTES = ["/db/:id/query", "/db/:id/execute", "/db/:id/transaction", "/d
2811
2854
  function refuseSql(res) {
2812
2855
  sendError(res, 403, "SQL_NOT_ACCEPTED", SQL_NOT_ACCEPTED_MESSAGE);
2813
2856
  }
2814
- var DEFAULT_MAX_BODY_BYTES = 1048576;
2815
- var DEFAULT_WS_BACKPRESSURE_BYTES = 16 * 1048576;
2816
- var UWS_MAX_LIMIT_BYTES = 4294967295;
2817
- function resolveMaxBodyBytes(value) {
2818
- if (value === void 0) return DEFAULT_MAX_BODY_BYTES;
2819
- if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
2820
- throw new SirannonError(
2821
- "ServerOptions.maxBodyBytes must be a positive integer number of bytes",
2822
- "INVALID_MAX_BODY_BYTES"
2823
- );
2824
- }
2825
- if (value > UWS_MAX_LIMIT_BYTES) {
2826
- throw new SirannonError(
2827
- `ServerOptions.maxBodyBytes must be at most ${UWS_MAX_LIMIT_BYTES} bytes; uWebSockets.js stores the limit as an unsigned 32-bit integer and would silently wrap a larger value modulo 2^32`,
2828
- "INVALID_MAX_BODY_BYTES"
2829
- );
2830
- }
2831
- return value;
2832
- }
2833
- function resolveWsBackpressure(value, maxBodyBytes) {
2834
- const resolved = value ?? Math.max(DEFAULT_WS_BACKPRESSURE_BYTES, maxBodyBytes);
2835
- if (typeof resolved !== "number" || !Number.isInteger(resolved) || resolved <= 0) {
2836
- throw new SirannonError(
2837
- "ServerOptions.maxWebSocketBackpressureBytes must be a positive integer number of bytes",
2838
- "INVALID_WS_BACKPRESSURE"
2839
- );
2840
- }
2841
- if (resolved > UWS_MAX_LIMIT_BYTES) {
2842
- throw new SirannonError(
2843
- `ServerOptions.maxWebSocketBackpressureBytes must be at most ${UWS_MAX_LIMIT_BYTES} bytes; uWebSockets.js stores the limit as an unsigned 32-bit integer and would silently wrap a larger value modulo 2^32`,
2844
- "INVALID_WS_BACKPRESSURE"
2845
- );
2846
- }
2847
- if (resolved < maxBodyBytes) {
2848
- throw new SirannonError(
2849
- "ServerOptions.maxWebSocketBackpressureBytes must be at least maxBodyBytes so a single frame fits",
2850
- "INVALID_WS_BACKPRESSURE"
2851
- );
2852
- }
2853
- return resolved;
2854
- }
2855
2857
  var SirannonServer = class {
2856
2858
  app;
2857
2859
  listenSocket = null;
@@ -2897,6 +2899,11 @@ var SirannonServer = class {
2897
2899
  this.app = uWS.App();
2898
2900
  this.registerRoutes();
2899
2901
  }
2902
+ /**
2903
+ * Binds the configured host and port and starts serving.
2904
+ *
2905
+ * @throws When the port is already in use.
2906
+ */
2900
2907
  listen() {
2901
2908
  return new Promise((resolve, reject) => {
2902
2909
  this.app.listen(this.host, this.port, (socket) => {
@@ -2909,6 +2916,9 @@ var SirannonServer = class {
2909
2916
  });
2910
2917
  });
2911
2918
  }
2919
+ /**
2920
+ * Stops serving and closes every open connection.
2921
+ */
2912
2922
  async close() {
2913
2923
  try {
2914
2924
  await this.wsHandler.close();
@@ -2919,6 +2929,9 @@ var SirannonServer = class {
2919
2929
  }
2920
2930
  }
2921
2931
  }
2932
+ /**
2933
+ * Port the server bound to, which is the resolved port when you asked for 0.
2934
+ */
2922
2935
  get listeningPort() {
2923
2936
  if (!this.listenSocket) return -1;
2924
2937
  return uWS.us_socket_local_port(this.listenSocket);