@framers/sql-storage-adapter 0.6.13 → 0.6.14

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 CHANGED
@@ -131,13 +131,13 @@ See [Platform Strategy Guide](./PLATFORM_STRATEGY.md) for detailed pros/cons and
131
131
 
132
132
  | Adapter | Package | Ideal for | Pros | Considerations |
133
133
  | --- | --- | --- | --- | --- |
134
- | **🆕 `electron`** | bundled | **Electron desktop apps** | IPC bridge, multi-window, WAL, auto-migrations, crash recovery | Requires Electron runtime |
134
+ | **🆕 `electron`** | bundled | **Electron desktop apps** | IPC bridge, multi-window, WAL, auto-migrations, crash recovery | Requires Electron runtime; create it from `@framers/sql-storage-adapter/electron` (the resolver does not build the `electron-main` and `electron-renderer` kinds) |
135
135
  | **🆕 `indexeddb`** | bundled (sql.js) | **Browsers, PWAs** | sql.js + IndexedDB persistence wrapper, browser-native storage, 50MB-1GB+ quota, offline-first | IndexedDB quotas vary, WASM overhead (sql.js), not a separate SQL engine |
136
136
  | `better-sqlite3` | `better-sqlite3` | Node/Electron, CLI, CI | Native performance, transactional semantics, WAL support | Needs native toolchain; version must match Node ABI; 13.x needs Node-API 10 (Node.js 22.14+, Electron 35+) |
137
137
  | `postgres` | `pg` | Hosted or on-prem PostgreSQL | Connection pooling, rich SQL features, cloud friendly | Requires `DATABASE_URL`/credentials |
138
138
  | `sqljs` | bundled | Browsers, serverless edge, native fallback | Pure WASM SQLite, no native deps, optional filesystem persistence | Write performance limited vs native, in-memory by default |
139
139
  | `capacitor` | `@capacitor-community/sqlite` | Mobile (iOS/Android, Capacitor) | Native SQLite on mobile, encryption | Requires Capacitor runtime |
140
- | `memory` | built-in | Unit tests, storybooks, constrained sandboxes | Zero dependencies, instant startup | Non-durable, single-process only |
140
+ | `memory` | bundled (sql.js) | Unit tests, storybooks, constrained sandboxes | Zero dependencies, instant startup | The resolver builds the sql.js adapter for it, as for `sqljs`: in memory in a browser, persisted to the resolver's file path on Node |
141
141
 
142
142
  ### Platform Priorities
143
143
 
@@ -243,9 +243,24 @@ await sync.connect();
243
243
  - environment variables (`STORAGE_ADAPTER`, `DATABASE_URL`),
244
244
  - runtime hints (Capacitor detection, browser globals, IndexedDB availability).
245
245
  - Adapters are attempted in priority order until one opens successfully; a `StorageResolutionError` includes the full failure chain.
246
+ - The resolver builds `postgres`, `better-sqlite3`, `capacitor`, `indexeddb` and `sqljs`, and builds sql.js for `memory`. Any other kind (`electron-main`, `electron-renderer`, `supabase`, or an unknown name, from `priority` or `STORAGE_ADAPTER`) fails as a candidate with an error that names it, and the next candidate is tried.
247
+ - On Node, `createDatabase({ url })`, `createDatabase({ postgres })` and `connectDatabase()` open PostgreSQL, with every Postgres option (pool size, SSL, timeouts, application name, or host, port, database, user and password without a connection string) passed on, and do not fall back to SQLite. In a browser and on Deno, `createDatabase()` opens sql.js whatever the options say. `DATABASE_URL` in the environment does not change what `createDatabase()` picks; `resolveStorageAdapter()` without a `priority` tries Postgres first when it is set.
246
248
  - Provide `priority: ['indexeddb', 'sqljs']` for browser bundles or tests where native modules shouldn't load.
247
249
  - Use `createCloudBackupManager` for S3-compatible backups with gzip compression and retention limits.
248
250
 
251
+ ### Transactions
252
+
253
+ `transaction(fn)` commits when `fn` resolves and rolls back when it throws. Run the callback's statements through the handle it receives:
254
+
255
+ ```typescript
256
+ await db.transaction(async (trx) => {
257
+ await trx.run('UPDATE accounts SET balance = balance - ? WHERE id = ?', [100, 'a']);
258
+ await trx.run('UPDATE accounts SET balance = balance + ? WHERE id = ?', [100, 'b']);
259
+ });
260
+ ```
261
+
262
+ The IndexedDB, Capacitor and better-sqlite3 adapters run every transaction on one connection, so they run transactions one at a time, and a statement from another caller waits until the open transaction ends: it neither joins the transaction (and vanishes in its rollback) nor reads what the transaction has not committed. A browser or a WebView has no async context to tell the callback's own statements apart, so on the IndexedDB and Capacitor adapters a statement the callback issues through the adapter itself, not through its handle, waits for the transaction too. The two then wait on each other, and the adapter logs a warning after 10 seconds. (On Node, better-sqlite3 tells them apart with `AsyncLocalStorage`.) Inside a callback, run every statement through the handle, and do not await work that itself needs the database.
263
+
249
264
  ### IndexedDB-Specific Config
250
265
 
251
266
  ```typescript
@@ -269,6 +284,8 @@ await adapter.open();
269
284
  - ✅ Export/import (Uint8Array SQLite file format)
270
285
  - ✅ Auto-save with batching (reduce IDB overhead)
271
286
 
287
+ **When it saves:** every `saveIntervalMs`, the adapter writes the database image to IndexedDB if anything changed. It skips the tick while a transaction is open, its own or one begun with `BEGIN`, because sql.js's export closes and reopens the connection, which would end the transaction; the next tick saves it once it has committed. A save counts as done when IndexedDB commits it, not when the put request succeeds. A save that fails or aborts is reported once, and the next tick tries again. A write made while a save is in flight is saved by the next one. A transaction's commit marks its writes for saving, including writes made through `all()` or `get()` (`INSERT ... RETURNING`). `close()` rolls back a transaction still open and saves the committed state. `importDatabase()` saves the imported image before it resolves. `exportDatabase()` throws while a transaction is open.
288
+
272
289
  **Why IndexedDB Adapter vs sql.js Adapter?**
273
290
 
274
291
  | Feature | IndexedDB Adapter | sql.js Adapter |
@@ -503,7 +520,7 @@ On Postgres, `features.exporter` requires a Node runtime plus an adapter that wa
503
520
  ## CI, Releases, and Badges
504
521
 
505
522
  - GitHub Actions workflows:
506
- - `ci.yml` runs on pushes and pull requests to `master`: lint, type check, tests with coverage and the build, then it packs the package, installs the tarball into a new ES module project and type-checks a consumer with `--module nodenext --moduleResolution nodenext`.
523
+ - `ci.yml` runs on pushes and pull requests to `master`: lint, type check, tests with coverage and the build, then it packs the package, installs the tarball into a new ES module project and type-checks a consumer with `--module nodenext --moduleResolution nodenext`. The job starts a PostgreSQL 16 service, and the specs that need a server read its URL from `POSTGRES_TEST_URL`.
507
524
  - `release.yml` publishes new versions to npm, tags the commit (`vX.Y.Z`), and creates/updates the GitHub Release when `CHANGELOG.md` and `package.json` bump the version.
508
525
  - Check badge health whenever builds fail:
509
526
  - CI badge should be green for `master`.
@@ -11,6 +11,12 @@ export interface CapacitorAdapterOptions {
11
11
  }
12
12
  /**
13
13
  * Adapter using @capacitor-community/sqlite for native mobile targets.
14
+ *
15
+ * Transactions use the plugin's beginTransaction, commitTransaction and
16
+ * rollbackTransaction (plugin 5.0.7 and later). The plugin runs every other
17
+ * execute and run call in a transaction of its own, which cannot nest in an
18
+ * open one, so the statements of a transaction's callback go to the plugin
19
+ * with `transaction` false.
14
20
  */
15
21
  export declare class CapacitorSqliteAdapter implements StorageAdapter {
16
22
  private readonly options;
@@ -19,14 +25,50 @@ export declare class CapacitorSqliteAdapter implements StorageAdapter {
19
25
  private plugin;
20
26
  private connection;
21
27
  private dbName;
28
+ /** The connection is shared, so transaction() runs one callback at a time. */
29
+ private readonly runSerializedTransaction;
30
+ /**
31
+ * Holds statements from outside an open transaction until it ends. A WebView
32
+ * has no async context to tell the callback's own statements apart, so the
33
+ * callback's handle is the only way into an open transaction.
34
+ */
35
+ private readonly gate;
36
+ /** Statements sent to the plugin from outside a transaction and not yet answered. */
37
+ private readonly inFlight;
38
+ private longWaitReported;
39
+ private readonly longWait;
22
40
  constructor(options?: CapacitorAdapterOptions);
23
41
  open(options?: StorageOpenOptions): Promise<void>;
24
42
  run(statement: string, parameters?: StorageParameters): Promise<StorageRunResult>;
25
43
  get<T>(statement: string, parameters?: StorageParameters): Promise<T | null>;
26
44
  all<T>(statement: string, parameters?: StorageParameters): Promise<T[]>;
27
45
  exec(script: string): Promise<void>;
46
+ /**
47
+ * Executes a callback within a database transaction.
48
+ *
49
+ * Callbacks run one at a time, since every transaction shares the one
50
+ * connection. The callback's statements go through the handle it receives;
51
+ * a statement issued through the adapter itself while the callback runs
52
+ * waits until the transaction ends, so a callback must not await one.
53
+ */
28
54
  transaction<T>(fn: (trx: StorageAdapter) => Promise<T>): Promise<T>;
29
55
  close(): Promise<void>;
56
+ /**
57
+ * The statements of one transaction's handle: they carry the transaction's
58
+ * token, so the gate admits them while the transaction is open, and run
59
+ * inside the plugin's open transaction.
60
+ */
61
+ private handleStatements;
62
+ /**
63
+ * @param ownTransaction - true for a statement from outside a transaction:
64
+ * the plugin runs it in a transaction of its own, as it always has.
65
+ */
66
+ private runNow;
67
+ private allNow;
68
+ private execNow;
69
+ /** Keeps a statement sent from outside a transaction in `inFlight` until it answers. */
70
+ private track;
71
+ private reportLongWait;
30
72
  private ensureConnection;
31
73
  }
32
74
  export declare const createCapacitorSqliteAdapter: (options?: CapacitorAdapterOptions) => StorageAdapter;
@@ -1 +1 @@
1
- {"version":3,"file":"capacitorSqliteAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/capacitorSqliteAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAK3B,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAuCD;;GAEG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IAa/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZpC,SAAgB,IAAI,sBAAsB;IAC1C,SAAgB,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAKzD;IAEH,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,MAAM,CAAS;gBAEM,OAAO,GAAE,uBAA4B;IAIrD,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BjD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOjF,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAK5E,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAOvE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnC,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAanE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,OAAO,CAAC,gBAAgB;CAMzB;AAED,eAAO,MAAM,4BAA4B,aAAc,uBAAuB,KAAG,cAC5C,CAAC"}
1
+ {"version":3,"file":"capacitorSqliteAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/capacitorSqliteAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAa3B,MAAM,WAAW,uBAAuB;IACtC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAyDD;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,YAAW,cAAc;IA4B/C,OAAO,CAAC,QAAQ,CAAC,OAAO;IA3BpC,SAAgB,IAAI,sBAAsB;IAC1C,SAAgB,YAAY,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAKzD;IAEH,OAAO,CAAC,MAAM,CAAsC;IACpD,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,MAAM,CAAS;IACvB,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC,wBAAwB,CAAuC;IAChF;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0D;IAC/E,qFAAqF;IACrF,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA+B;IACxD,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAGvB;gBAE2B,OAAO,GAAE,uBAA4B;IAIrD,IAAI,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BjD,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAIjF,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAK5E,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,CAAC,EAAE,CAAC;IAIvE,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD;;;;;;;OAOG;IACU,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA8BnE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAmBxB;;;OAGG;YACW,MAAM;YAUN,MAAM;YAON,OAAO;IAKrB,wFAAwF;IACxF,OAAO,CAAC,KAAK;IASb,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;CAMzB;AAED,eAAO,MAAM,4BAA4B,aAAc,uBAAuB,KAAG,cAC5C,CAAC"}
@@ -1,4 +1,8 @@
1
1
  import { normaliseParameters } from '../shared/parameterUtils.js';
2
+ import { createSerializedTransactionRunner, createSharedConnectionTransactionAdapter, } from '../shared/serializedTransaction.js';
3
+ import { createConnectionGate, whenAdmitted } from '../shared/connectionGate.js';
4
+ /** How long a statement waits for an open transaction before the adapter warns. */
5
+ const LONG_WAIT_MS = 10000;
2
6
  const isCapacitorPlugin = (value) => {
3
7
  if (!value || typeof value !== 'object') {
4
8
  return false;
@@ -28,8 +32,30 @@ const loadCapacitorSqlite = async () => {
28
32
  return null;
29
33
  }
30
34
  };
35
+ /**
36
+ * The plugin answers run() with `{ changes: { changes, lastId } }`
37
+ * (`capSQLiteChanges`); a flat `{ changes, lastId }` is read as well.
38
+ */
39
+ const toRunResult = (answer) => {
40
+ const outer = (answer ?? {});
41
+ const inner = typeof outer.changes === 'object' && outer.changes !== null
42
+ ? outer.changes
43
+ : outer;
44
+ const changes = typeof inner.changes === 'number' ? inner.changes : 0;
45
+ const lastId = inner.lastId;
46
+ return {
47
+ changes,
48
+ lastInsertRowid: typeof lastId === 'number' || typeof lastId === 'string' ? lastId : null,
49
+ };
50
+ };
31
51
  /**
32
52
  * Adapter using @capacitor-community/sqlite for native mobile targets.
53
+ *
54
+ * Transactions use the plugin's beginTransaction, commitTransaction and
55
+ * rollbackTransaction (plugin 5.0.7 and later). The plugin runs every other
56
+ * execute and run call in a transaction of its own, which cannot nest in an
57
+ * open one, so the statements of a transaction's callback go to the plugin
58
+ * with `transaction` false.
33
59
  */
34
60
  export class CapacitorSqliteAdapter {
35
61
  constructor(options = {}) {
@@ -43,6 +69,21 @@ export class CapacitorSqliteAdapter {
43
69
  ]);
44
70
  this.plugin = null;
45
71
  this.connection = null;
72
+ /** The connection is shared, so transaction() runs one callback at a time. */
73
+ this.runSerializedTransaction = createSerializedTransactionRunner();
74
+ /**
75
+ * Holds statements from outside an open transaction until it ends. A WebView
76
+ * has no async context to tell the callback's own statements apart, so the
77
+ * callback's handle is the only way into an open transaction.
78
+ */
79
+ this.gate = createConnectionGate(null, { withoutContext: 'wait' });
80
+ /** Statements sent to the plugin from outside a transaction and not yet answered. */
81
+ this.inFlight = new Set();
82
+ this.longWaitReported = false;
83
+ this.longWait = {
84
+ afterMs: LONG_WAIT_MS,
85
+ onLongWait: () => this.reportLongWait(),
86
+ };
46
87
  this.dbName = options.database ?? 'app';
47
88
  }
48
89
  async open(options) {
@@ -69,37 +110,56 @@ export class CapacitorSqliteAdapter {
69
110
  }
70
111
  }
71
112
  async run(statement, parameters) {
72
- const conn = this.ensureConnection();
73
- const { positional } = normaliseParameters(parameters);
74
- const result = await conn.run(statement, positional ?? []);
75
- return { changes: result.changes ?? 0, lastInsertRowid: result.lastId ?? null };
113
+ return whenAdmitted(this.gate, () => this.track(this.runNow(statement, parameters, true)), undefined, this.longWait);
76
114
  }
77
115
  async get(statement, parameters) {
78
116
  const rows = await this.all(statement, parameters);
79
117
  return rows.length > 0 ? rows[0] : null;
80
118
  }
81
119
  async all(statement, parameters) {
82
- const conn = this.ensureConnection();
83
- const { positional } = normaliseParameters(parameters);
84
- const result = await conn.query(statement, positional ?? []);
85
- return (result.values ?? []);
120
+ return whenAdmitted(this.gate, () => this.track(this.allNow(statement, parameters)), undefined, this.longWait);
86
121
  }
87
122
  async exec(script) {
88
- const conn = this.ensureConnection();
89
- await conn.execute(script);
123
+ return whenAdmitted(this.gate, () => this.track(this.execNow(script, true)), undefined, this.longWait);
90
124
  }
125
+ /**
126
+ * Executes a callback within a database transaction.
127
+ *
128
+ * Callbacks run one at a time, since every transaction shares the one
129
+ * connection. The callback's statements go through the handle it receives;
130
+ * a statement issued through the adapter itself while the callback runs
131
+ * waits until the transaction ends, so a callback must not await one.
132
+ */
91
133
  async transaction(fn) {
92
- const conn = this.ensureConnection();
93
- await conn.execute('BEGIN TRANSACTION;');
94
- try {
95
- const result = await fn(this);
96
- await conn.execute('COMMIT;');
97
- return result;
98
- }
99
- catch (error) {
100
- await conn.execute('ROLLBACK;');
101
- throw error;
102
- }
134
+ this.ensureConnection();
135
+ const queued = setTimeout(() => this.reportLongWait(), LONG_WAIT_MS);
136
+ return this.runSerializedTransaction(() => {
137
+ clearTimeout(queued);
138
+ return this.gate.hold(async (token) => {
139
+ // The gate now holds new statements back; let the ones already sent
140
+ // answer before the transaction begins.
141
+ await Promise.allSettled([...this.inFlight]);
142
+ const conn = this.ensureConnection();
143
+ // Outside the try: when beginTransaction fails, no transaction of this
144
+ // call is open to roll back.
145
+ await conn.beginTransaction();
146
+ const transactionAdapter = createSharedConnectionTransactionAdapter(this.handleStatements(token));
147
+ try {
148
+ const result = await fn(transactionAdapter);
149
+ await conn.commitTransaction();
150
+ return result;
151
+ }
152
+ catch (error) {
153
+ try {
154
+ await conn.rollbackTransaction();
155
+ }
156
+ catch {
157
+ // The transaction already ended.
158
+ }
159
+ throw error;
160
+ }
161
+ });
162
+ });
103
163
  }
104
164
  async close() {
105
165
  if (this.connection) {
@@ -107,6 +167,64 @@ export class CapacitorSqliteAdapter {
107
167
  this.connection = null;
108
168
  }
109
169
  }
170
+ /**
171
+ * The statements of one transaction's handle: they carry the transaction's
172
+ * token, so the gate admits them while the transaction is open, and run
173
+ * inside the plugin's open transaction.
174
+ */
175
+ handleStatements(token) {
176
+ return {
177
+ kind: this.kind,
178
+ capabilities: this.capabilities,
179
+ open: async () => { },
180
+ close: async () => { },
181
+ run: (statement, parameters) => whenAdmitted(this.gate, () => this.runNow(statement, parameters, false), token),
182
+ get: async (statement, parameters) => {
183
+ const rows = await whenAdmitted(this.gate, () => this.allNow(statement, parameters), token);
184
+ return rows.length > 0 ? rows[0] : null;
185
+ },
186
+ all: (statement, parameters) => whenAdmitted(this.gate, () => this.allNow(statement, parameters), token),
187
+ exec: (script) => whenAdmitted(this.gate, () => this.execNow(script, false), token),
188
+ // The handle answers a nested transaction() itself and never calls this.
189
+ transaction: (fn) => fn(this),
190
+ };
191
+ }
192
+ /**
193
+ * @param ownTransaction - true for a statement from outside a transaction:
194
+ * the plugin runs it in a transaction of its own, as it always has.
195
+ */
196
+ async runNow(statement, parameters, ownTransaction) {
197
+ const conn = this.ensureConnection();
198
+ const { positional } = normaliseParameters(parameters);
199
+ return toRunResult(await conn.run(statement, positional ?? [], ownTransaction));
200
+ }
201
+ async allNow(statement, parameters) {
202
+ const conn = this.ensureConnection();
203
+ const { positional } = normaliseParameters(parameters);
204
+ const result = await conn.query(statement, positional ?? []);
205
+ return (result.values ?? []);
206
+ }
207
+ async execNow(script, ownTransaction) {
208
+ const conn = this.ensureConnection();
209
+ await conn.execute(script, ownTransaction);
210
+ }
211
+ /** Keeps a statement sent from outside a transaction in `inFlight` until it answers. */
212
+ track(sent) {
213
+ this.inFlight.add(sent);
214
+ const forget = () => {
215
+ this.inFlight.delete(sent);
216
+ };
217
+ sent.then(forget, forget);
218
+ return sent;
219
+ }
220
+ reportLongWait() {
221
+ if (this.longWaitReported)
222
+ return;
223
+ this.longWaitReported = true;
224
+ console.warn(`[StorageAdapter] A Capacitor SQLite statement has waited ${LONG_WAIT_MS / 1000} s for an open transaction to end. ` +
225
+ "Inside a transaction() callback, run statements through the callback's handle: one run through the adapter " +
226
+ 'itself waits for the transaction, and the transaction waits for it.');
227
+ }
110
228
  ensureConnection() {
111
229
  if (!this.connection) {
112
230
  throw new Error('Storage adapter not opened. Call open() before executing statements.');
@@ -1 +1 @@
1
- {"version":3,"file":"capacitorSqliteAdapter.js","sourceRoot":"","sources":["../../src/adapters/capacitorSqliteAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"capacitorSqliteAdapter.js","sourceRoot":"","sources":["../../src/adapters/capacitorSqliteAdapter.ts"],"names":[],"mappings":"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"}
@@ -134,7 +134,32 @@ export declare class IndexedDbAdapter implements StorageAdapter {
134
134
  private db;
135
135
  private idb;
136
136
  private saveTimer;
137
- private dirty;
137
+ /** Bumped by every statement that can change the database. */
138
+ private writeGeneration;
139
+ /** The generation the last completed save exported; the writes after it are unsaved. */
140
+ private savedGeneration;
141
+ /** The save in progress, if any. */
142
+ private saving;
143
+ /** Whether a failed auto-save has been reported since the last one that succeeded. */
144
+ private saveFailureReported;
145
+ /** Set while close() runs: no statement or transaction starts. */
146
+ private closing;
147
+ /** The close() in progress, which a second call waits for. */
148
+ private closeRun;
149
+ private longWaitReported;
150
+ /**
151
+ * The connection is shared, so transaction() runs one callback at a time.
152
+ */
153
+ private readonly runSerializedTransaction;
154
+ /**
155
+ * Holds statements from outside an open transaction until it ends, so they
156
+ * neither join it (and vanish in its rollback) nor read what it has not
157
+ * committed. Browsers have no async context to tell the callback's own
158
+ * statements apart, so the callback's handle is the only way into an open
159
+ * transaction: a statement through the adapter itself waits.
160
+ */
161
+ private readonly gate;
162
+ private readonly longWait;
138
163
  private readonly dbName;
139
164
  private readonly storeName;
140
165
  private readonly autoSave;
@@ -157,6 +182,7 @@ export declare class IndexedDbAdapter implements StorageAdapter {
157
182
  * @returns Result with changes count and last insert row ID
158
183
  */
159
184
  run(statement: string, parameters?: StorageParameters): Promise<StorageRunResult>;
185
+ private runNow;
160
186
  /**
161
187
  * Executes a SQL query and returns the first row.
162
188
  * @param statement SELECT statement
@@ -171,17 +197,32 @@ export declare class IndexedDbAdapter implements StorageAdapter {
171
197
  * @returns Array of result rows as objects
172
198
  */
173
199
  all<T>(statement: string, parameters?: StorageParameters): Promise<T[]>;
200
+ private allNow;
174
201
  /**
175
202
  * Executes a script containing multiple SQL statements.
176
203
  */
177
204
  exec(script: string): Promise<void>;
205
+ private execNow;
178
206
  /**
179
207
  * Executes a callback within a database transaction.
208
+ *
209
+ * Callbacks run one at a time, since every transaction shares the one
210
+ * connection. The callback's statements go through the handle it receives;
211
+ * a statement issued through the adapter itself while the callback runs
212
+ * waits until the transaction ends, so a callback must not await one. The
213
+ * auto-save tick does not save while a transaction is open.
180
214
  */
181
215
  transaction<T>(fn: (trx: StorageAdapter) => Promise<T>): Promise<T>;
182
216
  /**
183
- * Begins a transaction. sql.js executes all statements in implicit transactions,
184
- * so this is a no-op for compatibility.
217
+ * The statements of one transaction's handle: they carry the transaction's
218
+ * token, so the gate admits them while the transaction is open.
219
+ */
220
+ private handleStatements;
221
+ /** Rolls back the open transaction; one that already ended (a failed statement, close()) is left alone. */
222
+ private rollbackQuietly;
223
+ /**
224
+ * Begins a transaction the caller ends with commit() or rollback(). It is not
225
+ * the callback form: other callers' statements are not held out of it.
185
226
  */
186
227
  beginTransaction(): Promise<void>;
187
228
  /**
@@ -193,18 +234,27 @@ export declare class IndexedDbAdapter implements StorageAdapter {
193
234
  */
194
235
  rollback(): Promise<void>;
195
236
  /**
196
- * Closes the database and persists final state to IndexedDB.
237
+ * Closes the database and saves its committed state to IndexedDB.
238
+ *
239
+ * A transaction still open is rolled back, as closing a SQLite connection
240
+ * does, before the save; the save then holds committed writes only. A call
241
+ * made while a close is running waits for that close.
197
242
  */
198
243
  close(): Promise<void>;
244
+ private closeNow;
199
245
  /**
200
246
  * Exports the database as a Uint8Array (SQLite file format).
201
247
  * Can be downloaded or stored externally.
248
+ *
249
+ * Throws while a transaction is open: sql.js's export closes and reopens the
250
+ * connection, which would end the transaction.
202
251
  * @returns SQLite database file as binary
203
252
  */
204
253
  exportDatabase(): Uint8Array;
205
254
  /**
206
255
  * Imports a database from a Uint8Array (SQLite file).
207
- * Replaces the current database.
256
+ * Replaces the current database once any open transaction() has ended, and
257
+ * saves it to IndexedDB before it resolves.
208
258
  * @param data SQLite database file
209
259
  */
210
260
  importDatabase(data: Uint8Array): Promise<void>;
@@ -231,22 +281,51 @@ export declare class IndexedDbAdapter implements StorageAdapter {
231
281
  */
232
282
  private loadFromIndexedDb;
233
283
  /**
234
- * Saves the SQLite database to IndexedDB.
284
+ * Writes the current image to IndexedDB. Never called while a transaction is
285
+ * open (see saveIfIdle): sql.js's export() closes and reopens the connection,
286
+ * which ends an open transaction.
287
+ *
288
+ * Settles when the IndexedDB transaction completes, not when its put request
289
+ * succeeds: the transaction can still abort after that (a quota error at
290
+ * commit), and the image is then not stored. On abort the writes stay
291
+ * unsaved, so the next save writes them. A write made after the export stays
292
+ * unsaved too.
235
293
  */
236
294
  private saveToIndexedDb;
295
+ /** Whether writes were made since the image the last completed save exported. */
296
+ private hasUnsavedWrites;
297
+ /**
298
+ * Whether a transaction is open on the connection: one transaction() is
299
+ * running, or one the caller began with BEGIN or SAVEPOINT. sql.js does not
300
+ * export sqlite3_get_autocommit, so the adapter asks SQLite: BEGIN fails
301
+ * inside a transaction, and outside one it is rolled back at once. A probe
302
+ * that fails for any reason counts as open, so the adapter does not export.
303
+ */
304
+ private inTransaction;
305
+ /**
306
+ * Starts a save of the unsaved writes, unless a save is running or a
307
+ * transaction is open; the auto-save tick tries again later.
308
+ */
309
+ private saveIfIdle;
310
+ /**
311
+ * Starts a save at once and keeps it as the save in progress. The caller has
312
+ * made sure no transaction is open: the export would end it.
313
+ */
314
+ private startSave;
315
+ /** Waits for a save in progress to settle, whether it succeeded or not. */
316
+ private settleSave;
317
+ private reportLongWait;
237
318
  /**
238
319
  * Wraps a transaction operation with retry logic.
239
320
  * Handles "NotFoundError" by reopening IndexedDB connection.
240
321
  */
241
322
  private withTransactionRetry;
242
- /**
243
- * Persists to IndexedDB if auto-save is enabled.
244
- */
245
- private persistIfNeeded;
246
323
  /**
247
324
  * Starts auto-save interval.
248
325
  */
249
326
  private startAutoSave;
327
+ /** One auto-save tick: a failed save is reported once and tried again on the next tick. */
328
+ private autoSaveTick;
250
329
  /**
251
330
  * Ensures the database is open.
252
331
  */
@@ -1 +1 @@
1
- {"version":3,"file":"indexedDbAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/indexedDbAdapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"indexedDbAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/indexedDbAdapter.ts"],"names":[],"mappings":"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"}