@capgo/capacitor-fast-sql 8.1.0 → 8.2.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.
package/README.md CHANGED
@@ -65,7 +65,7 @@ This plugin provides direct native SQLite database access with a custom communic
65
65
  - **Direct Native SQLite**: Full SQL support with transactions, batch operations, and binary data
66
66
  - **Sync-Friendly**: Designed for local sync systems (CRDTs, operational transforms, etc.)
67
67
  - **IndexedDB Replacement**: Provides reliable alternative to broken/limited IndexedDB implementations
68
- - **Cross-Platform**: iOS, Android, and Web (using sql.js + IndexedDB for persistence)
68
+ - **Cross-Platform**: iOS, Android, and Web (using [@sqlite.org/sqlite-wasm](https://github.com/sqlite/sqlite-wasm) with OPFS persistence)
69
69
  - **Optional RAG VectorStore**: Persist many named vector stores for retrieval-augmented generation without adding a native dependency
70
70
 
71
71
  ## iOS Configuration
@@ -154,25 +154,50 @@ pod 'CapgoCapacitorFastSql/SQLCipher', :path => '../../node_modules/@capgo/capac
154
154
 
155
155
  Then run `pod install` in the `ios/App` directory. If you skip this subspec, keep `encrypted: false`.
156
156
 
157
- ## Web Platform
158
-
159
- On the web, this plugin uses [sql.js](https://sql.js.org/) (SQLite compiled to WebAssembly) with IndexedDB for persistence.
160
-
161
- By default, the plugin loads `sql-wasm.js` and `sql-wasm.wasm` from the cdnjs CDN. If you want to bundle these files with your web application (to avoid a CDN dependency), call `configureWeb()` once at startup **before** the first `connect()`:
162
-
163
- ```typescript
164
- import { CapgoCapacitorFastSql, FastSQL } from '@capgo/capacitor-fast-sql';
165
-
166
- // Point to your locally bundled sql.js files
167
- await CapgoCapacitorFastSql.configureWeb({
168
- sqlJsUrl: '/assets/sql-wasm.js',
169
- wasmUrl: '/assets/sql-wasm.wasm',
170
- });
171
-
172
- const db = await FastSQL.connect({ database: 'myapp' });
173
- ```
174
-
175
- `configureWeb()` is a no-op on iOS and Android — it is safe to call unconditionally.
157
+ ## Web Platform
158
+
159
+ On the web, this plugin uses the official [@sqlite.org/sqlite-wasm](https://github.com/sqlite/sqlite-wasm) build with [OPFS](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API/Origin_private_file_system) for persistence. SQLite reads and writes the database file directly — it is not loaded entirely into RAM or mirrored through IndexedDB.
160
+
161
+ For OPFS to work, your web server must send Cross-Origin Isolation headers:
162
+
163
+ ```http
164
+ Cross-Origin-Opener-Policy: same-origin
165
+ Cross-Origin-Embedder-Policy: require-corp
166
+ ```
167
+
168
+ With Vite:
169
+
170
+ ```typescript
171
+ import { defineConfig } from 'vite';
172
+
173
+ export default defineConfig({
174
+ server: {
175
+ headers: {
176
+ 'Cross-Origin-Opener-Policy': 'same-origin',
177
+ 'Cross-Origin-Embedder-Policy': 'require-corp',
178
+ },
179
+ },
180
+ optimizeDeps: {
181
+ exclude: ['@sqlite.org/sqlite-wasm'],
182
+ },
183
+ });
184
+ ```
185
+
186
+ Optional web configuration (call before the first `connect()`):
187
+
188
+ ```typescript
189
+ import { CapgoCapacitorFastSql, FastSQL } from '@capgo/capacitor-fast-sql';
190
+
191
+ await CapgoCapacitorFastSql.configureWeb({
192
+ useOpfs: true,
193
+ });
194
+
195
+ const db = await FastSQL.connect({ database: 'myapp' });
196
+ ```
197
+
198
+ `configureWeb()` is a no-op on iOS and Android — it is safe to call unconditionally.
199
+
200
+ > **Note:** Existing databases previously stored in IndexedDB by sql.js are not migrated automatically. Re-seed or import data after upgrading if needed.
176
201
 
177
202
  ## Usage
178
203
 
@@ -486,11 +511,10 @@ Get the native Capacitor plugin version.
486
511
  configureWeb(config: WebConfig) => Promise<void>
487
512
  ```
488
513
 
489
- Configure web-specific options for the sql.js WASM module.
514
+ Configure web-specific options for the official SQLite Wasm module.
490
515
 
491
- Call this **before** the first `connect()` call to load sql.js from a
492
- locally bundled path instead of the default CDN. This method is a no-op
493
- on iOS and Android.
516
+ Call this **before** the first `connect()` call if you need to disable OPFS
517
+ or supply a custom Worker. This method is a no-op on iOS and Android.
494
518
 
495
519
  | Param | Type | Description |
496
520
  | ------------ | ----------------------------------------------- | --------------------------- |
@@ -611,14 +635,17 @@ buffer as needed.
611
635
 
612
636
  #### WebConfig
613
637
 
614
- Web platform configuration for the sql.js WASM module.
615
- Use with `configureWeb()` to load sql.js
616
- from a locally bundled path instead of the default CDN.
638
+ Web platform configuration for the official SQLite Wasm module.
639
+ Use with `configureWeb()` before the first `connect()`.
617
640
 
618
- | Prop | Type | Description |
619
- | -------------- | ------------------- | ---------------------------------------------------------------------------------------------------------- |
620
- | **`sqlJsUrl`** | <code>string</code> | URL to the sql.js JavaScript file (`sql-wasm.js`). When omitted, the plugin loads from the cdnjs CDN. |
621
- | **`wasmUrl`** | <code>string</code> | URL to the sql.js WebAssembly binary (`sql-wasm.wasm`). When omitted, the plugin loads from the cdnjs CDN. |
641
+ OPFS persistence requires Cross-Origin Isolation headers on your web server:
642
+ `Cross-Origin-Opener-Policy: same-origin` and
643
+ `Cross-Origin-Embedder-Policy: require-corp`.
644
+
645
+ | Prop | Type | Description | Default |
646
+ | ------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------- |
647
+ | **`useOpfs`** | <code>boolean</code> | Prefer OPFS persistence via a Web Worker (default: `true`). When OPFS is unavailable, the plugin falls back to a non-persistent database and logs a warning. | <code>true</code> |
648
+ | **`worker`** | <code><a href="#sqlitewebworker">SqliteWebWorker</a></code> | Custom Worker instance or factory for SQLite Wasm. Advanced: override the default worker from `@sqlite.org/sqlite-wasm`. | |
622
649
 
623
650
 
624
651
  ### Type Aliases
@@ -636,6 +663,14 @@ SQL value types supported by the plugin
636
663
  <code>ArrayBufferTypes[keyof ArrayBufferTypes]</code>
637
664
 
638
665
 
666
+ #### SqliteWebWorker
667
+
668
+ Browser Worker instance or a factory that returns one.
669
+ Used to override the default SQLite Wasm worker.
670
+
671
+ <code>Worker | (() =&gt; Worker)</code>
672
+
673
+
639
674
  ### Enums
640
675
 
641
676
 
@@ -19,7 +19,7 @@ import java.util.Map;
19
19
  @CapacitorPlugin(name = "CapgoCapacitorFastSql")
20
20
  public class CapgoCapacitorFastSqlPlugin extends Plugin {
21
21
 
22
- private final String pluginVersion = "8.1.0";
22
+ private final String pluginVersion = "8.2.0";
23
23
 
24
24
  private Map<String, DatabaseConnection> databases = new HashMap<>();
25
25
  private SQLHTTPServer server;
@@ -74,23 +74,31 @@ export interface SQLConnectionOptions {
74
74
  performancePresets?: boolean;
75
75
  }
76
76
  /**
77
- * Web platform configuration for the sql.js WASM module.
78
- * Use with `configureWeb()` to load sql.js
79
- * from a locally bundled path instead of the default CDN.
77
+ * Browser Worker instance or a factory that returns one.
78
+ * Used to override the default SQLite Wasm worker.
79
+ */
80
+ export type SqliteWebWorker = Worker | (() => Worker);
81
+ /**
82
+ * Web platform configuration for the official SQLite Wasm module.
83
+ * Use with `configureWeb()` before the first `connect()`.
84
+ *
85
+ * OPFS persistence requires Cross-Origin Isolation headers on your web server:
86
+ * `Cross-Origin-Opener-Policy: same-origin` and
87
+ * `Cross-Origin-Embedder-Policy: require-corp`.
80
88
  */
81
89
  export interface WebConfig {
82
90
  /**
83
- * URL to the sql.js JavaScript file (`sql-wasm.js`).
84
- * When omitted, the plugin loads from the cdnjs CDN.
85
- * @example '/assets/sql-wasm.js'
91
+ * Prefer OPFS persistence via a Web Worker (default: `true`).
92
+ * When OPFS is unavailable, the plugin falls back to a non-persistent database
93
+ * and logs a warning.
94
+ * @default true
86
95
  */
87
- sqlJsUrl?: string;
96
+ useOpfs?: boolean;
88
97
  /**
89
- * URL to the sql.js WebAssembly binary (`sql-wasm.wasm`).
90
- * When omitted, the plugin loads from the cdnjs CDN.
91
- * @example '/assets/sql-wasm.wasm'
98
+ * Custom Worker instance or factory for SQLite Wasm.
99
+ * Advanced: override the default worker from `@sqlite.org/sqlite-wasm`.
92
100
  */
93
- wasmUrl?: string;
101
+ worker?: SqliteWebWorker;
94
102
  }
95
103
  /**
96
104
  * Transaction isolation levels
@@ -255,11 +263,10 @@ export interface CapgoCapacitorFastSqlPlugin {
255
263
  version: string;
256
264
  }>;
257
265
  /**
258
- * Configure web-specific options for the sql.js WASM module.
266
+ * Configure web-specific options for the official SQLite Wasm module.
259
267
  *
260
- * Call this **before** the first `connect()` call to load sql.js from a
261
- * locally bundled path instead of the default CDN. This method is a no-op
262
- * on iOS and Android.
268
+ * Call this **before** the first `connect()` call if you need to disable OPFS
269
+ * or supply a custom Worker. This method is a no-op on iOS and Android.
263
270
  *
264
271
  * @param config - Web configuration options
265
272
  * @returns Promise that resolves when the configuration is applied
@@ -268,8 +275,7 @@ export interface CapgoCapacitorFastSqlPlugin {
268
275
  * ```typescript
269
276
  * // Configure once at app startup (web only)
270
277
  * await CapgoCapacitorFastSql.configureWeb({
271
- * sqlJsUrl: '/assets/sql-wasm.js',
272
- * wasmUrl: '/assets/sql-wasm.wasm',
278
+ * useOpfs: true,
273
279
  * });
274
280
  * const db = await FastSQL.connect({ database: 'myapp' });
275
281
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,UAAU,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,EAAE,CAAC;IAEf;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,oBAAY,cAAc;IACxB,eAAe,qBAAqB;IACpC,aAAa,mBAAmB;IAChC,cAAc,oBAAoB;IAClC,YAAY,iBAAiB;CAC9B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAC9C,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IAEH;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzD;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACpD,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;IAEH;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnG;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhG;;;;;;;;;;;OAWG;IACH,iBAAiB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhE;;;;;;;;;;;;;;;;;OAiBG;IACH,mBAAmB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElE;;;;;;;;;;;OAWG;IACH,gBAAgB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAEjD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD"}
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"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"}
package/dist/esm/web.d.ts CHANGED
@@ -1,27 +1,24 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
2
  import type { CapgoCapacitorFastSqlPlugin, SQLConnectionOptions, SQLResult, SQLValue, IsolationLevel, WebConfig } from './definitions';
3
3
  /**
4
- * Web implementation using sql.js (SQLite compiled to WebAssembly)
4
+ * Web implementation using the official SQLite Wasm build with OPFS persistence.
5
5
  *
6
- * This provides a compatible API on the web platform, storing databases
7
- * in IndexedDB for persistence.
6
+ * Databases are stored in the Origin Private File System when available (requires
7
+ * Cross-Origin Isolation: COOP/COEP). No full-database copy is kept in RAM or
8
+ * IndexedDB — SQLite reads/writes the OPFS file directly from a worker.
8
9
  */
9
10
  export declare class CapgoCapacitorFastSqlWeb extends WebPlugin implements CapgoCapacitorFastSqlPlugin {
10
11
  private databases;
11
- private sqlPromise;
12
+ private promiserPromise;
12
13
  private nextPort;
13
14
  private webConfig;
14
- constructor();
15
15
  /**
16
16
  * Configure web-specific options (no-op on native platforms).
17
- * Must be called before connect() when using locally bundled sql.js files.
17
+ * Must be called before connect() when overriding the default worker.
18
18
  */
19
19
  configureWeb(config: WebConfig): Promise<void>;
20
- /**
21
- * Load sql.js library (lazy – called on first connect()).
22
- * Returns the cached promise so callers can await it directly.
23
- */
24
- private loadSqlJs;
20
+ private getPromiser;
21
+ private dbPath;
25
22
  connect(options: SQLConnectionOptions): Promise<{
26
23
  port: number;
27
24
  token: string;
@@ -51,22 +48,8 @@ export declare class CapgoCapacitorFastSqlWeb extends WebPlugin implements Capgo
51
48
  rollbackTransaction(options: {
52
49
  database: string;
53
50
  }): Promise<void>;
54
- /**
55
- * Generate a random authentication token
56
- */
51
+ private applyPerformanceConfig;
57
52
  private generateToken;
58
- /**
59
- * Get last insert row ID
60
- */
61
- private getLastInsertId;
62
- /**
63
- * Save database to IndexedDB
64
- */
65
- private saveToIndexedDB;
66
- /**
67
- * Load database from IndexedDB
68
- */
69
- private loadFromIndexedDB;
70
53
  getPluginVersion(): Promise<{
71
54
  version: string;
72
55
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,KAAK,EACV,2BAA2B,EAC3B,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,SAAS,EACV,MAAM,eAAe,CAAC;AAMvB;;;;;GAKG;AACH,qBAAa,wBAAyB,SAAQ,SAAU,YAAW,2BAA2B;IAC5F,OAAO,CAAC,SAAS,CAAoE;IACrF,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAiB;;IAMlC;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAMpD;;;OAGG;IACH,OAAO,CAAC,SAAS;IA4BX,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IA0BlG,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxD,aAAa,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAYtF,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAiClG,gBAAgB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/F,iBAAiB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/D,mBAAmB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvE;;OAEG;IACH,OAAO,CAAC,aAAa;IAMrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAYvB;;OAEG;YACW,eAAe;IAgC7B;;OAEG;YACW,iBAAiB;IAgCzB,gBAAgB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAGvD"}
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAI5C,OAAO,KAAK,EACV,2BAA2B,EAC3B,oBAAoB,EACpB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,SAAS,EACV,MAAM,eAAe,CAAC;AAcvB;;;;;;GAMG;AACH,qBAAa,wBAAyB,SAAQ,SAAU,YAAW,2BAA2B;IAC5F,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,SAAS,CAAiB;IAElC;;;OAGG;IACG,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpD,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,MAAM;IAIR,OAAO,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAmDlG,UAAU,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAYxD,aAAa,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAYtF,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IA6ClG,gBAAgB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/F,iBAAiB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO/D,mBAAmB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAOzD,sBAAsB;IAkBpC,OAAO,CAAC,aAAa;IAMf,gBAAgB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAGvD"}
package/dist/esm/web.js CHANGED
@@ -1,76 +1,75 @@
1
1
  import { WebPlugin } from '@capacitor/core';
2
- import { applyPerformanceConfig } from './performance-config';
3
- const DEFAULT_SQLJS_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js';
4
- const DEFAULT_WASM_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.wasm';
2
+ import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
5
3
  /**
6
- * Web implementation using sql.js (SQLite compiled to WebAssembly)
4
+ * Web implementation using the official SQLite Wasm build with OPFS persistence.
7
5
  *
8
- * This provides a compatible API on the web platform, storing databases
9
- * in IndexedDB for persistence.
6
+ * Databases are stored in the Origin Private File System when available (requires
7
+ * Cross-Origin Isolation: COOP/COEP). No full-database copy is kept in RAM or
8
+ * IndexedDB — SQLite reads/writes the OPFS file directly from a worker.
10
9
  */
11
10
  export class CapgoCapacitorFastSqlWeb extends WebPlugin {
12
11
  constructor() {
13
- super();
12
+ super(...arguments);
14
13
  this.databases = new Map();
15
- this.sqlPromise = null;
14
+ this.promiserPromise = null;
16
15
  this.nextPort = 9000;
17
16
  this.webConfig = {};
18
17
  }
19
18
  /**
20
19
  * Configure web-specific options (no-op on native platforms).
21
- * Must be called before connect() when using locally bundled sql.js files.
20
+ * Must be called before connect() when overriding the default worker.
22
21
  */
23
22
  async configureWeb(config) {
24
23
  this.webConfig = config;
25
- // Reset any in-progress load so the next connect() uses the new config
26
- this.sqlPromise = null;
24
+ this.promiserPromise = null;
27
25
  }
28
- /**
29
- * Load sql.js library (lazy – called on first connect()).
30
- * Returns the cached promise so callers can await it directly.
31
- */
32
- loadSqlJs() {
33
- var _a, _b;
34
- if (!this.sqlPromise) {
35
- const jsUrl = (_a = this.webConfig.sqlJsUrl) !== null && _a !== void 0 ? _a : DEFAULT_SQLJS_URL;
36
- const wasmUrl = (_b = this.webConfig.wasmUrl) !== null && _b !== void 0 ? _b : DEFAULT_WASM_URL;
37
- this.sqlPromise = new Promise((resolve, reject) => {
38
- try {
39
- // Load sql.js from the configured URL (CDN or local bundle)
40
- const script = document.createElement('script');
41
- script.src = jsUrl;
42
- script.onload = async () => {
43
- const initSqlJs = window.initSqlJs;
44
- const SQL = await initSqlJs({
45
- locateFile: (file) => (file.endsWith('.wasm') ? wasmUrl : file),
46
- });
47
- resolve(SQL);
48
- };
49
- script.onerror = reject;
50
- document.head.appendChild(script);
51
- }
52
- catch (error) {
53
- reject(error);
54
- }
55
- });
26
+ getPromiser() {
27
+ if (!this.promiserPromise) {
28
+ const config = this.webConfig.worker !== undefined ? { worker: this.webConfig.worker } : undefined;
29
+ this.promiserPromise = sqlite3Worker1Promiser.v2(config);
56
30
  }
57
- return this.sqlPromise;
31
+ return this.promiserPromise;
32
+ }
33
+ dbPath(database) {
34
+ return `/capgo-fast-sql/${database}.sqlite3`;
58
35
  }
59
36
  async connect(options) {
60
- const SQL = await this.loadSqlJs();
61
- // Check if database already exists in IndexedDB
62
- const savedData = await this.loadFromIndexedDB(options.database);
63
- let db;
64
- if (savedData) {
65
- db = new SQL.Database(savedData);
37
+ if (this.databases.has(options.database)) {
38
+ const existing = this.databases.get(options.database);
39
+ return {
40
+ port: existing.port,
41
+ token: existing.token,
42
+ database: options.database,
43
+ };
44
+ }
45
+ const promiser = await this.getPromiser();
46
+ const path = this.dbPath(options.database);
47
+ const useOpfs = this.webConfig.useOpfs !== false;
48
+ let openResult;
49
+ if (useOpfs) {
50
+ try {
51
+ openResult = await promiser('open', {
52
+ filename: `file:${path}?vfs=opfs`,
53
+ });
54
+ }
55
+ catch (opfsError) {
56
+ console.warn('[CapgoCapacitorFastSql] OPFS unavailable; web database will not persist across reloads. ' +
57
+ 'Serve with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp.', opfsError);
58
+ openResult = await promiser('open', { filename: path });
59
+ }
66
60
  }
67
61
  else {
68
- db = new SQL.Database();
62
+ openResult = await promiser('open', { filename: path });
63
+ }
64
+ const dbId = openResult.result.dbId;
65
+ const persistent = Boolean(openResult.result.persistent);
66
+ if (!dbId) {
67
+ throw new Error('Failed to open SQLite Wasm database: missing dbId');
69
68
  }
70
- applyPerformanceConfig(db, options);
69
+ await this.applyPerformanceConfig(promiser, dbId, options);
71
70
  const token = this.generateToken();
72
71
  const port = this.nextPort++;
73
- this.databases.set(options.database, { db, token, port });
72
+ this.databases.set(options.database, { dbId, token, port, persistent });
74
73
  return {
75
74
  port,
76
75
  token,
@@ -82,10 +81,9 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
82
81
  if (!dbInfo) {
83
82
  throw new Error(`Database '${options.database}' is not connected`);
84
83
  }
85
- // Save to IndexedDB before closing
86
- const data = dbInfo.db.export();
87
- await this.saveToIndexedDB(options.database, data);
88
- dbInfo.db.close();
84
+ const promiser = await this.getPromiser();
85
+ // OPFS-backed DBs persist automatically; no export/IndexedDB write needed.
86
+ await promiser({ type: 'close', dbId: dbInfo.dbId, args: {} });
89
87
  this.databases.delete(options.database);
90
88
  }
91
89
  async getServerInfo(options) {
@@ -99,32 +97,45 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
99
97
  };
100
98
  }
101
99
  async execute(options) {
100
+ var _a, _b, _c, _d;
102
101
  const dbInfo = this.databases.get(options.database);
103
102
  if (!dbInfo) {
104
103
  throw new Error(`Database '${options.database}' is not connected`);
105
104
  }
106
105
  try {
107
- const stmt = dbInfo.db.prepare(options.statement);
108
- if (options.params) {
109
- stmt.bind(options.params);
110
- }
106
+ const promiser = await this.getPromiser();
111
107
  const rows = [];
112
- while (stmt.step()) {
113
- const row = stmt.getAsObject();
114
- rows.push(row);
115
- }
116
- stmt.free();
117
- // Get changes and last insert ID
118
- const changes = dbInfo.db.getRowsModified();
119
- const insertId = this.getLastInsertId(dbInfo.db);
108
+ // countChanges / lastInsertRowId are supported by Worker1 at runtime but
109
+ // omitted from the published Worker1ExecArgs typings.
110
+ const result = await promiser({
111
+ type: 'exec',
112
+ dbId: dbInfo.dbId,
113
+ args: {
114
+ sql: options.statement,
115
+ bind: options.params,
116
+ rowMode: 'object',
117
+ countChanges: true,
118
+ lastInsertRowId: true,
119
+ callback: (msg) => {
120
+ if (msg.rowNumber != null && msg.row && typeof msg.row === 'object' && !Array.isArray(msg.row)) {
121
+ rows.push(msg.row);
122
+ }
123
+ },
124
+ },
125
+ });
126
+ const execResult = result.result;
127
+ const rowsAffected = Number((_a = execResult.changeCount) !== null && _a !== void 0 ? _a : 0);
128
+ const rawInsertId = execResult.lastInsertRowId;
129
+ const insertId = rawInsertId !== undefined && rawInsertId !== null ? Number(rawInsertId) : undefined;
120
130
  return {
121
131
  rows,
122
- rowsAffected: changes,
123
- insertId: insertId > 0 ? insertId : undefined,
132
+ rowsAffected,
133
+ insertId: insertId !== undefined && insertId > 0 ? insertId : undefined,
124
134
  };
125
135
  }
126
136
  catch (error) {
127
- throw new Error(`SQL execution failed: ${error.message}`);
137
+ const message = (_d = (_c = (_b = error === null || error === void 0 ? void 0 : error.result) === null || _b === void 0 ? void 0 : _b.message) !== null && _c !== void 0 ? _c : error === null || error === void 0 ? void 0 : error.message) !== null && _d !== void 0 ? _d : String(error);
138
+ throw new Error(`SQL execution failed: ${message}`);
128
139
  }
129
140
  }
130
141
  async beginTransaction(options) {
@@ -145,87 +156,22 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
145
156
  statement: 'ROLLBACK',
146
157
  });
147
158
  }
148
- /**
149
- * Generate a random authentication token
150
- */
159
+ async applyPerformanceConfig(promiser, dbId, options) {
160
+ await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA foreign_keys = ON' } });
161
+ if (options.walMode) {
162
+ await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA journal_mode = WAL' } });
163
+ }
164
+ if (options.performancePresets) {
165
+ await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA synchronous = NORMAL' } });
166
+ await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA busy_timeout = 5000' } });
167
+ await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA cache_size = -2000' } });
168
+ }
169
+ }
151
170
  generateToken() {
152
171
  return Array.from(crypto.getRandomValues(new Uint8Array(32)))
153
172
  .map((b) => b.toString(16).padStart(2, '0'))
154
173
  .join('');
155
174
  }
156
- /**
157
- * Get last insert row ID
158
- */
159
- getLastInsertId(db) {
160
- try {
161
- const result = db.exec('SELECT last_insert_rowid()');
162
- if (result.length > 0 && result[0].values.length > 0) {
163
- return result[0].values[0][0];
164
- }
165
- }
166
- catch (_a) {
167
- // Ignore error
168
- }
169
- return -1;
170
- }
171
- /**
172
- * Save database to IndexedDB
173
- */
174
- async saveToIndexedDB(dbName, data) {
175
- return new Promise((resolve, reject) => {
176
- const request = indexedDB.open('CapacitorNativeSQL', 1);
177
- request.onerror = () => reject(request.error);
178
- request.onupgradeneeded = (event) => {
179
- const db = event.target.result;
180
- if (!db.objectStoreNames.contains('databases')) {
181
- db.createObjectStore('databases');
182
- }
183
- };
184
- request.onsuccess = () => {
185
- const db = request.result;
186
- const transaction = db.transaction(['databases'], 'readwrite');
187
- const store = transaction.objectStore('databases');
188
- const putRequest = store.put(data, dbName);
189
- putRequest.onsuccess = () => {
190
- db.close();
191
- resolve();
192
- };
193
- putRequest.onerror = () => {
194
- db.close();
195
- reject(putRequest.error);
196
- };
197
- };
198
- });
199
- }
200
- /**
201
- * Load database from IndexedDB
202
- */
203
- async loadFromIndexedDB(dbName) {
204
- return new Promise((resolve, reject) => {
205
- const request = indexedDB.open('CapacitorNativeSQL', 1);
206
- request.onerror = () => reject(request.error);
207
- request.onupgradeneeded = (event) => {
208
- const db = event.target.result;
209
- if (!db.objectStoreNames.contains('databases')) {
210
- db.createObjectStore('databases');
211
- }
212
- };
213
- request.onsuccess = () => {
214
- const db = request.result;
215
- const transaction = db.transaction(['databases'], 'readonly');
216
- const store = transaction.objectStore('databases');
217
- const getRequest = store.get(dbName);
218
- getRequest.onsuccess = () => {
219
- db.close();
220
- resolve(getRequest.result || null);
221
- };
222
- getRequest.onerror = () => {
223
- db.close();
224
- reject(getRequest.error);
225
- };
226
- };
227
- });
228
- }
229
175
  async getPluginVersion() {
230
176
  return { version: 'web' };
231
177
  }