@unvired/react-native-unvired-sdk 0.0.46 → 0.0.48

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/BuildNo.txt CHANGED
@@ -1 +1 @@
1
- R-0.000.0046
1
+ R-0.000.0048
@@ -1,13 +1,11 @@
1
1
  import { IDatabaseAdapter } from "../types";
2
2
  /**
3
- * DatabaseWeb - SQLite WebAssembly adapter for React Native Web using sql.js
4
- * Persists SQLite databases to localStorage
3
+ * DatabaseWeb - Native stub.
4
+ * This class is a placeholder for React Native mobile builds where SQLite is handled
5
+ * by DatabaseNative (@op-engineering/op-sqlite) or DatabaseExpo (expo-sqlite).
6
+ * The full WebAssembly/sql.js implementation is in DatabaseWeb.web.ts for Webpack/Web bundlers.
5
7
  */
6
8
  export declare class DatabaseWeb {
7
- private databases;
8
- private txDepths;
9
- private defaultLocation;
10
- private getDatabase;
11
- private persistDatabase;
9
+ static isAvailable(): boolean;
12
10
  getAdapter(): IDatabaseAdapter;
13
11
  }
@@ -1,367 +1,44 @@
1
- let SQL = null;
2
- let initPromise = null;
3
- function getSqlJs() {
4
- if (!initPromise) {
5
- let initSqlJs;
6
- try {
7
- initSqlJs = require("sql.js");
8
- if (initSqlJs && initSqlJs.default) {
9
- initSqlJs = initSqlJs.default;
10
- }
11
- }
12
- catch {
13
- initSqlJs = globalThis.initSqlJs;
14
- }
15
- if (typeof initSqlJs === "function") {
16
- initPromise = initSqlJs({
17
- locateFile: (file) => {
18
- if (typeof window !== "undefined" && window.SQL_WASM_PATH) {
19
- return `${window.SQL_WASM_PATH}/${file}`;
20
- }
21
- return `https://cdn.jsdelivr.net/npm/sql.js@1.14.2/dist/${file}`;
22
- },
23
- }).then((sql) => {
24
- SQL = sql;
25
- return sql;
26
- }).catch((err) => {
27
- console.warn("[DatabaseWeb] Failed loading sql.js from jsdelivr, trying cdnjs fallback:", err);
28
- return initSqlJs({
29
- locateFile: (file) => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.12.0/${file}`,
30
- }).then((sql) => {
31
- SQL = sql;
32
- return sql;
33
- });
34
- });
35
- }
36
- else {
37
- initPromise = Promise.reject(new Error("sql.js module not found"));
38
- }
39
- }
40
- return initPromise || Promise.reject(new Error("sql.js not initialized"));
41
- }
42
1
  /**
43
- * DatabaseWeb - SQLite WebAssembly adapter for React Native Web using sql.js
44
- * Persists SQLite databases to localStorage
2
+ * DatabaseWeb - Native stub.
3
+ * This class is a placeholder for React Native mobile builds where SQLite is handled
4
+ * by DatabaseNative (@op-engineering/op-sqlite) or DatabaseExpo (expo-sqlite).
5
+ * The full WebAssembly/sql.js implementation is in DatabaseWeb.web.ts for Webpack/Web bundlers.
45
6
  */
46
7
  export class DatabaseWeb {
47
- constructor() {
48
- this.databases = new Map();
49
- this.txDepths = new Map();
50
- this.defaultLocation = "default";
51
- }
52
- async getDatabase(name, location) {
53
- const dbKey = `${name}_${location || this.defaultLocation}`;
54
- if (this.databases.has(dbKey)) {
55
- return this.databases.get(dbKey);
56
- }
57
- if (!name) {
58
- throw new Error("Database name is required");
59
- }
60
- const sql = await getSqlJs();
61
- let db;
62
- if (typeof localStorage !== "undefined") {
63
- try {
64
- const savedData = localStorage.getItem(`__sqlite_${name}`);
65
- if (savedData) {
66
- const u8 = new Uint8Array(JSON.parse(savedData));
67
- db = new sql.Database(u8);
68
- this.databases.set(dbKey, db);
69
- return db;
70
- }
71
- }
72
- catch (e) {
73
- console.warn("[DatabaseWeb] Failed to load database from localStorage:", e);
74
- }
75
- }
76
- db = new sql.Database();
77
- this.databases.set(dbKey, db);
78
- return db;
79
- }
80
- persistDatabase(name, location) {
81
- const dbKey = `${name}_${location || this.defaultLocation}`;
82
- const db = this.databases.get(dbKey);
83
- if (db && typeof localStorage !== "undefined") {
84
- try {
85
- const data = db.export();
86
- localStorage.setItem(`__sqlite_${name}`, JSON.stringify(Array.from(data)));
87
- }
88
- catch (e) {
89
- console.warn("[DatabaseWeb] Failed to persist database to localStorage:", e);
90
- }
91
- }
8
+ static isAvailable() {
9
+ return false;
92
10
  }
93
11
  getAdapter() {
94
12
  return {
95
- create: async (options, successCallback, errorCallback) => {
96
- try {
97
- const dbName = (options.name || options.userId || "default");
98
- await this.getDatabase(dbName, options.location);
99
- successCallback({ success: true, database: dbName });
100
- }
101
- catch (error) {
102
- errorCallback(error instanceof Error ? error.message : String(error));
103
- }
13
+ create: (_options, _successCallback, errorCallback) => {
14
+ errorCallback("DatabaseWeb is only available on Web (Platform.OS === 'web'). On native mobile, use DatabaseNative or DatabaseExpo.");
104
15
  },
105
- execute: async (options, successCallback, errorCallback) => {
106
- try {
107
- const dbName = (options.dbName || options.userId || "default");
108
- const params = options.params || options.args || [];
109
- const db = await this.getDatabase(dbName);
110
- const rawQuery = options.query || "";
111
- const trimmedQuery = rawQuery.trim().replace(/;+$/, "").toUpperCase().replace(/\s+/g, " ");
112
- // Intercept transaction commands to prevent "cannot start a transaction within a transaction"
113
- if (trimmedQuery === "BEGIN" || trimmedQuery === "BEGIN TRANSACTION") {
114
- const currentDepth = this.txDepths.get(dbName) || 0;
115
- if (currentDepth === 0) {
116
- this.txDepths.set(dbName, 1);
117
- try {
118
- db.run("BEGIN TRANSACTION;");
119
- }
120
- catch (txErr) {
121
- const msg = (txErr && (txErr.message || String(txErr))) || "";
122
- if (msg.includes("within a transaction") || msg.includes("already in a transaction")) {
123
- this.txDepths.set(dbName, currentDepth + 1);
124
- }
125
- else {
126
- throw txErr;
127
- }
128
- }
129
- }
130
- else {
131
- this.txDepths.set(dbName, currentDepth + 1);
132
- try {
133
- db.run(`SAVEPOINT trans_sp_${currentDepth};`);
134
- }
135
- catch (spErr) { }
136
- }
137
- successCallback([]);
138
- return;
139
- }
140
- if (trimmedQuery === "COMMIT" || trimmedQuery === "END" || trimmedQuery === "END TRANSACTION" || trimmedQuery === "COMMIT TRANSACTION") {
141
- const currentDepth = this.txDepths.get(dbName) || 0;
142
- if (currentDepth > 1) {
143
- const newDepth = currentDepth - 1;
144
- this.txDepths.set(dbName, newDepth);
145
- try {
146
- db.run(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
147
- }
148
- catch (spErr) { }
149
- }
150
- else if (currentDepth === 1) {
151
- this.txDepths.set(dbName, 0);
152
- try {
153
- db.run("COMMIT;");
154
- }
155
- catch (txErr) {
156
- const msg = (txErr && (txErr.message || String(txErr))) || "";
157
- if (!msg.includes("no transaction is active") && !msg.includes("cannot commit")) {
158
- throw txErr;
159
- }
160
- }
161
- this.persistDatabase(dbName);
162
- }
163
- successCallback([]);
164
- return;
165
- }
166
- if (trimmedQuery === "ROLLBACK" || trimmedQuery === "ROLLBACK TRANSACTION") {
167
- const currentDepth = this.txDepths.get(dbName) || 0;
168
- if (currentDepth > 1) {
169
- const newDepth = currentDepth - 1;
170
- this.txDepths.set(dbName, newDepth);
171
- try {
172
- db.run(`ROLLBACK TO SAVEPOINT trans_sp_${newDepth};`);
173
- }
174
- catch (spErr) { }
175
- try {
176
- db.run(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
177
- }
178
- catch (spErr) { }
179
- }
180
- else if (currentDepth === 1) {
181
- this.txDepths.set(dbName, 0);
182
- try {
183
- db.run("ROLLBACK;");
184
- }
185
- catch (txErr) {
186
- const msg = (txErr && (txErr.message || String(txErr))) || "";
187
- if (!msg.includes("no transaction is active") && !msg.includes("cannot rollback")) {
188
- throw txErr;
189
- }
190
- }
191
- }
192
- else {
193
- this.txDepths.set(dbName, 0);
194
- }
195
- successCallback([]);
196
- return;
197
- }
198
- const isSelect = /^SELECT\b/i.test(trimmedQuery);
199
- let resultToReturn = [];
200
- if (isSelect) {
201
- const stmt = db.prepare(options.query);
202
- if (params && params.length > 0) {
203
- stmt.bind(params);
204
- }
205
- while (stmt.step()) {
206
- resultToReturn.push(stmt.getAsObject());
207
- }
208
- stmt.free();
209
- }
210
- else {
211
- const stmt = db.prepare(options.query);
212
- if (params && params.length > 0) {
213
- stmt.bind(params);
214
- }
215
- stmt.step();
216
- stmt.free();
217
- let insertId = 0;
218
- let rowsAffected = 0;
219
- try {
220
- const res = db.exec("SELECT last_insert_rowid() as id, changes() as changes;");
221
- if (res.length > 0 && res[0].values && res[0].values.length > 0) {
222
- insertId = res[0].values[0][0];
223
- rowsAffected = res[0].values[0][1];
224
- }
225
- }
226
- catch (e) { }
227
- resultToReturn.insertId = insertId;
228
- resultToReturn.rowsAffected = rowsAffected;
229
- // Only persist if not in an uncommitted transaction
230
- const currentDepth = this.txDepths.get(dbName) || 0;
231
- if (currentDepth === 0) {
232
- this.persistDatabase(dbName);
233
- }
234
- }
235
- successCallback(resultToReturn);
236
- }
237
- catch (error) {
238
- const msg = (error && (error.message || String(error))) || "";
239
- if (msg.includes("cannot start a transaction within a transaction")) {
240
- const dbName = (options.dbName || options.userId || "default");
241
- const currentDepth = this.txDepths.get(dbName) || 0;
242
- this.txDepths.set(dbName, currentDepth + 1);
243
- successCallback([]);
244
- return;
245
- }
246
- if (msg.includes("no transaction is active") || msg.includes("cannot rollback") || msg.includes("cannot commit")) {
247
- const dbName = (options.dbName || options.userId || "default");
248
- this.txDepths.set(dbName, 0);
249
- successCallback([]);
250
- return;
251
- }
252
- errorCallback(error instanceof Error ? error.message : String(error));
253
- }
16
+ execute: (_options, _successCallback, errorCallback) => {
17
+ errorCallback("DatabaseWeb is only available on Web. On native mobile, use DatabaseNative or DatabaseExpo.");
254
18
  },
255
- executeStatementOnPath: async (dbPath, sqlQuery, callback) => {
256
- var _a;
257
- try {
258
- const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
259
- const db = await this.getDatabase(dbName);
260
- const stmt = db.prepare(sqlQuery);
261
- const resultToReturn = [];
262
- while (stmt.step()) {
263
- resultToReturn.push(stmt.getAsObject());
264
- }
265
- stmt.free();
266
- let insertId = 0;
267
- let rowsAffected = 0;
268
- try {
269
- const res = db.exec("SELECT last_insert_rowid() as id, changes() as changes;");
270
- if (res.length > 0 && res[0].values && res[0].values.length > 0) {
271
- insertId = res[0].values[0][0];
272
- rowsAffected = res[0].values[0][1];
273
- }
274
- }
275
- catch (e) { }
276
- resultToReturn.insertId = insertId;
277
- resultToReturn.rowsAffected = rowsAffected;
278
- this.persistDatabase(dbName);
279
- callback(resultToReturn);
280
- }
281
- catch (error) {
282
- console.error("[DatabaseWeb] executeStatementOnPath error:", error);
283
- callback([]);
284
- }
19
+ executeStatementOnPath: (_dbPath, _sqlQuery, callback) => {
20
+ callback([]);
285
21
  },
286
- selectFromPath: async (dbPath, sqlQuery, callback) => {
287
- var _a;
288
- try {
289
- const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
290
- const db = await this.getDatabase(dbName);
291
- const stmt = db.prepare(sqlQuery);
292
- const resultToReturn = [];
293
- while (stmt.step()) {
294
- resultToReturn.push(stmt.getAsObject());
295
- }
296
- stmt.free();
297
- callback(resultToReturn);
298
- }
299
- catch (error) {
300
- console.error("[DatabaseWeb] selectFromPath error:", error);
301
- callback([]);
302
- }
22
+ selectFromPath: (_dbPath, _sqlQuery, callback) => {
23
+ callback([]);
303
24
  },
304
- createDatabase: async (dbPath, callback) => {
305
- var _a;
306
- try {
307
- const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
308
- await this.getDatabase(dbName);
309
- callback();
310
- }
311
- catch (error) {
312
- console.error("[DatabaseWeb] createDatabase error:", error);
313
- callback();
314
- }
25
+ createDatabase: (_dbPath, callback) => {
26
+ callback();
315
27
  },
316
28
  getDBFilePath: (options, callback) => {
317
29
  callback(options.name);
318
30
  },
319
- saveWebDB: (options, callback, errorCallback) => {
320
- try {
321
- const dbName = (options.dbName || "default");
322
- this.persistDatabase(dbName);
323
- callback({ success: true, message: "Database saved to localStorage" });
324
- }
325
- catch (error) {
326
- errorCallback(error instanceof Error ? error.message : String(error));
327
- }
31
+ saveWebDB: (_options, _callback, errorCallback) => {
32
+ errorCallback("DatabaseWeb is only available on Web.");
328
33
  },
329
- exportWebDB: (options, callback, errorCallback) => {
330
- try {
331
- const dbName = (options.dbName || "default");
332
- const dbKey = `${dbName}_${this.defaultLocation}`;
333
- const db = this.databases.get(dbKey);
334
- if (db) {
335
- const data = db.export();
336
- callback({ success: true, data: Array.from(data) });
337
- }
338
- else {
339
- errorCallback("Database not found");
340
- }
341
- }
342
- catch (error) {
343
- errorCallback(error instanceof Error ? error.message : String(error));
344
- }
34
+ exportWebDB: (_options, _callback, errorCallback) => {
35
+ errorCallback("DatabaseWeb is only available on Web.");
345
36
  },
346
- deleteUserData: async (options, callback, errorCallback) => {
347
- try {
348
- const dbName = (options.dbName || options.userId || "default");
349
- const db = await this.getDatabase(dbName);
350
- db.run("DELETE FROM user_data;");
351
- this.persistDatabase(dbName);
352
- callback();
353
- }
354
- catch (error) {
355
- errorCallback(error instanceof Error ? error.message : String(error));
356
- }
37
+ deleteUserData: (_options, callback, _errorCallback) => {
38
+ callback();
357
39
  },
358
- getEncryptionKey: (options, successCallback, errorCallback) => {
359
- try {
360
- successCallback("unvired_default_key");
361
- }
362
- catch (error) {
363
- errorCallback();
364
- }
40
+ getEncryptionKey: (_options, _successCallback, errorCallback) => {
41
+ errorCallback();
365
42
  },
366
43
  };
367
44
  }
@@ -0,0 +1,13 @@
1
+ import { IDatabaseAdapter } from "../types";
2
+ /**
3
+ * DatabaseWeb - SQLite WebAssembly adapter for React Native Web using sql.js
4
+ * Persists SQLite databases to localStorage
5
+ */
6
+ export declare class DatabaseWeb {
7
+ private databases;
8
+ private txDepths;
9
+ private defaultLocation;
10
+ private getDatabase;
11
+ private persistDatabase;
12
+ getAdapter(): IDatabaseAdapter;
13
+ }
@@ -0,0 +1,368 @@
1
+ let SQL = null;
2
+ let initPromise = null;
3
+ function getSqlJs() {
4
+ if (!initPromise) {
5
+ let initSqlJs;
6
+ try {
7
+ initSqlJs = require("sql.js");
8
+ if (initSqlJs && initSqlJs.default) {
9
+ initSqlJs = initSqlJs.default;
10
+ }
11
+ }
12
+ catch {
13
+ initSqlJs = globalThis.initSqlJs;
14
+ }
15
+ if (typeof initSqlJs === "function") {
16
+ initPromise = initSqlJs({
17
+ locateFile: (file) => {
18
+ if (typeof window !== "undefined" && window.SQL_WASM_PATH) {
19
+ return `${window.SQL_WASM_PATH}/${file}`;
20
+ }
21
+ return `https://cdn.jsdelivr.net/npm/sql.js@1.14.2/dist/${file}`;
22
+ },
23
+ }).then((sql) => {
24
+ SQL = sql;
25
+ return sql;
26
+ }).catch((err) => {
27
+ console.warn("[DatabaseWeb] Failed loading sql.js from jsdelivr, trying cdnjs fallback:", err);
28
+ return initSqlJs({
29
+ locateFile: (file) => `https://cdnjs.cloudflare.com/ajax/libs/sql.js/1.12.0/${file}`,
30
+ }).then((sql) => {
31
+ SQL = sql;
32
+ return sql;
33
+ });
34
+ });
35
+ }
36
+ else {
37
+ initPromise = Promise.reject(new Error("sql.js module not found"));
38
+ }
39
+ }
40
+ return initPromise || Promise.reject(new Error("sql.js not initialized"));
41
+ }
42
+ /**
43
+ * DatabaseWeb - SQLite WebAssembly adapter for React Native Web using sql.js
44
+ * Persists SQLite databases to localStorage
45
+ */
46
+ export class DatabaseWeb {
47
+ constructor() {
48
+ this.databases = new Map();
49
+ this.txDepths = new Map();
50
+ this.defaultLocation = "default";
51
+ }
52
+ async getDatabase(name, location) {
53
+ const dbKey = `${name}_${location || this.defaultLocation}`;
54
+ if (this.databases.has(dbKey)) {
55
+ return this.databases.get(dbKey);
56
+ }
57
+ if (!name) {
58
+ throw new Error("Database name is required");
59
+ }
60
+ const sql = await getSqlJs();
61
+ let db;
62
+ if (typeof localStorage !== "undefined") {
63
+ try {
64
+ const savedData = localStorage.getItem(`__sqlite_${name}`);
65
+ if (savedData) {
66
+ const u8 = new Uint8Array(JSON.parse(savedData));
67
+ db = new sql.Database(u8);
68
+ this.databases.set(dbKey, db);
69
+ return db;
70
+ }
71
+ }
72
+ catch (e) {
73
+ console.warn("[DatabaseWeb] Failed to load database from localStorage:", e);
74
+ }
75
+ }
76
+ db = new sql.Database();
77
+ this.databases.set(dbKey, db);
78
+ return db;
79
+ }
80
+ persistDatabase(name, location) {
81
+ const dbKey = `${name}_${location || this.defaultLocation}`;
82
+ const db = this.databases.get(dbKey);
83
+ if (db && typeof localStorage !== "undefined") {
84
+ try {
85
+ const data = db.export();
86
+ localStorage.setItem(`__sqlite_${name}`, JSON.stringify(Array.from(data)));
87
+ }
88
+ catch (e) {
89
+ console.warn("[DatabaseWeb] Failed to persist database to localStorage:", e);
90
+ }
91
+ }
92
+ }
93
+ getAdapter() {
94
+ return {
95
+ create: async (options, successCallback, errorCallback) => {
96
+ try {
97
+ const dbName = (options.name || options.userId || "default");
98
+ await this.getDatabase(dbName, options.location);
99
+ successCallback({ success: true, database: dbName });
100
+ }
101
+ catch (error) {
102
+ errorCallback(error instanceof Error ? error.message : String(error));
103
+ }
104
+ },
105
+ execute: async (options, successCallback, errorCallback) => {
106
+ try {
107
+ const dbName = (options.dbName || options.userId || "default");
108
+ const params = options.params || options.args || [];
109
+ const db = await this.getDatabase(dbName);
110
+ const rawQuery = options.query || "";
111
+ const trimmedQuery = rawQuery.trim().replace(/;+$/, "").toUpperCase().replace(/\s+/g, " ");
112
+ // Intercept transaction commands to prevent "cannot start a transaction within a transaction"
113
+ if (trimmedQuery === "BEGIN" || trimmedQuery === "BEGIN TRANSACTION") {
114
+ const currentDepth = this.txDepths.get(dbName) || 0;
115
+ if (currentDepth === 0) {
116
+ this.txDepths.set(dbName, 1);
117
+ try {
118
+ db.run("BEGIN TRANSACTION;");
119
+ }
120
+ catch (txErr) {
121
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
122
+ if (msg.includes("within a transaction") || msg.includes("already in a transaction")) {
123
+ this.txDepths.set(dbName, currentDepth + 1);
124
+ }
125
+ else {
126
+ throw txErr;
127
+ }
128
+ }
129
+ }
130
+ else {
131
+ this.txDepths.set(dbName, currentDepth + 1);
132
+ try {
133
+ db.run(`SAVEPOINT trans_sp_${currentDepth};`);
134
+ }
135
+ catch (spErr) { }
136
+ }
137
+ successCallback([]);
138
+ return;
139
+ }
140
+ if (trimmedQuery === "COMMIT" || trimmedQuery === "END" || trimmedQuery === "END TRANSACTION" || trimmedQuery === "COMMIT TRANSACTION") {
141
+ const currentDepth = this.txDepths.get(dbName) || 0;
142
+ if (currentDepth > 1) {
143
+ const newDepth = currentDepth - 1;
144
+ this.txDepths.set(dbName, newDepth);
145
+ try {
146
+ db.run(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
147
+ }
148
+ catch (spErr) { }
149
+ }
150
+ else if (currentDepth === 1) {
151
+ this.txDepths.set(dbName, 0);
152
+ try {
153
+ db.run("COMMIT;");
154
+ }
155
+ catch (txErr) {
156
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
157
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot commit")) {
158
+ throw txErr;
159
+ }
160
+ }
161
+ this.persistDatabase(dbName);
162
+ }
163
+ successCallback([]);
164
+ return;
165
+ }
166
+ if (trimmedQuery === "ROLLBACK" || trimmedQuery === "ROLLBACK TRANSACTION") {
167
+ const currentDepth = this.txDepths.get(dbName) || 0;
168
+ if (currentDepth > 1) {
169
+ const newDepth = currentDepth - 1;
170
+ this.txDepths.set(dbName, newDepth);
171
+ try {
172
+ db.run(`ROLLBACK TO SAVEPOINT trans_sp_${newDepth};`);
173
+ }
174
+ catch (spErr) { }
175
+ try {
176
+ db.run(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
177
+ }
178
+ catch (spErr) { }
179
+ }
180
+ else if (currentDepth === 1) {
181
+ this.txDepths.set(dbName, 0);
182
+ try {
183
+ db.run("ROLLBACK;");
184
+ }
185
+ catch (txErr) {
186
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
187
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot rollback")) {
188
+ throw txErr;
189
+ }
190
+ }
191
+ }
192
+ else {
193
+ this.txDepths.set(dbName, 0);
194
+ }
195
+ successCallback([]);
196
+ return;
197
+ }
198
+ const isSelect = /^SELECT\b/i.test(trimmedQuery);
199
+ let resultToReturn = [];
200
+ if (isSelect) {
201
+ const stmt = db.prepare(options.query);
202
+ if (params && params.length > 0) {
203
+ stmt.bind(params);
204
+ }
205
+ while (stmt.step()) {
206
+ resultToReturn.push(stmt.getAsObject());
207
+ }
208
+ stmt.free();
209
+ }
210
+ else {
211
+ const stmt = db.prepare(options.query);
212
+ if (params && params.length > 0) {
213
+ stmt.bind(params);
214
+ }
215
+ stmt.step();
216
+ stmt.free();
217
+ let insertId = 0;
218
+ let rowsAffected = 0;
219
+ try {
220
+ const res = db.exec("SELECT last_insert_rowid() as id, changes() as changes;");
221
+ if (res.length > 0 && res[0].values && res[0].values.length > 0) {
222
+ insertId = res[0].values[0][0];
223
+ rowsAffected = res[0].values[0][1];
224
+ }
225
+ }
226
+ catch (e) { }
227
+ resultToReturn.insertId = insertId;
228
+ resultToReturn.rowsAffected = rowsAffected;
229
+ // Only persist if not in an uncommitted transaction
230
+ const currentDepth = this.txDepths.get(dbName) || 0;
231
+ if (currentDepth === 0) {
232
+ this.persistDatabase(dbName);
233
+ }
234
+ }
235
+ successCallback(resultToReturn);
236
+ }
237
+ catch (error) {
238
+ const msg = (error && (error.message || String(error))) || "";
239
+ if (msg.includes("cannot start a transaction within a transaction")) {
240
+ const dbName = (options.dbName || options.userId || "default");
241
+ const currentDepth = this.txDepths.get(dbName) || 0;
242
+ this.txDepths.set(dbName, currentDepth + 1);
243
+ successCallback([]);
244
+ return;
245
+ }
246
+ if (msg.includes("no transaction is active") || msg.includes("cannot rollback") || msg.includes("cannot commit")) {
247
+ const dbName = (options.dbName || options.userId || "default");
248
+ this.txDepths.set(dbName, 0);
249
+ successCallback([]);
250
+ return;
251
+ }
252
+ errorCallback(error instanceof Error ? error.message : String(error));
253
+ }
254
+ },
255
+ executeStatementOnPath: async (dbPath, sqlQuery, callback) => {
256
+ var _a;
257
+ try {
258
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
259
+ const db = await this.getDatabase(dbName);
260
+ const stmt = db.prepare(sqlQuery);
261
+ const resultToReturn = [];
262
+ while (stmt.step()) {
263
+ resultToReturn.push(stmt.getAsObject());
264
+ }
265
+ stmt.free();
266
+ let insertId = 0;
267
+ let rowsAffected = 0;
268
+ try {
269
+ const res = db.exec("SELECT last_insert_rowid() as id, changes() as changes;");
270
+ if (res.length > 0 && res[0].values && res[0].values.length > 0) {
271
+ insertId = res[0].values[0][0];
272
+ rowsAffected = res[0].values[0][1];
273
+ }
274
+ }
275
+ catch (e) { }
276
+ resultToReturn.insertId = insertId;
277
+ resultToReturn.rowsAffected = rowsAffected;
278
+ this.persistDatabase(dbName);
279
+ callback(resultToReturn);
280
+ }
281
+ catch (error) {
282
+ console.error("[DatabaseWeb] executeStatementOnPath error:", error);
283
+ callback([]);
284
+ }
285
+ },
286
+ selectFromPath: async (dbPath, sqlQuery, callback) => {
287
+ var _a;
288
+ try {
289
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
290
+ const db = await this.getDatabase(dbName);
291
+ const stmt = db.prepare(sqlQuery);
292
+ const resultToReturn = [];
293
+ while (stmt.step()) {
294
+ resultToReturn.push(stmt.getAsObject());
295
+ }
296
+ stmt.free();
297
+ callback(resultToReturn);
298
+ }
299
+ catch (error) {
300
+ console.error("[DatabaseWeb] selectFromPath error:", error);
301
+ callback([]);
302
+ }
303
+ },
304
+ createDatabase: async (dbPath, callback) => {
305
+ var _a;
306
+ try {
307
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
308
+ await this.getDatabase(dbName);
309
+ callback();
310
+ }
311
+ catch (error) {
312
+ console.error("[DatabaseWeb] createDatabase error:", error);
313
+ callback();
314
+ }
315
+ },
316
+ getDBFilePath: (options, callback) => {
317
+ callback(options.name);
318
+ },
319
+ saveWebDB: (options, callback, errorCallback) => {
320
+ try {
321
+ const dbName = (options.dbName || "default");
322
+ this.persistDatabase(dbName);
323
+ callback({ success: true, message: "Database saved to localStorage" });
324
+ }
325
+ catch (error) {
326
+ errorCallback(error instanceof Error ? error.message : String(error));
327
+ }
328
+ },
329
+ exportWebDB: (options, callback, errorCallback) => {
330
+ try {
331
+ const dbName = (options.dbName || "default");
332
+ const dbKey = `${dbName}_${this.defaultLocation}`;
333
+ const db = this.databases.get(dbKey);
334
+ if (db) {
335
+ const data = db.export();
336
+ callback({ success: true, data: Array.from(data) });
337
+ }
338
+ else {
339
+ errorCallback("Database not found");
340
+ }
341
+ }
342
+ catch (error) {
343
+ errorCallback(error instanceof Error ? error.message : String(error));
344
+ }
345
+ },
346
+ deleteUserData: async (options, callback, errorCallback) => {
347
+ try {
348
+ const dbName = (options.dbName || options.userId || "default");
349
+ const db = await this.getDatabase(dbName);
350
+ db.run("DELETE FROM user_data;");
351
+ this.persistDatabase(dbName);
352
+ callback();
353
+ }
354
+ catch (error) {
355
+ errorCallback(error instanceof Error ? error.message : String(error));
356
+ }
357
+ },
358
+ getEncryptionKey: (options, successCallback, errorCallback) => {
359
+ try {
360
+ successCallback("unvired_default_key");
361
+ }
362
+ catch (error) {
363
+ errorCallback();
364
+ }
365
+ },
366
+ };
367
+ }
368
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unvired/react-native-unvired-sdk",
3
- "version": "0.0.46",
3
+ "version": "0.0.48",
4
4
  "description": "Unvired SDK for React Native with logging, database, notifications, and file system support",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",