@framers/sql-storage-adapter 0.7.2 → 0.7.3
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 +20 -0
- package/dist/adapters/electron/preload.cjs +289 -0
- package/dist/adapters/electron/renderer.d.ts +9 -0
- package/dist/adapters/electron/renderer.d.ts.map +1 -0
- package/dist/adapters/electron/renderer.js +8 -0
- package/dist/adapters/electron/renderer.js.map +1 -0
- package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.d.ts +2 -0
- package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.js +133 -0
- package/dist/cjs/adapters/baseStorageAdapter.d.ts +368 -0
- package/dist/cjs/adapters/baseStorageAdapter.js +744 -0
- package/dist/cjs/adapters/betterSqliteAdapter.d.ts +124 -0
- package/dist/cjs/adapters/betterSqliteAdapter.js +334 -0
- package/dist/cjs/adapters/capacitorSqliteAdapter.d.ts +83 -0
- package/dist/cjs/adapters/capacitorSqliteAdapter.js +250 -0
- package/dist/cjs/adapters/electron/electronMainAdapter.d.ts +251 -0
- package/dist/cjs/adapters/electron/electronMainAdapter.js +392 -0
- package/dist/cjs/adapters/electron/electronRendererAdapter.d.ts +177 -0
- package/dist/cjs/adapters/electron/electronRendererAdapter.js +283 -0
- package/dist/cjs/adapters/electron/index.d.ts +74 -0
- package/dist/cjs/adapters/electron/index.js +86 -0
- package/dist/cjs/adapters/electron/ipc/channels.d.ts +196 -0
- package/dist/cjs/adapters/electron/ipc/channels.js +127 -0
- package/dist/cjs/adapters/electron/ipc/index.d.ts +11 -0
- package/dist/cjs/adapters/electron/ipc/index.js +38 -0
- package/dist/cjs/adapters/electron/ipc/protocol.d.ts +78 -0
- package/dist/cjs/adapters/electron/ipc/protocol.js +341 -0
- package/dist/cjs/adapters/electron/ipc/types.d.ts +248 -0
- package/dist/cjs/adapters/electron/ipc/types.js +15 -0
- package/dist/cjs/adapters/electron/migration/autoMigrator.d.ts +184 -0
- package/dist/cjs/adapters/electron/migration/autoMigrator.js +441 -0
- package/dist/cjs/adapters/electron/migration/index.d.ts +9 -0
- package/dist/cjs/adapters/electron/migration/index.js +29 -0
- package/dist/cjs/adapters/electron/preload.d.ts +126 -0
- package/dist/cjs/adapters/electron/preload.js +233 -0
- package/dist/cjs/adapters/electron/recovery/corruptionDetector.d.ts +214 -0
- package/dist/cjs/adapters/electron/recovery/corruptionDetector.js +359 -0
- package/dist/cjs/adapters/electron/recovery/index.d.ts +11 -0
- package/dist/cjs/adapters/electron/recovery/index.js +34 -0
- package/dist/cjs/adapters/electron/recovery/walCheckpoint.d.ts +186 -0
- package/dist/cjs/adapters/electron/recovery/walCheckpoint.js +263 -0
- package/dist/cjs/adapters/electron/renderer.d.ts +9 -0
- package/dist/cjs/adapters/electron/renderer.js +33 -0
- package/dist/cjs/adapters/electron/window/index.d.ts +9 -0
- package/dist/cjs/adapters/electron/window/index.js +29 -0
- package/dist/cjs/adapters/electron/window/windowManager.d.ts +190 -0
- package/dist/cjs/adapters/electron/window/windowManager.js +321 -0
- package/dist/cjs/adapters/indexedDbAdapter.d.ts +490 -0
- package/dist/cjs/adapters/indexedDbAdapter.js +993 -0
- package/dist/cjs/adapters/postgresAdapter.d.ts +424 -0
- package/dist/cjs/adapters/postgresAdapter.js +889 -0
- package/dist/cjs/adapters/sqlJsAdapter.d.ts +64 -0
- package/dist/cjs/adapters/sqlJsAdapter.js +268 -0
- package/dist/cjs/adapters/supabase.d.ts +58 -0
- package/dist/cjs/adapters/supabase.js +401 -0
- package/dist/cjs/codecs/BrowserBlobCodec.d.ts +14 -0
- package/dist/cjs/codecs/BrowserBlobCodec.js +57 -0
- package/dist/cjs/codecs/NodeBlobCodec.d.ts +14 -0
- package/dist/cjs/codecs/NodeBlobCodec.js +59 -0
- package/dist/cjs/core/contracts/blobCodec.d.ts +15 -0
- package/dist/cjs/core/contracts/blobCodec.js +15 -0
- package/dist/cjs/core/contracts/context.d.ts +221 -0
- package/dist/cjs/core/contracts/context.js +15 -0
- package/dist/cjs/core/contracts/dialect.d.ts +154 -0
- package/dist/cjs/core/contracts/dialect.js +15 -0
- package/dist/cjs/core/contracts/events.d.ts +225 -0
- package/dist/cjs/core/contracts/events.js +15 -0
- package/dist/cjs/core/contracts/exporter.d.ts +13 -0
- package/dist/cjs/core/contracts/exporter.js +15 -0
- package/dist/cjs/core/contracts/extensions.d.ts +73 -0
- package/dist/cjs/core/contracts/extensions.js +15 -0
- package/dist/cjs/core/contracts/features.d.ts +25 -0
- package/dist/cjs/core/contracts/features.js +61 -0
- package/dist/cjs/core/contracts/fts.d.ts +66 -0
- package/dist/cjs/core/contracts/fts.js +15 -0
- package/dist/cjs/core/contracts/hooks.d.ts +481 -0
- package/dist/cjs/core/contracts/hooks.js +140 -0
- package/dist/cjs/core/contracts/index.d.ts +260 -0
- package/dist/cjs/core/contracts/index.js +41 -0
- package/dist/cjs/core/contracts/limitations.d.ts +46 -0
- package/dist/cjs/core/contracts/limitations.js +218 -0
- package/dist/cjs/core/contracts/performance.d.ts +308 -0
- package/dist/cjs/core/contracts/performance.js +144 -0
- package/dist/cjs/core/database.d.ts +220 -0
- package/dist/cjs/core/database.js +136 -0
- package/dist/cjs/core/portable.d.ts +23 -0
- package/dist/cjs/core/portable.js +66 -0
- package/dist/cjs/core/resolver.d.ts +77 -0
- package/dist/cjs/core/resolver.js +235 -0
- package/dist/cjs/dialects/PostgresDialect.d.ts +35 -0
- package/dist/cjs/dialects/PostgresDialect.js +143 -0
- package/dist/cjs/dialects/SqliteDialect.d.ts +35 -0
- package/dist/cjs/dialects/SqliteDialect.js +142 -0
- package/dist/cjs/dialects/shared.d.ts +17 -0
- package/dist/cjs/dialects/shared.js +90 -0
- package/dist/cjs/exporters/PostgresExporter.d.ts +14 -0
- package/dist/cjs/exporters/PostgresExporter.js +61 -0
- package/dist/cjs/exporters/SqliteFileExporter.d.ts +16 -0
- package/dist/cjs/exporters/SqliteFileExporter.js +43 -0
- package/dist/cjs/features/backup/cloudBackup.d.ts +219 -0
- package/dist/cjs/features/backup/cloudBackup.js +209 -0
- package/dist/cjs/features/kv/idb.d.ts +79 -0
- package/dist/cjs/features/kv/idb.js +32 -0
- package/dist/cjs/features/kv/index.d.ts +14 -0
- package/dist/cjs/features/kv/index.js +40 -0
- package/dist/cjs/features/kv/indexedDbKeyValueStore.d.ts +77 -0
- package/dist/cjs/features/kv/indexedDbKeyValueStore.js +116 -0
- package/dist/cjs/features/kv/keyValueStore.d.ts +48 -0
- package/dist/cjs/features/kv/keyValueStore.js +67 -0
- package/dist/cjs/features/kv/sqlKeyValueStore.d.ts +34 -0
- package/dist/cjs/features/kv/sqlKeyValueStore.js +81 -0
- package/dist/cjs/features/kv/valueCodec.d.ts +35 -0
- package/dist/cjs/features/kv/valueCodec.js +426 -0
- package/dist/cjs/features/migrations/dataExport.d.ts +77 -0
- package/dist/cjs/features/migrations/dataExport.js +194 -0
- package/dist/cjs/features/migrations/dataImport.d.ts +54 -0
- package/dist/cjs/features/migrations/dataImport.js +300 -0
- package/dist/cjs/features/migrations/migration.d.ts +89 -0
- package/dist/cjs/features/migrations/migration.js +187 -0
- package/dist/cjs/features/migrations/schemaMigrations.d.ts +93 -0
- package/dist/cjs/features/migrations/schemaMigrations.js +220 -0
- package/dist/cjs/features/sync/conflicts/conflictResolver.d.ts +222 -0
- package/dist/cjs/features/sync/conflicts/conflictResolver.js +366 -0
- package/dist/cjs/features/sync/conflicts/index.d.ts +9 -0
- package/dist/cjs/features/sync/conflicts/index.js +21 -0
- package/dist/cjs/features/sync/crossPlatformSync.d.ts +281 -0
- package/dist/cjs/features/sync/crossPlatformSync.js +551 -0
- package/dist/cjs/features/sync/devices/deviceManager.d.ts +243 -0
- package/dist/cjs/features/sync/devices/deviceManager.js +450 -0
- package/dist/cjs/features/sync/devices/index.d.ts +10 -0
- package/dist/cjs/features/sync/devices/index.js +21 -0
- package/dist/cjs/features/sync/index.d.ts +37 -0
- package/dist/cjs/features/sync/index.js +111 -0
- package/dist/cjs/features/sync/protocol/index.d.ts +11 -0
- package/dist/cjs/features/sync/protocol/index.js +23 -0
- package/dist/cjs/features/sync/protocol/messages.d.ts +348 -0
- package/dist/cjs/features/sync/protocol/messages.js +215 -0
- package/dist/cjs/features/sync/protocol/vectorClock.d.ts +164 -0
- package/dist/cjs/features/sync/protocol/vectorClock.js +256 -0
- package/dist/cjs/features/sync/syncManager.d.ts +348 -0
- package/dist/cjs/features/sync/syncManager.js +455 -0
- package/dist/cjs/features/sync/tables/index.d.ts +10 -0
- package/dist/cjs/features/sync/tables/index.js +21 -0
- package/dist/cjs/features/sync/tables/syncLogManager.d.ts +216 -0
- package/dist/cjs/features/sync/tables/syncLogManager.js +423 -0
- package/dist/cjs/features/sync/transport/httpTransport.d.ts +123 -0
- package/dist/cjs/features/sync/transport/httpTransport.js +346 -0
- package/dist/cjs/features/sync/transport/index.d.ts +12 -0
- package/dist/cjs/features/sync/transport/index.js +25 -0
- package/dist/cjs/features/sync/transport/transport.d.ts +259 -0
- package/dist/cjs/features/sync/transport/transport.js +163 -0
- package/dist/cjs/features/sync/transport/websocketTransport.d.ts +126 -0
- package/dist/cjs/features/sync/transport/websocketTransport.js +342 -0
- package/dist/cjs/fts/PostgresFts.d.ts +29 -0
- package/dist/cjs/fts/PostgresFts.js +77 -0
- package/dist/cjs/fts/SqliteFts5.d.ts +22 -0
- package/dist/cjs/fts/SqliteFts5.js +58 -0
- package/dist/cjs/index.d.ts +30 -0
- package/dist/cjs/index.js +101 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/shared/connectionGate.d.ts +94 -0
- package/dist/cjs/shared/connectionGate.js +77 -0
- package/dist/cjs/shared/errors.d.ts +23 -0
- package/dist/cjs/shared/errors.js +45 -0
- package/dist/cjs/shared/logger.d.ts +26 -0
- package/dist/cjs/shared/logger.js +40 -0
- package/dist/cjs/shared/parameterUtils.d.ts +16 -0
- package/dist/cjs/shared/parameterUtils.js +59 -0
- package/dist/cjs/shared/postgresTarget.d.ts +11 -0
- package/dist/cjs/shared/postgresTarget.js +30 -0
- package/dist/cjs/shared/segment.d.ts +43 -0
- package/dist/cjs/shared/segment.js +63 -0
- package/dist/cjs/shared/serializedTransaction.d.ts +14 -0
- package/dist/cjs/shared/serializedTransaction.js +74 -0
- package/dist/cjs/shared/splitSqlStatements.d.ts +27 -0
- package/dist/cjs/shared/splitSqlStatements.js +163 -0
- package/dist/cjs/shared/sqlPlaceholders.d.ts +48 -0
- package/dist/cjs/shared/sqlPlaceholders.js +263 -0
- package/dist/cjs/types/index.d.ts +29 -0
- package/dist/cjs/types/index.js +33 -0
- package/dist/core/portable.d.ts +23 -0
- package/dist/core/portable.d.ts.map +1 -0
- package/dist/core/portable.js +23 -0
- package/dist/core/portable.js.map +1 -0
- package/package.json +139 -24
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview IndexedDB Storage Adapter
|
|
3
|
+
* @description Browser-native SQL storage using sql.js (WASM) for SQL execution and IndexedDB for persistence.
|
|
4
|
+
*
|
|
5
|
+
* **Architecture:**
|
|
6
|
+
* - **SQL Execution**: Uses sql.js (SQLite compiled to WebAssembly) for full SQL support
|
|
7
|
+
* - **Persistence**: Stores the SQLite database file (as binary blob) in IndexedDB
|
|
8
|
+
* - **Workflow**: Load DB from IndexedDB → Execute SQL in memory (sql.js) → Save back to IndexedDB
|
|
9
|
+
*
|
|
10
|
+
* **Why this approach?**
|
|
11
|
+
* - IndexedDB is NOT SQL - it's a NoSQL key-value store
|
|
12
|
+
* - sql.js provides full SQLite compatibility (transactions, joins, etc.)
|
|
13
|
+
* - IndexedDB provides durable browser-native persistence
|
|
14
|
+
* - Together: Full SQL capabilities + browser persistence = best of both worlds
|
|
15
|
+
*
|
|
16
|
+
* **Use cases:**
|
|
17
|
+
* - Fully client-side applications (no backend needed)
|
|
18
|
+
* - Progressive Web Apps (PWAs)
|
|
19
|
+
* - Offline-capable web apps
|
|
20
|
+
* - Privacy-first applications (data never leaves browser)
|
|
21
|
+
*
|
|
22
|
+
* **Performance:**
|
|
23
|
+
* - Fast reads (in-memory SQL via sql.js)
|
|
24
|
+
* - Moderate writes (IndexedDB persistence adds ~10-50ms)
|
|
25
|
+
* - Auto-save batching reduces IDB overhead
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { IndexedDbAdapter } from '@framers/sql-storage-adapter';
|
|
30
|
+
*
|
|
31
|
+
* const adapter = new IndexedDbAdapter({
|
|
32
|
+
* dbName: 'my-app-db',
|
|
33
|
+
* durability: 'commit', // each write is in IndexedDB before it resolves
|
|
34
|
+
* crossTab: true, // two tabs of the site keep each other's writes
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* await adapter.open();
|
|
38
|
+
* await adapter.run('CREATE TABLE sessions (id TEXT PRIMARY KEY, data TEXT)');
|
|
39
|
+
* await adapter.run('INSERT INTO sessions VALUES (?, ?)', ['session-1', '{"events": []}']);
|
|
40
|
+
*
|
|
41
|
+
* const session = await adapter.get('SELECT * FROM sessions WHERE id = ?', ['session-1']);
|
|
42
|
+
* console.log(session);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
import type { StorageAdapter, StorageCapability, StorageOpenOptions, StorageParameters, StorageRunResult } from '../core/contracts/index.js';
|
|
46
|
+
/**
|
|
47
|
+
* The part of the Web Locks API (`navigator.locks`) the adapter uses: an
|
|
48
|
+
* exclusive lock per name, granted to one holder at a time, in the order
|
|
49
|
+
* asked, and held until the callback's promise settles.
|
|
50
|
+
*/
|
|
51
|
+
export interface IndexedDbLockManager {
|
|
52
|
+
request<T>(name: string, options: {
|
|
53
|
+
mode: 'exclusive';
|
|
54
|
+
}, callback: () => Promise<T>): Promise<T>;
|
|
55
|
+
}
|
|
56
|
+
/** How tabs coordinate their saves. */
|
|
57
|
+
export interface IndexedDbCrossTabOptions {
|
|
58
|
+
/**
|
|
59
|
+
* The lock manager: the browser's `navigator.locks` when left out. `null`
|
|
60
|
+
* coordinates by the version stamp alone, as the adapter does where the
|
|
61
|
+
* browser has no Web Locks.
|
|
62
|
+
*/
|
|
63
|
+
locks?: IndexedDbLockManager | null;
|
|
64
|
+
}
|
|
65
|
+
/** When a write is stored in IndexedDB. */
|
|
66
|
+
export type IndexedDbDurability = 'interval' | 'commit';
|
|
67
|
+
/**
|
|
68
|
+
* Configuration for IndexedDB adapter.
|
|
69
|
+
*/
|
|
70
|
+
export interface IndexedDbAdapterOptions {
|
|
71
|
+
/** IndexedDB database name (default: 'app-db') */
|
|
72
|
+
dbName?: string;
|
|
73
|
+
/** IndexedDB object store name (default: 'sqliteDb') */
|
|
74
|
+
storeName?: string;
|
|
75
|
+
/** Auto-save to IndexedDB on a timer (default: true) */
|
|
76
|
+
autoSave?: boolean;
|
|
77
|
+
/** Save interval in milliseconds for batched writes (default: 5000) */
|
|
78
|
+
saveIntervalMs?: number;
|
|
79
|
+
/** sql.js configuration (e.g., locateFile for wasm) */
|
|
80
|
+
sqlJsConfig?: any;
|
|
81
|
+
/**
|
|
82
|
+
* When a write is stored in IndexedDB.
|
|
83
|
+
*
|
|
84
|
+
* - `'interval'`, the default: the auto-save tick stores the writes made
|
|
85
|
+
* since the last save, every `saveIntervalMs`; `flush()` and `close()`
|
|
86
|
+
* store them at once. A write can be lost when the page goes before the
|
|
87
|
+
* next tick.
|
|
88
|
+
* - `'commit'`: `run()`, `exec()`, a write through `all()` or `get()`
|
|
89
|
+
* (`INSERT ... RETURNING`) and `transaction()` resolve once their write is
|
|
90
|
+
* in IndexedDB, and reject when IndexedDB refuses it (the write stays in
|
|
91
|
+
* the database and the next save stores it). Each save writes the whole
|
|
92
|
+
* database image, so batch many writes in one `transaction()`. While a
|
|
93
|
+
* transaction a caller opened with `BEGIN` is open, nothing can be saved:
|
|
94
|
+
* its statements resolve at once, and its rows are stored when its
|
|
95
|
+
* `COMMIT` resolves.
|
|
96
|
+
*/
|
|
97
|
+
durability?: IndexedDbDurability;
|
|
98
|
+
/**
|
|
99
|
+
* Keeps the writes of two tabs of the site that open the same database.
|
|
100
|
+
* Each tab holds the whole database in memory and writes it back whole, so
|
|
101
|
+
* without this the tab that saves last overwrites the other's writes.
|
|
102
|
+
*
|
|
103
|
+
* With `crossTab`, every statement and transaction runs under a Web Lock on
|
|
104
|
+
* the database, on the newest stored image (a tab reloads it when another
|
|
105
|
+
* has saved), and is stored before the lock is let go: `durability` is
|
|
106
|
+
* `'commit'` whatever it says. Where the browser has no Web Locks (Safari
|
|
107
|
+
* before 15.4, an insecure origin, Lockdown Mode), the version stamp stored
|
|
108
|
+
* beside the image keeps both tabs' writes alone: a statement that finds
|
|
109
|
+
* another tab saved first runs again on the newer image, and a
|
|
110
|
+
* `transaction()` is refused with `IndexedDbConflictError`, storing
|
|
111
|
+
* nothing, for its caller to run again. The adapter says once when it runs
|
|
112
|
+
* without Web Locks.
|
|
113
|
+
*
|
|
114
|
+
* A transaction begun with `BEGIN` through `run()` or `exec()` cannot be
|
|
115
|
+
* held across tabs: it is rolled back and refused. Use `transaction()`.
|
|
116
|
+
*/
|
|
117
|
+
crossTab?: boolean | IndexedDbCrossTabOptions;
|
|
118
|
+
/**
|
|
119
|
+
* A database of its own: the segment is appended to `dbName`
|
|
120
|
+
* (`app-db` becomes `app-db-agentos`). Lower-case letters, digits and
|
|
121
|
+
* underscores.
|
|
122
|
+
*/
|
|
123
|
+
segment?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* A `transaction()` another tab saved over: refused, with nothing of it
|
|
127
|
+
* stored. The adapter has loaded the other tab's image, so running the
|
|
128
|
+
* transaction again keeps both tabs' writes.
|
|
129
|
+
*/
|
|
130
|
+
export declare class IndexedDbConflictError extends Error {
|
|
131
|
+
constructor(message: string);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Storage adapter using IndexedDB + sql.js for client-side SQL persistence.
|
|
135
|
+
*
|
|
136
|
+
* **The Key Difference: Automatic Persistence**
|
|
137
|
+
*
|
|
138
|
+
* **sql.js adapter alone:**
|
|
139
|
+
* - In-memory SQLite database (lost on page refresh)
|
|
140
|
+
* - You must manually call `db.export()` and save it yourself
|
|
141
|
+
* - No automatic persistence in browsers
|
|
142
|
+
* - Good for: Edge functions, temporary calculations, prototyping
|
|
143
|
+
*
|
|
144
|
+
* **IndexedDB adapter (this):**
|
|
145
|
+
* - Same sql.js SQL engine, but automatically saves to IndexedDB
|
|
146
|
+
* - Data survives page refreshes automatically
|
|
147
|
+
* - Auto-save batching reduces overhead
|
|
148
|
+
* - Good for: Production PWAs, offline-first apps, persistent client-side storage
|
|
149
|
+
*
|
|
150
|
+
* **How It Works:**
|
|
151
|
+
* 1. IndexedDB stores the SQLite database file (binary blob) - this is just storage
|
|
152
|
+
* 2. sql.js (WASM) loads the database into memory and executes SQL - this provides SQL capabilities
|
|
153
|
+
* 3. After writes, the updated database is saved back to IndexedDB: on a timer
|
|
154
|
+
* (the default), before each write resolves (`durability: 'commit'`), or
|
|
155
|
+
* under a cross-tab lock (`crossTab`)
|
|
156
|
+
*
|
|
157
|
+
* **Capabilities:**
|
|
158
|
+
* - ✅ Transactions (via sql.js)
|
|
159
|
+
* - ✅ Persistence (via IndexedDB - automatic!)
|
|
160
|
+
* - ✅ Full SQL support (via sql.js)
|
|
161
|
+
* - ✅ Export/import
|
|
162
|
+
* - ✅ Several tabs on one database, with `crossTab`
|
|
163
|
+
* - ❌ Server-side (browser only)
|
|
164
|
+
*
|
|
165
|
+
* @example Client-side application
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const adapter = new IndexedDbAdapter({ dbName: 'my-app-db' });
|
|
168
|
+
* await adapter.open();
|
|
169
|
+
* await adapter.run('CREATE TABLE sessions (id TEXT PRIMARY KEY, data TEXT)');
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
export declare class IndexedDbAdapter implements StorageAdapter {
|
|
173
|
+
readonly kind = "indexeddb";
|
|
174
|
+
readonly capabilities: ReadonlySet<StorageCapability>;
|
|
175
|
+
private SQL;
|
|
176
|
+
private db;
|
|
177
|
+
/** Foreign-key enforcement as open() was asked for it (undefined: the engine default); sql.js forgets the PRAGMA when export() reopens the connection. */
|
|
178
|
+
private foreignKeys;
|
|
179
|
+
private idb;
|
|
180
|
+
private saveTimer;
|
|
181
|
+
/** Bumped by every statement that can change the database. */
|
|
182
|
+
private writeGeneration;
|
|
183
|
+
/** The generation the last completed save exported; the writes after it are unsaved. */
|
|
184
|
+
private savedGeneration;
|
|
185
|
+
/** The save in progress, if any. */
|
|
186
|
+
private saving;
|
|
187
|
+
/** The generation the save in progress exported. */
|
|
188
|
+
private savingGeneration;
|
|
189
|
+
/** Whether a failed auto-save has been reported since the last one that succeeded. */
|
|
190
|
+
private saveFailureReported;
|
|
191
|
+
/** The open() in progress, which a second call waits for. */
|
|
192
|
+
private opening;
|
|
193
|
+
/** Set while close() runs: no statement or transaction starts. */
|
|
194
|
+
private closing;
|
|
195
|
+
/** The close() in progress, which a second call waits for. */
|
|
196
|
+
private closeRun;
|
|
197
|
+
private longWaitReported;
|
|
198
|
+
private lockWaitReported;
|
|
199
|
+
/** The stamp of the image the database in memory was loaded from or last saved as. */
|
|
200
|
+
private loadedStamp;
|
|
201
|
+
/** How many stamps this adapter has made, which keeps two of its stamps apart. */
|
|
202
|
+
private stampCount;
|
|
203
|
+
/** The connection settings a fresh connection has, which a save need not set again. */
|
|
204
|
+
private pragmaDefaults;
|
|
205
|
+
/**
|
|
206
|
+
* With `crossTab`, the lock manager, or null for the version stamp alone;
|
|
207
|
+
* undefined without `crossTab`.
|
|
208
|
+
*/
|
|
209
|
+
private locks;
|
|
210
|
+
/** Without Web Locks, this adapter's coordinated operations run one at a time. */
|
|
211
|
+
private readonly runCoordinatedInTurn;
|
|
212
|
+
/**
|
|
213
|
+
* The connection is shared, so transaction() runs one callback at a time.
|
|
214
|
+
*/
|
|
215
|
+
private readonly runSerializedTransaction;
|
|
216
|
+
/**
|
|
217
|
+
* Holds statements from outside an open transaction until it ends, so they
|
|
218
|
+
* neither join it (and vanish in its rollback) nor read what it has not
|
|
219
|
+
* committed. Browsers have no async context to tell the callback's own
|
|
220
|
+
* statements apart, so the callback's handle is the only way into an open
|
|
221
|
+
* transaction: a statement through the adapter itself waits.
|
|
222
|
+
*/
|
|
223
|
+
private readonly gate;
|
|
224
|
+
private readonly longWait;
|
|
225
|
+
private readonly dbName;
|
|
226
|
+
private readonly storeName;
|
|
227
|
+
private readonly autoSave;
|
|
228
|
+
private readonly saveIntervalMs;
|
|
229
|
+
private readonly durability;
|
|
230
|
+
private readonly crossTab;
|
|
231
|
+
private readonly sqlJsConfig;
|
|
232
|
+
/** @throws {Error} When `options.segment` is not a name a segment can take. */
|
|
233
|
+
constructor(options?: IndexedDbAdapterOptions);
|
|
234
|
+
/** The name of the Web Lock that coordinates the tabs on this database. */
|
|
235
|
+
private get lockName();
|
|
236
|
+
/**
|
|
237
|
+
* Opens IndexedDB and initializes sql.js database.
|
|
238
|
+
* Loads existing database from IndexedDB if present.
|
|
239
|
+
*
|
|
240
|
+
* Uses a global sql.js singleton to prevent race conditions when
|
|
241
|
+
* multiple adapters (e.g., fabric_codex_db and quarry-codex-local)
|
|
242
|
+
* are initialized simultaneously. Two calls at once open once.
|
|
243
|
+
*/
|
|
244
|
+
open(options?: StorageOpenOptions): Promise<void>;
|
|
245
|
+
private openNow;
|
|
246
|
+
/** The lock manager crossTab uses, or null for the version stamp alone. */
|
|
247
|
+
private resolveLocks;
|
|
248
|
+
/**
|
|
249
|
+
* Executes a SQL statement that doesn't return rows (INSERT, UPDATE, DELETE, CREATE, etc.).
|
|
250
|
+
* @param statement SQL statement with ? or :name placeholders
|
|
251
|
+
* @param parameters Positional array or named object
|
|
252
|
+
* @returns Result with changes count and last insert row ID
|
|
253
|
+
*/
|
|
254
|
+
run(statement: string, parameters?: StorageParameters): Promise<StorageRunResult>;
|
|
255
|
+
private runNow;
|
|
256
|
+
/**
|
|
257
|
+
* Executes a SQL query and returns the first row.
|
|
258
|
+
* @param statement SELECT statement
|
|
259
|
+
* @param parameters Query parameters
|
|
260
|
+
* @returns First row as object or null if no results
|
|
261
|
+
*/
|
|
262
|
+
get<T>(statement: string, parameters?: StorageParameters): Promise<T | null>;
|
|
263
|
+
/**
|
|
264
|
+
* Executes a SQL query and returns all matching rows. A statement that
|
|
265
|
+
* writes (`INSERT ... RETURNING`) is saved like a `run()`.
|
|
266
|
+
* @param statement SELECT statement
|
|
267
|
+
* @param parameters Query parameters
|
|
268
|
+
* @returns Array of result rows as objects
|
|
269
|
+
*/
|
|
270
|
+
all<T>(statement: string, parameters?: StorageParameters): Promise<T[]>;
|
|
271
|
+
private allNow;
|
|
272
|
+
/** The rows changed on this connection since it opened. */
|
|
273
|
+
private totalChanges;
|
|
274
|
+
/**
|
|
275
|
+
* Executes a script containing multiple SQL statements.
|
|
276
|
+
*/
|
|
277
|
+
exec(script: string): Promise<void>;
|
|
278
|
+
private execNow;
|
|
279
|
+
/**
|
|
280
|
+
* With `durability: 'commit'`, resolves with `result` once the write that
|
|
281
|
+
* produced it is stored; otherwise with `result` at once.
|
|
282
|
+
*/
|
|
283
|
+
private stored;
|
|
284
|
+
/**
|
|
285
|
+
* Executes a callback within a database transaction.
|
|
286
|
+
*
|
|
287
|
+
* Callbacks run one at a time, since every transaction shares the one
|
|
288
|
+
* connection. The callback's statements go through the handle it receives;
|
|
289
|
+
* a statement issued through the adapter itself while the callback runs
|
|
290
|
+
* waits until the transaction ends, so a callback must not await one. The
|
|
291
|
+
* auto-save tick does not save while a transaction is open. With
|
|
292
|
+
* `durability: 'commit'` the transaction resolves once it is stored.
|
|
293
|
+
*/
|
|
294
|
+
transaction<T>(fn: (trx: StorageAdapter) => Promise<T>): Promise<T>;
|
|
295
|
+
/** Runs one transaction: BEGIN, the callback through its handle, COMMIT or ROLLBACK. */
|
|
296
|
+
private transactionNow;
|
|
297
|
+
/**
|
|
298
|
+
* The statements of one transaction's handle: they carry the transaction's
|
|
299
|
+
* token, so the gate admits them while the transaction is open.
|
|
300
|
+
*/
|
|
301
|
+
private handleStatements;
|
|
302
|
+
/** Rolls back the open transaction; one that already ended (a failed statement, close()) is left alone. */
|
|
303
|
+
private rollbackQuietly;
|
|
304
|
+
/**
|
|
305
|
+
* Begins a transaction the caller ends with commit() or rollback(). It is not
|
|
306
|
+
* the callback form: other callers' statements are not held out of it. With
|
|
307
|
+
* `crossTab` it is refused: use transaction().
|
|
308
|
+
*/
|
|
309
|
+
beginTransaction(): Promise<void>;
|
|
310
|
+
/**
|
|
311
|
+
* Commits the current transaction.
|
|
312
|
+
*/
|
|
313
|
+
commit(): Promise<void>;
|
|
314
|
+
/**
|
|
315
|
+
* Rolls back the current transaction.
|
|
316
|
+
*/
|
|
317
|
+
rollback(): Promise<void>;
|
|
318
|
+
/**
|
|
319
|
+
* Stores every write made so far in IndexedDB. A `transaction()` that is
|
|
320
|
+
* open is waited for and stored with the rest; a transaction a caller began
|
|
321
|
+
* with `BEGIN` cannot be stored without ending it, so flush() rejects while
|
|
322
|
+
* one is open. Resolves at once when nothing is waiting to be saved.
|
|
323
|
+
*/
|
|
324
|
+
flush(): Promise<void>;
|
|
325
|
+
/**
|
|
326
|
+
* Closes the database and saves its committed state to IndexedDB.
|
|
327
|
+
*
|
|
328
|
+
* A transaction still open is rolled back, as closing a SQLite connection
|
|
329
|
+
* does, before the save; the save then holds committed writes only. A call
|
|
330
|
+
* made while a close is running waits for that close.
|
|
331
|
+
*/
|
|
332
|
+
close(): Promise<void>;
|
|
333
|
+
private closeNow;
|
|
334
|
+
/**
|
|
335
|
+
* Exports the database as a Uint8Array (SQLite file format).
|
|
336
|
+
* Can be downloaded or stored externally. With `crossTab` it is this tab's
|
|
337
|
+
* image, which another tab's save can have overtaken.
|
|
338
|
+
*
|
|
339
|
+
* Throws while a transaction is open: sql.js's export closes and reopens the
|
|
340
|
+
* connection, which would end the transaction.
|
|
341
|
+
* @returns SQLite database file as binary
|
|
342
|
+
*/
|
|
343
|
+
exportDatabase(): Uint8Array;
|
|
344
|
+
/**
|
|
345
|
+
* Applies the connection settings open() was asked for. sql.js loses them
|
|
346
|
+
* whenever export() reopens the connection; a save, an export, an import
|
|
347
|
+
* and a reload set them again with the other settings a caller changed
|
|
348
|
+
* (exportImage, replaceDatabase).
|
|
349
|
+
*/
|
|
350
|
+
private applyConnectionSettings;
|
|
351
|
+
/**
|
|
352
|
+
* Imports a database from a Uint8Array (SQLite file).
|
|
353
|
+
* Replaces the current database once any open transaction() has ended, and
|
|
354
|
+
* saves it to IndexedDB before it resolves; with `crossTab`, in place of
|
|
355
|
+
* what every tab stored. Bytes that are not a SQLite database are refused,
|
|
356
|
+
* and the adapter keeps its database.
|
|
357
|
+
* @param data SQLite database file
|
|
358
|
+
*/
|
|
359
|
+
importDatabase(data: Uint8Array): Promise<void>;
|
|
360
|
+
/** Replaces the database with an image, once sql.js has read it as a SQLite database. */
|
|
361
|
+
private swapIn;
|
|
362
|
+
/** Puts `next` in place of the database, with the connection settings the current one has. */
|
|
363
|
+
private replaceDatabase;
|
|
364
|
+
/**
|
|
365
|
+
* Runs `work` with this tab holding the database: under the Web Lock, or,
|
|
366
|
+
* without Web Locks, after this adapter's earlier coordinated work.
|
|
367
|
+
*/
|
|
368
|
+
private withCoordination;
|
|
369
|
+
/**
|
|
370
|
+
* One statement across tabs: on the newest stored image, and stored before
|
|
371
|
+
* it resolves. Without Web Locks another tab can save between the load and
|
|
372
|
+
* the save; the statement then runs again on that tab's image.
|
|
373
|
+
*/
|
|
374
|
+
private coordinatedStatement;
|
|
375
|
+
/**
|
|
376
|
+
* One transaction across tabs: on the newest stored image, and stored before
|
|
377
|
+
* it resolves. Without Web Locks another tab can save while the callback
|
|
378
|
+
* runs; the transaction is then refused, nothing of it is stored, and the
|
|
379
|
+
* other tab's image is loaded for the caller to run it again.
|
|
380
|
+
*/
|
|
381
|
+
private coordinatedTransaction;
|
|
382
|
+
/** Loads the stored image when another tab (or adapter) has saved since this one loaded or saved. */
|
|
383
|
+
private syncFromStore;
|
|
384
|
+
/** Reads the stored stamp, and the image with it when the stamp is not `known`; null when it is. */
|
|
385
|
+
private readIfChanged;
|
|
386
|
+
/**
|
|
387
|
+
* Stores the image when the stored stamp is still `expected`, in one
|
|
388
|
+
* IndexedDB transaction, so no other tab's save lands between the check and
|
|
389
|
+
* the write. `undefined` stores it whatever the stamp is. Resolves with
|
|
390
|
+
* whether it stored the image.
|
|
391
|
+
*/
|
|
392
|
+
private saveIfStampIs;
|
|
393
|
+
/** A stamp no other save of this or another tab writes. */
|
|
394
|
+
private nextStamp;
|
|
395
|
+
/**
|
|
396
|
+
* Exports the database for a save, keeping the connection settings a
|
|
397
|
+
* caller made: sql.js's export() closes the connection and opens it again.
|
|
398
|
+
*/
|
|
399
|
+
private exportImage;
|
|
400
|
+
/** The connection settings that differ from a fresh connection's. */
|
|
401
|
+
private changedPragmas;
|
|
402
|
+
/** Sets connection settings on the database, after a save or a reload. */
|
|
403
|
+
private applyPragmas;
|
|
404
|
+
/**
|
|
405
|
+
* Opens or creates the IndexedDB database.
|
|
406
|
+
*/
|
|
407
|
+
private openIndexedDb;
|
|
408
|
+
/**
|
|
409
|
+
* Opens IndexedDB with retry logic and exponential backoff.
|
|
410
|
+
* Handles race conditions when multiple adapters initialize simultaneously.
|
|
411
|
+
*
|
|
412
|
+
* The "NotFoundError" for object stores typically occurs when:
|
|
413
|
+
* 1. Two adapters try to open/upgrade simultaneously
|
|
414
|
+
* 2. One adapter opens the DB while another is still upgrading
|
|
415
|
+
* 3. Schema version mismatch during concurrent initialization
|
|
416
|
+
*
|
|
417
|
+
* @param maxRetries Maximum number of retry attempts (default: 3)
|
|
418
|
+
* @param baseDelayMs Base delay in milliseconds (default: 100)
|
|
419
|
+
*/
|
|
420
|
+
private openIndexedDbWithRetry;
|
|
421
|
+
/**
|
|
422
|
+
* Loads the SQLite database and its stamp from IndexedDB, in one
|
|
423
|
+
* transaction, so the two belong together.
|
|
424
|
+
*/
|
|
425
|
+
private loadFromIndexedDb;
|
|
426
|
+
/**
|
|
427
|
+
* Writes the current image to IndexedDB, with a new stamp. Never called
|
|
428
|
+
* while a transaction is open (see saveIfIdle): sql.js's export() closes and
|
|
429
|
+
* reopens the connection, which ends an open transaction.
|
|
430
|
+
*
|
|
431
|
+
* Settles when the IndexedDB transaction completes, not when its put request
|
|
432
|
+
* succeeds: the transaction can still abort after that (a quota error at
|
|
433
|
+
* commit), and the image is then not stored. On abort the writes stay
|
|
434
|
+
* unsaved, so the next save writes them. A write made after the export stays
|
|
435
|
+
* unsaved too.
|
|
436
|
+
*/
|
|
437
|
+
private saveToIndexedDb;
|
|
438
|
+
/** Whether writes were made since the image the last completed save exported. */
|
|
439
|
+
private hasUnsavedWrites;
|
|
440
|
+
/**
|
|
441
|
+
* Whether a transaction is open on the connection: one transaction() is
|
|
442
|
+
* running, or one the caller began with BEGIN or SAVEPOINT. sql.js does not
|
|
443
|
+
* export sqlite3_get_autocommit, so the adapter asks SQLite: BEGIN fails
|
|
444
|
+
* inside a transaction, and outside one it is rolled back at once. A probe
|
|
445
|
+
* that fails for any reason counts as open, so the adapter does not export.
|
|
446
|
+
*/
|
|
447
|
+
private inTransaction;
|
|
448
|
+
/**
|
|
449
|
+
* Starts a save of the unsaved writes, unless a save is running or a
|
|
450
|
+
* transaction is open; the auto-save tick tries again later.
|
|
451
|
+
*/
|
|
452
|
+
private saveIfIdle;
|
|
453
|
+
/**
|
|
454
|
+
* Resolves once the writes up to `generation` are stored. A save in
|
|
455
|
+
* progress that holds them is waited for; an open transaction() is waited
|
|
456
|
+
* for, since its own save holds them; while a transaction a caller began
|
|
457
|
+
* with BEGIN is open, nothing can be stored, and its COMMIT stores them.
|
|
458
|
+
* Rejects when the save that held them failed.
|
|
459
|
+
*/
|
|
460
|
+
private saveThrough;
|
|
461
|
+
/**
|
|
462
|
+
* Starts a save at once and keeps it as the save in progress. The caller has
|
|
463
|
+
* made sure no transaction is open: the export would end it.
|
|
464
|
+
*/
|
|
465
|
+
private startSave;
|
|
466
|
+
/** Waits for a save in progress to settle, whether it succeeded or not. */
|
|
467
|
+
private settleSave;
|
|
468
|
+
private reportLongWait;
|
|
469
|
+
private reportLockWait;
|
|
470
|
+
/**
|
|
471
|
+
* Wraps a transaction operation with retry logic.
|
|
472
|
+
* Handles "NotFoundError" by reopening IndexedDB connection.
|
|
473
|
+
*/
|
|
474
|
+
private withTransactionRetry;
|
|
475
|
+
/**
|
|
476
|
+
* Starts auto-save interval.
|
|
477
|
+
*/
|
|
478
|
+
private startAutoSave;
|
|
479
|
+
/** One auto-save tick: a failed save is reported once and tried again on the next tick. */
|
|
480
|
+
private autoSaveTick;
|
|
481
|
+
/**
|
|
482
|
+
* Ensures the database is open.
|
|
483
|
+
*/
|
|
484
|
+
private ensureOpen;
|
|
485
|
+
/**
|
|
486
|
+
* Normalizes last insert row ID to string or number.
|
|
487
|
+
*/
|
|
488
|
+
private normaliseRowId;
|
|
489
|
+
}
|
|
490
|
+
//# sourceMappingURL=indexedDbAdapter.d.ts.map
|