firebird-wasm 0.1.0

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 (66) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +120 -0
  3. package/dist/.tsbuildinfo.build +1 -0
  4. package/dist/browser/db-lock.d.ts +92 -0
  5. package/dist/browser/db-lock.d.ts.map +1 -0
  6. package/dist/browser/db-lock.js +163 -0
  7. package/dist/browser/db-lock.js.map +1 -0
  8. package/dist/browser/engine-transport.d.ts +94 -0
  9. package/dist/browser/engine-transport.d.ts.map +1 -0
  10. package/dist/browser/engine-transport.js +217 -0
  11. package/dist/browser/engine-transport.js.map +1 -0
  12. package/dist/browser/field-types.d.ts +19 -0
  13. package/dist/browser/field-types.d.ts.map +1 -0
  14. package/dist/browser/field-types.js +79 -0
  15. package/dist/browser/field-types.js.map +1 -0
  16. package/dist/browser/firebird-browser.d.ts +249 -0
  17. package/dist/browser/firebird-browser.d.ts.map +1 -0
  18. package/dist/browser/firebird-browser.js +401 -0
  19. package/dist/browser/firebird-browser.js.map +1 -0
  20. package/dist/browser/index.d.ts +31 -0
  21. package/dist/browser/index.d.ts.map +1 -0
  22. package/dist/browser/index.js +39 -0
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/indexeddb-vfs.d.ts +132 -0
  25. package/dist/browser/indexeddb-vfs.d.ts.map +1 -0
  26. package/dist/browser/indexeddb-vfs.js +285 -0
  27. package/dist/browser/indexeddb-vfs.js.map +1 -0
  28. package/dist/browser/params.d.ts +33 -0
  29. package/dist/browser/params.d.ts.map +1 -0
  30. package/dist/browser/params.js +92 -0
  31. package/dist/browser/params.js.map +1 -0
  32. package/dist/browser/sql-script.d.ts +27 -0
  33. package/dist/browser/sql-script.d.ts.map +1 -0
  34. package/dist/browser/sql-script.js +132 -0
  35. package/dist/browser/sql-script.js.map +1 -0
  36. package/dist/browser/worker-entry.d.ts +45 -0
  37. package/dist/browser/worker-entry.d.ts.map +1 -0
  38. package/dist/browser/worker-entry.js +79 -0
  39. package/dist/browser/worker-entry.js.map +1 -0
  40. package/dist/browser/worker-protocol.d.ts +37 -0
  41. package/dist/browser/worker-protocol.d.ts.map +1 -0
  42. package/dist/browser/worker-protocol.js +10 -0
  43. package/dist/browser/worker-protocol.js.map +1 -0
  44. package/dist/browser/worker-transport.d.ts +63 -0
  45. package/dist/browser/worker-transport.d.ts.map +1 -0
  46. package/dist/browser/worker-transport.js +133 -0
  47. package/dist/browser/worker-transport.js.map +1 -0
  48. package/dist/firebird.d.ts +73 -0
  49. package/dist/firebird.d.ts.map +1 -0
  50. package/dist/firebird.js +208 -0
  51. package/dist/firebird.js.map +1 -0
  52. package/dist/index.d.ts +22 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +28 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/types.d.ts +88 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +6 -0
  59. package/dist/types.js.map +1 -0
  60. package/dist/wasm/firebird-embedded.js +2 -0
  61. package/dist/wasm/firebird-embedded.wasm +0 -0
  62. package/dist/wasm-loader.d.ts +162 -0
  63. package/dist/wasm-loader.d.ts.map +1 -0
  64. package/dist/wasm-loader.js +103 -0
  65. package/dist/wasm-loader.js.map +1 -0
  66. package/package.json +86 -0
@@ -0,0 +1,249 @@
1
+ /**
2
+ * firebird-browser.ts – Browser-compatible FirebirdLite backed by WASM + IndexedDB.
3
+ *
4
+ * Provides the same PGlite-style async API as the Node.js `FirebirdLite` class,
5
+ * but runs entirely in the browser using:
6
+ *
7
+ * 1. The Firebird Embedded engine compiled to WebAssembly (see `wasm/`).
8
+ * 2. An IndexedDB-backed virtual filesystem for durable page storage.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import { FirebirdBrowser } from 'firebird-wasm/browser';
13
+ *
14
+ * // A browser must run the engine in a Worker — see the `worker` option.
15
+ * const db = new FirebirdBrowser('mydb', {
16
+ * worker: new Worker('/firebird-engine-worker.js'),
17
+ * });
18
+ *
19
+ * await db.exec('CREATE TABLE t (id INTEGER, name VARCHAR(100))');
20
+ * const result = await db.query('SELECT * FROM t');
21
+ * await db.close();
22
+ * ```
23
+ */
24
+ import type { IndexedDBVFSOptions } from './indexeddb-vfs';
25
+ import type { EngineHandle, EngineTransport } from './engine-transport';
26
+ import type { QueryResult, Row, QueryParams, TransactionOptions } from '../types';
27
+ /** What a statement did. Returned by `exec()`. */
28
+ export interface ExecResult {
29
+ /** Rows affected — for INSERT, UPDATE and DELETE. 0 for DDL. */
30
+ affectedRows: number;
31
+ }
32
+ /** Options for creating a {@link FirebirdBrowser} instance. */
33
+ export interface FirebirdBrowserOptions {
34
+ /** Options forwarded to the IndexedDB VFS layer. */
35
+ vfs?: IndexedDBVFSOptions;
36
+ /**
37
+ * URL or `ArrayBuffer` of the `firebird-embedded.wasm` binary.
38
+ * Passed through to the engine loader.
39
+ */
40
+ wasmBinary?: ArrayBuffer | string;
41
+ /**
42
+ * Custom `locateFile` callback for Emscripten.
43
+ * @see {@link import('../wasm-loader').WasmLoadOptions.locateFile}
44
+ */
45
+ locateFile?: (filename: string) => string;
46
+ /**
47
+ * Worker running the engine.
48
+ *
49
+ * **Browsers need this.** The WASM build uses pthreads, so Firebird blocks
50
+ * on mutexes while opening a database, and a browser main thread is not
51
+ * allowed to block — without a Worker the page deadlocks. Build the Worker
52
+ * script from `firebird-wasm/browser/worker-entry`.
53
+ *
54
+ * Omit it only where blocking the calling thread is acceptable, such as
55
+ * Node or a test harness driving a stub engine.
56
+ */
57
+ worker?: Worker;
58
+ /**
59
+ * Use a transport of your own. Takes precedence over `worker`; mainly a
60
+ * seam for tests.
61
+ */
62
+ transport?: EngineTransport;
63
+ /**
64
+ * Persist to IndexedDB automatically after writes.
65
+ *
66
+ * Without this, a tab closed without `close()` loses everything written in
67
+ * that session — the common way to leave a page. Enabled by default:
68
+ * silently losing committed data is a worse default than the cost of
69
+ * writing it.
70
+ *
71
+ * Set `false` to persist only on `close()` and explicit `persist()` calls.
72
+ *
73
+ * @default true
74
+ */
75
+ autoPersist?: boolean;
76
+ /**
77
+ * How long to wait after the last write before persisting, in
78
+ * milliseconds. Bursts of statements coalesce into one persist.
79
+ *
80
+ * @default 500
81
+ */
82
+ autoPersistDebounceMs?: number;
83
+ /**
84
+ * Called when a background persist fails.
85
+ *
86
+ * Background persists cannot reject into caller code, and swallowing the
87
+ * error would hide data loss, so it is reported here. Defaults to
88
+ * `console.error`.
89
+ */
90
+ onPersistError?: (error: Error) => void;
91
+ /**
92
+ * What to do when the same database is already open in another tab.
93
+ *
94
+ * Every tab keeps its own complete copy of the database and persists the
95
+ * whole image, so two writers do not interleave — the later persist discards
96
+ * the earlier tab's work entirely, with both tabs reporting success.
97
+ *
98
+ * - `'exclusive'` (default) takes a cross-tab lock and fails with
99
+ * {@link DatabaseLockedError} if another tab will not release it in time.
100
+ * - `'allow-unsafe'` skips the lock. Only sound when at most one of the
101
+ * tabs writes.
102
+ *
103
+ * @default 'exclusive'
104
+ */
105
+ multiTab?: 'exclusive' | 'allow-unsafe';
106
+ /**
107
+ * How long to wait for another tab to release the database, in
108
+ * milliseconds. `Infinity` waits indefinitely.
109
+ *
110
+ * @default 5000
111
+ */
112
+ lockTimeoutMs?: number;
113
+ }
114
+ /**
115
+ * Browser-side Firebird database backed by WASM + IndexedDB.
116
+ *
117
+ * Mirrors the `FirebirdLite` API so application code can switch between the
118
+ * Node.js native driver and the in-browser WASM engine with minimal changes.
119
+ */
120
+ export declare class FirebirdBrowser {
121
+ private readonly dbName;
122
+ private readonly options;
123
+ private readonly vfs;
124
+ private readonly engine;
125
+ private dbHandle;
126
+ private closed;
127
+ private initPromise;
128
+ private readonly autoPersist;
129
+ private readonly autoPersistDebounceMs;
130
+ private readonly onPersistError;
131
+ private persistTimer;
132
+ /** In-flight persist, so two never overlap. */
133
+ private persistInFlight;
134
+ /** A write arrived while a persist was running; persist again after it. */
135
+ private persistAgain;
136
+ private lifecycleAttached;
137
+ private readonly multiTab;
138
+ private readonly lockTimeoutMs;
139
+ /** Held for the connection's lifetime; released by close(). */
140
+ private lock;
141
+ /**
142
+ * @param dbName Logical database name. Used as the IndexedDB store name
143
+ * and the filename inside Emscripten's virtual FS.
144
+ * @param options Optional configuration.
145
+ */
146
+ constructor(dbName: string, options?: FirebirdBrowserOptions);
147
+ /** Path of the database inside Emscripten's filesystem. */
148
+ private get dbPath();
149
+ /**
150
+ * Execute one or more statements that do not return rows.
151
+ *
152
+ * A script may contain several statements, which is what makes this usable
153
+ * for migrations. Statement boundaries respect string literals, quoted
154
+ * identifiers, comments and `SET TERM`, so a stored procedure body full of
155
+ * semicolons survives intact. Each statement runs in its own transaction,
156
+ * committed on success — a failure part-way leaves the statements before it
157
+ * committed, as it would in `isql`.
158
+ *
159
+ * Parameters may only be supplied for a single statement: there is no way to
160
+ * say which statement a value belongs to otherwise. Use `query()` for
161
+ * parameterised statements that return rows.
162
+ *
163
+ * @returns one result per statement, in order.
164
+ */
165
+ exec(sql: string, params?: QueryParams): Promise<ExecResult[]>;
166
+ /**
167
+ * Execute a SQL query and return the result rows.
168
+ *
169
+ * Parameters are bound with `?` placeholders, as in the Node.js backend:
170
+ *
171
+ * ```ts
172
+ * await db.query('SELECT * FROM items WHERE id = ?', [1]);
173
+ * ```
174
+ */
175
+ query<T extends Row = Row>(sql: string, params?: QueryParams, _options?: TransactionOptions): Promise<QueryResult<T>>;
176
+ /**
177
+ * Run a function inside an explicit transaction.
178
+ */
179
+ transaction<T>(fn: (tx: FirebirdBrowserTransaction) => Promise<T>, _options?: TransactionOptions): Promise<T>;
180
+ /**
181
+ * Persist the in-memory database pages to IndexedDB.
182
+ * Call this periodically or before the page unloads to avoid data loss.
183
+ */
184
+ persist(): Promise<void>;
185
+ /**
186
+ * Close the database and release all resources.
187
+ */
188
+ close(): Promise<void>;
189
+ /** Release the cross-tab lock, if this instance holds one. */
190
+ private releaseLock;
191
+ /** Note that the database has changed and schedule a persist. */
192
+ private markDirty;
193
+ private cancelScheduledPersist;
194
+ /**
195
+ * Persist without a caller to reject into.
196
+ *
197
+ * Failures are reported through `onPersistError`; letting them become
198
+ * unhandled rejections would hide data loss.
199
+ */
200
+ private persistInBackground;
201
+ /**
202
+ * Flush when the page is being hidden or unloaded.
203
+ *
204
+ * `visibilitychange` to hidden is the event to rely on: it fires on mobile
205
+ * when an app is backgrounded, where `beforeunload` and `unload` often do
206
+ * not fire at all. `pagehide` covers the bfcache case. Neither can await
207
+ * an async write, so this is best-effort — which is why writes are also
208
+ * persisted on a debounce rather than only here.
209
+ */
210
+ private attachLifecycleListeners;
211
+ private detachLifecycleListeners;
212
+ private readonly onVisibilityChange;
213
+ private readonly onPageHide;
214
+ private ensureReady;
215
+ private init;
216
+ }
217
+ /**
218
+ * A handle to an active transaction in the browser WASM engine.
219
+ *
220
+ * Statements issued here are bound to the transaction handle, so a rollback
221
+ * really does undo them.
222
+ */
223
+ export declare class FirebirdBrowserTransaction {
224
+ private readonly engine;
225
+ private readonly dbHandle;
226
+ private readonly txHandle;
227
+ private finished;
228
+ constructor(engine: EngineTransport, dbHandle: EngineHandle, txHandle: EngineHandle);
229
+ /** Whether this transaction has already been rolled back. */
230
+ get isFinished(): boolean;
231
+ /**
232
+ * Roll this transaction back and stop.
233
+ *
234
+ * The enclosing `transaction()` will not commit afterwards. Use this to
235
+ * abandon a transaction deliberately, rather than throwing an error you do
236
+ * not mean — throwing also rolls back, but it propagates to the caller.
237
+ */
238
+ rollback(): Promise<void>;
239
+ private assertUsable;
240
+ /**
241
+ * Execute a DDL/DML statement inside this transaction.
242
+ *
243
+ * @returns the number of rows affected.
244
+ */
245
+ exec(sql: string, params?: QueryParams): Promise<ExecResult>;
246
+ /** Execute a SELECT inside this transaction and return rows. */
247
+ query<T extends Row = Row>(sql: string, params?: QueryParams): Promise<QueryResult<T>>;
248
+ }
249
+ //# sourceMappingURL=firebird-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebird-browser.d.ts","sourceRoot":"","sources":["../../src/browser/firebird-browser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,401 @@
1
+ "use strict";
2
+ /**
3
+ * firebird-browser.ts – Browser-compatible FirebirdLite backed by WASM + IndexedDB.
4
+ *
5
+ * Provides the same PGlite-style async API as the Node.js `FirebirdLite` class,
6
+ * but runs entirely in the browser using:
7
+ *
8
+ * 1. The Firebird Embedded engine compiled to WebAssembly (see `wasm/`).
9
+ * 2. An IndexedDB-backed virtual filesystem for durable page storage.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * import { FirebirdBrowser } from 'firebird-wasm/browser';
14
+ *
15
+ * // A browser must run the engine in a Worker — see the `worker` option.
16
+ * const db = new FirebirdBrowser('mydb', {
17
+ * worker: new Worker('/firebird-engine-worker.js'),
18
+ * });
19
+ *
20
+ * await db.exec('CREATE TABLE t (id INTEGER, name VARCHAR(100))');
21
+ * const result = await db.query('SELECT * FROM t');
22
+ * await db.close();
23
+ * ```
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.FirebirdBrowserTransaction = exports.FirebirdBrowser = void 0;
27
+ const indexeddb_vfs_1 = require("./indexeddb-vfs");
28
+ const engine_transport_1 = require("./engine-transport");
29
+ const worker_transport_1 = require("./worker-transport");
30
+ const sql_script_1 = require("./sql-script");
31
+ const db_lock_1 = require("./db-lock");
32
+ // ---------------------------------------------------------------------------
33
+ // Shared helpers
34
+ // ---------------------------------------------------------------------------
35
+ // ---------------------------------------------------------------------------
36
+ // Implementation
37
+ // ---------------------------------------------------------------------------
38
+ /**
39
+ * Browser-side Firebird database backed by WASM + IndexedDB.
40
+ *
41
+ * Mirrors the `FirebirdLite` API so application code can switch between the
42
+ * Node.js native driver and the in-browser WASM engine with minimal changes.
43
+ */
44
+ class FirebirdBrowser {
45
+ /**
46
+ * @param dbName Logical database name. Used as the IndexedDB store name
47
+ * and the filename inside Emscripten's virtual FS.
48
+ * @param options Optional configuration.
49
+ */
50
+ constructor(dbName, options = {}) {
51
+ this.dbHandle = 0;
52
+ this.closed = false;
53
+ this.initPromise = null;
54
+ this.persistTimer = null;
55
+ /** In-flight persist, so two never overlap. */
56
+ this.persistInFlight = null;
57
+ /** A write arrived while a persist was running; persist again after it. */
58
+ this.persistAgain = false;
59
+ this.lifecycleAttached = false;
60
+ /** Held for the connection's lifetime; released by close(). */
61
+ this.lock = null;
62
+ this.onVisibilityChange = () => {
63
+ if (document.visibilityState === 'hidden') {
64
+ this.cancelScheduledPersist();
65
+ void this.persistInBackground();
66
+ }
67
+ };
68
+ this.onPageHide = () => {
69
+ this.cancelScheduledPersist();
70
+ void this.persistInBackground();
71
+ };
72
+ this.dbName = dbName;
73
+ this.options = options;
74
+ this.vfs = new indexeddb_vfs_1.IndexedDBVFS(options.vfs);
75
+ this.multiTab = options.multiTab ?? 'exclusive';
76
+ this.lockTimeoutMs = options.lockTimeoutMs ?? 5000;
77
+ this.autoPersist = options.autoPersist ?? true;
78
+ this.autoPersistDebounceMs = options.autoPersistDebounceMs ?? 500;
79
+ this.onPersistError =
80
+ options.onPersistError ??
81
+ ((error) => console.error('[firebird-wasm] background persist failed', error));
82
+ this.engine =
83
+ options.transport ??
84
+ (options.worker
85
+ ? new worker_transport_1.WorkerTransport(options.worker)
86
+ : new engine_transport_1.DirectTransport({
87
+ wasmBinary: options.wasmBinary,
88
+ locateFile: options.locateFile,
89
+ }));
90
+ }
91
+ /** Path of the database inside Emscripten's filesystem. */
92
+ get dbPath() {
93
+ return `/data/${this.dbName}.fdb`;
94
+ }
95
+ // ── Public API (mirrors FirebirdLite) ─────────────────────────────────
96
+ /**
97
+ * Execute one or more statements that do not return rows.
98
+ *
99
+ * A script may contain several statements, which is what makes this usable
100
+ * for migrations. Statement boundaries respect string literals, quoted
101
+ * identifiers, comments and `SET TERM`, so a stored procedure body full of
102
+ * semicolons survives intact. Each statement runs in its own transaction,
103
+ * committed on success — a failure part-way leaves the statements before it
104
+ * committed, as it would in `isql`.
105
+ *
106
+ * Parameters may only be supplied for a single statement: there is no way to
107
+ * say which statement a value belongs to otherwise. Use `query()` for
108
+ * parameterised statements that return rows.
109
+ *
110
+ * @returns one result per statement, in order.
111
+ */
112
+ async exec(sql, params = []) {
113
+ await this.ensureReady();
114
+ const statements = (0, sql_script_1.splitStatements)(sql);
115
+ if (params.length > 0 && statements.length > 1) {
116
+ throw new Error(`Parameters cannot be used with a multi-statement script ` +
117
+ `(${statements.length} statements found); run the statements separately`);
118
+ }
119
+ const results = [];
120
+ for (const statement of statements) {
121
+ const affectedRows = await this.engine.execute(this.dbHandle, 0, statement.sql, params);
122
+ results.push({ affectedRows });
123
+ }
124
+ if (results.length > 0) {
125
+ this.markDirty();
126
+ }
127
+ return results;
128
+ }
129
+ /**
130
+ * Execute a SQL query and return the result rows.
131
+ *
132
+ * Parameters are bound with `?` placeholders, as in the Node.js backend:
133
+ *
134
+ * ```ts
135
+ * await db.query('SELECT * FROM items WHERE id = ?', [1]);
136
+ * ```
137
+ */
138
+ async query(sql, params = [], _options = {}) {
139
+ await this.ensureReady();
140
+ return this.engine.query(this.dbHandle, 0, sql, params);
141
+ }
142
+ /**
143
+ * Run a function inside an explicit transaction.
144
+ */
145
+ async transaction(fn, _options = {}) {
146
+ await this.ensureReady();
147
+ const txHandle = await this.engine.startTransaction(this.dbHandle);
148
+ const tx = new FirebirdBrowserTransaction(this.engine, this.dbHandle, txHandle);
149
+ let result;
150
+ try {
151
+ result = await fn(tx);
152
+ }
153
+ catch (err) {
154
+ if (!tx.isFinished) {
155
+ await this.engine.rollback(txHandle);
156
+ }
157
+ throw err;
158
+ }
159
+ // The callback may have rolled back explicitly; committing after that
160
+ // would target a handle the engine has already finished with.
161
+ if (tx.isFinished) {
162
+ this.markDirty();
163
+ return result;
164
+ }
165
+ // A failed commit finishes the transaction too, so there is nothing left
166
+ // to roll back here.
167
+ await this.engine.commit(txHandle);
168
+ this.markDirty();
169
+ return result;
170
+ }
171
+ /**
172
+ * Persist the in-memory database pages to IndexedDB.
173
+ * Call this periodically or before the page unloads to avoid data loss.
174
+ */
175
+ async persist() {
176
+ if (!this.dbHandle)
177
+ return;
178
+ // Two persists must not interleave: both read the image and write the
179
+ // same store, and the later one could finish first and roll the database
180
+ // back to an older state.
181
+ if (this.persistInFlight) {
182
+ this.persistAgain = true;
183
+ await this.persistInFlight;
184
+ return;
185
+ }
186
+ this.cancelScheduledPersist();
187
+ const run = (async () => {
188
+ const image = await this.engine.readFile(this.dbPath);
189
+ await this.vfs.importDatabase(image);
190
+ })();
191
+ this.persistInFlight = run;
192
+ try {
193
+ await run;
194
+ }
195
+ finally {
196
+ this.persistInFlight = null;
197
+ }
198
+ // Writes that arrived mid-persist are not covered by the image just
199
+ // written, so go again.
200
+ if (this.persistAgain) {
201
+ this.persistAgain = false;
202
+ await this.persist();
203
+ }
204
+ }
205
+ /**
206
+ * Close the database and release all resources.
207
+ */
208
+ async close() {
209
+ if (this.closed)
210
+ return;
211
+ // Stop scheduling before marking closed, so nothing fires mid-teardown.
212
+ this.cancelScheduledPersist();
213
+ this.detachLifecycleListeners();
214
+ // A background persist may still be running; let it finish so it cannot
215
+ // write after the engine has gone.
216
+ if (this.persistInFlight) {
217
+ try {
218
+ await this.persistInFlight;
219
+ }
220
+ catch {
221
+ // Already reported through onPersistError.
222
+ }
223
+ }
224
+ this.closed = true;
225
+ if (this.dbHandle) {
226
+ // Persist before closing.
227
+ await this.persist();
228
+ await this.engine.detachDatabase(this.dbHandle);
229
+ this.dbHandle = 0;
230
+ }
231
+ try {
232
+ await this.vfs.close();
233
+ await this.engine.dispose();
234
+ }
235
+ finally {
236
+ // Last, and unconditionally: a lock still held after a failed teardown
237
+ // locks the database out of every future tab until the page is gone.
238
+ await this.releaseLock();
239
+ }
240
+ }
241
+ /** Release the cross-tab lock, if this instance holds one. */
242
+ async releaseLock() {
243
+ const lock = this.lock;
244
+ this.lock = null;
245
+ await lock?.release();
246
+ }
247
+ // ── Automatic persistence ─────────────────────────────────────────────
248
+ /** Note that the database has changed and schedule a persist. */
249
+ markDirty() {
250
+ if (!this.autoPersist || this.closed)
251
+ return;
252
+ if (this.persistTimer !== null) {
253
+ clearTimeout(this.persistTimer);
254
+ }
255
+ this.persistTimer = setTimeout(() => {
256
+ this.persistTimer = null;
257
+ void this.persistInBackground();
258
+ }, this.autoPersistDebounceMs);
259
+ }
260
+ cancelScheduledPersist() {
261
+ if (this.persistTimer !== null) {
262
+ clearTimeout(this.persistTimer);
263
+ this.persistTimer = null;
264
+ }
265
+ }
266
+ /**
267
+ * Persist without a caller to reject into.
268
+ *
269
+ * Failures are reported through `onPersistError`; letting them become
270
+ * unhandled rejections would hide data loss.
271
+ */
272
+ async persistInBackground() {
273
+ if (this.closed)
274
+ return;
275
+ try {
276
+ await this.persist();
277
+ }
278
+ catch (err) {
279
+ this.onPersistError(err instanceof Error ? err : new Error(String(err)));
280
+ }
281
+ }
282
+ /**
283
+ * Flush when the page is being hidden or unloaded.
284
+ *
285
+ * `visibilitychange` to hidden is the event to rely on: it fires on mobile
286
+ * when an app is backgrounded, where `beforeunload` and `unload` often do
287
+ * not fire at all. `pagehide` covers the bfcache case. Neither can await
288
+ * an async write, so this is best-effort — which is why writes are also
289
+ * persisted on a debounce rather than only here.
290
+ */
291
+ attachLifecycleListeners() {
292
+ if (this.lifecycleAttached || !this.autoPersist)
293
+ return;
294
+ if (typeof document === 'undefined' || typeof addEventListener !== 'function') {
295
+ return; // not a browser
296
+ }
297
+ this.lifecycleAttached = true;
298
+ document.addEventListener('visibilitychange', this.onVisibilityChange);
299
+ addEventListener('pagehide', this.onPageHide);
300
+ }
301
+ detachLifecycleListeners() {
302
+ if (!this.lifecycleAttached)
303
+ return;
304
+ this.lifecycleAttached = false;
305
+ document.removeEventListener('visibilitychange', this.onVisibilityChange);
306
+ removeEventListener('pagehide', this.onPageHide);
307
+ }
308
+ // ── Initialisation ────────────────────────────────────────────────────
309
+ async ensureReady() {
310
+ if (this.dbHandle)
311
+ return;
312
+ if (this.closed) {
313
+ throw new Error('FirebirdBrowser instance has been closed');
314
+ }
315
+ // Prevent concurrent initialisation
316
+ if (!this.initPromise) {
317
+ this.initPromise = this.init();
318
+ }
319
+ await this.initPromise;
320
+ }
321
+ async init() {
322
+ // Before anything reads the stored image. A tab that loaded the database
323
+ // and then waited for the lock would resume with a snapshot the departing
324
+ // tab has since replaced — the very overwrite the lock prevents.
325
+ if (this.multiTab === 'exclusive') {
326
+ this.lock = await (0, db_lock_1.acquireDatabaseLock)(this.dbName, {
327
+ timeoutMs: this.lockTimeoutMs,
328
+ });
329
+ }
330
+ await this.engine.init();
331
+ await this.engine.mkdir('/data');
332
+ // Restore any previously persisted image into the engine's filesystem
333
+ // before attaching, so a reload reopens the same database.
334
+ await this.vfs.open(this.dbName);
335
+ const stored = await this.vfs.exportDatabase();
336
+ if (stored.byteLength > 0) {
337
+ await this.engine.writeFile(this.dbPath, stored);
338
+ }
339
+ this.dbHandle = (await this.engine.exists(this.dbPath))
340
+ ? await this.engine.attachDatabase(this.dbPath)
341
+ : await this.engine.createDatabase(this.dbPath);
342
+ this.attachLifecycleListeners();
343
+ }
344
+ }
345
+ exports.FirebirdBrowser = FirebirdBrowser;
346
+ // ---------------------------------------------------------------------------
347
+ // Transaction handle
348
+ // ---------------------------------------------------------------------------
349
+ /**
350
+ * A handle to an active transaction in the browser WASM engine.
351
+ *
352
+ * Statements issued here are bound to the transaction handle, so a rollback
353
+ * really does undo them.
354
+ */
355
+ class FirebirdBrowserTransaction {
356
+ constructor(engine, dbHandle, txHandle) {
357
+ this.engine = engine;
358
+ this.dbHandle = dbHandle;
359
+ this.txHandle = txHandle;
360
+ this.finished = false;
361
+ }
362
+ /** Whether this transaction has already been rolled back. */
363
+ get isFinished() {
364
+ return this.finished;
365
+ }
366
+ /**
367
+ * Roll this transaction back and stop.
368
+ *
369
+ * The enclosing `transaction()` will not commit afterwards. Use this to
370
+ * abandon a transaction deliberately, rather than throwing an error you do
371
+ * not mean — throwing also rolls back, but it propagates to the caller.
372
+ */
373
+ async rollback() {
374
+ if (this.finished)
375
+ return;
376
+ this.finished = true;
377
+ await this.engine.rollback(this.txHandle);
378
+ }
379
+ assertUsable() {
380
+ if (this.finished) {
381
+ throw new Error('Transaction has already been rolled back');
382
+ }
383
+ }
384
+ /**
385
+ * Execute a DDL/DML statement inside this transaction.
386
+ *
387
+ * @returns the number of rows affected.
388
+ */
389
+ async exec(sql, params = []) {
390
+ this.assertUsable();
391
+ const affectedRows = await this.engine.execute(this.dbHandle, this.txHandle, sql, params);
392
+ return { affectedRows };
393
+ }
394
+ /** Execute a SELECT inside this transaction and return rows. */
395
+ async query(sql, params = []) {
396
+ this.assertUsable();
397
+ return this.engine.query(this.dbHandle, this.txHandle, sql, params);
398
+ }
399
+ }
400
+ exports.FirebirdBrowserTransaction = FirebirdBrowserTransaction;
401
+ //# sourceMappingURL=firebird-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firebird-browser.js","sourceRoot":"","sources":["../../src/browser/firebird-browser.ts"],"names":[],"mappings":"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"}