@delali/sirannon-db 0.2.3-next.35 → 0.2.3-next.37

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 (37) hide show
  1. package/README.md +4 -2
  2. package/dist/backup/index.d.ts +128 -8
  3. package/dist/backup/index.mjs +561 -29
  4. package/dist/backup-scheduler/index.d.ts +1 -1
  5. package/dist/backup-scheduler/index.mjs +2 -1
  6. package/dist/{chain-queries-BFRYrmNE.d.ts → chain-queries-D5aZ-8v2.d.ts} +1 -1
  7. package/dist/{change-tracker-DNisL4aw.d.ts → change-tracker-DXHPFe9J.d.ts} +1 -1
  8. package/dist/chunk-72I5UI5C.mjs +96 -0
  9. package/dist/{chunk-7HVBKOII.mjs → chunk-BQTVNI5H.mjs} +67 -51
  10. package/dist/chunk-GBM4AU24.mjs +42 -0
  11. package/dist/{chunk-4H45GMYI.mjs → chunk-YVF2ZJTE.mjs} +52 -21
  12. package/dist/{chunk-JFZXO5S2.mjs → chunk-ZKDBGX7H.mjs} +327 -163
  13. package/dist/client/index.d.ts +8 -8
  14. package/dist/client/topology.d.ts +4 -4
  15. package/dist/{client-base-0QBh8JC4.d.ts → client-base-CGBpjZUB.d.ts} +2 -2
  16. package/dist/core/index.d.ts +9 -9
  17. package/dist/core/index.mjs +5 -3
  18. package/dist/{database-CKZP6SiT.d.ts → database-955qag_W.d.ts} +8 -6
  19. package/dist/driver/better-sqlite3.d.ts +1 -1
  20. package/dist/driver/better-sqlite3.mjs +5 -3
  21. package/dist/driver/bun.d.ts +1 -1
  22. package/dist/driver/expo.d.ts +1 -1
  23. package/dist/driver/node.d.ts +1 -1
  24. package/dist/driver/node.mjs +5 -3
  25. package/dist/driver/wa-sqlite.d.ts +1 -1
  26. package/dist/file-migrations/index.d.ts +1 -1
  27. package/dist/{protocol-2vVZ4ijz.d.ts → protocol-BfiujBsE.d.ts} +1 -1
  28. package/dist/replication/index.d.ts +45 -10
  29. package/dist/replication/index.mjs +23 -2
  30. package/dist/server/index.d.ts +8 -8
  31. package/dist/{server-options-DxHqvZw6.d.ts → server-options-D4VmfTHw.d.ts} +1 -1
  32. package/dist/{sirannon-Clqx8Xyu.d.ts → sirannon-DaGUawHs.d.ts} +2 -2
  33. package/dist/transport/grpc.d.ts +3 -3
  34. package/dist/transport/memory.d.ts +3 -3
  35. package/dist/{types-DAemUqLQ.d.ts → types-BEjS69rs.d.ts} +2 -2
  36. package/dist/{types-GuxbxlwL.d.ts → types-Xb0L3o3w.d.ts} +157 -9
  37. package/package.json +7 -7
package/README.md CHANGED
@@ -66,6 +66,7 @@ React Native uses the same shape through `expoSqlite()` with `readPoolSize: 1`.
66
66
  | `@delali/sirannon-db` | Core library: queries, transactions, CDC, live queries, migrations, backups, hooks, metrics, lifecycle |
67
67
  | `@delali/sirannon-db/driver/*` | SQLite driver adapters (see the table above) |
68
68
  | `@delali/sirannon-db/file-migrations` | Load `.up.sql` and `.down.sql` files from a directory |
69
+ | `@delali/sirannon-db/backup` | Backup destination types, chain records, and `restoreBackup` |
69
70
  | `@delali/sirannon-db/backup-scheduler` | Cron-scheduled backup runner with file rotation |
70
71
  | `@delali/sirannon-db/server` | HTTP and WebSocket server powered by uWebSockets.js |
71
72
  | `@delali/sirannon-db/client` | Client SDK with auto-reconnect, subscription restore, and device sync |
@@ -93,7 +94,7 @@ const balance = await db.transaction(async tx => {
93
94
  })
94
95
  ```
95
96
 
96
- A large import runs faster through `bulkLoad`, which trades durability for speed inside one transaction and restores the configured level afterwards. The [core engine guide](../../docs/core.md) covers it, along with migrations, backups, hooks, metrics, and the multi-tenant lifecycle.
97
+ A large import runs faster through `bulkLoad`, which trades durability for speed inside one transaction and restores the configured level afterwards. The [core engine guide](../../docs/core.md) covers it, along with migrations, hooks, metrics, and the multi-tenant lifecycle. Backups have a [guide of their own](../../docs/backups.md).
97
98
 
98
99
  ## Change data capture and live queries
99
100
 
@@ -225,7 +226,8 @@ The [security guide](https://sirannon.sondelali.com/docs) covers each of these i
225
226
 
226
227
  | Guide | What it covers |
227
228
  | --- | --- |
228
- | [Core engine](../../docs/core.md) | Bulk load, live queries, migrations, backups, hooks, metrics, and the multi-tenant lifecycle |
229
+ | [Core engine](../../docs/core.md) | Bulk load, live queries, migrations, hooks, metrics, and the multi-tenant lifecycle |
230
+ | [Backups](../../docs/backups.md) | Copies to a file or to storage you supply, the chain of changes after one, and restoring from a moment you name |
229
231
  | [Server](../../docs/server.md) | HTTP routes, WebSocket messages, authentication, write shapes, the writer worker, and value encoding |
230
232
  | [Registered operations](../../docs/operations.md) | Naming the statements a server runs, identity-filled arguments, capabilities, and code generation |
231
233
  | [Live queries](../../docs/live-queries.md) | Maintained query results locally, over the network, and in React |
@@ -1,6 +1,6 @@
1
- import { e as BackupDestination, f as BackupRunReport } from '../types-GuxbxlwL.js';
2
- export { g as BackupChain, h as BackupChainBase, i as BackupChainChange, j as BackupChainPosition, k as BackupChainRecord, l as BackupCycle, m as BackupCycleOptions, n as BackupPiece, o as BackupProgress, p as BackupToDestinationOptions, q as DEFAULT_CHAIN_NAME, r as chainLogName, s as readBackupChains } from '../types-GuxbxlwL.js';
3
- export { B as BackupCapabilities, a as BackupRestorePlan, b as BackupSafeToDeleteOptions, c as backupPiecesSafeToDelete, p as planBackupRestore } from '../chain-queries-BFRYrmNE.js';
1
+ import { j as BackupDestination, k as BackupRunReport, a as SQLiteDriver } from '../types-Xb0L3o3w.js';
2
+ export { g as BackupChain, e as BackupChainBase, f as BackupChainChange, l as BackupChainPosition, h as BackupChainRecord, m as BackupCycle, n as BackupCycleOptions, o as BackupGroupMembership, p as BackupGroupSource, q as BackupNodePreference, r as BackupPiece, s as BackupProgress, t as BackupSkip, u as BackupSkipReason, v as BackupToDestinationOptions, w as DEFAULT_CHAIN_NAME, x as chainLogName, y as readBackupChains } from '../types-Xb0L3o3w.js';
3
+ export { B as BackupCapabilities, a as BackupRestorePlan, b as BackupSafeToDeleteOptions, c as backupPiecesSafeToDelete, p as planBackupRestore } from '../chain-queries-D5aZ-8v2.js';
4
4
  import '../query-types-Cv8N7pXj.js';
5
5
 
6
6
  /** What one assembled file took to build.
@@ -15,12 +15,11 @@ interface AssembleResult {
15
15
  fingerprint?: string;
16
16
  }
17
17
  /**
18
- * Builds a local file from the pieces a destination holds, fetching one piece
19
- * at a time and writing it where its index places it, so a piece SQLite never
20
- * wrote leaves zeros rather than moving every later byte.
18
+ * Builds a local file from the pieces a destination holds, checking the result
19
+ * against what the run that wrote them reported.
21
20
  *
22
21
  * @param destination - Where the pieces are read from.
23
- * @param report - What the run that wrote those pieces recorded, which the assembly checks its result against.
22
+ * @param report - What the run that wrote those pieces recorded.
24
23
  * @param destPath - Path the assembled file is written to.
25
24
  * @returns The bytes and pieces the assembly wrote, and the fingerprint it computed.
26
25
  *
@@ -28,4 +27,125 @@ interface AssembleResult {
28
27
  */
29
28
  declare function assembleFromDestination(destination: BackupDestination, report: BackupRunReport, destPath: string): Promise<AssembleResult>;
30
29
 
31
- export { type AssembleResult, BackupDestination, BackupRunReport, assembleFromDestination };
30
+ /** How far one restore has got, reported after every piece it fetches.
31
+ * @public
32
+ */
33
+ interface BackupRestoreProgress {
34
+ /** Whether the restore is fetching the full copy or replaying the change pieces on top of it. */
35
+ phase: 'full-copy' | 'changes';
36
+ /** Pieces the restore has fetched. */
37
+ piecesFetched: number;
38
+ /** Bytes it has fetched. */
39
+ bytesFetched: number;
40
+ /** Change pieces it has replayed. */
41
+ changesApplied: number;
42
+ /** Change pieces the plan holds altogether. */
43
+ changesTotal: number;
44
+ }
45
+ /**
46
+ * How Sirannon rebuilds a database from a moment you name.
47
+ *
48
+ * @public
49
+ */
50
+ interface BackupRestoreOptions {
51
+ /** Where the backups and their records are stored. */
52
+ destination: BackupDestination;
53
+ /** Driver the restore opens the rebuilt database through, so it can fold each batch of changes in. */
54
+ driver: SQLiteDriver;
55
+ /** Path Sirannon writes the rebuilt database to. A file already there stops the restore unless you set {@link BackupRestoreOptions.replaceExisting}. */
56
+ destPath: string;
57
+ /**
58
+ * Whether to replace a database already at that path. It defaults to false,
59
+ * because a restore removes the write-ahead log beside the path it writes to
60
+ * and any commit that log still held would go with it. Set this where you
61
+ * mean to restore over a database you no longer want.
62
+ */
63
+ replaceExisting?: boolean;
64
+ /** Epoch milliseconds you want back. Defaults to now, which reaches the newest backup the destination holds. */
65
+ moment?: number;
66
+ /** Name the list of chains is stored under. Defaults to `sirannon-backup-chain`. */
67
+ chainName?: string;
68
+ /**
69
+ * How many change pieces to replay between one checkpoint and the next.
70
+ * Defaults to 16. This is what bounds the log the restore writes beside the
71
+ * database, so lower it where disk is tight and raise it where a long chain
72
+ * takes too many checkpoints.
73
+ */
74
+ batchSize?: number;
75
+ /** Milliseconds one call to the destination may take before the restore stops with an error. Defaults to 10 minutes, and zero leaves the calls unbounded. */
76
+ destinationTimeoutMs?: number;
77
+ /** Called after every piece the restore fetches. */
78
+ onProgress?: (progress: BackupRestoreProgress) => void;
79
+ }
80
+ /** What one finished restore produced.
81
+ * @public
82
+ */
83
+ interface BackupRestoreReport {
84
+ /** The chain the restore read. */
85
+ chainId: string;
86
+ /** Path of the rebuilt database. */
87
+ destPath: string;
88
+ /** Name the full copy underneath it is stored under. */
89
+ baseName: string;
90
+ /** Epoch milliseconds the rebuilt database reflects, which is when the last piece replayed was captured. */
91
+ restoresTo: number;
92
+ /** Pieces the restore fetched, counting the full copy and every change piece. */
93
+ pieceCount: number;
94
+ /** Bytes it fetched. */
95
+ bytesFetched: number;
96
+ /** Change pieces it replayed. */
97
+ changesApplied: number;
98
+ /** Log frames those pieces held. */
99
+ framesApplied: number;
100
+ /** Batches it replayed them in, each one folded into the database by a checkpoint of its own. */
101
+ batchCount: number;
102
+ /** Epoch milliseconds the restore started. */
103
+ startedAt: number;
104
+ /** Epoch milliseconds it finished. */
105
+ finishedAt: number;
106
+ /** Milliseconds it took. */
107
+ durationMs: number;
108
+ }
109
+
110
+ /**
111
+ * Rebuilds a database from the moment you name and leaves it at a path of your
112
+ * choosing.
113
+ *
114
+ * Sirannon reads the chain records at your destination and takes the newest
115
+ * full copy finished at or before that moment. It then replays every change
116
+ * piece captured from that copy up to the same moment, fetching one stored
117
+ * piece and applying it before it asks for the next. One stored piece is
118
+ * therefore all a restore holds, however large the database it rebuilds.
119
+ *
120
+ * Two kinds of gap fail the call. A chain missing a change piece fails with
121
+ * `BACKUP_CHAIN_BROKEN` naming the piece its sequence stops at, and a
122
+ * destination missing one of the numbered pieces a file was stored in fails
123
+ * with `BACKUP_DESTINATION_ERROR` naming that piece. Sirannon also checks each
124
+ * file against the byte count and the fingerprint its backup recorded, both of
125
+ * which cover the whole file.
126
+ *
127
+ * Sirannon assembles the rebuilt database beside the path you named and renames
128
+ * it onto that path once the last batch is folded in. A restore that fails, or
129
+ * one the machine kills part-way, therefore leaves that path holding whatever
130
+ * it held before. Where a database already sits at that path, Sirannon folds its
131
+ * write-ahead log back into it before the rename, so a machine that stops the
132
+ * restore between those two steps leaves that database whole. Where the fold
133
+ * cannot empty that log, because another connection holds the database or
134
+ * SQLite cannot open the file at all, Sirannon removes that database together
135
+ * with its log, so a machine stopping there leaves the path plainly empty
136
+ * rather than quietly short of its last commits. A database already there stops
137
+ * the call unless you set `replaceExisting`, because the rename leaves the
138
+ * rebuilt database at that path and nothing of the one it replaced.
139
+ *
140
+ * The disk this needs is the finished database, plus one stored piece, plus the
141
+ * log Sirannon writes for one batch of change pieces. `batchSize` sets that
142
+ * last part.
143
+ *
144
+ * @param options - Where to read from, what moment to reach, and where to put the result.
145
+ * @returns The chain it read, the moment the result reflects, and what the restore fetched and replayed.
146
+ *
147
+ * @public
148
+ */
149
+ declare function restoreBackup(options: BackupRestoreOptions): Promise<BackupRestoreReport>;
150
+
151
+ export { type AssembleResult, BackupDestination, type BackupRestoreOptions, type BackupRestoreProgress, type BackupRestoreReport, BackupRunReport, assembleFromDestination, restoreBackup };