browser-sqlite 1.0.0-rc.4 → 1.0.0-rc.5
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/README.md +66 -430
- package/dist/abandon.d.ts +77 -0
- package/dist/api.d.ts +62 -12
- package/dist/bulk.d.ts +15 -0
- package/dist/client.d.ts +43 -20
- package/dist/delete.d.ts +11 -5
- package/dist/epochs.d.ts +36 -6
- package/dist/errors.d.ts +44 -5
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/inspect.d.ts +96 -0
- package/dist/locks.d.ts +124 -6
- package/dist/pool.d.ts +101 -8
- package/dist/queries.d.ts +36 -7
- package/dist/scheduler.d.ts +14 -0
- package/dist/sqlite-codes.d.ts +154 -0
- package/dist/supervisor.d.ts +1 -1
- package/dist/transaction.d.ts +24 -1
- package/dist/types.d.ts +322 -28
- package/dist/utils.d.ts +42 -2
- package/dist/worker/probes.d.ts +26 -0
- package/dist/worker/sqlite-code.d.ts +9 -0
- package/dist/worker/statement-cache.d.ts +17 -3
- package/dist/worker/worker.js +1 -1
- package/dist/worker/worker.js.map +1 -1
- package/package.json +15 -7
package/dist/api.d.ts
CHANGED
|
@@ -10,23 +10,25 @@
|
|
|
10
10
|
* caller passes to a query, and what comes back.
|
|
11
11
|
*/
|
|
12
12
|
import type { ClientDebugState } from './debug';
|
|
13
|
+
import type { ClientInspection } from './inspect';
|
|
14
|
+
import type { SQLiteBuild, SQLiteVFS } from './types';
|
|
13
15
|
/**
|
|
14
16
|
* Marks an options type as carrying an abort signal.
|
|
15
17
|
*
|
|
16
|
-
* The name is the point. `options?:
|
|
18
|
+
* The name is the point. `options?: Interruptible<…>` says at the signature
|
|
17
19
|
* that the method can be abandoned, where a bare alias would make a reader open
|
|
18
20
|
* the type to find out. Every abortable option type in this file is built from
|
|
19
21
|
* it, so `signal` is documented once and cannot drift between them.
|
|
20
22
|
*
|
|
21
23
|
* Not the bare `Abortable` that `@types/node` uses: this reads as an options
|
|
22
24
|
* bag augmented with one member — `PropsWithChildren`, not an adjective — which
|
|
23
|
-
* is what it is both wrapped, `
|
|
24
|
-
* alone, `options?:
|
|
25
|
+
* is what it is both wrapped, `Interruptible<{ chunkSize?: number }>`, and
|
|
26
|
+
* alone, `options?: Interruptible`.
|
|
25
27
|
*
|
|
26
28
|
* `T = unknown` rather than `Record<string, never>`: intersecting with the
|
|
27
29
|
* latter collapses `signal` to `never` and makes it unassignable.
|
|
28
30
|
*/
|
|
29
|
-
export type
|
|
31
|
+
export type Interruptible<T = unknown> = T & {
|
|
30
32
|
/**
|
|
31
33
|
* Aborts the work. Rejects with `signal.reason` — your reason, not an error
|
|
32
34
|
* of this library's making.
|
|
@@ -37,11 +39,26 @@ export type OptionsWithSignal<T = unknown> = T & {
|
|
|
37
39
|
* `bulkWrite()` leaves the batches already written in place; an aborted
|
|
38
40
|
* `output()` is observationally a no-op, dropping its staging table and
|
|
39
41
|
* touching nothing else.
|
|
42
|
+
*
|
|
43
|
+
* Whether it also stops the statement SQLite is already executing depends on
|
|
44
|
+
* your build and your page: see the Interrupting a call section of API.md.
|
|
40
45
|
*/
|
|
41
46
|
signal?: AbortSignal | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Milliseconds from the call within which it must finish, after which it is
|
|
49
|
+
* aborted and rejected with `OPERATION_TIMEOUT`. It is wall clock: time your
|
|
50
|
+
* own code spends — between two chunks of a `stream()`, inside a
|
|
51
|
+
* `transaction()` callback, between two `enqueue()` calls — counts against
|
|
52
|
+
* it, as does time spent waiting for a pool worker or for another tab's
|
|
53
|
+
* write lock.
|
|
54
|
+
*
|
|
55
|
+
* It aborts through the same path a `signal` does, so the same limit applies:
|
|
56
|
+
* see the Interrupting a call section of API.md.
|
|
57
|
+
*/
|
|
58
|
+
timeout?: number | undefined;
|
|
42
59
|
};
|
|
43
60
|
/** Options every query method accepts. */
|
|
44
|
-
export type SQLiteQueryOptions =
|
|
61
|
+
export type SQLiteQueryOptions = Interruptible;
|
|
45
62
|
/**
|
|
46
63
|
* Options for the methods that cross the worker boundary in chunks.
|
|
47
64
|
*
|
|
@@ -50,7 +67,7 @@ export type SQLiteQueryOptions = OptionsWithSignal;
|
|
|
50
67
|
* ahead of the consumer. On `stream()` that is the only lever on how many rows
|
|
51
68
|
* are in flight.
|
|
52
69
|
*/
|
|
53
|
-
export type SQLiteChunkOptions =
|
|
70
|
+
export type SQLiteChunkOptions = Interruptible<{
|
|
54
71
|
/** Rows per chunk. Defaults to 500. */
|
|
55
72
|
chunkSize?: number;
|
|
56
73
|
}>;
|
|
@@ -80,9 +97,9 @@ export type SQLiteWriteResult<T extends Record<string, unknown>> = {
|
|
|
80
97
|
* That window is short on a VFS holding one access handle per connection, and
|
|
81
98
|
* it is not on a VFS rotating a single exclusive one: there such a statement
|
|
82
99
|
* waits for whichever client holds the file, and your signal cannot shorten
|
|
83
|
-
* that wait. See the reduced mode described
|
|
100
|
+
* that wait. See the reduced mode described in VFS.md.
|
|
84
101
|
*/
|
|
85
|
-
export type SQLiteTransactionOptions =
|
|
102
|
+
export type SQLiteTransactionOptions = Interruptible<{
|
|
86
103
|
/** Rejects write statements with `READ_ONLY_TRANSACTION`. Defaults to false. */
|
|
87
104
|
readOnly?: boolean;
|
|
88
105
|
/** Commits when the callback resolves. Defaults to true. */
|
|
@@ -102,7 +119,7 @@ export type Index<SCHEMA extends Schema> = keyof SCHEMA | (keyof SCHEMA)[] | ({
|
|
|
102
119
|
} | {
|
|
103
120
|
columns: (keyof SCHEMA)[];
|
|
104
121
|
}));
|
|
105
|
-
export type SQLiteOutputOptions<SCHEMA extends Schema> =
|
|
122
|
+
export type SQLiteOutputOptions<SCHEMA extends Schema> = Interruptible<{
|
|
106
123
|
indexes?: Index<SCHEMA>[];
|
|
107
124
|
/** Rows queued for writing above which `enqueue()` defers. See `SQLiteBulkWriteOptions`. */
|
|
108
125
|
queueSize?: number | undefined;
|
|
@@ -126,7 +143,7 @@ export type SQLiteOutputOptions<SCHEMA extends Schema> = OptionsWithSignal<{
|
|
|
126
143
|
* 1 is raised to 1: a batch always holds at least one row, so a lower cap could
|
|
127
144
|
* never be satisfied.
|
|
128
145
|
*/
|
|
129
|
-
export type SQLiteBulkWriteOptions =
|
|
146
|
+
export type SQLiteBulkWriteOptions = Interruptible<{
|
|
130
147
|
/** Rows queued for writing above which `enqueue()` defers. */
|
|
131
148
|
queueSize?: number | undefined;
|
|
132
149
|
}>;
|
|
@@ -200,7 +217,7 @@ export type SQLiteQueryAPI = {
|
|
|
200
217
|
* @returns Promise resolving to `{ result: T[], affected: number }` where
|
|
201
218
|
* `affected` is the SQLite `changes()` count for the statement.
|
|
202
219
|
*/
|
|
203
|
-
write: <T extends Record<string, unknown>>(sql: string, params?: unknown[], options?:
|
|
220
|
+
write: <T extends Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteQueryOptions) => Promise<SQLiteWriteResult<T>>;
|
|
204
221
|
/**
|
|
205
222
|
* Executes a query and yields result rows in chunks via an async generator.
|
|
206
223
|
* Memory-efficient for large result sets — rows are not buffered in full.
|
|
@@ -253,7 +270,7 @@ export type SQLiteQueryAPI = {
|
|
|
253
270
|
* @param options - Optional query options (`signal`).
|
|
254
271
|
* @returns Promise resolving to the first row as `T`, or `undefined` if no rows.
|
|
255
272
|
*/
|
|
256
|
-
first: <T extends Record<string, unknown>>(sql: string, params?: unknown[], options?:
|
|
273
|
+
first: <T extends Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteQueryOptions) => Promise<T | undefined>;
|
|
257
274
|
/**
|
|
258
275
|
* Creates a buffered bulk-insert utility that batches rows to stay within
|
|
259
276
|
* SQLite's variable limit (`SQLITE_MAX_VARS = 32766`).
|
|
@@ -362,6 +379,31 @@ export type SQLiteDB = SQLiteQueryAPI & {
|
|
|
362
379
|
* check what your chosen VFS actually writes.
|
|
363
380
|
*/
|
|
364
381
|
close: () => Promise<void>;
|
|
382
|
+
/** This client's UUID, unique across the origin. */
|
|
383
|
+
readonly id: string;
|
|
384
|
+
/** This client's label, index included — what its log lines are prefixed with. */
|
|
385
|
+
readonly name: string;
|
|
386
|
+
/** The database file, normalized: the identity every lock name is built on. */
|
|
387
|
+
readonly file: string;
|
|
388
|
+
readonly vfs: SQLiteVFS;
|
|
389
|
+
/** The build actually loaded, resolved by `defaultBuildFor` when not passed. */
|
|
390
|
+
readonly build: SQLiteBuild;
|
|
391
|
+
/**
|
|
392
|
+
* The number of workers the pool runs: `poolSize` as requested, capped by
|
|
393
|
+
* the VFS and by the environment. Exact once every worker has opened or
|
|
394
|
+
* declined; every query waits for that, so it is settled by the time any
|
|
395
|
+
* query returns.
|
|
396
|
+
*/
|
|
397
|
+
readonly poolSize: number;
|
|
398
|
+
/**
|
|
399
|
+
* Who else is live on this database, right now, in every tab of this origin.
|
|
400
|
+
*
|
|
401
|
+
* A snapshot, stale the instant it resolves: it informs a UI and never
|
|
402
|
+
* authorizes an action. Poll it if you want it to move — each call is a fresh
|
|
403
|
+
* census costing well under a tenth of a millisecond, and it takes no lock,
|
|
404
|
+
* so it cannot slow a query down.
|
|
405
|
+
*/
|
|
406
|
+
inspect: () => Promise<ClientInspection>;
|
|
365
407
|
/**
|
|
366
408
|
* Internal diagnostic handle. Not part of the stable public API.
|
|
367
409
|
* Shape is subject to change without notice.
|
|
@@ -372,5 +414,13 @@ export type SQLiteDB = SQLiteQueryAPI & {
|
|
|
372
414
|
export type SQLiteTransactionDB = SQLiteQueryAPI & {
|
|
373
415
|
commit: () => Promise<void>;
|
|
374
416
|
rollback: () => Promise<void>;
|
|
417
|
+
/**
|
|
418
|
+
* Aborted when this transaction fails or is abandoned — its own signal or
|
|
419
|
+
* timeout, close(), an abandoned write, or an error the callback lets
|
|
420
|
+
* escape — with the value `transaction()` rejects with. Never aborted when
|
|
421
|
+
* it succeeds. Hand it to work of your own the callback awaits, such as a
|
|
422
|
+
* `fetch`, so that work stops with the transaction.
|
|
423
|
+
*/
|
|
424
|
+
readonly signal: AbortSignal;
|
|
375
425
|
};
|
|
376
426
|
export {};
|
package/dist/bulk.d.ts
CHANGED
|
@@ -29,6 +29,21 @@ export declare const createBulk: (shared: {
|
|
|
29
29
|
read: ReadFn;
|
|
30
30
|
write: WriteFn;
|
|
31
31
|
transaction: TransactionFn;
|
|
32
|
+
/**
|
|
33
|
+
* Takes this batch's place in the caller's statement queue, SYNCHRONOUSLY,
|
|
34
|
+
* at the moment `flush()` commits to it — from `close()` or from the
|
|
35
|
+
* `enqueue()` that filled the buffer. `started` is what was issued before
|
|
36
|
+
* it; `done()` gives the place back.
|
|
37
|
+
*
|
|
38
|
+
* Supplied by a transaction, where every statement shares one connection.
|
|
39
|
+
* The client path supplies none: there each statement takes its own lease.
|
|
40
|
+
* Without it the batch posts a microtask after `flush()` returns, so a
|
|
41
|
+
* statement issued AFTER it runs first — a stale read rather than an error.
|
|
42
|
+
*/
|
|
43
|
+
reserve?: () => {
|
|
44
|
+
started: Promise<void>;
|
|
45
|
+
done: () => void;
|
|
46
|
+
};
|
|
32
47
|
}) => {
|
|
33
48
|
bulkWrite: <KEYS extends string>(table: string, keys: KEYS[], options?: SQLiteBulkWriteOptions, before?: Promise<unknown>) => {
|
|
34
49
|
enqueue: (data: { [K in KEYS]: any; }) => Promise<void>;
|
package/dist/client.d.ts
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SQLiteChunkOptions, SQLiteQueryOptions } from './api';
|
|
2
2
|
import { SQLiteError } from './errors';
|
|
3
|
+
import { type ClientInspection } from './inspect';
|
|
3
4
|
import { type SQLiteBuild, type SQLiteVFS } from './types';
|
|
4
5
|
/**
|
|
5
6
|
* Configuration options for creating a SQLite client.
|
|
6
7
|
*/
|
|
7
8
|
export type CreateSQLiteClientOptions = {
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* A label for this client, never for the database — the database file is
|
|
11
|
+
* the FIRST argument to `createSQLiteClient`, and this option has no effect
|
|
12
|
+
* on what is opened or where.
|
|
13
|
+
*
|
|
14
|
+
* It is reported as `db.debug.name`, and prefixes the `debug` logger's
|
|
15
|
+
* console output as `"<name> <n>"`, where `n` counts the clients created in
|
|
16
|
+
* this tab. Neither form is unique across the origin: the counter is
|
|
17
|
+
* per-tab, so two tabs both produce `"SQLite 1"`.
|
|
18
|
+
*
|
|
19
|
+
* @defaultValue `"SQLite"`
|
|
12
20
|
*/
|
|
13
21
|
name?: string;
|
|
14
22
|
/**
|
|
15
23
|
* Number of Web Workers spawned in the pool at initialization.
|
|
16
24
|
* A larger pool allows more concurrent read operations but increases
|
|
17
25
|
* memory consumption and OPFS file handle usage.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
26
|
+
* A VFS that holds a single connection, or gains nothing from a second one,
|
|
27
|
+
* caps this at `1` (`OPFSCoopSyncVFS` among them), and passing more throws at
|
|
28
|
+
* construction time. Omitting it never throws: the default is capped to what
|
|
29
|
+
* the VFS allows.
|
|
30
|
+
* The environment can cap it too: `OPFSWriteAheadVFS` and `OPFSAdaptiveVFS`
|
|
31
|
+
* run on one worker wherever `readwrite-unsafe` is missing, with no error, and
|
|
32
|
+
* warn once only when this option was passed. `db.poolSize` reports the size
|
|
33
|
+
* the pool runs at.
|
|
34
|
+
* @defaultValue `2`, or the VFS's maximum when it is lower
|
|
20
35
|
*/
|
|
21
36
|
poolSize?: number;
|
|
22
37
|
/**
|
|
23
38
|
* Which VFS stores the database. Required: a VFS decides *where* the bytes
|
|
24
39
|
* live, and a database written through one VFS is not visible through
|
|
25
|
-
* another. See
|
|
40
|
+
* another. See Browser compatibility and recommendations in VFS.md.
|
|
26
41
|
*/
|
|
27
42
|
vfs: SQLiteVFS;
|
|
28
43
|
/**
|
|
29
44
|
* Which wa-sqlite WebAssembly build to load. Defaults to the first entry of
|
|
30
45
|
* `VFS_CAPABILITIES[vfs]` — `sync` where the VFS supports it, since it is both the
|
|
31
46
|
* fastest and the most portable, otherwise `async`. `jspi` needs engine
|
|
32
|
-
* support; see the
|
|
47
|
+
* support; see the Builds section of VFS.md for versions.
|
|
33
48
|
*
|
|
34
49
|
* @throws at construction when the build is not one the chosen VFS supports.
|
|
35
50
|
*/
|
|
@@ -83,8 +98,10 @@ export type CreateSQLiteClientOptions = {
|
|
|
83
98
|
maxWorkerRestarts?: number;
|
|
84
99
|
/**
|
|
85
100
|
* Milliseconds a worker has to post `ready` after its `open` message is sent.
|
|
86
|
-
* On expiry the slot is failed immediately
|
|
87
|
-
*
|
|
101
|
+
* On expiry the slot is failed immediately, with a message naming the cause
|
|
102
|
+
* the client roster supports: another live client of this library holding
|
|
103
|
+
* the database, or a holder the roster cannot see — a page reloaded without
|
|
104
|
+
* `close()`, another library, native code.
|
|
88
105
|
* @defaultValue `30_000`
|
|
89
106
|
*/
|
|
90
107
|
openTimeout?: number;
|
|
@@ -97,15 +114,15 @@ export type CreateSQLiteClientOptions = {
|
|
|
97
114
|
/**
|
|
98
115
|
* Turns on the introspection subsystem exposed as `db.debug`, and the
|
|
99
116
|
* lifecycle log. A string is used as the log prefix; `true` falls back to the
|
|
100
|
-
* client
|
|
117
|
+
* client name (`"<name> <index>"`), which already names the workers.
|
|
101
118
|
*
|
|
102
119
|
* @defaultValue undefined — no collection, no output, `db.debug` undefined.
|
|
103
120
|
*/
|
|
104
121
|
debug?: string | boolean;
|
|
105
122
|
/**
|
|
106
123
|
* Called whenever a worker slot is permanently lost. Receives the slot index,
|
|
107
|
-
* the number of workers still alive after the loss, the
|
|
108
|
-
* and the error that killed the slot.
|
|
124
|
+
* the number of workers still alive after the loss, the pool's size
|
|
125
|
+
* (`db.poolSize`), and the error that killed the slot.
|
|
109
126
|
*
|
|
110
127
|
* Guaranteed to be called **before** the client is failed when the last slot
|
|
111
128
|
* is lost. Wrapped in try/catch — a throwing callback is reported through
|
|
@@ -125,7 +142,7 @@ export type WorkerLostEvent = {
|
|
|
125
142
|
index: number;
|
|
126
143
|
/** Number of workers still alive after this loss. */
|
|
127
144
|
live: number;
|
|
128
|
-
/** The
|
|
145
|
+
/** The number of workers the pool runs — `db.poolSize`, not the `poolSize` option: the two differ where the environment caps the pool. */
|
|
129
146
|
size: number;
|
|
130
147
|
/** The error that killed the worker. */
|
|
131
148
|
cause: SQLiteError;
|
|
@@ -164,7 +181,6 @@ export type WorkerLostEvent = {
|
|
|
164
181
|
* import { createSQLiteClient } from 'browser-sqlite';
|
|
165
182
|
*
|
|
166
183
|
* const db = createSQLiteClient('myapp.sqlite', {
|
|
167
|
-
* poolSize: 3,
|
|
168
184
|
* vfs: 'OPFSAdaptiveVFS',
|
|
169
185
|
* pragmas: { journal_mode: 'WAL', synchronous: 'NORMAL' },
|
|
170
186
|
* });
|
|
@@ -176,14 +192,14 @@ export type WorkerLostEvent = {
|
|
|
176
192
|
* ```
|
|
177
193
|
*/
|
|
178
194
|
export declare const createSQLiteClient: (file: string, clientOptions: CreateSQLiteClientOptions) => {
|
|
179
|
-
chunk: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteChunkOptions) => AsyncGenerator<T[], void,
|
|
180
|
-
read: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?:
|
|
181
|
-
write: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?:
|
|
195
|
+
chunk: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteChunkOptions) => AsyncGenerator<T[], void, unknown>;
|
|
196
|
+
read: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteChunkOptions) => Promise<T[]>;
|
|
197
|
+
write: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteQueryOptions) => Promise<{
|
|
182
198
|
result: T[];
|
|
183
199
|
affected: number;
|
|
184
200
|
}>;
|
|
185
|
-
stream: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteChunkOptions) => AsyncGenerator<T, void,
|
|
186
|
-
first: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?:
|
|
201
|
+
stream: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteChunkOptions) => AsyncGenerator<T, void, unknown>;
|
|
202
|
+
first: <T extends Record<string, unknown> = Record<string, unknown>>(sql: string, params?: unknown[], options?: SQLiteQueryOptions) => Promise<T | undefined>;
|
|
187
203
|
transaction: <T = void>(callback: (db: import("./api").SQLiteTransactionDB) => Promise<T>, options?: import("./api").SQLiteTransactionOptions) => Promise<T>;
|
|
188
204
|
bulkWrite: <KEYS extends string>(table: string, keys: KEYS[], options?: import("./api").SQLiteBulkWriteOptions, before?: Promise<unknown>) => {
|
|
189
205
|
enqueue: (data: { [K in KEYS]: any; }) => Promise<void>;
|
|
@@ -194,5 +210,12 @@ export declare const createSQLiteClient: (file: string, clientOptions: CreateSQL
|
|
|
194
210
|
close: () => Promise<number>;
|
|
195
211
|
};
|
|
196
212
|
close: () => Promise<void>;
|
|
213
|
+
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
|
214
|
+
readonly name: string;
|
|
215
|
+
readonly file: string;
|
|
216
|
+
readonly vfs: "AccessHandlePoolVFS" | "IDBBatchAtomicVFS" | "IDBMirrorVFS" | "MemoryAsyncVFS" | "MemoryVFS" | "OPFSAdaptiveVFS" | "OPFSAnyContextVFS" | "OPFSCoopSyncVFS" | "OPFSWriteAheadVFS";
|
|
217
|
+
readonly build: SQLiteBuild;
|
|
218
|
+
readonly poolSize: number;
|
|
219
|
+
inspect: () => Promise<ClientInspection>;
|
|
197
220
|
debug: import("./debug").ClientDebugState | undefined;
|
|
198
221
|
};
|
package/dist/delete.d.ts
CHANGED
|
@@ -24,9 +24,11 @@ export type DeleteDatabaseOptions = {
|
|
|
24
24
|
/**
|
|
25
25
|
* Deletes a database and the two siblings SQLite may leave beside it.
|
|
26
26
|
*
|
|
27
|
-
* Deleting a database that is not there
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* Deleting a database that is not there REJECTS with `DATABASE_NOT_FOUND`.
|
|
28
|
+
* This paragraph said the opposite until 2026-09-16 — that absence was success,
|
|
29
|
+
* as SQLite's own `xDelete` treats it — but the probe in `deleteDatabaseFiles`
|
|
30
|
+
* has always reported absence, and `delete.test.ts` pins that with a falsifier.
|
|
31
|
+
* The doc was the stale half, and it ships in the published `.d.ts`.
|
|
30
32
|
*
|
|
31
33
|
* Nothing a VFS keeps for itself is touched: not the IndexedDB store, which is
|
|
32
34
|
* shared by every database that VFS holds on this origin, and not the
|
|
@@ -35,8 +37,12 @@ export type DeleteDatabaseOptions = {
|
|
|
35
37
|
*
|
|
36
38
|
* @throws {SQLiteError} `INVALID_OPTION` when `vfs` is missing or the `build`
|
|
37
39
|
* is not one the VFS supports — synchronously in spirit, as a rejection here.
|
|
38
|
-
* @throws {SQLiteError} `
|
|
39
|
-
*
|
|
40
|
+
* @throws {SQLiteError} `DATABASE_IN_USE` when the database is open, in this
|
|
41
|
+
* tab or another. A connection already holding its handles cannot be
|
|
40
42
|
* revoked from here; see the README's Known Limitations.
|
|
43
|
+
* @throws {SQLiteError} `BUSY` when the database is being opened or deleted
|
|
44
|
+
* elsewhere. Try again in a moment.
|
|
45
|
+
* @throws {SQLiteError} `DATABASE_NOT_FOUND` when there is no such database.
|
|
46
|
+
* A caller deleting speculatively should catch this one code.
|
|
41
47
|
*/
|
|
42
48
|
export declare const deleteDatabase: (file: string, options: DeleteDatabaseOptions) => Promise<void>;
|
package/dist/epochs.d.ts
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* The `v1` suffix separates incompatible shapes. Bump it ONLY if the shape
|
|
13
13
|
* changes — bumping it per release recreates the fragmentation it prevents.
|
|
14
14
|
*/
|
|
15
|
+
import type { Locks } from './locks';
|
|
16
|
+
import type { SQLiteVFS } from './types';
|
|
15
17
|
/**
|
|
16
18
|
* The statement the barrier runs and discards.
|
|
17
19
|
*
|
|
@@ -23,19 +25,47 @@
|
|
|
23
25
|
* the refresh still returns the stale result.
|
|
24
26
|
*/
|
|
25
27
|
export declare const BARRIER_SQL = "SELECT count(*) FROM sqlite_master";
|
|
28
|
+
/**
|
|
29
|
+
* The marker a realm holds to publish the epoch it last committed.
|
|
30
|
+
*
|
|
31
|
+
* Held in SHARED mode: many realms may hold one name at once, so publishing
|
|
32
|
+
* never waits and two realms can never collide on a number. Nobody reads the
|
|
33
|
+
* lock — the NAME is the state, which is why this beats a BroadcastChannel:
|
|
34
|
+
* there is no message that can still be in flight.
|
|
35
|
+
*/
|
|
36
|
+
export declare const epochLockName: (ns: string, file: string, n: number) => string;
|
|
37
|
+
/**
|
|
38
|
+
* The highest epoch any realm in this origin has published under `prefix`.
|
|
39
|
+
*
|
|
40
|
+
* The tail after the prefix must be ALL digits, which is stricter than a
|
|
41
|
+
* prefix match plus `lastIndexOf(':')` and is the point: a normalized file may
|
|
42
|
+
* contain a colon (`new URL('./a:b', 'file://').pathname` is `a:b`), so the
|
|
43
|
+
* loose form would read another database's epoch as this one's.
|
|
44
|
+
*/
|
|
45
|
+
export declare const maxEpochIn: (heldNames: string[], prefix: string) => number;
|
|
26
46
|
export type Epochs = {
|
|
27
|
-
/** The number of commits observed
|
|
47
|
+
/** The number of commits observed for this database, floor included. */
|
|
28
48
|
current: () => number;
|
|
29
49
|
/** Records one commit and returns the new epoch. */
|
|
30
50
|
bump: () => number;
|
|
51
|
+
/** Raises the local floor. Never lowers it. */
|
|
52
|
+
raiseTo: (n: number) => void;
|
|
53
|
+
/** The highest epoch published by any realm in this origin. */
|
|
54
|
+
originMax: () => Promise<number>;
|
|
55
|
+
/** Publishes `n` for this realm, replacing its previous marker. */
|
|
56
|
+
publish: (n: number) => Promise<void>;
|
|
31
57
|
};
|
|
32
58
|
/**
|
|
33
|
-
* Handles onto the counter for `file`, which MUST already be
|
|
34
|
-
* `normalizeDatabaseFile`. Entries are never removed: deleting
|
|
35
|
-
* restart the counter at 0, and a worker still alive with `seen = 5`
|
|
36
|
-
* then read `5 > 0`, believe itself current forever, and serve stale
|
|
59
|
+
* Handles onto the counter for `(namespace, file)`, which MUST already be
|
|
60
|
+
* normalized by `normalizeDatabaseFile`. Entries are never removed: deleting
|
|
61
|
+
* one would restart the counter at 0, and a worker still alive with `seen = 5`
|
|
62
|
+
* would then read `5 > 0`, believe itself current forever, and serve stale
|
|
63
|
+
* data.
|
|
64
|
+
*
|
|
65
|
+
* The cell is realm-wide, so every client in a tab shares one counter AND one
|
|
66
|
+
* marker — publication is per realm, not per client.
|
|
37
67
|
*/
|
|
38
|
-
export declare const epochsFor: (file: string) => Epochs;
|
|
68
|
+
export declare const epochsFor: (vfs: SQLiteVFS, file: string, locks: Locks) => Epochs;
|
|
39
69
|
/**
|
|
40
70
|
* Where a worker's `seen` lands after the write it just served.
|
|
41
71
|
*
|
package/dist/errors.d.ts
CHANGED
|
@@ -2,19 +2,58 @@
|
|
|
2
2
|
* Every failure this library raises on its own behalf. A caller discriminates
|
|
3
3
|
* on `code`, or on `name` — they carry the same value, so `err.name` reads the
|
|
4
4
|
* way `'AbortError'` does on the DOMException an aborted signal throws.
|
|
5
|
+
* `DATABASE_IN_USE` is this library's own: a database that a live client holds,
|
|
6
|
+
* as opposed to `BUSY`, which covers a transient conflict worth retrying.
|
|
7
|
+
* `DATABASE_NOT_FOUND` is raised only by `deleteDatabase`: there is nothing at
|
|
8
|
+
* that name to delete. `createSQLiteClient` creates what is absent, so it has
|
|
9
|
+
* no such case.
|
|
10
|
+
* `UNSUPPORTED` means the platform cannot answer the question — raised by
|
|
11
|
+
* `inspectDatabase` where Web Locks is missing, because reporting zero clients
|
|
12
|
+
* there would be indistinguishable from a database nobody holds.
|
|
13
|
+
* `OPERATION_TIMEOUT` is the `timeout` a caller set on a call being spent. It is
|
|
14
|
+
* deliberately not `TIMEOUT`, which means a deadline this library imposed on
|
|
15
|
+
* itself — a worker that never became ready, a deletion that did not complete.
|
|
16
|
+
* `STATEMENT_FAILED` is a statement SQLite refused or failed for any reason
|
|
17
|
+
* but a lock conflict — a constraint, a syntax error, a full disk. `message` is
|
|
18
|
+
* SQLite's own; `sqliteCode` carries its result code, and `sqliteExtendedCode`
|
|
19
|
+
* its subtype when SQLite reports one.
|
|
5
20
|
*/
|
|
6
|
-
|
|
21
|
+
import type { SQLiteExtendedResultCode, SQLiteResultCode } from './sqlite-codes';
|
|
22
|
+
export type SQLiteErrorCode = 'NOT_A_READ_QUERY' | 'CLIENT_CLOSED' | 'WORKER_CRASHED' | 'TIMEOUT' | 'PROTOCOL_ERROR' | 'INVALID_IDENTIFIER' | 'INVALID_OPTION' | 'INVALID_PRAGMA' | 'BULK_WRITE_FAILED' | 'BUSY' | 'STATEMENT_FAILED' | 'DATABASE_IN_USE' | 'DATABASE_NOT_FOUND' | 'READ_ONLY_TRANSACTION' | 'UNSUPPORTED' | 'WORKER_BUSY' | 'OPERATION_TIMEOUT' | 'TRANSACTION_CLOSED';
|
|
7
23
|
export declare class SQLiteError extends Error {
|
|
8
24
|
readonly code: SQLiteErrorCode;
|
|
9
25
|
/**
|
|
10
26
|
* SQLite's own numeric result code, present only when the failure came from
|
|
11
|
-
* SQLite rather than from this library.
|
|
12
|
-
* and SQLITE_LOCKED (6); this is how a caller
|
|
27
|
+
* SQLite rather than from this library. Always the PRIMARY code. `BUSY`
|
|
28
|
+
* covers both SQLITE_BUSY (5) and SQLITE_LOCKED (6); this is how a caller
|
|
29
|
+
* tells them apart. Typed `SQLiteResultCode` (D10): since `sqliteCodeOf`,
|
|
30
|
+
* it is always a primary code of the bundled SQLite, so comparing it with
|
|
31
|
+
* an extended code does not compile.
|
|
13
32
|
*/
|
|
14
|
-
readonly sqliteCode?:
|
|
33
|
+
readonly sqliteCode?: SQLiteResultCode;
|
|
34
|
+
/**
|
|
35
|
+
* SQLite's extended result code, present only when a statement SQLite ran
|
|
36
|
+
* failed WITH A SUBTYPE — `STATEMENT_FAILED` or `BUSY` from a query, never
|
|
37
|
+
* an open or a delete: 2067 (`SQLITE_EXTENDED_CODES.CONSTRAINT_UNIQUE`)
|
|
38
|
+
* under `sqliteCode` 19. Absent when SQLite has no subtype for the failure
|
|
39
|
+
* (a full disk, a syntax error), since `sqliteCode` already says it. For a
|
|
40
|
+
* subtype SQLite reports, `(sqliteExtendedCode & 0xff) === sqliteCode` is
|
|
41
|
+
* SQLite's own guarantee, not something this library enforces: the client
|
|
42
|
+
* deliberately lets a differing value through (a 0 from a wrong read).
|
|
43
|
+
* Typed open (`SQLiteExtendedResultCode | (number & {})`, D10): D9 lets a
|
|
44
|
+
* wrong read through, which a strict type would misdescribe.
|
|
45
|
+
*/
|
|
46
|
+
readonly sqliteExtendedCode?: SQLiteExtendedResultCode | (number & {});
|
|
47
|
+
/**
|
|
48
|
+
* The `timeout` that was exceeded, in milliseconds. Present only on
|
|
49
|
+
* `OPERATION_TIMEOUT`, so a log need not parse the message for it.
|
|
50
|
+
*/
|
|
51
|
+
readonly timeout?: number;
|
|
15
52
|
constructor(code: SQLiteErrorCode, message: string, options?: {
|
|
16
53
|
cause?: unknown;
|
|
17
|
-
sqliteCode?:
|
|
54
|
+
sqliteCode?: SQLiteResultCode;
|
|
55
|
+
sqliteExtendedCode?: SQLiteExtendedResultCode | (number & {});
|
|
56
|
+
timeout?: number;
|
|
18
57
|
});
|
|
19
58
|
}
|
|
20
59
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -3,4 +3,6 @@ export { detectFeatures, missingFeature } from './capabilities';
|
|
|
3
3
|
export * from './client';
|
|
4
4
|
export * from './delete';
|
|
5
5
|
export * from './errors';
|
|
6
|
+
export { type ClientInspection, type DatabaseClient, type DatabaseInspection, type InspectDatabaseOptions, type InspectionBase, inspectDatabase, } from './inspect';
|
|
7
|
+
export { SQLITE_CODES, SQLITE_EXTENDED_CODES, type SQLiteExtendedResultCode, type SQLiteResultCode, } from './sqlite-codes';
|
|
6
8
|
export { defaultBuildFor, type PlatformFeature, type SQLiteBuild, type SQLiteVFS, VFS_CAPABILITIES, type VFSCapability, type VFSLayout, type VFSMemoryModel, type VFSStorage, } from './types';
|