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.
- package/NOTICE +56 -0
- package/README.md +435 -63
- package/dist/LICENSE +21 -0
- package/dist/NOTICE +56 -0
- package/dist/api.d.ts +376 -0
- package/dist/bulk.d.ts +42 -0
- package/dist/capabilities.d.ts +23 -0
- package/dist/client.d.ts +198 -0
- package/dist/credits.d.ts +31 -0
- package/dist/{esm/src/debug.d.ts → debug.d.ts} +21 -10
- package/dist/delete.d.ts +42 -0
- package/dist/epochs.d.ts +55 -0
- package/dist/errors.d.ts +37 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/locks.d.ts +54 -0
- package/dist/logger.d.ts +24 -0
- package/dist/pool.d.ts +98 -0
- package/dist/queries.d.ts +36 -0
- package/dist/scheduler.d.ts +131 -0
- package/dist/supervisor.d.ts +17 -0
- package/dist/transaction.d.ts +38 -0
- package/dist/types.d.ts +348 -0
- package/dist/utils.d.ts +116 -0
- package/dist/worker/cloneable.d.ts +25 -0
- package/dist/worker/statement-cache.d.ts +22 -0
- package/dist/worker/wa-sqlite-async.wasm +0 -0
- package/dist/worker/wa-sqlite-jspi.wasm +0 -0
- package/dist/worker/wa-sqlite.wasm +0 -0
- package/dist/worker/worker.js +11 -0
- package/dist/worker/worker.js.map +1 -0
- package/package.json +36 -20
- package/dist/esm/index.js +0 -424
- package/dist/esm/rslib.config.d.ts +0 -2
- package/dist/esm/rstest.config.d.ts +0 -2
- package/dist/esm/src/client.d.ts +0 -332
- package/dist/esm/src/index.d.ts +0 -1
- package/dist/esm/src/orchestrator.d.ts +0 -87
- package/dist/esm/src/types.d.ts +0 -83
- package/dist/esm/src/utils.d.ts +0 -6
- /package/dist/{esm/src → worker}/worker.d.ts +0 -0
package/dist/types.d.ts
ADDED
|
@@ -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 {};
|
package/dist/utils.d.ts
ADDED
|
@@ -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
|