@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 +66 -31
- package/android/src/main/java/app/capgo/capacitor/fastsql/CapgoCapacitorFastSqlPlugin.java +1 -1
- package/dist/esm/definitions.d.ts +23 -17
- package/dist/esm/definitions.d.ts.map +1 -1
- package/dist/esm/web.d.ts +9 -26
- package/dist/esm/web.d.ts.map +1 -1
- package/dist/esm/web.js +90 -144
- package/dist/plugin.cjs.js +90 -158
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +15878 -155
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCapacitorFastSqlPlugin/CapgoCapacitorFastSqlPlugin.swift +1 -1
- package/package.json +9 -4
- package/dist/esm/performance-config.d.ts +0 -8
- package/dist/esm/performance-config.d.ts.map +0 -1
- package/dist/esm/performance-config.js +0 -14
package/dist/plugin.cjs.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var core = require('@capacitor/core');
|
|
4
|
+
var sqliteWasm = require('@sqlite.org/sqlite-wasm');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Transaction isolation levels
|
|
@@ -1071,91 +1072,75 @@ FastSQLVectorStore.connectionRefs = new Map();
|
|
|
1071
1072
|
FastSQLVectorStore.ownedConnections = new Set();
|
|
1072
1073
|
|
|
1073
1074
|
/**
|
|
1074
|
-
*
|
|
1075
|
-
*/
|
|
1076
|
-
function applyPerformanceConfig(db, options) {
|
|
1077
|
-
db.run('PRAGMA foreign_keys = ON');
|
|
1078
|
-
if (options.walMode) {
|
|
1079
|
-
db.run('PRAGMA journal_mode = WAL');
|
|
1080
|
-
}
|
|
1081
|
-
if (options.performancePresets) {
|
|
1082
|
-
db.run('PRAGMA synchronous = NORMAL');
|
|
1083
|
-
db.run('PRAGMA busy_timeout = 5000');
|
|
1084
|
-
db.run('PRAGMA cache_size = -2000');
|
|
1085
|
-
}
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
const DEFAULT_SQLJS_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.js';
|
|
1089
|
-
const DEFAULT_WASM_URL = 'https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.8.0/sql-wasm.wasm';
|
|
1090
|
-
/**
|
|
1091
|
-
* Web implementation using sql.js (SQLite compiled to WebAssembly)
|
|
1075
|
+
* Web implementation using the official SQLite Wasm build with OPFS persistence.
|
|
1092
1076
|
*
|
|
1093
|
-
*
|
|
1094
|
-
* in
|
|
1077
|
+
* Databases are stored in the Origin Private File System when available (requires
|
|
1078
|
+
* Cross-Origin Isolation: COOP/COEP). No full-database copy is kept in RAM or
|
|
1079
|
+
* IndexedDB — SQLite reads/writes the OPFS file directly from a worker.
|
|
1095
1080
|
*/
|
|
1096
1081
|
class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
1097
1082
|
constructor() {
|
|
1098
|
-
super();
|
|
1083
|
+
super(...arguments);
|
|
1099
1084
|
this.databases = new Map();
|
|
1100
|
-
this.
|
|
1085
|
+
this.promiserPromise = null;
|
|
1101
1086
|
this.nextPort = 9000;
|
|
1102
1087
|
this.webConfig = {};
|
|
1103
1088
|
}
|
|
1104
1089
|
/**
|
|
1105
1090
|
* Configure web-specific options (no-op on native platforms).
|
|
1106
|
-
* Must be called before connect() when
|
|
1091
|
+
* Must be called before connect() when overriding the default worker.
|
|
1107
1092
|
*/
|
|
1108
1093
|
async configureWeb(config) {
|
|
1109
1094
|
this.webConfig = config;
|
|
1110
|
-
|
|
1111
|
-
this.sqlPromise = null;
|
|
1095
|
+
this.promiserPromise = null;
|
|
1112
1096
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
loadSqlJs() {
|
|
1118
|
-
var _a, _b;
|
|
1119
|
-
if (!this.sqlPromise) {
|
|
1120
|
-
const jsUrl = (_a = this.webConfig.sqlJsUrl) !== null && _a !== void 0 ? _a : DEFAULT_SQLJS_URL;
|
|
1121
|
-
const wasmUrl = (_b = this.webConfig.wasmUrl) !== null && _b !== void 0 ? _b : DEFAULT_WASM_URL;
|
|
1122
|
-
this.sqlPromise = new Promise((resolve, reject) => {
|
|
1123
|
-
try {
|
|
1124
|
-
// Load sql.js from the configured URL (CDN or local bundle)
|
|
1125
|
-
const script = document.createElement('script');
|
|
1126
|
-
script.src = jsUrl;
|
|
1127
|
-
script.onload = async () => {
|
|
1128
|
-
const initSqlJs = window.initSqlJs;
|
|
1129
|
-
const SQL = await initSqlJs({
|
|
1130
|
-
locateFile: (file) => (file.endsWith('.wasm') ? wasmUrl : file),
|
|
1131
|
-
});
|
|
1132
|
-
resolve(SQL);
|
|
1133
|
-
};
|
|
1134
|
-
script.onerror = reject;
|
|
1135
|
-
document.head.appendChild(script);
|
|
1136
|
-
}
|
|
1137
|
-
catch (error) {
|
|
1138
|
-
reject(error);
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1097
|
+
getPromiser() {
|
|
1098
|
+
if (!this.promiserPromise) {
|
|
1099
|
+
const config = this.webConfig.worker !== undefined ? { worker: this.webConfig.worker } : undefined;
|
|
1100
|
+
this.promiserPromise = sqliteWasm.sqlite3Worker1Promiser.v2(config);
|
|
1141
1101
|
}
|
|
1142
|
-
return this.
|
|
1102
|
+
return this.promiserPromise;
|
|
1103
|
+
}
|
|
1104
|
+
dbPath(database) {
|
|
1105
|
+
return `/capgo-fast-sql/${database}.sqlite3`;
|
|
1143
1106
|
}
|
|
1144
1107
|
async connect(options) {
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1108
|
+
if (this.databases.has(options.database)) {
|
|
1109
|
+
const existing = this.databases.get(options.database);
|
|
1110
|
+
return {
|
|
1111
|
+
port: existing.port,
|
|
1112
|
+
token: existing.token,
|
|
1113
|
+
database: options.database,
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
const promiser = await this.getPromiser();
|
|
1117
|
+
const path = this.dbPath(options.database);
|
|
1118
|
+
const useOpfs = this.webConfig.useOpfs !== false;
|
|
1119
|
+
let openResult;
|
|
1120
|
+
if (useOpfs) {
|
|
1121
|
+
try {
|
|
1122
|
+
openResult = await promiser('open', {
|
|
1123
|
+
filename: `file:${path}?vfs=opfs`,
|
|
1124
|
+
});
|
|
1125
|
+
}
|
|
1126
|
+
catch (opfsError) {
|
|
1127
|
+
console.warn('[CapgoCapacitorFastSql] OPFS unavailable; web database will not persist across reloads. ' +
|
|
1128
|
+
'Serve with Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp.', opfsError);
|
|
1129
|
+
openResult = await promiser('open', { filename: path });
|
|
1130
|
+
}
|
|
1151
1131
|
}
|
|
1152
1132
|
else {
|
|
1153
|
-
|
|
1133
|
+
openResult = await promiser('open', { filename: path });
|
|
1134
|
+
}
|
|
1135
|
+
const dbId = openResult.result.dbId;
|
|
1136
|
+
const persistent = Boolean(openResult.result.persistent);
|
|
1137
|
+
if (!dbId) {
|
|
1138
|
+
throw new Error('Failed to open SQLite Wasm database: missing dbId');
|
|
1154
1139
|
}
|
|
1155
|
-
applyPerformanceConfig(
|
|
1140
|
+
await this.applyPerformanceConfig(promiser, dbId, options);
|
|
1156
1141
|
const token = this.generateToken();
|
|
1157
1142
|
const port = this.nextPort++;
|
|
1158
|
-
this.databases.set(options.database, {
|
|
1143
|
+
this.databases.set(options.database, { dbId, token, port, persistent });
|
|
1159
1144
|
return {
|
|
1160
1145
|
port,
|
|
1161
1146
|
token,
|
|
@@ -1167,10 +1152,9 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1167
1152
|
if (!dbInfo) {
|
|
1168
1153
|
throw new Error(`Database '${options.database}' is not connected`);
|
|
1169
1154
|
}
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
await
|
|
1173
|
-
dbInfo.db.close();
|
|
1155
|
+
const promiser = await this.getPromiser();
|
|
1156
|
+
// OPFS-backed DBs persist automatically; no export/IndexedDB write needed.
|
|
1157
|
+
await promiser({ type: 'close', dbId: dbInfo.dbId, args: {} });
|
|
1174
1158
|
this.databases.delete(options.database);
|
|
1175
1159
|
}
|
|
1176
1160
|
async getServerInfo(options) {
|
|
@@ -1184,32 +1168,45 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1184
1168
|
};
|
|
1185
1169
|
}
|
|
1186
1170
|
async execute(options) {
|
|
1171
|
+
var _a, _b, _c, _d;
|
|
1187
1172
|
const dbInfo = this.databases.get(options.database);
|
|
1188
1173
|
if (!dbInfo) {
|
|
1189
1174
|
throw new Error(`Database '${options.database}' is not connected`);
|
|
1190
1175
|
}
|
|
1191
1176
|
try {
|
|
1192
|
-
const
|
|
1193
|
-
if (options.params) {
|
|
1194
|
-
stmt.bind(options.params);
|
|
1195
|
-
}
|
|
1177
|
+
const promiser = await this.getPromiser();
|
|
1196
1178
|
const rows = [];
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1179
|
+
// countChanges / lastInsertRowId are supported by Worker1 at runtime but
|
|
1180
|
+
// omitted from the published Worker1ExecArgs typings.
|
|
1181
|
+
const result = await promiser({
|
|
1182
|
+
type: 'exec',
|
|
1183
|
+
dbId: dbInfo.dbId,
|
|
1184
|
+
args: {
|
|
1185
|
+
sql: options.statement,
|
|
1186
|
+
bind: options.params,
|
|
1187
|
+
rowMode: 'object',
|
|
1188
|
+
countChanges: true,
|
|
1189
|
+
lastInsertRowId: true,
|
|
1190
|
+
callback: (msg) => {
|
|
1191
|
+
if (msg.rowNumber != null && msg.row && typeof msg.row === 'object' && !Array.isArray(msg.row)) {
|
|
1192
|
+
rows.push(msg.row);
|
|
1193
|
+
}
|
|
1194
|
+
},
|
|
1195
|
+
},
|
|
1196
|
+
});
|
|
1197
|
+
const execResult = result.result;
|
|
1198
|
+
const rowsAffected = Number((_a = execResult.changeCount) !== null && _a !== void 0 ? _a : 0);
|
|
1199
|
+
const rawInsertId = execResult.lastInsertRowId;
|
|
1200
|
+
const insertId = rawInsertId !== undefined && rawInsertId !== null ? Number(rawInsertId) : undefined;
|
|
1205
1201
|
return {
|
|
1206
1202
|
rows,
|
|
1207
|
-
rowsAffected
|
|
1208
|
-
insertId: insertId > 0 ? insertId : undefined,
|
|
1203
|
+
rowsAffected,
|
|
1204
|
+
insertId: insertId !== undefined && insertId > 0 ? insertId : undefined,
|
|
1209
1205
|
};
|
|
1210
1206
|
}
|
|
1211
1207
|
catch (error) {
|
|
1212
|
-
|
|
1208
|
+
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);
|
|
1209
|
+
throw new Error(`SQL execution failed: ${message}`);
|
|
1213
1210
|
}
|
|
1214
1211
|
}
|
|
1215
1212
|
async beginTransaction(options) {
|
|
@@ -1230,87 +1227,22 @@ class CapgoCapacitorFastSqlWeb extends core.WebPlugin {
|
|
|
1230
1227
|
statement: 'ROLLBACK',
|
|
1231
1228
|
});
|
|
1232
1229
|
}
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1230
|
+
async applyPerformanceConfig(promiser, dbId, options) {
|
|
1231
|
+
await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA foreign_keys = ON' } });
|
|
1232
|
+
if (options.walMode) {
|
|
1233
|
+
await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA journal_mode = WAL' } });
|
|
1234
|
+
}
|
|
1235
|
+
if (options.performancePresets) {
|
|
1236
|
+
await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA synchronous = NORMAL' } });
|
|
1237
|
+
await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA busy_timeout = 5000' } });
|
|
1238
|
+
await promiser({ type: 'exec', dbId, args: { sql: 'PRAGMA cache_size = -2000' } });
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1236
1241
|
generateToken() {
|
|
1237
1242
|
return Array.from(crypto.getRandomValues(new Uint8Array(32)))
|
|
1238
1243
|
.map((b) => b.toString(16).padStart(2, '0'))
|
|
1239
1244
|
.join('');
|
|
1240
1245
|
}
|
|
1241
|
-
/**
|
|
1242
|
-
* Get last insert row ID
|
|
1243
|
-
*/
|
|
1244
|
-
getLastInsertId(db) {
|
|
1245
|
-
try {
|
|
1246
|
-
const result = db.exec('SELECT last_insert_rowid()');
|
|
1247
|
-
if (result.length > 0 && result[0].values.length > 0) {
|
|
1248
|
-
return result[0].values[0][0];
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
catch (_a) {
|
|
1252
|
-
// Ignore error
|
|
1253
|
-
}
|
|
1254
|
-
return -1;
|
|
1255
|
-
}
|
|
1256
|
-
/**
|
|
1257
|
-
* Save database to IndexedDB
|
|
1258
|
-
*/
|
|
1259
|
-
async saveToIndexedDB(dbName, data) {
|
|
1260
|
-
return new Promise((resolve, reject) => {
|
|
1261
|
-
const request = indexedDB.open('CapacitorNativeSQL', 1);
|
|
1262
|
-
request.onerror = () => reject(request.error);
|
|
1263
|
-
request.onupgradeneeded = (event) => {
|
|
1264
|
-
const db = event.target.result;
|
|
1265
|
-
if (!db.objectStoreNames.contains('databases')) {
|
|
1266
|
-
db.createObjectStore('databases');
|
|
1267
|
-
}
|
|
1268
|
-
};
|
|
1269
|
-
request.onsuccess = () => {
|
|
1270
|
-
const db = request.result;
|
|
1271
|
-
const transaction = db.transaction(['databases'], 'readwrite');
|
|
1272
|
-
const store = transaction.objectStore('databases');
|
|
1273
|
-
const putRequest = store.put(data, dbName);
|
|
1274
|
-
putRequest.onsuccess = () => {
|
|
1275
|
-
db.close();
|
|
1276
|
-
resolve();
|
|
1277
|
-
};
|
|
1278
|
-
putRequest.onerror = () => {
|
|
1279
|
-
db.close();
|
|
1280
|
-
reject(putRequest.error);
|
|
1281
|
-
};
|
|
1282
|
-
};
|
|
1283
|
-
});
|
|
1284
|
-
}
|
|
1285
|
-
/**
|
|
1286
|
-
* Load database from IndexedDB
|
|
1287
|
-
*/
|
|
1288
|
-
async loadFromIndexedDB(dbName) {
|
|
1289
|
-
return new Promise((resolve, reject) => {
|
|
1290
|
-
const request = indexedDB.open('CapacitorNativeSQL', 1);
|
|
1291
|
-
request.onerror = () => reject(request.error);
|
|
1292
|
-
request.onupgradeneeded = (event) => {
|
|
1293
|
-
const db = event.target.result;
|
|
1294
|
-
if (!db.objectStoreNames.contains('databases')) {
|
|
1295
|
-
db.createObjectStore('databases');
|
|
1296
|
-
}
|
|
1297
|
-
};
|
|
1298
|
-
request.onsuccess = () => {
|
|
1299
|
-
const db = request.result;
|
|
1300
|
-
const transaction = db.transaction(['databases'], 'readonly');
|
|
1301
|
-
const store = transaction.objectStore('databases');
|
|
1302
|
-
const getRequest = store.get(dbName);
|
|
1303
|
-
getRequest.onsuccess = () => {
|
|
1304
|
-
db.close();
|
|
1305
|
-
resolve(getRequest.result || null);
|
|
1306
|
-
};
|
|
1307
|
-
getRequest.onerror = () => {
|
|
1308
|
-
db.close();
|
|
1309
|
-
reject(getRequest.error);
|
|
1310
|
-
};
|
|
1311
|
-
};
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
1246
|
async getPluginVersion() {
|
|
1315
1247
|
return { version: 'web' };
|
|
1316
1248
|
}
|