@capgo/capacitor-fast-sql 8.2.16 → 8.2.18
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 +17 -16
- package/android/build.gradle +1 -0
- package/android/consumer-rules.pro +14 -0
- package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +29 -6
- package/android/src/main/java/app/capgo/capacitor/fastsql/DatabaseConnection.java +2 -0
- package/android/src/main/java/app/capgo/capacitor/fastsql/EncryptedSQLDatabase.java +33 -46
- package/android/src/main/java/app/capgo/capacitor/fastsql/SQLDatabase.java +32 -50
- package/android/src/main/java/app/capgo/capacitor/fastsql/SQLHTTPServer.java +11 -23
- package/dist/esm/definitions.d.ts +17 -2
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/definitions.js +3 -1
- package/dist/esm/fast-sql.d.ts +4 -0
- package/dist/esm/fast-sql.d.ts.map +1 -1
- package/dist/esm/fast-sql.js +35 -3
- package/dist/esm/native-sql-connection.d.ts +1 -0
- package/dist/esm/native-sql-connection.d.ts.map +1 -1
- package/dist/esm/native-sql-connection.js +13 -6
- package/dist/esm/transaction-isolation.d.ts +3 -0
- package/dist/esm/transaction-isolation.d.ts.map +1 -0
- package/dist/esm/transaction-isolation.js +6 -0
- package/dist/esm/vector-store.d.ts.map +1 -1
- package/dist/esm/vector-store.js +5 -2
- package/dist/esm/web-sql-connection.d.ts.map +1 -1
- package/dist/esm/web-sql-connection.js +2 -0
- package/dist/esm/web.d.ts +2 -0
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +32 -4
- package/dist/plugin.cjs.js +93 -16
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +93 -16
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +25 -3
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLDatabase.swift +15 -5
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/SQLHTTPServer.swift +6 -0
- package/ios/Tests/CapgoCapacitorFastSqlPluginTests/CapgoCapacitorFastSqlPluginTests.swift +13 -3
- package/ios/Tests/CapgoCapacitorFastSqlPluginTests/SQLResultMetadataTests.swift +15 -0
- package/package.json +4 -2
package/dist/esm/fast-sql.js
CHANGED
|
@@ -16,12 +16,40 @@ export class FastSQL {
|
|
|
16
16
|
* @returns SQLConnection instance for executing queries
|
|
17
17
|
*/
|
|
18
18
|
static async connect(options) {
|
|
19
|
-
|
|
20
|
-
const
|
|
19
|
+
var _a;
|
|
20
|
+
const saved = this.openOptions.get(options.database);
|
|
21
|
+
if (saved && !this.optionsMatch(saved, options)) {
|
|
22
|
+
throw new Error(`Database '${options.database}' is already opening or open with different options`);
|
|
23
|
+
}
|
|
24
|
+
const existing = (_a = this.connections.get(options.database)) !== null && _a !== void 0 ? _a : this.opening.get(options.database);
|
|
21
25
|
if (existing) {
|
|
22
26
|
this.sharedConnections.add(options.database);
|
|
23
27
|
return existing;
|
|
24
28
|
}
|
|
29
|
+
const snapshot = Object.assign({}, options);
|
|
30
|
+
this.openOptions.set(options.database, snapshot);
|
|
31
|
+
const pending = this.open(snapshot);
|
|
32
|
+
this.opening.set(options.database, pending);
|
|
33
|
+
try {
|
|
34
|
+
return await pending;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.openOptions.delete(options.database);
|
|
38
|
+
this.sharedConnections.delete(options.database);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
this.opening.delete(options.database);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
static optionsMatch(left, right) {
|
|
46
|
+
return (Boolean(left.encrypted) === Boolean(right.encrypted) &&
|
|
47
|
+
left.encryptionKey === right.encryptionKey &&
|
|
48
|
+
Boolean(left.readOnly) === Boolean(right.readOnly) &&
|
|
49
|
+
Boolean(left.walMode) === Boolean(right.walMode) &&
|
|
50
|
+
Boolean(left.performancePresets) === Boolean(right.performancePresets));
|
|
51
|
+
}
|
|
52
|
+
static async open(options) {
|
|
25
53
|
// Connect via native plugin
|
|
26
54
|
const info = await CapgoCapacitorFastSql.connect(options);
|
|
27
55
|
// Create connection instance appropriate for the current platform
|
|
@@ -44,6 +72,7 @@ export class FastSQL {
|
|
|
44
72
|
*/
|
|
45
73
|
static async disconnect(database) {
|
|
46
74
|
var _a;
|
|
75
|
+
await this.opening.get(database);
|
|
47
76
|
const connection = this.connections.get(database);
|
|
48
77
|
if (!connection) {
|
|
49
78
|
throw new Error(`Database '${database}' is not connected`);
|
|
@@ -56,6 +85,7 @@ export class FastSQL {
|
|
|
56
85
|
await CapgoCapacitorFastSql.disconnect({ database });
|
|
57
86
|
// Remove connection
|
|
58
87
|
this.connections.delete(database);
|
|
88
|
+
this.openOptions.delete(database);
|
|
59
89
|
this.sharedConnections.delete(database);
|
|
60
90
|
this.connectionRetainers.delete(database);
|
|
61
91
|
this.pendingDisconnects.delete(database);
|
|
@@ -107,7 +137,7 @@ export class FastSQL {
|
|
|
107
137
|
* Close all open connections
|
|
108
138
|
*/
|
|
109
139
|
static async disconnectAll() {
|
|
110
|
-
const databases = Array.from(this.connections.keys());
|
|
140
|
+
const databases = Array.from(new Set([...this.connections.keys(), ...this.opening.keys()]));
|
|
111
141
|
await Promise.all(databases.map((db) => {
|
|
112
142
|
this.connectionRetainers.delete(db);
|
|
113
143
|
this.pendingDisconnects.delete(db);
|
|
@@ -123,6 +153,8 @@ export class FastSQL {
|
|
|
123
153
|
return Array.from(this.connections.keys());
|
|
124
154
|
}
|
|
125
155
|
}
|
|
156
|
+
FastSQL.opening = new Map();
|
|
157
|
+
FastSQL.openOptions = new Map();
|
|
126
158
|
FastSQL.connections = new Map();
|
|
127
159
|
FastSQL.sharedConnections = new Set();
|
|
128
160
|
FastSQL.connectionRetainers = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-sql-connection.d.ts","sourceRoot":"","sources":["../../src/native-sql-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-sql-connection.d.ts","sourceRoot":"","sources":["../../src/native-sql-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACpF,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD;;;;;GAKG;AACH,qBAAa,mBAAoB,YAAW,aAAa;IACvD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAS;gBAElB,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAOzD,OAAO,CAAC,YAAY;IAMpB;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;;OAMG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAuBzE;;;;;OAKG;IACG,YAAY,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAyBzE;;;;OAIG;IACG,gBAAgB,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IA0BtE;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB7B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB/B;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAYhH;;;;;;OAMG;IACG,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtE;;;;;;OAMG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAQvG;;;OAGG;IACH,OAAO,CAAC,eAAe;IAYvB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAkBzB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAQ3B"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IsolationLevel } from './definitions';
|
|
2
|
+
import { assertSupportedIsolation } from './transaction-isolation';
|
|
2
3
|
/**
|
|
3
4
|
* SQL Connection class that uses HTTP protocol for efficient communication
|
|
4
5
|
* with native SQLite databases, bypassing Capacitor's standard bridge.
|
|
@@ -11,7 +12,12 @@ export class NativeSQLConnection {
|
|
|
11
12
|
this.database = database;
|
|
12
13
|
this.port = port;
|
|
13
14
|
this.token = token;
|
|
14
|
-
this.baseUrl = `http://
|
|
15
|
+
this.baseUrl = `http://127.0.0.1:${port}`;
|
|
16
|
+
}
|
|
17
|
+
browserFetch(input, init) {
|
|
18
|
+
const savedFetch = Reflect.get(globalThis, 'CapacitorWebFetch');
|
|
19
|
+
const browserFetch = typeof savedFetch === 'function' ? savedFetch : globalThis.fetch;
|
|
20
|
+
return browserFetch.call(globalThis, input, init);
|
|
15
21
|
}
|
|
16
22
|
/**
|
|
17
23
|
* Get the database name
|
|
@@ -27,7 +33,7 @@ export class NativeSQLConnection {
|
|
|
27
33
|
* @returns Query results
|
|
28
34
|
*/
|
|
29
35
|
async execute(statement, params) {
|
|
30
|
-
const response = await
|
|
36
|
+
const response = await this.browserFetch(`${this.baseUrl}/execute`, {
|
|
31
37
|
method: 'POST',
|
|
32
38
|
headers: {
|
|
33
39
|
'Content-Type': 'application/json',
|
|
@@ -53,7 +59,7 @@ export class NativeSQLConnection {
|
|
|
53
59
|
* @returns Array of results for each operation
|
|
54
60
|
*/
|
|
55
61
|
async executeBatch(operations) {
|
|
56
|
-
const response = await
|
|
62
|
+
const response = await this.browserFetch(`${this.baseUrl}/batch`, {
|
|
57
63
|
method: 'POST',
|
|
58
64
|
headers: {
|
|
59
65
|
'Content-Type': 'application/json',
|
|
@@ -80,10 +86,11 @@ export class NativeSQLConnection {
|
|
|
80
86
|
* @param isolationLevel - Optional isolation level
|
|
81
87
|
*/
|
|
82
88
|
async beginTransaction(isolationLevel) {
|
|
89
|
+
assertSupportedIsolation(isolationLevel);
|
|
83
90
|
if (this.inTransaction) {
|
|
84
91
|
throw new Error('Transaction already in progress');
|
|
85
92
|
}
|
|
86
|
-
const response = await
|
|
93
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/begin`, {
|
|
87
94
|
method: 'POST',
|
|
88
95
|
headers: {
|
|
89
96
|
'Content-Type': 'application/json',
|
|
@@ -107,7 +114,7 @@ export class NativeSQLConnection {
|
|
|
107
114
|
if (!this.inTransaction) {
|
|
108
115
|
throw new Error('No transaction in progress');
|
|
109
116
|
}
|
|
110
|
-
const response = await
|
|
117
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/commit`, {
|
|
111
118
|
method: 'POST',
|
|
112
119
|
headers: {
|
|
113
120
|
Authorization: `Bearer ${this.token}`,
|
|
@@ -127,7 +134,7 @@ export class NativeSQLConnection {
|
|
|
127
134
|
if (!this.inTransaction) {
|
|
128
135
|
throw new Error('No transaction in progress');
|
|
129
136
|
}
|
|
130
|
-
const response = await
|
|
137
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/rollback`, {
|
|
131
138
|
method: 'POST',
|
|
132
139
|
headers: {
|
|
133
140
|
Authorization: `Bearer ${this.token}`,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction-isolation.d.ts","sourceRoot":"","sources":["../../src/transaction-isolation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,wBAAgB,wBAAwB,CAAC,KAAK,CAAC,EAAE,cAAc,GAAG,IAAI,CAIrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vector-store.d.ts","sourceRoot":"","sources":["../../src/vector-store.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"vector-store.d.ts","sourceRoot":"","sources":["../../src/vector-store.ts"],"names":[],"mappings":"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"}
|
package/dist/esm/vector-store.js
CHANGED
|
@@ -162,8 +162,11 @@ export class FastSQLVectorStore {
|
|
|
162
162
|
.map((row) => this.rowToGetResult(row))
|
|
163
163
|
.filter(params.predicate)
|
|
164
164
|
.map((row) => row.id);
|
|
165
|
-
for (
|
|
166
|
-
await this.connection.
|
|
165
|
+
for (let offset = 0; offset < ids.length; offset += 100) {
|
|
166
|
+
await this.connection.executeBatch(ids.slice(offset, offset + 100).map((id) => ({
|
|
167
|
+
statement: `DELETE FROM ${VECTOR_TABLE} WHERE store = ? AND id = ?`,
|
|
168
|
+
params: [this.store, id],
|
|
169
|
+
})));
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
async query(params) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-sql-connection.d.ts","sourceRoot":"","sources":["../../src/web-sql-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,QAAQ,EACR,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"web-sql-connection.d.ts","sourceRoot":"","sources":["../../src/web-sql-connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,QAAQ,EACR,MAAM,EACN,SAAS,EACT,iBAAiB,EACjB,cAAc,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAGtD;;;GAGG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,aAAa,CAAS;gBAElB,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,2BAA2B;IAKjE;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;;;;;OAMG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC;IAIzE;;;;;OAKG;IACG,YAAY,CAAC,UAAU,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAQzE;;;;OAIG;IACG,gBAAgB,CAAC,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtE;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAS/B;;;;;OAKG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBhH;;;;;;OAMG;IACG,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtE;;;;;;OAMG;IACG,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAOxG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { assertSupportedIsolation } from './transaction-isolation';
|
|
1
2
|
/**
|
|
2
3
|
* Web implementation of SQLConnection that calls the Capacitor plugin directly,
|
|
3
4
|
* avoiding HTTP network requests which are not available on the web platform.
|
|
@@ -43,6 +44,7 @@ export class WebSQLConnection {
|
|
|
43
44
|
* @param isolationLevel - Optional isolation level
|
|
44
45
|
*/
|
|
45
46
|
async beginTransaction(isolationLevel) {
|
|
47
|
+
assertSupportedIsolation(isolationLevel);
|
|
46
48
|
if (this.inTransaction) {
|
|
47
49
|
throw new Error('Transaction already in progress');
|
|
48
50
|
}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export declare class CapgoCapacitorFastSqlWeb extends WebPlugin implements Capgo
|
|
|
23
23
|
port: number;
|
|
24
24
|
token: string;
|
|
25
25
|
database: string;
|
|
26
|
+
persistent: boolean;
|
|
26
27
|
}>;
|
|
27
28
|
disconnect(options: {
|
|
28
29
|
database: string;
|
|
@@ -32,6 +33,7 @@ export declare class CapgoCapacitorFastSqlWeb extends WebPlugin implements Capgo
|
|
|
32
33
|
}): Promise<{
|
|
33
34
|
port: number;
|
|
34
35
|
token: string;
|
|
36
|
+
persistent: boolean;
|
|
35
37
|
}>;
|
|
36
38
|
execute(options: {
|
|
37
39
|
database: string;
|
package/dist/esm/web.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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;
|
|
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;AAevB;;;;;;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;IAWpD,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,MAAM;IAOR,OAAO,CACX,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAiE5E,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,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAa3G,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;IA+ClG,gBAAgB,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ/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,5 +1,6 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
2
|
import { sqlite3Worker1Promiser } from '@sqlite.org/sqlite-wasm';
|
|
3
|
+
import { assertSupportedIsolation } from './transaction-isolation';
|
|
3
4
|
/**
|
|
4
5
|
* Web implementation using the official SQLite Wasm build with OPFS persistence.
|
|
5
6
|
*
|
|
@@ -20,7 +21,13 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
20
21
|
* Must be called before connect() when overriding the default worker.
|
|
21
22
|
*/
|
|
22
23
|
async configureWeb(config) {
|
|
23
|
-
this.
|
|
24
|
+
if (this.promiserPromise || this.databases.size > 0) {
|
|
25
|
+
throw new Error('Configure web storage before opening the first database');
|
|
26
|
+
}
|
|
27
|
+
if (config.requirePersistence && config.useOpfs === false) {
|
|
28
|
+
throw new Error('requirePersistence requires OPFS');
|
|
29
|
+
}
|
|
30
|
+
this.webConfig = Object.assign({}, config);
|
|
24
31
|
this.promiserPromise = null;
|
|
25
32
|
}
|
|
26
33
|
getPromiser() {
|
|
@@ -31,28 +38,37 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
31
38
|
return this.promiserPromise;
|
|
32
39
|
}
|
|
33
40
|
dbPath(database) {
|
|
41
|
+
if (!database || database === '.' || database === '..' || /[/\\\0]/.test(database)) {
|
|
42
|
+
throw new Error('Database must be a non-empty file name without path separators');
|
|
43
|
+
}
|
|
34
44
|
return `/capgo-fast-sql/${database}.sqlite3`;
|
|
35
45
|
}
|
|
36
46
|
async connect(options) {
|
|
47
|
+
if (options.readOnly) {
|
|
48
|
+
throw new Error('Read-only opens are not supported by the SQLite Wasm Worker transport');
|
|
49
|
+
}
|
|
37
50
|
if (this.databases.has(options.database)) {
|
|
38
51
|
const existing = this.databases.get(options.database);
|
|
39
52
|
return {
|
|
40
53
|
port: existing.port,
|
|
41
54
|
token: existing.token,
|
|
42
55
|
database: options.database,
|
|
56
|
+
persistent: existing.persistent,
|
|
43
57
|
};
|
|
44
58
|
}
|
|
45
|
-
const promiser = await this.getPromiser();
|
|
46
59
|
const path = this.dbPath(options.database);
|
|
60
|
+
const promiser = await this.getPromiser();
|
|
47
61
|
const useOpfs = this.webConfig.useOpfs !== false;
|
|
48
62
|
let openResult;
|
|
49
63
|
if (useOpfs) {
|
|
50
64
|
try {
|
|
51
65
|
openResult = await promiser('open', {
|
|
52
|
-
filename: `file
|
|
66
|
+
filename: `file:/capgo-fast-sql/${encodeURIComponent(options.database)}.sqlite3?vfs=opfs`,
|
|
53
67
|
});
|
|
54
68
|
}
|
|
55
69
|
catch (opfsError) {
|
|
70
|
+
if (this.webConfig.requirePersistence)
|
|
71
|
+
throw opfsError;
|
|
56
72
|
console.warn('[CapgoCapacitorFastSql] OPFS unavailable; web database will not persist across reloads. ' +
|
|
57
73
|
'Serve with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp.', opfsError);
|
|
58
74
|
openResult = await promiser('open', { filename: path });
|
|
@@ -66,7 +82,16 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
66
82
|
if (!dbId) {
|
|
67
83
|
throw new Error('Failed to open SQLite Wasm database: missing dbId');
|
|
68
84
|
}
|
|
69
|
-
|
|
85
|
+
try {
|
|
86
|
+
if (this.webConfig.requirePersistence && !persistent) {
|
|
87
|
+
throw new Error('SQLite Worker did not confirm persistent storage');
|
|
88
|
+
}
|
|
89
|
+
await this.applyPerformanceConfig(promiser, dbId, options);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
await promiser({ type: 'close', dbId, args: {} });
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
70
95
|
const token = this.generateToken();
|
|
71
96
|
const port = this.nextPort++;
|
|
72
97
|
this.databases.set(options.database, { dbId, token, port, persistent });
|
|
@@ -74,6 +99,7 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
74
99
|
port,
|
|
75
100
|
token,
|
|
76
101
|
database: options.database,
|
|
102
|
+
persistent,
|
|
77
103
|
};
|
|
78
104
|
}
|
|
79
105
|
async disconnect(options) {
|
|
@@ -94,6 +120,7 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
94
120
|
return {
|
|
95
121
|
port: dbInfo.port,
|
|
96
122
|
token: dbInfo.token,
|
|
123
|
+
persistent: dbInfo.persistent,
|
|
97
124
|
};
|
|
98
125
|
}
|
|
99
126
|
async execute(options) {
|
|
@@ -141,6 +168,7 @@ export class CapgoCapacitorFastSqlWeb extends WebPlugin {
|
|
|
141
168
|
}
|
|
142
169
|
}
|
|
143
170
|
async beginTransaction(options) {
|
|
171
|
+
assertSupportedIsolation(options.isolationLevel);
|
|
144
172
|
await this.execute({
|
|
145
173
|
database: options.database,
|
|
146
174
|
statement: 'BEGIN TRANSACTION',
|
package/dist/plugin.cjs.js
CHANGED
|
@@ -4,7 +4,9 @@ var core = require('@capacitor/core');
|
|
|
4
4
|
var sqliteWasm = require('@sqlite.org/sqlite-wasm');
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Transaction isolation levels
|
|
7
|
+
* Transaction isolation levels. Only Serializable is supported by the current
|
|
8
|
+
* SQLite backends. Other values are retained for source compatibility but reject
|
|
9
|
+
* before starting a transaction; they are not silently mapped to another level.
|
|
8
10
|
*/
|
|
9
11
|
exports.IsolationLevel = void 0;
|
|
10
12
|
(function (IsolationLevel) {
|
|
@@ -18,6 +20,12 @@ const CapgoCapacitorFastSql = core.registerPlugin('CapgoCapacitorFastSql', {
|
|
|
18
20
|
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CapgoCapacitorFastSqlWeb()),
|
|
19
21
|
});
|
|
20
22
|
|
|
23
|
+
function assertSupportedIsolation(level) {
|
|
24
|
+
if (level !== undefined && level !== exports.IsolationLevel.Serializable) {
|
|
25
|
+
throw new Error('Only SERIALIZABLE transaction isolation is supported');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
21
29
|
/**
|
|
22
30
|
* SQL Connection class that uses HTTP protocol for efficient communication
|
|
23
31
|
* with native SQLite databases, bypassing Capacitor's standard bridge.
|
|
@@ -30,7 +38,12 @@ class NativeSQLConnection {
|
|
|
30
38
|
this.database = database;
|
|
31
39
|
this.port = port;
|
|
32
40
|
this.token = token;
|
|
33
|
-
this.baseUrl = `http://
|
|
41
|
+
this.baseUrl = `http://127.0.0.1:${port}`;
|
|
42
|
+
}
|
|
43
|
+
browserFetch(input, init) {
|
|
44
|
+
const savedFetch = Reflect.get(globalThis, 'CapacitorWebFetch');
|
|
45
|
+
const browserFetch = typeof savedFetch === 'function' ? savedFetch : globalThis.fetch;
|
|
46
|
+
return browserFetch.call(globalThis, input, init);
|
|
34
47
|
}
|
|
35
48
|
/**
|
|
36
49
|
* Get the database name
|
|
@@ -46,7 +59,7 @@ class NativeSQLConnection {
|
|
|
46
59
|
* @returns Query results
|
|
47
60
|
*/
|
|
48
61
|
async execute(statement, params) {
|
|
49
|
-
const response = await
|
|
62
|
+
const response = await this.browserFetch(`${this.baseUrl}/execute`, {
|
|
50
63
|
method: 'POST',
|
|
51
64
|
headers: {
|
|
52
65
|
'Content-Type': 'application/json',
|
|
@@ -72,7 +85,7 @@ class NativeSQLConnection {
|
|
|
72
85
|
* @returns Array of results for each operation
|
|
73
86
|
*/
|
|
74
87
|
async executeBatch(operations) {
|
|
75
|
-
const response = await
|
|
88
|
+
const response = await this.browserFetch(`${this.baseUrl}/batch`, {
|
|
76
89
|
method: 'POST',
|
|
77
90
|
headers: {
|
|
78
91
|
'Content-Type': 'application/json',
|
|
@@ -99,10 +112,11 @@ class NativeSQLConnection {
|
|
|
99
112
|
* @param isolationLevel - Optional isolation level
|
|
100
113
|
*/
|
|
101
114
|
async beginTransaction(isolationLevel) {
|
|
115
|
+
assertSupportedIsolation(isolationLevel);
|
|
102
116
|
if (this.inTransaction) {
|
|
103
117
|
throw new Error('Transaction already in progress');
|
|
104
118
|
}
|
|
105
|
-
const response = await
|
|
119
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/begin`, {
|
|
106
120
|
method: 'POST',
|
|
107
121
|
headers: {
|
|
108
122
|
'Content-Type': 'application/json',
|
|
@@ -126,7 +140,7 @@ class NativeSQLConnection {
|
|
|
126
140
|
if (!this.inTransaction) {
|
|
127
141
|
throw new Error('No transaction in progress');
|
|
128
142
|
}
|
|
129
|
-
const response = await
|
|
143
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/commit`, {
|
|
130
144
|
method: 'POST',
|
|
131
145
|
headers: {
|
|
132
146
|
Authorization: `Bearer ${this.token}`,
|
|
@@ -146,7 +160,7 @@ class NativeSQLConnection {
|
|
|
146
160
|
if (!this.inTransaction) {
|
|
147
161
|
throw new Error('No transaction in progress');
|
|
148
162
|
}
|
|
149
|
-
const response = await
|
|
163
|
+
const response = await this.browserFetch(`${this.baseUrl}/transaction/rollback`, {
|
|
150
164
|
method: 'POST',
|
|
151
165
|
headers: {
|
|
152
166
|
Authorization: `Bearer ${this.token}`,
|
|
@@ -307,6 +321,7 @@ class WebSQLConnection {
|
|
|
307
321
|
* @param isolationLevel - Optional isolation level
|
|
308
322
|
*/
|
|
309
323
|
async beginTransaction(isolationLevel) {
|
|
324
|
+
assertSupportedIsolation(isolationLevel);
|
|
310
325
|
if (this.inTransaction) {
|
|
311
326
|
throw new Error('Transaction already in progress');
|
|
312
327
|
}
|
|
@@ -401,12 +416,40 @@ class FastSQL {
|
|
|
401
416
|
* @returns SQLConnection instance for executing queries
|
|
402
417
|
*/
|
|
403
418
|
static async connect(options) {
|
|
404
|
-
|
|
405
|
-
const
|
|
419
|
+
var _a;
|
|
420
|
+
const saved = this.openOptions.get(options.database);
|
|
421
|
+
if (saved && !this.optionsMatch(saved, options)) {
|
|
422
|
+
throw new Error(`Database '${options.database}' is already opening or open with different options`);
|
|
423
|
+
}
|
|
424
|
+
const existing = (_a = this.connections.get(options.database)) !== null && _a !== void 0 ? _a : this.opening.get(options.database);
|
|
406
425
|
if (existing) {
|
|
407
426
|
this.sharedConnections.add(options.database);
|
|
408
427
|
return existing;
|
|
409
428
|
}
|
|
429
|
+
const snapshot = Object.assign({}, options);
|
|
430
|
+
this.openOptions.set(options.database, snapshot);
|
|
431
|
+
const pending = this.open(snapshot);
|
|
432
|
+
this.opening.set(options.database, pending);
|
|
433
|
+
try {
|
|
434
|
+
return await pending;
|
|
435
|
+
}
|
|
436
|
+
catch (error) {
|
|
437
|
+
this.openOptions.delete(options.database);
|
|
438
|
+
this.sharedConnections.delete(options.database);
|
|
439
|
+
throw error;
|
|
440
|
+
}
|
|
441
|
+
finally {
|
|
442
|
+
this.opening.delete(options.database);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
static optionsMatch(left, right) {
|
|
446
|
+
return (Boolean(left.encrypted) === Boolean(right.encrypted) &&
|
|
447
|
+
left.encryptionKey === right.encryptionKey &&
|
|
448
|
+
Boolean(left.readOnly) === Boolean(right.readOnly) &&
|
|
449
|
+
Boolean(left.walMode) === Boolean(right.walMode) &&
|
|
450
|
+
Boolean(left.performancePresets) === Boolean(right.performancePresets));
|
|
451
|
+
}
|
|
452
|
+
static async open(options) {
|
|
410
453
|
// Connect via native plugin
|
|
411
454
|
const info = await CapgoCapacitorFastSql.connect(options);
|
|
412
455
|
// Create connection instance appropriate for the current platform
|
|
@@ -429,6 +472,7 @@ class FastSQL {
|
|
|
429
472
|
*/
|
|
430
473
|
static async disconnect(database) {
|
|
431
474
|
var _a;
|
|
475
|
+
await this.opening.get(database);
|
|
432
476
|
const connection = this.connections.get(database);
|
|
433
477
|
if (!connection) {
|
|
434
478
|
throw new Error(`Database '${database}' is not connected`);
|
|
@@ -441,6 +485,7 @@ class FastSQL {
|
|
|
441
485
|
await CapgoCapacitorFastSql.disconnect({ database });
|
|
442
486
|
// Remove connection
|
|
443
487
|
this.connections.delete(database);
|
|
488
|
+
this.openOptions.delete(database);
|
|
444
489
|
this.sharedConnections.delete(database);
|
|
445
490
|
this.connectionRetainers.delete(database);
|
|
446
491
|
this.pendingDisconnects.delete(database);
|
|
@@ -492,7 +537,7 @@ class FastSQL {
|
|
|
492
537
|
* Close all open connections
|
|
493
538
|
*/
|
|
494
539
|
static async disconnectAll() {
|
|
495
|
-
const databases = Array.from(this.connections.keys());
|
|
540
|
+
const databases = Array.from(new Set([...this.connections.keys(), ...this.opening.keys()]));
|
|
496
541
|
await Promise.all(databases.map((db) => {
|
|
497
542
|
this.connectionRetainers.delete(db);
|
|
498
543
|
this.pendingDisconnects.delete(db);
|
|
@@ -508,6 +553,8 @@ class FastSQL {
|
|
|
508
553
|
return Array.from(this.connections.keys());
|
|
509
554
|
}
|
|
510
555
|
}
|
|
556
|
+
FastSQL.opening = new Map();
|
|
557
|
+
FastSQL.openOptions = new Map();
|
|
511
558
|
FastSQL.connections = new Map();
|
|
512
559
|
FastSQL.sharedConnections = new Set();
|
|
513
560
|
FastSQL.connectionRetainers = new Map();
|
|
@@ -859,8 +906,11 @@ class FastSQLVectorStore {
|
|
|
859
906
|
.map((row) => this.rowToGetResult(row))
|
|
860
907
|
.filter(params.predicate)
|
|
861
908
|
.map((row) => row.id);
|
|
862
|
-
for (
|
|
863
|
-
await this.connection.
|
|
909
|
+
for (let offset = 0; offset < ids.length; offset += 100) {
|
|
910
|
+
await this.connection.executeBatch(ids.slice(offset, offset + 100).map((id) => ({
|
|
911
|
+
statement: `DELETE FROM ${VECTOR_TABLE} WHERE store = ? AND id = ?`,
|
|
912
|
+
params: [this.store, id],
|
|
913
|
+
})));
|
|
864
914
|
}
|
|
865
915
|
}
|
|
866
916
|
async query(params) {
|
|
@@ -1093,7 +1143,13 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1093
1143
|
* Must be called before connect() when overriding the default worker.
|
|
1094
1144
|
*/
|
|
1095
1145
|
async configureWeb(config) {
|
|
1096
|
-
this.
|
|
1146
|
+
if (this.promiserPromise || this.databases.size > 0) {
|
|
1147
|
+
throw new Error('Configure web storage before opening the first database');
|
|
1148
|
+
}
|
|
1149
|
+
if (config.requirePersistence && config.useOpfs === false) {
|
|
1150
|
+
throw new Error('requirePersistence requires OPFS');
|
|
1151
|
+
}
|
|
1152
|
+
this.webConfig = Object.assign({}, config);
|
|
1097
1153
|
this.promiserPromise = null;
|
|
1098
1154
|
}
|
|
1099
1155
|
getPromiser() {
|
|
@@ -1104,28 +1160,37 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1104
1160
|
return this.promiserPromise;
|
|
1105
1161
|
}
|
|
1106
1162
|
dbPath(database) {
|
|
1163
|
+
if (!database || database === '.' || database === '..' || /[/\\\0]/.test(database)) {
|
|
1164
|
+
throw new Error('Database must be a non-empty file name without path separators');
|
|
1165
|
+
}
|
|
1107
1166
|
return `/capgo-fast-sql/${database}.sqlite3`;
|
|
1108
1167
|
}
|
|
1109
1168
|
async connect(options) {
|
|
1169
|
+
if (options.readOnly) {
|
|
1170
|
+
throw new Error('Read-only opens are not supported by the SQLite Wasm Worker transport');
|
|
1171
|
+
}
|
|
1110
1172
|
if (this.databases.has(options.database)) {
|
|
1111
1173
|
const existing = this.databases.get(options.database);
|
|
1112
1174
|
return {
|
|
1113
1175
|
port: existing.port,
|
|
1114
1176
|
token: existing.token,
|
|
1115
1177
|
database: options.database,
|
|
1178
|
+
persistent: existing.persistent,
|
|
1116
1179
|
};
|
|
1117
1180
|
}
|
|
1118
|
-
const promiser = await this.getPromiser();
|
|
1119
1181
|
const path = this.dbPath(options.database);
|
|
1182
|
+
const promiser = await this.getPromiser();
|
|
1120
1183
|
const useOpfs = this.webConfig.useOpfs !== false;
|
|
1121
1184
|
let openResult;
|
|
1122
1185
|
if (useOpfs) {
|
|
1123
1186
|
try {
|
|
1124
1187
|
openResult = await promiser('open', {
|
|
1125
|
-
filename: `file
|
|
1188
|
+
filename: `file:/capgo-fast-sql/${encodeURIComponent(options.database)}.sqlite3?vfs=opfs`,
|
|
1126
1189
|
});
|
|
1127
1190
|
}
|
|
1128
1191
|
catch (opfsError) {
|
|
1192
|
+
if (this.webConfig.requirePersistence)
|
|
1193
|
+
throw opfsError;
|
|
1129
1194
|
console.warn('[CapgoCapacitorFastSql] OPFS unavailable; web database will not persist across reloads. ' +
|
|
1130
1195
|
'Serve with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp.', opfsError);
|
|
1131
1196
|
openResult = await promiser('open', { filename: path });
|
|
@@ -1139,7 +1204,16 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1139
1204
|
if (!dbId) {
|
|
1140
1205
|
throw new Error('Failed to open SQLite Wasm database: missing dbId');
|
|
1141
1206
|
}
|
|
1142
|
-
|
|
1207
|
+
try {
|
|
1208
|
+
if (this.webConfig.requirePersistence && !persistent) {
|
|
1209
|
+
throw new Error('SQLite Worker did not confirm persistent storage');
|
|
1210
|
+
}
|
|
1211
|
+
await this.applyPerformanceConfig(promiser, dbId, options);
|
|
1212
|
+
}
|
|
1213
|
+
catch (error) {
|
|
1214
|
+
await promiser({ type: 'close', dbId, args: {} });
|
|
1215
|
+
throw error;
|
|
1216
|
+
}
|
|
1143
1217
|
const token = this.generateToken();
|
|
1144
1218
|
const port = this.nextPort++;
|
|
1145
1219
|
this.databases.set(options.database, { dbId, token, port, persistent });
|
|
@@ -1147,6 +1221,7 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1147
1221
|
port,
|
|
1148
1222
|
token,
|
|
1149
1223
|
database: options.database,
|
|
1224
|
+
persistent,
|
|
1150
1225
|
};
|
|
1151
1226
|
}
|
|
1152
1227
|
async disconnect(options) {
|
|
@@ -1167,6 +1242,7 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1167
1242
|
return {
|
|
1168
1243
|
port: dbInfo.port,
|
|
1169
1244
|
token: dbInfo.token,
|
|
1245
|
+
persistent: dbInfo.persistent,
|
|
1170
1246
|
};
|
|
1171
1247
|
}
|
|
1172
1248
|
async execute(options) {
|
|
@@ -1214,6 +1290,7 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1214
1290
|
}
|
|
1215
1291
|
}
|
|
1216
1292
|
async beginTransaction(options) {
|
|
1293
|
+
assertSupportedIsolation(options.isolationLevel);
|
|
1217
1294
|
await this.execute({
|
|
1218
1295
|
database: options.database,
|
|
1219
1296
|
statement: 'BEGIN TRANSACTION',
|