@capgo/capacitor-fast-sql 8.2.15 → 8.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +8 -8
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +29 -6
  4. package/android/src/main/java/app/capgo/capacitor/fastsql/DatabaseConnection.java +2 -0
  5. package/android/src/main/java/app/capgo/capacitor/fastsql/EncryptedSQLDatabase.java +33 -46
  6. package/android/src/main/java/app/capgo/capacitor/fastsql/SQLDatabase.java +32 -50
  7. package/android/src/main/java/app/capgo/capacitor/fastsql/SQLHTTPServer.java +11 -23
  8. package/dist/esm/definitions.d.ts +6 -2
  9. package/dist/esm/definitions.d.ts.map +1 -1
  10. package/dist/esm/definitions.js +3 -1
  11. package/dist/esm/fast-sql.d.ts +4 -0
  12. package/dist/esm/fast-sql.d.ts.map +1 -1
  13. package/dist/esm/fast-sql.js +35 -3
  14. package/dist/esm/native-sql-connection.d.ts +1 -0
  15. package/dist/esm/native-sql-connection.d.ts.map +1 -1
  16. package/dist/esm/native-sql-connection.js +13 -6
  17. package/dist/esm/transaction-isolation.d.ts +3 -0
  18. package/dist/esm/transaction-isolation.d.ts.map +1 -0
  19. package/dist/esm/transaction-isolation.js +6 -0
  20. package/dist/esm/vector-store.d.ts.map +1 -1
  21. package/dist/esm/vector-store.js +5 -2
  22. package/dist/esm/web-sql-connection.d.ts.map +1 -1
  23. package/dist/esm/web-sql-connection.js +2 -0
  24. package/dist/esm/web.d.ts.map +1 -1
  25. package/dist/esm/web.js +10 -2
  26. package/dist/plugin.cjs.js +71 -14
  27. package/dist/plugin.cjs.js.map +1 -1
  28. package/dist/plugin.js +71 -14
  29. package/dist/plugin.js.map +1 -1
  30. package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +25 -3
  31. package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLDatabase.swift +15 -5
  32. package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLHTTPServer.swift +6 -0
  33. package/ios/Tests/CapgoCapacitorFastSqlPluginTests/CapgoCapacitorFastSqlPluginTests.swift +13 -3
  34. package/ios/Tests/CapgoCapacitorFastSqlPluginTests/SQLResultMetadataTests.swift +15 -0
  35. package/package.json +1 -1
package/dist/plugin.js CHANGED
@@ -3,7 +3,9 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
3
3
 
4
4
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
5
5
  /**
6
- * Transaction isolation levels
6
+ * Transaction isolation levels. Only Serializable is supported by the current
7
+ * SQLite backends. Other values are retained for source compatibility but reject
8
+ * before starting a transaction; they are not silently mapped to another level.
7
9
  */
8
10
  exports.IsolationLevel = void 0;
9
11
  (function (IsolationLevel) {
@@ -17,6 +19,12 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
17
19
  web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoCapacitorFastSqlWeb()),
18
20
  });
19
21
 
22
+ function assertSupportedIsolation(level) {
23
+ if (level !== undefined && level !== exports.IsolationLevel.Serializable) {
24
+ throw new Error('Only SERIALIZABLE transaction isolation is supported');
25
+ }
26
+ }
27
+
20
28
  /**
21
29
  * SQL Connection class that uses HTTP protocol for efficient communication
22
30
  * with native SQLite databases, bypassing Capacitor's standard bridge.
@@ -29,7 +37,12 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
29
37
  this.database = database;
30
38
  this.port = port;
31
39
  this.token = token;
32
- this.baseUrl = `http://localhost:${port}`;
40
+ this.baseUrl = `http://127.0.0.1:${port}`;
41
+ }
42
+ browserFetch(input, init) {
43
+ const savedFetch = Reflect.get(globalThis, 'CapacitorWebFetch');
44
+ const browserFetch = typeof savedFetch === 'function' ? savedFetch : globalThis.fetch;
45
+ return browserFetch.call(globalThis, input, init);
33
46
  }
34
47
  /**
35
48
  * Get the database name
@@ -45,7 +58,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
45
58
  * @returns Query results
46
59
  */
47
60
  async execute(statement, params) {
48
- const response = await fetch(`${this.baseUrl}/execute`, {
61
+ const response = await this.browserFetch(`${this.baseUrl}/execute`, {
49
62
  method: 'POST',
50
63
  headers: {
51
64
  'Content-Type': 'application/json',
@@ -71,7 +84,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
71
84
  * @returns Array of results for each operation
72
85
  */
73
86
  async executeBatch(operations) {
74
- const response = await fetch(`${this.baseUrl}/batch`, {
87
+ const response = await this.browserFetch(`${this.baseUrl}/batch`, {
75
88
  method: 'POST',
76
89
  headers: {
77
90
  'Content-Type': 'application/json',
@@ -98,10 +111,11 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
98
111
  * @param isolationLevel - Optional isolation level
99
112
  */
100
113
  async beginTransaction(isolationLevel) {
114
+ assertSupportedIsolation(isolationLevel);
101
115
  if (this.inTransaction) {
102
116
  throw new Error('Transaction already in progress');
103
117
  }
104
- const response = await fetch(`${this.baseUrl}/transaction/begin`, {
118
+ const response = await this.browserFetch(`${this.baseUrl}/transaction/begin`, {
105
119
  method: 'POST',
106
120
  headers: {
107
121
  'Content-Type': 'application/json',
@@ -125,7 +139,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
125
139
  if (!this.inTransaction) {
126
140
  throw new Error('No transaction in progress');
127
141
  }
128
- const response = await fetch(`${this.baseUrl}/transaction/commit`, {
142
+ const response = await this.browserFetch(`${this.baseUrl}/transaction/commit`, {
129
143
  method: 'POST',
130
144
  headers: {
131
145
  Authorization: `Bearer ${this.token}`,
@@ -145,7 +159,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
145
159
  if (!this.inTransaction) {
146
160
  throw new Error('No transaction in progress');
147
161
  }
148
- const response = await fetch(`${this.baseUrl}/transaction/rollback`, {
162
+ const response = await this.browserFetch(`${this.baseUrl}/transaction/rollback`, {
149
163
  method: 'POST',
150
164
  headers: {
151
165
  Authorization: `Bearer ${this.token}`,
@@ -306,6 +320,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
306
320
  * @param isolationLevel - Optional isolation level
307
321
  */
308
322
  async beginTransaction(isolationLevel) {
323
+ assertSupportedIsolation(isolationLevel);
309
324
  if (this.inTransaction) {
310
325
  throw new Error('Transaction already in progress');
311
326
  }
@@ -400,12 +415,40 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
400
415
  * @returns SQLConnection instance for executing queries
401
416
  */
402
417
  static async connect(options) {
403
- // Check if already connected
404
- const existing = this.connections.get(options.database);
418
+ var _a;
419
+ const saved = this.openOptions.get(options.database);
420
+ if (saved && !this.optionsMatch(saved, options)) {
421
+ throw new Error(`Database '${options.database}' is already opening or open with different options`);
422
+ }
423
+ const existing = (_a = this.connections.get(options.database)) !== null && _a !== void 0 ? _a : this.opening.get(options.database);
405
424
  if (existing) {
406
425
  this.sharedConnections.add(options.database);
407
426
  return existing;
408
427
  }
428
+ const snapshot = Object.assign({}, options);
429
+ this.openOptions.set(options.database, snapshot);
430
+ const pending = this.open(snapshot);
431
+ this.opening.set(options.database, pending);
432
+ try {
433
+ return await pending;
434
+ }
435
+ catch (error) {
436
+ this.openOptions.delete(options.database);
437
+ this.sharedConnections.delete(options.database);
438
+ throw error;
439
+ }
440
+ finally {
441
+ this.opening.delete(options.database);
442
+ }
443
+ }
444
+ static optionsMatch(left, right) {
445
+ return (Boolean(left.encrypted) === Boolean(right.encrypted) &&
446
+ left.encryptionKey === right.encryptionKey &&
447
+ Boolean(left.readOnly) === Boolean(right.readOnly) &&
448
+ Boolean(left.walMode) === Boolean(right.walMode) &&
449
+ Boolean(left.performancePresets) === Boolean(right.performancePresets));
450
+ }
451
+ static async open(options) {
409
452
  // Connect via native plugin
410
453
  const info = await CapgoCapacitorFastSql.connect(options);
411
454
  // Create connection instance appropriate for the current platform
@@ -428,6 +471,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
428
471
  */
429
472
  static async disconnect(database) {
430
473
  var _a;
474
+ await this.opening.get(database);
431
475
  const connection = this.connections.get(database);
432
476
  if (!connection) {
433
477
  throw new Error(`Database '${database}' is not connected`);
@@ -440,6 +484,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
440
484
  await CapgoCapacitorFastSql.disconnect({ database });
441
485
  // Remove connection
442
486
  this.connections.delete(database);
487
+ this.openOptions.delete(database);
443
488
  this.sharedConnections.delete(database);
444
489
  this.connectionRetainers.delete(database);
445
490
  this.pendingDisconnects.delete(database);
@@ -491,7 +536,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
491
536
  * Close all open connections
492
537
  */
493
538
  static async disconnectAll() {
494
- const databases = Array.from(this.connections.keys());
539
+ const databases = Array.from(new Set([...this.connections.keys(), ...this.opening.keys()]));
495
540
  await Promise.all(databases.map((db) => {
496
541
  this.connectionRetainers.delete(db);
497
542
  this.pendingDisconnects.delete(db);
@@ -507,6 +552,8 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
507
552
  return Array.from(this.connections.keys());
508
553
  }
509
554
  }
555
+ FastSQL.opening = new Map();
556
+ FastSQL.openOptions = new Map();
510
557
  FastSQL.connections = new Map();
511
558
  FastSQL.sharedConnections = new Set();
512
559
  FastSQL.connectionRetainers = new Map();
@@ -858,8 +905,11 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
858
905
  .map((row) => this.rowToGetResult(row))
859
906
  .filter(params.predicate)
860
907
  .map((row) => row.id);
861
- for (const id of ids) {
862
- await this.connection.run(`DELETE FROM ${VECTOR_TABLE} WHERE store = ? AND id = ?`, [this.store, id]);
908
+ for (let offset = 0; offset < ids.length; offset += 100) {
909
+ await this.connection.executeBatch(ids.slice(offset, offset + 100).map((id) => ({
910
+ statement: `DELETE FROM ${VECTOR_TABLE} WHERE store = ? AND id = ?`,
911
+ params: [this.store, id],
912
+ })));
863
913
  }
864
914
  }
865
915
  async query(params) {
@@ -16897,9 +16947,15 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
16897
16947
  return this.promiserPromise;
16898
16948
  }
16899
16949
  dbPath(database) {
16950
+ if (!database || database === '.' || database === '..' || /[/\\\0]/.test(database)) {
16951
+ throw new Error('Database must be a non-empty file name without path separators');
16952
+ }
16900
16953
  return `/capgo-fast-sql/${database}.sqlite3`;
16901
16954
  }
16902
16955
  async connect(options) {
16956
+ if (options.readOnly) {
16957
+ throw new Error('Read-only opens are not supported by the SQLite Wasm Worker transport');
16958
+ }
16903
16959
  if (this.databases.has(options.database)) {
16904
16960
  const existing = this.databases.get(options.database);
16905
16961
  return {
@@ -16908,14 +16964,14 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
16908
16964
  database: options.database,
16909
16965
  };
16910
16966
  }
16911
- const promiser = await this.getPromiser();
16912
16967
  const path = this.dbPath(options.database);
16968
+ const promiser = await this.getPromiser();
16913
16969
  const useOpfs = this.webConfig.useOpfs !== false;
16914
16970
  let openResult;
16915
16971
  if (useOpfs) {
16916
16972
  try {
16917
16973
  openResult = await promiser('open', {
16918
- filename: `file:${path}?vfs=opfs`,
16974
+ filename: `file:/capgo-fast-sql/${encodeURIComponent(options.database)}.sqlite3?vfs=opfs`,
16919
16975
  });
16920
16976
  }
16921
16977
  catch (opfsError) {
@@ -17007,6 +17063,7 @@ var capacitorCapgoCapacitorFastSql = (function (exports, core) {
17007
17063
  }
17008
17064
  }
17009
17065
  async beginTransaction(options) {
17066
+ assertSupportedIsolation(options.isolationLevel);
17010
17067
  await this.execute({
17011
17068
  database: options.database,
17012
17069
  statement: 'BEGIN TRANSACTION',