browser-sqlite 1.0.0-rc.3 → 1.0.0-rc.4

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 (42) hide show
  1. package/NOTICE +56 -0
  2. package/README.md +435 -63
  3. package/dist/LICENSE +21 -0
  4. package/dist/NOTICE +56 -0
  5. package/dist/api.d.ts +376 -0
  6. package/dist/bulk.d.ts +42 -0
  7. package/dist/capabilities.d.ts +23 -0
  8. package/dist/client.d.ts +198 -0
  9. package/dist/credits.d.ts +31 -0
  10. package/dist/{esm/src/debug.d.ts → debug.d.ts} +21 -10
  11. package/dist/delete.d.ts +42 -0
  12. package/dist/epochs.d.ts +55 -0
  13. package/dist/errors.d.ts +37 -0
  14. package/dist/index.d.ts +6 -0
  15. package/dist/index.js +5 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/locks.d.ts +54 -0
  18. package/dist/logger.d.ts +24 -0
  19. package/dist/pool.d.ts +98 -0
  20. package/dist/queries.d.ts +36 -0
  21. package/dist/scheduler.d.ts +131 -0
  22. package/dist/supervisor.d.ts +17 -0
  23. package/dist/transaction.d.ts +38 -0
  24. package/dist/types.d.ts +348 -0
  25. package/dist/utils.d.ts +116 -0
  26. package/dist/worker/cloneable.d.ts +25 -0
  27. package/dist/worker/statement-cache.d.ts +22 -0
  28. package/dist/worker/wa-sqlite-async.wasm +0 -0
  29. package/dist/worker/wa-sqlite-jspi.wasm +0 -0
  30. package/dist/worker/wa-sqlite.wasm +0 -0
  31. package/dist/worker/worker.js +11 -0
  32. package/dist/worker/worker.js.map +1 -0
  33. package/package.json +36 -20
  34. package/dist/esm/index.js +0 -424
  35. package/dist/esm/rslib.config.d.ts +0 -2
  36. package/dist/esm/rstest.config.d.ts +0 -2
  37. package/dist/esm/src/client.d.ts +0 -332
  38. package/dist/esm/src/index.d.ts +0 -1
  39. package/dist/esm/src/orchestrator.d.ts +0 -87
  40. package/dist/esm/src/types.d.ts +0 -83
  41. package/dist/esm/src/utils.d.ts +0 -6
  42. /package/dist/{esm/src → worker}/worker.d.ts +0 -0
@@ -0,0 +1,348 @@
1
+ export type SQLiteWorkerMessageData<_T = unknown> = {
2
+ callId: number;
3
+ terminate?: boolean;
4
+ } & (SQLWorkerResultData[keyof SQLWorkerResultData] | {
5
+ type: 'error';
6
+ message: string;
7
+ });
8
+ export type SQLWorkerResultData<T = unknown> = {
9
+ open: {
10
+ success: boolean;
11
+ };
12
+ sql: {
13
+ type: 'partial';
14
+ result: T[];
15
+ } | {
16
+ type: 'one';
17
+ sizes: number[];
18
+ };
19
+ abort: {
20
+ type: 'done';
21
+ };
22
+ };
23
+ export declare const SharedArrayTypes: {
24
+ INT: number;
25
+ STRING: number;
26
+ OBJECT: number;
27
+ };
28
+ type SQLOptions = {
29
+ chunkSize?: number;
30
+ /** Chunks the worker may send before waiting for a credit. Spec §3.2. */
31
+ credits?: number;
32
+ };
33
+ /**
34
+ * Where a worker fetches its `.wasm` from, when the consumer overrode it.
35
+ *
36
+ * Discriminated rather than a single string because the two forms differ in
37
+ * what they leave to the Emscripten glue. `base` is a directory: the glue
38
+ * supplies the file name (`locateFile('wa-sqlite-async.wasm')`), so nothing
39
+ * here names the three builds' files — and nothing has to be renamed when
40
+ * wa-sqlite renames one. `file` is the whole URL, typically content-hashed by
41
+ * a bundler, so the glue's file name is discarded.
42
+ *
43
+ * Always absolute: `resolveWasmLocation` (`src/utils.ts`) resolves against the
44
+ * page before the `open` message is posted, so the worker applies it without
45
+ * knowing what it was relative to.
46
+ */
47
+ export type WasmLocation = {
48
+ base: string;
49
+ } | {
50
+ file: string;
51
+ };
52
+ export type ClientMessageData = {
53
+ type: 'open';
54
+ file: string;
55
+ vfs: SQLiteVFS;
56
+ build?: SQLiteBuild;
57
+ pragmas?: Record<string, string>;
58
+ /** Statements retained per worker; see `src/client.ts`. Internal. */
59
+ statementCacheSize?: number;
60
+ wasm?: WasmLocation;
61
+ } | {
62
+ type: 'query';
63
+ callId: number;
64
+ sql: string;
65
+ params: unknown[];
66
+ options?: SQLOptions;
67
+ } | {
68
+ type: 'close';
69
+ callId: number;
70
+ } | {
71
+ type: 'credit';
72
+ callId: number;
73
+ n: number;
74
+ } | {
75
+ type: 'stop';
76
+ callId: number;
77
+ } | {
78
+ type: 'delete';
79
+ callId: number;
80
+ file: string;
81
+ vfs: SQLiteVFS;
82
+ build?: SQLiteBuild;
83
+ wasm?: WasmLocation;
84
+ };
85
+ export type WorkerMessageData = {
86
+ type: 'ready';
87
+ callId: number;
88
+ } | {
89
+ type: 'chunk';
90
+ callId: number;
91
+ data: unknown[];
92
+ } | {
93
+ type: 'done';
94
+ callId: number;
95
+ affected: number;
96
+ /**
97
+ * Statements compiled while serving this query — zero on a cache hit.
98
+ * Rides the same message as `affected` rather than opening a channel:
99
+ * the effect this instruments is a count, not a duration (`mem:lessons`,
100
+ * "for a sub-millisecond effect, count the round trips").
101
+ */
102
+ prepared: number;
103
+ } | {
104
+ type: 'error';
105
+ callId: number;
106
+ message: string;
107
+ cause?: unknown;
108
+ /** SQLite's numeric result code, when the failure came from SQLite. */
109
+ sqliteCode?: number;
110
+ } | {
111
+ type: 'closed';
112
+ callId: number;
113
+ } | {
114
+ type: 'deleted';
115
+ callId: number;
116
+ } | {
117
+ type: 'open-error';
118
+ callId: number;
119
+ message: string;
120
+ cause?: unknown;
121
+ /** SQLite's numeric result code, when the failure came from SQLite. */
122
+ sqliteCode?: number;
123
+ };
124
+ /** Which wa-sqlite WebAssembly build a worker loads. */
125
+ export type SQLiteBuild = 'sync' | 'async' | 'jspi';
126
+ /**
127
+ * What each build needs from the engine beyond plain WebAssembly.
128
+ *
129
+ * `satisfies Record<SQLiteBuild, …>` and not `SQLiteBuild = keyof typeof …`:
130
+ * the check must run in this direction. Adding a build to the union then fails
131
+ * to compile until its requirements are declared, where `keyof` would let a
132
+ * forgotten entry mean silently that the build does not exist. `VFS_CAPABILITIES`
133
+ * derives `SQLiteVFS` from its keys because it *is* the VFS registry; the build
134
+ * registry is `WA_SQLITE_BUILDS` in the worker, and this table describes one
135
+ * attribute of builds rather than the builds themselves.
136
+ */
137
+ export declare const BUILD_REQUIREMENTS: {
138
+ readonly sync: readonly [];
139
+ readonly async: readonly [];
140
+ readonly jspi: readonly ["jspi"];
141
+ };
142
+ /**
143
+ * A platform feature a VFS may need. Which browser versions ship each one is
144
+ * documentation data, not runtime data, so it lives in the README generator
145
+ * (`scripts/render-vfs-matrix.ts`) with its sources — not here, where it would
146
+ * ship to every consumer for nothing.
147
+ */
148
+ export type PlatformFeature = 'opfs' | 'readwrite-unsafe' | 'jspi' | 'writable-stream';
149
+ /** Where a VFS keeps the database. */
150
+ export type VFSStorage = 'opfs' | 'indexeddb' | 'memory';
151
+ /**
152
+ * How a VFS arranges a database in its storage — which is not the same
153
+ * question as `storage`, and cannot be derived from it: `AccessHandlePoolVFS`
154
+ * is `storage: 'opfs'` yet keeps opaque, randomly named slot files whose
155
+ * association with a SQLite path lives in a header inside each file.
156
+ *
157
+ * `deleteDatabase` reads this to decide whether the database is also an OPFS
158
+ * entry it can remove by name after `jDelete` — the pass that covers the two
159
+ * VFS whose `jDelete` does not delete. A wrong value here is a deletion that
160
+ * reports success over an intact file.
161
+ */
162
+ export type VFSLayout = 'opfs-path' | 'opfs-pool' | 'idb-store' | 'memory';
163
+ /** How much of the database a VFS keeps resident in RAM. */
164
+ export type VFSMemoryModel = 'page-cache' | 'whole-database';
165
+ /** What a VFS can and cannot do. One entry per VFS, and no second table. */
166
+ export type VFSCapability = {
167
+ /** Builds this VFS can run on, most preferred first. */
168
+ readonly builds: readonly [SQLiteBuild, ...SQLiteBuild[]];
169
+ /** Largest pool this VFS supports; `null` when unbounded. */
170
+ readonly maxPoolSize: number | null;
171
+ /** Why the cap exists. Required whenever `maxPoolSize` is not null. */
172
+ readonly poolLimitReason: string | null;
173
+ /** Whether several connections may share one database. */
174
+ readonly multiConnection: boolean;
175
+ /** Whether data outlives `close()`. */
176
+ readonly persistent: boolean;
177
+ /**
178
+ * `page-cache`: only SQLite's page cache is resident, bounded by
179
+ * `PRAGMA cache_size`. `whole-database`: the entire database is resident,
180
+ * and `poolSize` multiplies it.
181
+ */
182
+ readonly memoryModel: VFSMemoryModel;
183
+ /** Where the database actually lives. */
184
+ readonly storage: VFSStorage;
185
+ /** How the database is arranged within that storage. */
186
+ readonly layout: VFSLayout;
187
+ /**
188
+ * Platform features without which this VFS cannot work at all.
189
+ *
190
+ * `readwrite-unsafe` is the one that bites: WebIDL ignores the unknown
191
+ * dictionary member on engines that do not implement it, so the handle
192
+ * silently opens exclusive and the second connection hangs rather than
193
+ * failing. Declaring it is what lets the conformance suite probe for it and
194
+ * skip, instead of leaving it to surface as a 60-second timeout.
195
+ */
196
+ readonly requires: readonly PlatformFeature[];
197
+ /**
198
+ * Platform features this VFS uses when present and works without, at a cost.
199
+ *
200
+ * `OPFSAdaptiveVFS` is the case this field exists for. Without
201
+ * `readwrite-unsafe` it rotates a single exclusive access handle between
202
+ * connections instead of holding one each. That works — 102 of 104 browser
203
+ * tests pass on Firefox — but it serializes the whole pool for the duration
204
+ * of a long uninterruptible statement.
205
+ *
206
+ * Without this distinction, a support table derived from browser specs would
207
+ * mark that VFS broken everywhere outside Chromium, when it merely degrades.
208
+ */
209
+ readonly degradesWithout: readonly PlatformFeature[];
210
+ };
211
+ /**
212
+ * The single source of truth for VFS selection. `SQLiteVFS` is derived from its
213
+ * keys, `worker/worker.ts` must supply a loader for every key, the guards in
214
+ * `client.ts` read it, the conformance suite gates its scenarios on it, and the
215
+ * README table is generated from it. Nothing may hold a second copy.
216
+ *
217
+ * Build order is a decision per VFS, not a rule: `sync` is both the fastest and
218
+ * the most portable build, so it leads wherever supported; `OPFSAdaptiveVFS`
219
+ * cannot use it and leads with `async` because `jspi` is Chromium-only.
220
+ *
221
+ * Every declared build combination is verified by running it against the pinned
222
+ * wa-sqlite v1.1.2, never copied from upstream's table.
223
+ */
224
+ export declare const VFS_CAPABILITIES: {
225
+ readonly OPFSAdaptiveVFS: {
226
+ readonly builds: readonly ["async", "jspi"];
227
+ readonly maxPoolSize: null;
228
+ readonly poolLimitReason: null;
229
+ readonly multiConnection: true;
230
+ readonly persistent: true;
231
+ readonly memoryModel: 'page-cache';
232
+ readonly storage: 'opfs';
233
+ readonly layout: 'opfs-path';
234
+ readonly requires: readonly ["opfs"];
235
+ readonly degradesWithout: readonly ["readwrite-unsafe"];
236
+ };
237
+ readonly OPFSWriteAheadVFS: {
238
+ readonly builds: readonly ["sync", "async", "jspi"];
239
+ readonly maxPoolSize: null;
240
+ readonly poolLimitReason: null;
241
+ readonly multiConnection: true;
242
+ readonly persistent: true;
243
+ readonly memoryModel: 'page-cache';
244
+ readonly storage: 'opfs';
245
+ readonly layout: 'opfs-path';
246
+ readonly requires: readonly ["opfs"];
247
+ readonly degradesWithout: readonly ["readwrite-unsafe"];
248
+ };
249
+ readonly OPFSCoopSyncVFS: {
250
+ readonly builds: readonly ["sync", "async", "jspi"];
251
+ readonly maxPoolSize: null;
252
+ readonly poolLimitReason: null;
253
+ readonly multiConnection: true;
254
+ readonly persistent: true;
255
+ readonly memoryModel: 'page-cache';
256
+ readonly storage: 'opfs';
257
+ readonly layout: 'opfs-path';
258
+ readonly requires: readonly ["opfs"];
259
+ readonly degradesWithout: readonly [];
260
+ };
261
+ readonly AccessHandlePoolVFS: {
262
+ readonly builds: readonly ["sync", "async", "jspi"];
263
+ readonly maxPoolSize: 1;
264
+ readonly poolLimitReason: 'it cannot share access handles between connections';
265
+ readonly multiConnection: false;
266
+ readonly persistent: true;
267
+ readonly memoryModel: 'page-cache';
268
+ readonly storage: 'opfs';
269
+ readonly layout: 'opfs-pool';
270
+ readonly requires: readonly ["opfs"];
271
+ readonly degradesWithout: readonly [];
272
+ };
273
+ readonly IDBBatchAtomicVFS: {
274
+ readonly builds: readonly ["async", "jspi"];
275
+ readonly maxPoolSize: null;
276
+ readonly poolLimitReason: null;
277
+ readonly multiConnection: true;
278
+ readonly persistent: true;
279
+ readonly memoryModel: 'page-cache';
280
+ readonly storage: 'indexeddb';
281
+ readonly layout: 'idb-store';
282
+ readonly requires: readonly [];
283
+ readonly degradesWithout: readonly [];
284
+ };
285
+ readonly IDBMirrorVFS: {
286
+ readonly builds: readonly ["async", "jspi"];
287
+ readonly maxPoolSize: 1;
288
+ readonly poolLimitReason: 'its pages are mirrored per worker and commits propagate asynchronously, so a larger pool reads stale data or fails outright';
289
+ readonly multiConnection: false;
290
+ readonly persistent: true;
291
+ readonly memoryModel: 'whole-database';
292
+ readonly storage: 'indexeddb';
293
+ readonly layout: 'idb-store';
294
+ readonly requires: readonly [];
295
+ readonly degradesWithout: readonly [];
296
+ };
297
+ readonly OPFSAnyContextVFS: {
298
+ readonly builds: readonly ["async", "jspi"];
299
+ readonly maxPoolSize: null;
300
+ readonly poolLimitReason: null;
301
+ readonly multiConnection: true;
302
+ readonly persistent: true;
303
+ readonly memoryModel: 'page-cache';
304
+ readonly storage: 'opfs';
305
+ readonly layout: 'opfs-path';
306
+ readonly requires: readonly ["opfs", "writable-stream"];
307
+ readonly degradesWithout: readonly [];
308
+ };
309
+ readonly MemoryVFS: {
310
+ readonly builds: readonly ["sync", "async", "jspi"];
311
+ readonly maxPoolSize: 1;
312
+ readonly poolLimitReason: 'its pages live in the worker that opened them, so a larger pool would open independent databases that diverge silently';
313
+ readonly multiConnection: false;
314
+ readonly persistent: false;
315
+ readonly memoryModel: 'whole-database';
316
+ readonly storage: 'memory';
317
+ readonly layout: 'memory';
318
+ readonly requires: readonly [];
319
+ readonly degradesWithout: readonly [];
320
+ };
321
+ readonly MemoryAsyncVFS: {
322
+ readonly builds: readonly ["async", "jspi"];
323
+ readonly maxPoolSize: 1;
324
+ readonly poolLimitReason: 'its pages live in the worker that opened them, so a larger pool would open independent databases that diverge silently';
325
+ readonly multiConnection: false;
326
+ readonly persistent: false;
327
+ readonly memoryModel: 'whole-database';
328
+ readonly storage: 'memory';
329
+ readonly layout: 'memory';
330
+ readonly requires: readonly [];
331
+ readonly degradesWithout: readonly [];
332
+ };
333
+ };
334
+ export type SQLiteVFS = keyof typeof VFS_CAPABILITIES;
335
+ /** The build used when the caller does not name one. */
336
+ export declare const defaultBuildFor: (vfs: SQLiteVFS) => SQLiteBuild;
337
+ /**
338
+ * The VFS this project recommends when a caller has no reason to choose
339
+ * another. It is NOT a default — `vfs` is required, precisely so that the name
340
+ * lives in the consumer's own source and cannot move underneath their data.
341
+ *
342
+ * It lives here, beside the table, because the README generator marks this row
343
+ * `(recommended)` and would otherwise hold a second copy. It is deliberately
344
+ * not exported: a consumer writing `vfs: RECOMMENDED_VFS` would be exposed to
345
+ * the same displacement the day the recommendation changes.
346
+ */
347
+ export declare const RECOMMENDED_VFS: SQLiteVFS;
348
+ export {};
@@ -0,0 +1,116 @@
1
+ import type { SQLiteBuild, WasmLocation } from './types';
2
+ export declare const sqlParams: () => {
3
+ addParam: (v: unknown) => string;
4
+ addParamArray: (values: unknown[]) => string;
5
+ params: unknown[];
6
+ };
7
+ export declare const isReadQuery: (sql: string) => boolean;
8
+ export declare const isWriteQuery: (sql: string) => boolean;
9
+ /**
10
+ * Combines two abort signals into one that fires with the reason of whichever
11
+ * source aborted first, plus the `release()` that unsubscribes it.
12
+ *
13
+ * NOT `AbortSignal.any()`. That is Chrome 116 / Firefox 124 / Safari 17.4, far
14
+ * above this library's floor (Chrome 92 / Firefox 95 / Safari 15.4), and
15
+ * adopting it would raise every row of the generated README matrix for every
16
+ * consumer.
17
+ *
18
+ * The common case allocates nothing: with one side absent, or one side already
19
+ * aborted, the surviving signal is returned as itself — no listener, no
20
+ * teardown owed, and the caller sees the original `reason` rather than a copy.
21
+ */
22
+ export declare const mergeSignals: (a: AbortSignal | undefined, b: AbortSignal | undefined) => {
23
+ signal: AbortSignal | undefined;
24
+ release: () => void;
25
+ };
26
+ /**
27
+ * Routing guard for the read-shaped methods (`read`, `chunk`, `stream`, `first`).
28
+ * Throws before a lease is taken, so a rejected statement costs no pool capacity.
29
+ *
30
+ * A bare read pragma (`PRAGMA journal_mode`) is accepted; a pragma that assigns
31
+ * (`PRAGMA journal_mode=WAL`), takes an argument, or is followed by anything
32
+ * else must go through `write()`.
33
+ */
34
+ export declare const assertReadable: (sql: string, method: string) => void;
35
+ /**
36
+ * Quotes an SQL identifier so it can never be read as anything but a name.
37
+ *
38
+ * The library interpolates table, column and index names into generated SQL —
39
+ * `bulkWrite`, `output` and their indexes. wa-sqlite's `statements()` executes
40
+ * `;`-separated statements, so an unquoted name is a stacked-query injection
41
+ * (B4). Quoting is what makes `t"; DROP TABLE users; --` one identifier.
42
+ *
43
+ * Note that quoting preserves case in `sqlite_master`; SQLite still resolves
44
+ * names case-insensitively.
45
+ */
46
+ export declare const quoteIdent: (name: string) => string;
47
+ /**
48
+ * A column type is not an identifier and cannot be quoted — it is an SQL
49
+ * fragment the caller writes. It is validated by shape instead: this is the
50
+ * narrowed, not closed, channel documented in the spec (§1.2).
51
+ */
52
+ export declare const assertColumnType: (type: string, column: string) => string;
53
+ /**
54
+ * A GENERATED ALWAYS AS expression is caller-authored SQL. It must at least be
55
+ * parenthesised and free of statement separators, so it cannot escape its slot.
56
+ */
57
+ export declare const assertGeneratedExpression: (expr: string, column: string) => string;
58
+ /**
59
+ * Renders the client's `pragmas` option into executable statements, rejecting
60
+ * anything that is not provably a name and a scalar value (B4).
61
+ *
62
+ * Validation is syntactic rather than a closed list of the ~60 SQLite pragmas:
63
+ * a fixed list makes every legitimate pragma outside it unreachable and drifts
64
+ * with SQLite versions, for no additional protection — no ";", no parenthesis
65
+ * and no comment marker survives these three shapes either.
66
+ *
67
+ * Called twice: by the client at construction, so a bad configuration fails at
68
+ * `createSQLiteClient()` rather than inside an unrelated query, and by the
69
+ * worker at open, which is the only place the statements actually run.
70
+ */
71
+ export declare const renderPragmas: (pragmas: Record<string, string>) => string[];
72
+ /**
73
+ * The single definition of database identity — one string used everywhere:
74
+ * the worker open call, the VFS, the epoch registry and every lock name.
75
+ *
76
+ * The form is **relative** (no leading `/`). `URL.pathname` is absolute by
77
+ * construction, so stripping the slash is necessary: SQLite core checks
78
+ * `nPathname + 8 > mxPathname` (64, `node_modules/wa-sqlite/src/VFS.js:10`)
79
+ * before `xOpen`, and a leading `/` costs a character the budget cannot spare —
80
+ * measured at task 1: it broke all 96 browser tests on 56-char names. The
81
+ * strip gives that character back, so a 56-char name that the caller wrote
82
+ * still fits after normalization. The VFS re-parse (`new URL(zName, 'file://')`
83
+ * for four of five; `AccessHandlePoolVFS` via `'file://localhost/'`) produces
84
+ * identical `pathname` whether the open call receives `'data'` or `'/data'`,
85
+ * so the opened OPFS file is the same regardless.
86
+ *
87
+ * Idempotent: the VFS re-parse of an already-normalized name is a no-op.
88
+ */
89
+ export declare const normalizeDatabaseFile: (file: string) => string;
90
+ /**
91
+ * Turns the `wasmUrl` client option into the absolute location posted in the
92
+ * `open` message, or `undefined` when the option was not given.
93
+ *
94
+ * `undefined` is the load-bearing case: the worker sets Emscripten's
95
+ * `locateFile` only when it receives a location, and `findWasmBinary` takes its
96
+ * `new URL('wa-sqlite.wasm', import.meta.url)` branch whenever `locateFile` is
97
+ * absent. So an omitted option leaves resolution byte-for-byte as it was
98
+ * before this option existed — which is the entire contract of the escape
99
+ * hatch.
100
+ *
101
+ * Resolution happens **here**, on the client, against the page: what the
102
+ * consumer writes means what it means from the page they wrote it on, not from
103
+ * the worker's own directory one level down. The callback is therefore called
104
+ * once, at client construction, before any worker exists — its result is
105
+ * reused by every worker in the pool and by every restart.
106
+ *
107
+ * A string is a **directory** and gets its missing trailing slash back before
108
+ * resolution: URL resolution treats a last segment without a slash as a
109
+ * document and replaces it, so `'/static/wasm'` would otherwise silently mean
110
+ * `/static/`. A callback names a **file**, so nothing is appended to it.
111
+ *
112
+ * @throws `SQLiteError('INVALID_OPTION')` when the value cannot be parsed as a
113
+ * URL — synchronously, at construction, rather than as an opaque open failure
114
+ * from a worker that could not fetch its module.
115
+ */
116
+ export declare const resolveWasmLocation: (wasmUrl: string | ((build: SQLiteBuild) => string) | undefined, build: SQLiteBuild, baseHref: string) => WasmLocation | undefined;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Makes a value safe to hand to `postMessage`.
3
+ *
4
+ * The whole point is a failure the caller cannot recover from: a cause that
5
+ * cannot be structured-cloned makes `postMessage` itself throw, and every call
6
+ * site here is already inside a `catch` building an error reply. The throw
7
+ * would replace that reply with nothing, and the client would wait for ever on
8
+ * a request that was answered by no message at all.
9
+ *
10
+ * Pure, and in its own module for the reason `statement-cache.ts` is: the
11
+ * remainder of `worker.ts` only runs in a browser, and this decides something
12
+ * worth testing in Node against a value that is deliberately unclonable.
13
+ */
14
+ /**
15
+ * Returns `value` when it survives the structured-clone algorithm, and its
16
+ * string form when it does not.
17
+ *
18
+ * `MessageChannel` rather than `structuredClone()`: the two run the same
19
+ * algorithm and throw the same `DataCloneError`, but `structuredClone` lands at
20
+ * Chrome 98 where `MessageChannel` is Chrome 2 / Firefox 41 / Safari 5. Using
21
+ * it would have raised this library's floor by six Chrome versions to protect
22
+ * an error *cause* — see `scripts/render-vfs-matrix.ts`, which computes that
23
+ * floor from the APIs named here.
24
+ */
25
+ export declare const cloneable: (value: unknown) => unknown;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A per-worker LRU of prepared statements, keyed by the exact SQL string.
3
+ *
4
+ * Pure bookkeeping: this module prepares nothing and finalises nothing.
5
+ * `worker.ts` owns every effect, which is what lets the policy be tested in
6
+ * Node against plain integers in a subsystem whose remainder only runs in a
7
+ * browser — the role `mem:architecture` describes for `scheduler.ts` and
8
+ * `supervisor.ts`.
9
+ */
10
+ /** A `sqlite3_stmt` pointer. Opaque here: the cache only files it. */
11
+ export type StatementHandle = number;
12
+ export type StatementCache = {
13
+ get: (sql: string) => StatementHandle | 'uncacheable' | undefined;
14
+ /** Returns the handles evicted by this insertion; the caller finalises them. */
15
+ set: (sql: string, handle: StatementHandle) => StatementHandle[];
16
+ /** Returns the handles evicted by this marking; the caller finalises them. */
17
+ markUncacheable: (sql: string) => StatementHandle[];
18
+ delete: (sql: string) => StatementHandle | undefined;
19
+ /** Empties the cache and returns every live handle, for close. */
20
+ drain: () => StatementHandle[];
21
+ };
22
+ export declare const createStatementCache: (capacity: number) => StatementCache;
Binary file
Binary file
Binary file