@evolu/sqlite-wasm 2.2.4 → 3.53.4-build1

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 (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +55 -218
  3. package/dist/src/CApi.d.ts +2108 -0
  4. package/dist/src/CApi.d.ts.map +1 -0
  5. package/dist/src/CApi.js +1919 -0
  6. package/dist/src/Constants.d.ts +868 -0
  7. package/dist/src/Constants.d.ts.map +1 -0
  8. package/dist/src/Constants.js +602 -0
  9. package/dist/src/Database.d.ts +641 -0
  10. package/dist/src/Database.d.ts.map +1 -0
  11. package/dist/src/Database.js +1177 -0
  12. package/dist/src/Memory.d.ts +119 -0
  13. package/dist/src/Memory.d.ts.map +1 -0
  14. package/dist/src/Memory.js +207 -0
  15. package/dist/src/Pointer.d.ts +100 -0
  16. package/dist/src/Pointer.d.ts.map +1 -0
  17. package/dist/src/Pointer.js +15 -0
  18. package/dist/src/SahPool.d.ts +744 -0
  19. package/dist/src/SahPool.d.ts.map +1 -0
  20. package/dist/src/SahPool.js +1985 -0
  21. package/dist/src/Wasm.d.ts +315 -0
  22. package/dist/src/Wasm.d.ts.map +1 -0
  23. package/dist/src/Wasm.js +756 -0
  24. package/dist/src/WasmUrl.d.ts +21 -0
  25. package/dist/src/WasmUrl.d.ts.map +1 -0
  26. package/dist/src/WasmUrl.js +20 -0
  27. package/dist/src/c-api/index.d.ts +9 -0
  28. package/dist/src/c-api/index.d.ts.map +1 -0
  29. package/dist/src/c-api/index.js +8 -0
  30. package/dist/src/index.d.ts +15 -0
  31. package/dist/src/index.d.ts.map +1 -0
  32. package/dist/src/index.js +13 -0
  33. package/dist/wasm/sqlite3.wasm +0 -0
  34. package/package.json +60 -60
  35. package/src/CApi.test.ts +217 -0
  36. package/src/CApi.ts +3294 -0
  37. package/src/Constants.ts +803 -0
  38. package/src/Database.ts +1714 -0
  39. package/src/Memory.test.ts +319 -0
  40. package/src/Memory.ts +237 -0
  41. package/src/Pointer.ts +121 -0
  42. package/src/SahPool.test.ts +180 -0
  43. package/src/SahPool.ts +2627 -0
  44. package/src/Wasm.test.ts +444 -0
  45. package/src/Wasm.ts +1026 -0
  46. package/src/WasmUrl.ts +26 -0
  47. package/src/c-api/index.ts +9 -0
  48. package/src/index.ts +15 -0
  49. package/bin/index.js +0 -110
  50. package/index.d.ts +0 -8118
  51. package/index.mjs +0 -7
  52. package/node.mjs +0 -3
  53. package/sqlite-wasm/jswasm/sqlite3-bundler-friendly.mjs +0 -13659
  54. package/sqlite-wasm/jswasm/sqlite3-node.mjs +0 -11671
  55. package/sqlite-wasm/jswasm/sqlite3-opfs-async-proxy.js +0 -691
  56. package/sqlite-wasm/jswasm/sqlite3-worker1-bundler-friendly.mjs +0 -35
  57. package/sqlite-wasm/jswasm/sqlite3-worker1-promiser.js +0 -193
  58. package/sqlite-wasm/jswasm/sqlite3-worker1-promiser.mjs +0 -187
  59. package/sqlite-wasm/jswasm/sqlite3-worker1.js +0 -46
  60. package/sqlite-wasm/jswasm/sqlite3.js +0 -13697
  61. package/sqlite-wasm/jswasm/sqlite3.mjs +0 -13661
  62. package/sqlite-wasm/jswasm/sqlite3.wasm +0 -0
@@ -0,0 +1,641 @@
1
+ /**
2
+ * Evolu's SQLite API: databases and statements over the CApi functions, with
3
+ * typed errors and explicit resource management.
4
+ *
5
+ * Status: {@link createSqliteDatabase} opens Memory databases, and File and
6
+ * EncryptedFile databases on a {@link SqliteVfs} or {@link SqliteEncryptingVfs},
7
+ * which a {@link SahPool} is, and {@link createEncryptedSqliteDatabase} also
8
+ * opens the encrypted databases `@evolu/web` 3 created with
9
+ * `@evolu/sqlite-wasm` 2.2.4 in a pool. The pool's own encryption is tested in
10
+ * Node.js over a fake OPFS against 2.2.4, which creates databases as
11
+ * `@evolu/web` does and leaves a hot journal the pool rolls back, and in
12
+ * Chromium, Firefox and WebKit on real OPFS against 2.2.4.
13
+ *
14
+ * ## Calls
15
+ *
16
+ * - Synchronous. Every call returns when SQLite returns. The only asynchronous
17
+ * step, deriving a legacy key with WebCrypto, runs between the two opens of
18
+ * {@link createEncryptedSqliteDatabase}.
19
+ * - Bound once per database. {@link createSqliteDatabase} binds the C functions
20
+ * and memory helpers it needs and allocates one {@link SqliteScratch}; running
21
+ * a statement then calls wasm exports directly.
22
+ * - Every fallible call returns a Result. {@link SqliteError} copies
23
+ * `sqlite3_errmsg` and `sqlite3_extended_errcode` right after the failing
24
+ * call, before any other call on the connection replaces them. It copies
25
+ * `sqlite3_error_offset` only for SQLITE_ERROR from prepare, exec or step,
26
+ * the code of the parser errors that set it, because SQLite keeps an offset
27
+ * until a later prepare succeeds or a statement resets.
28
+ * - The VFS records the first failure since the last top-level call (open,
29
+ * prepare, run, exec, export), and {@link SqliteError.cause} carries it. The
30
+ * database clears the record before each such call. A call that runs inside
31
+ * another call of a database on the same VFS, as a query a callback runs
32
+ * does, is not top-level, so it leaves the record to the outer call.
33
+ * - Every call, disposal included, enters wasm through {@link SqliteWasm.call}. An
34
+ * exception or trap that escapes wasm, such as from a call through a disposed
35
+ * function pointer, is a defect: it is rethrown, and every later call on any
36
+ * database of the instance throws without entering wasm, because the C stack
37
+ * and SQLite's state are left inconsistent. A trap after a File or
38
+ * EncryptedFile connection opened reaches the caller of the open as a
39
+ * `SuppressedError` whose `suppressed` is the trap, because the open's
40
+ * deferred close and the free of its scratch memory are refused as it
41
+ * unwinds.
42
+ *
43
+ * ## Opening
44
+ *
45
+ * - A Memory database opens `:memory:` on the default VFS.
46
+ * - A File or EncryptedFile database's path is a {@link SqliteVfsPath}, a
47
+ * canonical path, which SQLite passes to the VFS as it is, never as a URI or
48
+ * an in-memory database, followed by the name of the VFS.
49
+ * - A File or EncryptedFile database opens its path on its VFS, an EncryptedFile
50
+ * database keyed as the next section describes. Either then prepares a query
51
+ * of `sqlite_schema`, because SQLite reads a file only when a statement needs
52
+ * it. So the open rolls back a hot journal, and fails for a file that is not
53
+ * a database, with SQLITE_NOTADB, or for a hot journal that cannot be rolled
54
+ * back.
55
+ * - The database uses its VFS only through {@link SqliteVfs} or
56
+ * {@link SqliteEncryptingVfs}, so any VFS that implements them can hold it,
57
+ * and a driver can open each database on the VFS that has it, as
58
+ * {@link SqliteVfs.getPaths} tells.
59
+ * - Flags are READWRITE, CREATE and EXRESCODE, so failures during the open
60
+ * already carry extended codes.
61
+ * - When the open fails, the message is read first and then the handle SQLite
62
+ * returned anyway is closed with `sqlite3_close_v2`. Without a handle, as
63
+ * when memory runs out, the error is the open's result code.
64
+ *
65
+ * ## Encryption
66
+ *
67
+ * - The VFS encrypts an EncryptedFile database itself, and a {@link SahPool} does
68
+ * it as SQLite3 Multiple Ciphers' `sqlcipher` scheme did with its default
69
+ * parameters, those of SQLCipher 4, which `PRAGMA cipher = 'sqlcipher'`
70
+ * selected in `@evolu/web` 3 with 2.2.4. The open registers the key for the
71
+ * path with {@link SqliteEncryptingVfs.registerKey} before it enters wasm and
72
+ * disposes the registration when it returns, by when the VFS has taken the
73
+ * key for the database file; the module documentation of `SahPool.ts`
74
+ * describes the pool's format. The key never appears in SQL, a URI, an error
75
+ * or SQLite's memory, and the caller's key is never modified.
76
+ * - Then `sqlite3_file_control` with SQLITE_FCNTL_RESERVE_BYTES asks for 80 bytes
77
+ * at the end of each page, where the pool keeps the page's IV and HMAC, which
78
+ * takes effect for a new database, and `PRAGMA secure_delete = ON` makes
79
+ * deletes overwrite freed content, as SQLite3 Multiple Ciphers did for every
80
+ * encrypted connection. A {@link SahPool} refuses to turn it off for an
81
+ * encrypted database, because a freed page SQLite does not write would fail
82
+ * to authenticate, as `SahPool.ts` describes.
83
+ * - Registering validates nothing, so the read of `sqlite_schema` checks the key.
84
+ * A wrong key fails there with SQLITE_NOTADB, from page 1, or with
85
+ * SQLITE_CORRUPT when the first page of a hot journal is another page, and
86
+ * {@link SqliteError.cause} is the VFS's {@link SqlitePageAuthenticationError}.
87
+ * The rollback stops at that first page, which fails to authenticate, so it
88
+ * writes no page of the journal and keeps the journal for the right key.
89
+ * Before that page, SQLite truncates the database to the size the journal
90
+ * records, as the right key's rollback does too. It would extend a shorter
91
+ * database by one zeroed page, encrypted with the wrong key, but a commit
92
+ * shrinks the file only after it deletes the journal, and a pool refuses a
93
+ * VACUUM that would change an encrypted database's page size, so no database
94
+ * is shorter than its hot journal records.
95
+ * - `@evolu/web` with 2.2.4 ran `PRAGMA key = "x'<hex>'"`, SQLCipher's notation
96
+ * for a raw key, which SQLite3 Multiple Ciphers 2.2.4 took as a passphrase
97
+ * because of a bug
98
+ * (https://github.com/utelle/SQLite3MultipleCiphers/issues/218, fixed in
99
+ * 2.2.5), deriving the key with the `sqlcipher` scheme, so those databases
100
+ * fail as with a wrong key. {@link createEncryptedSqliteDatabase} then opens
101
+ * them with the key {@link deriveLegacySqliteKey} derives through
102
+ * {@link SubtleCryptoDep}, and {@link SqliteEncryptedDatabase.keyDerivation}
103
+ * says which key opened the database. Nothing rekeys a database.
104
+ * - `@evolu/web` 1.0.1-preview.6 to 2.4.0 also ran `PRAGMA legacy = 4`, so the
105
+ * databases it encrypted fail with SQLITE_NOTADB, as with a wrong key, since
106
+ * page 1 is encrypted from byte 16; they have not opened since `@evolu/web`
107
+ * 3.0.0 (see `SahPool.ts`).
108
+ * - Only page 1 of the database or a record of its journal that failed to
109
+ * authenticate counts as a wrong key. Another page of the database that fails
110
+ * means that page 1 proved the key and the page is damaged, so it fails with
111
+ * SQLITE_CORRUPT and that page as the cause, also with the key 2.2.4 derived.
112
+ * An I/O error fails with its own code, and the VFS's record as its cause,
113
+ * and a database whose pages authenticate but whose content is malformed
114
+ * fails with SQLite's code and no cause.
115
+ *
116
+ * ## Statements
117
+ *
118
+ * - SQL is copied into its own memory, which is freed when the call returns,
119
+ * because SQLite parses it in place and copies a statement's SQL, which a
120
+ * schema change prepares again, only after the parse. Meanwhile a callback,
121
+ * such as a collation-needed callback during the parse or a function during a
122
+ * step of {@link SqliteDatabase.exec}, can run a query on the same database,
123
+ * and that query reuses the scratch memory.
124
+ * - `sqlite3_prepare_v3` gets the SQL's byte length, counting a NUL terminator,
125
+ * which spares SQLite a copy, and, for statements
126
+ * {@link SqliteDatabase.prepare} returns, SQLITE_PREPARE_PERSISTENT. Empty SQL
127
+ * and SQL with more than one statement are errors, so nothing after the first
128
+ * statement is silently ignored. SQLite reads SQL only up to a NUL character,
129
+ * and UTF-8 cannot encode a lone surrogate, which encoding would replace with
130
+ * U+FFFD, so SQL that contains either fails with
131
+ * {@link SqliteInvalidSqlTextError} before SQLite sees it, in
132
+ * {@link SqliteDatabase.exec} too.
133
+ * - A second statement is found by scanning the rest of the SQL as SQLite
134
+ * 3.53.4's tokenizer reads it, not by preparing it, because SQLite applies
135
+ * many pragmas, such as `foreign_keys`, when it prepares them, so SQL that
136
+ * fails with {@link SqliteMultipleStatementsError} would still change the
137
+ * connection. Only semicolons, whitespace, UTF-8 byte order marks and
138
+ * comments may follow the first statement. A pragma in the first statement
139
+ * still takes effect when the SQL then fails, as SQLite documents for prepare
140
+ * (https://sqlite.org/pragma.html).
141
+ * - {@link SqliteDatabase.exec} prepares each statement where the previous one
142
+ * ended and steps it to completion, so {@link SqliteError.sqlOffset} counts
143
+ * from the start of the whole SQL.
144
+ * - Parameters are positional. Their number is read once at prepare and a run
145
+ * with a different number fails, so no binding leaks from a previous run.
146
+ * {@link SqliteDatabase.exec} binds none, so a statement with a parameter
147
+ * fails there without running, rather than run with NULL.
148
+ * - Binding: null binds NULL; a 32-bit integer binds with `sqlite3_bind_int`;
149
+ * another safe integer with `sqlite3_bind_int64`, so it stays INTEGER; any
150
+ * other number with `sqlite3_bind_double`. Text is encoded with `encodeInto`
151
+ * and bytes are copied into the scratch memory, both bound with
152
+ * SQLITE_TRANSIENT and an explicit byte length, so embedded NUL characters
153
+ * survive and an empty value stays non-NULL. A value that can take more than
154
+ * 64 KiB, counting 3 bytes per UTF-16 code unit of text, is allocated exactly
155
+ * and handed over with SQLITE_WASM_DEALLOC instead, so the scratch memory
156
+ * does not keep the size of the largest value, and SQLite does not copy it
157
+ * twice. Such text is encoded into a new array first, and when JavaScript
158
+ * cannot allocate it, the run fails with SQLITE_NOMEM and the operation
159
+ * `bind`, while the instance keeps working, because the encoding runs no
160
+ * wasm. {@link SqliteDatabase.exec} copies its SQL the same way and fails with
161
+ * the operation `exec`. SQLite keeps a bound value until its parameter is
162
+ * bound again, so a run that handed a value over clears the bindings before
163
+ * it returns, also when it fails, and a prepared statement keeps no large
164
+ * value between runs, while smaller ones keep the buffers SQLite reuses for
165
+ * them. A {@link SqliteValue} string may contain a lone surrogate, which UTF-8
166
+ * cannot encode, so text binds it as U+FFFD, as better-sqlite3 does.
167
+ * - Reading: `sqlite3_column_type` first. INTEGER and FLOAT read with
168
+ * `sqlite3_column_double`, so no BigInt is created; integers beyond 2^53 lose
169
+ * precision, as in better-sqlite3. TEXT reads the pointer, then the byte
170
+ * length, and decodes keeping a leading byte order mark. A BLOB is one copy
171
+ * into its own `ArrayBuffer`, so it can be transferred. With the type read
172
+ * first, a NULL pointer is never SQL NULL: for TEXT it is SQLITE_NOMEM, and
173
+ * for a BLOB it is an empty value unless `sqlite3_errcode`, read right after,
174
+ * returns SQLITE_NOMEM. A NULL column name is SQLITE_NOMEM too, and so is a
175
+ * TEXT or BLOB that JavaScript cannot allocate a copy of, whatever error the
176
+ * engine throws then, because the copy runs no wasm, so the instance keeps
177
+ * working. Each fails the run with the operation `step`. Rows are
178
+ * null-prototype objects, so a column named `__proto__` is an ordinary
179
+ * property, and of columns with the same name, the last one wins.
180
+ * - Column names are read after the first row and cached with the statement's
181
+ * SQLITE_STMTSTATUS_REPREPARE counter. A schema change re-prepares the
182
+ * statement, and `SELECT *` then returns other columns, so the names are read
183
+ * again when the counter changed.
184
+ * - {@link SqliteStatement.run} always resets the statement, so it is reusable
185
+ * after an error, and ignores the result: SQLITE_OK after SQLITE_DONE, and a
186
+ * failed step's error again after it. A deferred constraint or commit failure
187
+ * comes from the last step, so it is not lost. A run whose read fails is cut
188
+ * short, and its reset completes the statement, so a write with RETURNING is
189
+ * committed although the run fails.
190
+ * - `changes` compares `sqlite3_total_changes64` before and after the run: 0 when
191
+ * it did not move, `sqlite3_changes64` otherwise, as in better-sqlite3, and
192
+ * unlike it also 0 when `sqlite3_stmt_readonly` is true, as for a SELECT
193
+ * whose function writes. SQLite keeps one count per connection, of the last
194
+ * INSERT, UPDATE or DELETE that finished, so reading it alone would report a
195
+ * stale count after a SELECT or DDL. {@link SqliteRunResult.changes} says
196
+ * which writes the count can come from.
197
+ * - A callback may run queries on the database, but SQLite forbids resetting or
198
+ * finalizing a statement that is stepping and closing a connection while it
199
+ * runs. So running or disposing a statement during its own run, and disposing
200
+ * the database while one of its operations runs, throw before wasm is
201
+ * entered, and the instance keeps working. A callback installed with
202
+ * `installWasmFunctions` then fails as a defect.
203
+ *
204
+ * ## Exporting and closing
205
+ *
206
+ * - {@link SqliteDatabase.export} calls `sqlite3_serialize(db, NULL, &size, 0)`
207
+ * for the main schema, copies the pages into their own `ArrayBuffer` and
208
+ * frees SQLite's copy. The size has its own memory, because SQLite writes it
209
+ * before it finalizes its query, whose trace callback can run a query on the
210
+ * same database. `sqlite3_serialize` does not report a failed allocation to
211
+ * the connection, so the connection's error is cleared with
212
+ * `sqlite3_set_errmsg` first, and NULL then fails with the error the
213
+ * connection reports, or else SQLITE_NOMEM, as when JavaScript cannot
214
+ * allocate the copy of the pages, which still frees SQLite's copy. SQLite
215
+ * gives an empty database its first page before copying, so NULL with a size
216
+ * of 0 and no error is only a database that has no pages and cannot get one,
217
+ * such as a read-only empty one, which exports as zero bytes. Pages come
218
+ * through the pager, so an encrypted database exports as plaintext. SQLite
219
+ * zero-fills a page that fails to read and reports success, so the export of
220
+ * a File or EncryptedFile database fails when its VFS recorded a failure
221
+ * during it, caused by the VFS's record: with SQLITE_CORRUPT for a page that
222
+ * failed to authenticate, a {@link SqlitePageAuthenticationError}, and with
223
+ * SQLITE_IOERR otherwise.
224
+ * - Disposing a database finalizes its statements that are still open and then
225
+ * calls `sqlite3_close_v2`, so no deferred close keeps the VFS's files open.
226
+ *
227
+ * @module
228
+ */
229
+ import { type EncryptionKey, type Result, type SqliteRow, type SqliteValue, type Task, type Typed, type TypeError } from "@evolu/common";
230
+ import { type SqlitePrimaryResultCode, type SqliteResultCode } from "./Constants.ts";
231
+ import { type SahPool } from "./SahPool.ts";
232
+ import type { SqliteWasmDep } from "./Wasm.ts";
233
+ /**
234
+ * An open SQLite database. Disposing it while one of its operations runs, as
235
+ * from a callback, throws.
236
+ */
237
+ export interface SqliteDatabase extends Disposable {
238
+ /** Prepares one statement for repeated runs. */
239
+ readonly prepare: (sql: string) => Result<SqliteStatement, SqlitePrepareError>;
240
+ /**
241
+ * Prepares one statement, runs it once as {@link SqliteStatement.run} does and
242
+ * finalizes it.
243
+ *
244
+ * Without SQLITE_PREPARE_PERSISTENT, SQLite prepares it from its lookaside
245
+ * memory, so a statement that runs once is faster than one from
246
+ * {@link SqliteDatabase.prepare}: about 20% for a typical query in Node.js
247
+ * 24.
248
+ */
249
+ readonly run: (sql: string, parameters: ReadonlyArray<SqliteValue>) => Result<SqliteRunResult, SqlitePrepareError | SqliteRunError>;
250
+ /**
251
+ * Runs SQL that can hold several statements, without parameters, and discards
252
+ * any rows. Meant for schema changes and pragmas.
253
+ *
254
+ * It runs the statements in order and stops at the first that fails. A
255
+ * statement with a parameter fails with {@link SqliteParameterCountError}
256
+ * without running, so no parameter silently binds NULL.
257
+ */
258
+ readonly exec: (sql: string) => Result<void, SqliteExecError>;
259
+ /**
260
+ * Returns the whole database as bytes backed by their own `ArrayBuffer`, so
261
+ * they can be transferred to another worker.
262
+ */
263
+ readonly export: () => Result<Uint8Array<ArrayBuffer>, SqliteError>;
264
+ /**
265
+ * Whether no transaction is open.
266
+ *
267
+ * After errors such as SQLITE_FULL, SQLITE_IOERR or SQLITE_NOMEM, SQLite may
268
+ * roll back the transaction itself, and a ROLLBACK then fails. A transaction
269
+ * helper checks this before rolling back.
270
+ */
271
+ readonly isAutocommit: () => boolean;
272
+ }
273
+ /**
274
+ * A prepared statement. Running or disposing it during its own run, as from a
275
+ * callback, throws.
276
+ */
277
+ export interface SqliteStatement extends Disposable {
278
+ /** The number of SQL parameters, which each run must supply exactly. */
279
+ readonly parameterCount: number;
280
+ /**
281
+ * Binds the parameters, steps to completion, collects the rows and resets the
282
+ * statement, also when a step fails.
283
+ */
284
+ readonly run: (parameters: ReadonlyArray<SqliteValue>) => Result<SqliteRunResult, SqliteRunError>;
285
+ }
286
+ /** The result of {@link SqliteStatement.run}. */
287
+ export interface SqliteRunResult {
288
+ readonly rows: ReadonlyArray<SqliteRow>;
289
+ /**
290
+ * 0 for a read-only statement or a run that changed no rows, and otherwise
291
+ * SQLite's `sqlite3_changes64`: the rows the connection's last INSERT, UPDATE
292
+ * or DELETE that finished changed, without those of triggers, foreign key
293
+ * actions or REPLACE. For an INSERT, UPDATE or DELETE, that is its own count,
294
+ * unless a write on the same connection finished after it within the run, as
295
+ * one its profile trace callback runs. For another statement, it is the count
296
+ * of the last write that finished during the run, as one by a function it
297
+ * calls or by its trace callback.
298
+ */
299
+ readonly changes: number;
300
+ }
301
+ /** An error SQLite reported. */
302
+ export interface SqliteError extends Typed<"SqliteError"> {
303
+ readonly operation: SqliteOperation;
304
+ /**
305
+ * The extended result code, whose primary result code
306
+ * {@link sqliteResultCodeToPrimary} returns.
307
+ */
308
+ readonly extendedCode: SqliteResultCode;
309
+ /**
310
+ * From `sqlite3_errmsg`, or from `sqlite3_errstr` of the code when SQLite did
311
+ * not report the failure to the connection, as for an open without a handle,
312
+ * an allocation that failed, or an export whose VFS failed to read a page.
313
+ */
314
+ readonly message: string;
315
+ /**
316
+ * The byte offset in the UTF-8 SQL where SQLite detected the error, from
317
+ * `sqlite3_error_offset` for a parser error (SQLITE_ERROR from prepare, exec
318
+ * or step); null for any other error or when the error has no position.
319
+ */
320
+ readonly sqlOffset: number | null;
321
+ /**
322
+ * The first VFS failure since the top-level operation started, such as the
323
+ * `QuotaExceededError` behind SQLITE_FULL; null when the VFS reported none.
324
+ */
325
+ readonly cause: SqliteVfsFailure | null;
326
+ }
327
+ /** The operation a {@link SqliteError} comes from. */
328
+ export type SqliteOperation = "open" | "prepare" | "bind" | "step" | "exec" | "export";
329
+ /**
330
+ * Returns the primary result code of a result code, its low 8 bits, such as
331
+ * SQLITE_CONSTRAINT for SQLITE_CONSTRAINT_NOTNULL. A primary result code
332
+ * returns itself.
333
+ */
334
+ export declare const sqliteResultCodeToPrimary: (code: SqliteResultCode) => SqlitePrimaryResultCode;
335
+ /** A failure a VFS method recorded before returning an error code. */
336
+ export interface SqliteVfsFailure {
337
+ readonly method: SqliteVfsMethod;
338
+ /**
339
+ * The path of the file, or null for a method without one or a name that maps
340
+ * to no path.
341
+ */
342
+ readonly path: string | null;
343
+ /**
344
+ * What the browser threw, such as a `DOMException`, or what the VFS found
345
+ * wrong, such as a {@link SqliteShortWriteError}, a
346
+ * {@link SqlitePageAuthenticationError}, a {@link SahPoolFullError}, a
347
+ * {@link SahPoolInvalidPathError}, or a
348
+ * {@link SahPoolEncryptionUnsupportedError}.
349
+ */
350
+ readonly error: unknown;
351
+ }
352
+ /** A VFS or I/O method that can record a {@link SqliteVfsFailure}. */
353
+ export type SqliteVfsMethod = "xOpen" | "xDelete" | "xAccess" | "xClose" | "xRead" | "xWrite" | "xTruncate" | "xSync" | "xFileSize" | "xLock" | "xUnlock" | "xCheckReservedLock" | "xFileControl";
354
+ /**
355
+ * A write that stored fewer or more bytes than requested.
356
+ *
357
+ * Firefox reports a full disk with a short count, and Chromium's off-the-record
358
+ * storage has reported impossible counts; either way the data is not all there,
359
+ * so the write fails with SQLITE_FULL.
360
+ */
361
+ export interface SqliteShortWriteError extends Typed<"SqliteShortWrite"> {
362
+ readonly requested: number;
363
+ readonly written: number;
364
+ }
365
+ /** Why {@link SqliteDatabase.prepare} failed. */
366
+ export type SqlitePrepareError = SqliteError | SqliteEmptySqlError | SqliteMultipleStatementsError | SqliteInvalidSqlTextError;
367
+ /** The SQL contains no statement, only whitespace or comments. */
368
+ export interface SqliteEmptySqlError extends Typed<"SqliteEmptySqlError"> {
369
+ }
370
+ /** The SQL contains more than one statement. */
371
+ export interface SqliteMultipleStatementsError extends Typed<"SqliteMultipleStatementsError"> {
372
+ }
373
+ /**
374
+ * The SQL is text SQLite would read as other SQL, so it fails before SQLite
375
+ * sees it: it contains a NUL character, which SQLite reads SQL only up to, so
376
+ * it would silently ignore the rest, or a lone surrogate, which UTF-8 cannot
377
+ * encode, so it would run with U+FFFD in its place.
378
+ */
379
+ export interface SqliteInvalidSqlTextError extends Typed<"SqliteInvalidSqlText"> {
380
+ }
381
+ /** Why {@link SqliteDatabase.exec} failed. */
382
+ export type SqliteExecError = SqliteError | SqliteInvalidSqlTextError | SqliteParameterCountError;
383
+ /** Why {@link SqliteStatement.run} failed. */
384
+ export type SqliteRunError = SqliteError | SqliteParameterCountError;
385
+ /**
386
+ * A run supplied a different number of parameters than the SQL has, or
387
+ * {@link SqliteDatabase.exec}, which supplies none, met a statement with
388
+ * parameters.
389
+ */
390
+ export interface SqliteParameterCountError extends Typed<"SqliteParameterCountError"> {
391
+ readonly expected: number;
392
+ readonly actual: number;
393
+ }
394
+ /** How to open a database. */
395
+ export type SqliteDatabaseOptions = SqliteMemoryDatabaseOptions | SqliteFileDatabaseOptions | SqliteEncryptedFileDatabaseOptions;
396
+ /**
397
+ * An in-memory database on the default VFS, which never touches OPFS. Temporary
398
+ * tables and indexes stay in memory in every mode.
399
+ */
400
+ export interface SqliteMemoryDatabaseOptions extends Typed<"Memory"> {
401
+ }
402
+ /** An unencrypted database file on a {@link SqliteVfs}, such as a {@link SahPool}. */
403
+ export interface SqliteFileDatabaseOptions extends Typed<"File"> {
404
+ readonly vfs: SqliteVfs;
405
+ /**
406
+ * The canonical path of the file on the VFS, such as `/evolu1.db`, by which
407
+ * the VFS also lists and deletes it.
408
+ */
409
+ readonly path: SqliteVfsPath;
410
+ }
411
+ /**
412
+ * A database file on a {@link SqliteEncryptingVfs}, which encrypts it, as a
413
+ * {@link SahPool} does in the format of SQLite3 Multiple Ciphers' `sqlcipher`
414
+ * scheme.
415
+ *
416
+ * Only the database file and its journal are encrypted. `VACUUM INTO` and
417
+ * `ATTACH` open their file as a database of its own, which is encrypted only
418
+ * when a key is registered for its path with
419
+ * {@link SqliteEncryptingVfs.registerKey} while they open it. Otherwise they
420
+ * write it unencrypted, because SQLite ignores the `KEY` clause of `ATTACH` and
421
+ * `PRAGMA key`, `rekey` and `cipher`, where 2.2.4 encrypted both with the
422
+ * database's key, or with the `KEY` of `ATTACH`. A file that `ATTACH` creates
423
+ * cannot be encrypted, because SQLite reserves no bytes in it, so with a key
424
+ * registered its first write fails with SQLITE_IOERR_WRITE. `VACUUM INTO` keeps
425
+ * the reserved bytes, so it can create an encrypted copy, which `ATTACH` then
426
+ * opens with its key registered.
427
+ */
428
+ export interface SqliteEncryptedFileDatabaseOptions extends Typed<"EncryptedFile"> {
429
+ readonly vfs: SqliteEncryptingVfs;
430
+ /**
431
+ * The path of the file on the VFS, as {@link SqliteFileDatabaseOptions.path}
432
+ * describes.
433
+ */
434
+ readonly path: SqliteVfsPath;
435
+ /**
436
+ * The raw key, which {@link SqliteEncryptingVfs.registerKey} gets while the
437
+ * file opens.
438
+ */
439
+ readonly key: EncryptionKey;
440
+ }
441
+ /** Error returned when a string is not a valid {@link SqliteVfsPath}. */
442
+ export interface SqliteVfsPathError extends TypeError<"SqliteVfsPath"> {
443
+ readonly value: string;
444
+ }
445
+ /**
446
+ * The canonical path of a database file on a {@link SqliteVfs}, such as
447
+ * `/evolu1.db`, one spelling per file, as {@link SqliteVfs.getPaths} lists it.
448
+ *
449
+ * A path is canonical when it is its own `new URL(path,
450
+ * "file://localhost/").pathname`, the path a {@link SahPool} maps a name to, so
451
+ * the VFS opens, lists and deletes the file by the path the database opened it
452
+ * with, and an EncryptedFile database registers its key for that file. A
453
+ * canonical path starts with `/` and is printable ASCII without `?` or `#`, so
454
+ * SQLite passes it to the VFS as it is, and the paths SQLite derives from it by
455
+ * appending a suffix, as for the journal, are canonical too. It rejects:
456
+ *
457
+ * - Another spelling of a path, such as `evolu1.db`, `/x/../evolu1.db`,
458
+ * `FILE:evolu1.db` or `/a b.db` for `/a%20b.db`, and a name with a scheme,
459
+ * such as `db:evolu1.db`, which a pool would map to the relative path
460
+ * `evolu1.db`.
461
+ * - A path SQLite reads itself: an empty path and `:memory:`, which open an
462
+ * in-memory database, `:localStorage:` and `:sessionStorage:`, which SQLite
463
+ * opens on its kvvfs, and a `file:` URI, whose query and fragment SQLite
464
+ * strips and whose escapes it decodes, so the VFS would get another name, and
465
+ * an EncryptedFile database would be written without its key.
466
+ * - A path longer than {@link sahPoolMaxDatabasePathSize}, 498 bytes, because a
467
+ * pool slot's header holds a path of up to 510 bytes, and SQLite names a
468
+ * super-journal by appending 12 bytes to the database's path.
469
+ */
470
+ export declare const SqliteVfsPath: import("@evolu/common").BrandType<import("@evolu/common").Type<"String", string, string, import("@evolu/common").TypeOfError<"String">, null, import("@evolu/common").TypeOfError<"String">, never, string, true>, "SqliteVfsPath", SqliteVfsPathError>;
471
+ export type SqliteVfsPath = typeof SqliteVfsPath.Output;
472
+ /**
473
+ * What a database needs from the VFS it opens a file on, and what a driver
474
+ * needs to tell which databases the VFS has and to delete them. A
475
+ * {@link SahPool} is one.
476
+ */
477
+ export interface SqliteVfs {
478
+ /** The name of the VFS, which a database opens its path with. */
479
+ readonly vfsName: string;
480
+ /**
481
+ * Returns the first failure a method of the VFS recorded since the last
482
+ * {@link SqliteVfs.clearFailure}, which a {@link SqliteError} carries as its
483
+ * cause.
484
+ */
485
+ readonly getFailure: () => SqliteVfsFailure | null;
486
+ /**
487
+ * Forgets the recorded failure; a database calls it before each operation
488
+ * that does not run inside another operation on the VFS.
489
+ */
490
+ readonly clearFailure: () => void;
491
+ /**
492
+ * Returns the canonical paths of the files the VFS has, databases and their
493
+ * journals, such as `/evolu1.db`, so a database opened at a
494
+ * {@link SqliteVfsPath} is listed by that path. A VFS may derive a file's
495
+ * canonical path from the name SQLite opened it with, as a {@link SahPool}
496
+ * lists a file SQLite's opfs-sahpool opened as `evolu1.db` as `/evolu1.db`.
497
+ */
498
+ readonly getPaths: () => ReadonlyArray<string>;
499
+ /**
500
+ * Deletes the file with a canonical path, as {@link SqliteVfs.getPaths}
501
+ * returns it, and the files SQLite keeps beside it, such as its `-journal`.
502
+ * The file goes first, so a failure never leaves a database without the
503
+ * journal that would roll it back. Returns false when the VFS has no file
504
+ * with the path, as for a path that is not canonical, and throws when a
505
+ * connection has one of the files open.
506
+ */
507
+ readonly unlink: (path: string) => Result<boolean, SqliteVfsIoError>;
508
+ }
509
+ /**
510
+ * A {@link SqliteVfs} that encrypts a database file whose path has a key
511
+ * registered while the file opens, as an EncryptedFile database needs.
512
+ *
513
+ * The database asks SQLite to leave the last 80 bytes of each page of a new
514
+ * database unused, so the VFS can store data of its own there, as a
515
+ * {@link SahPool} stores the page's IV and HMAC.
516
+ *
517
+ * A read of a page that fails to authenticate fails with SQLITE_NOTADB for page
518
+ * 1 and SQLITE_CORRUPT for any other page, and records a
519
+ * {@link SqlitePageAuthenticationError}, by which the database tells it from
520
+ * other failures, so an export that reads the page fails with SQLITE_CORRUPT
521
+ * rather than SQLITE_IOERR.
522
+ */
523
+ export interface SqliteEncryptingVfs extends SqliteVfs {
524
+ /**
525
+ * Registers a raw key for a path until the registration is disposed, as an
526
+ * EncryptedFile database does while it opens. The path is the one spelling by
527
+ * which the VFS opens the file, so it is registered as it is. When the VFS
528
+ * opens the path as a main database, it copies the key and encrypts that file
529
+ * and its journal with it until the file closes, also for the file of an
530
+ * `ATTACH` or `VACUUM INTO` that opens it meanwhile. The caller's key is
531
+ * never modified.
532
+ */
533
+ readonly registerKey: (path: SqliteVfsPath, key: EncryptionKey) => Disposable;
534
+ }
535
+ /**
536
+ * The storage of a VFS failed outside SQLite, as when {@link SqliteVfs.unlink}
537
+ * deletes a file.
538
+ */
539
+ export interface SqliteVfsIoError extends Typed<"SqliteVfsIoError"> {
540
+ /**
541
+ * What the storage threw, such as a `DOMException`, or a
542
+ * {@link SqliteShortWriteError} for a write that stored a different number of
543
+ * bytes.
544
+ */
545
+ readonly cause: unknown;
546
+ }
547
+ /**
548
+ * A page of an encrypted file that failed to authenticate, because the key is
549
+ * wrong or the page was altered or cut short, as a {@link SqliteEncryptingVfs}
550
+ * records it.
551
+ */
552
+ export interface SqlitePageAuthenticationError extends Typed<"SqlitePageAuthenticationError"> {
553
+ /**
554
+ * The number of the database page, counting from 1, also for a page in a
555
+ * journal.
556
+ */
557
+ readonly pageNumber: number;
558
+ }
559
+ /**
560
+ * Opens a database.
561
+ *
562
+ * With a wrong key or a file that is not a database, it fails with
563
+ * SQLITE_NOTADB, or with SQLITE_CORRUPT for a wrong key and a hot journal whose
564
+ * first record is not page 1. On a {@link SahPool}, an encrypted database opened
565
+ * without its key while it has a hot journal that records pages fails with
566
+ * SQLITE_CANTOPEN, and the journal stays for the key. A leftover journal that
567
+ * is not hot, such as one `journal_mode = PERSIST` or TRUNCATE keeps, gives
568
+ * SQLITE_NOTADB, as no journal does. For encrypted databases that 2.2.4 may
569
+ * have keyed, use {@link createEncryptedSqliteDatabase}.
570
+ */
571
+ export declare const createSqliteDatabase: (deps: SqliteWasmDep) => (options: SqliteDatabaseOptions) => Result<SqliteDatabase, SqliteError>;
572
+ /**
573
+ * Options for {@link createEncryptedSqliteDatabase}: an EncryptedFile database
574
+ * on a {@link SahPool}, because 2.2.4 wrote only pool files, and the fallback to
575
+ * its key reads the salt with {@link SahPool.read}.
576
+ */
577
+ export interface SqliteEncryptedDatabaseOptions extends SqliteEncryptedFileDatabaseOptions {
578
+ readonly vfs: SahPool;
579
+ }
580
+ /**
581
+ * Opens an EncryptedFile database on a pool, falling back to the key
582
+ * `@evolu/sqlite-wasm` 2.2.4 derived.
583
+ *
584
+ * `@evolu/web` passed 2.2.4 the key as the SQL text `x'<hex>'`, SQLCipher's
585
+ * notation for a raw key, which SQLite3 Multiple Ciphers 2.2.4 treated as a
586
+ * passphrase because of a bug
587
+ * (https://github.com/utelle/SQLite3MultipleCiphers/issues/218, fixed in
588
+ * 2.2.5). So every database it encrypted is keyed with PBKDF2-HMAC-SHA512 of
589
+ * that text, not with the key itself. This Task:
590
+ *
591
+ * 1. Opens with the raw key. A new or empty file always accepts it.
592
+ * 2. Only when a wrong key failed it, so page 1 of the database or a record of its
593
+ * hot journal failed to authenticate, which the pool records as a
594
+ * {@link SqlitePageAuthenticationError}, reads the first 16 bytes of the file
595
+ * through {@link SahPool.read}: the unencrypted cipher salt. Another page of
596
+ * the database that fails to authenticate is damaged, because page 1 proved
597
+ * the key, so the open fails with SQLITE_CORRUPT.
598
+ * 3. Derives the legacy key with {@link deriveLegacySqliteKey}, opens again with it
599
+ * as the raw key, and zeroes it.
600
+ *
601
+ * The result says which key opened the database. When neither key opens it, the
602
+ * error is the raw key's, unless the second open failed otherwise. Rekeying a
603
+ * legacy database to the raw key is a separate decision: it rewrites every
604
+ * page, needs space, and makes the database unreadable to 2.2.4 tabs that share
605
+ * the pool.
606
+ */
607
+ export declare const createEncryptedSqliteDatabase: (options: SqliteEncryptedDatabaseOptions) => Task<SqliteEncryptedDatabase, SqliteError | SqliteVfsIoError, SqliteWasmDep & SubtleCryptoDep>;
608
+ /** The result of {@link createEncryptedSqliteDatabase}. */
609
+ export interface SqliteEncryptedDatabase {
610
+ readonly database: SqliteDatabase;
611
+ readonly keyDerivation: SqliteKeyDerivation;
612
+ }
613
+ /**
614
+ * Which key opened an encrypted database: the raw key, or the key 2.2.4 derived
615
+ * from it because of a bug in SQLite3 Multiple Ciphers, which
616
+ * {@link deriveLegacySqliteKey} describes.
617
+ */
618
+ export type SqliteKeyDerivation = "Raw" | "Legacy224";
619
+ /**
620
+ * Derives the key `@evolu/sqlite-wasm` 2.2.4 used: PBKDF2-HMAC-SHA512 with
621
+ * 256000 iterations and a 32-byte output, over the UTF-8 text `x'` followed by
622
+ * the key in lowercase hex and `'`, salted with the database's first 16 bytes.
623
+ *
624
+ * It exists because of a bug in SQLite3 Multiple Ciphers 2.2.4, which 2.2.4
625
+ * packaged. `x'<hex>'` is SQLCipher's notation for a raw key, which
626
+ * `@evolu/web` used, but that version took it as a passphrase and derived the
627
+ * key from the text
628
+ * (https://github.com/utelle/SQLite3MultipleCiphers/issues/218, fixed in
629
+ * 2.2.5). So the databases it encrypted are keyed with this derivation, and
630
+ * opening them needs it for as long as they exist, because nothing rekeys
631
+ * them.
632
+ *
633
+ * The text is built byte by byte, so no string holds the key, and zeroed once
634
+ * WebCrypto has imported it.
635
+ */
636
+ export declare const deriveLegacySqliteKey: (key: EncryptionKey, salt: Uint8Array) => Task<EncryptionKey, never, SubtleCryptoDep>;
637
+ /** WebCrypto, which derives legacy keys. */
638
+ export interface SubtleCryptoDep {
639
+ readonly subtleCrypto: SubtleCrypto;
640
+ }
641
+ //# sourceMappingURL=Database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Database.d.ts","sourceRoot":"","sources":["../../src/Database.ts"],"names":[],"mappings":"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"}