@unvired/react-native-unvired-sdk 0.0.45 → 0.0.47

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 (31) hide show
  1. package/BuildNo.txt +1 -1
  2. package/dist/database/DatabaseManager.d.ts +10 -1
  3. package/dist/database/DatabaseManager.js +22 -2
  4. package/dist/database/DatabaseManager.web.d.ts +7 -0
  5. package/dist/database/DatabaseManager.web.js +8 -1
  6. package/dist/database/index.d.ts +3 -0
  7. package/dist/database/index.js +3 -0
  8. package/dist/database/services/DatabaseExpo.d.ts +14 -0
  9. package/dist/database/services/DatabaseExpo.js +284 -0
  10. package/dist/database/services/DatabaseNative.d.ts +2 -0
  11. package/dist/database/services/DatabaseNative.js +134 -41
  12. package/dist/database/services/DatabaseWeb.d.ts +1 -0
  13. package/dist/database/services/DatabaseWeb.js +138 -34
  14. package/dist/device-info/services/DeviceInfoNative.js +50 -3
  15. package/dist/file-system/FileSystem.d.ts +12 -3
  16. package/dist/file-system/FileSystem.js +34 -6
  17. package/dist/file-system/index.d.ts +4 -1
  18. package/dist/file-system/index.js +3 -0
  19. package/dist/file-system/services/FileSystemExpo.d.ts +22 -0
  20. package/dist/file-system/services/FileSystemExpo.js +336 -0
  21. package/dist/file-system/services/FileSystemNative.d.ts +24 -3
  22. package/dist/file-system/services/FileSystemNative.js +127 -36
  23. package/dist/file-system/services/FileSystemWeb.d.ts +1 -1
  24. package/dist/file-system/services/FileSystemWeb.js +86 -94
  25. package/dist/local-storage/services/StorageNative.d.ts +1 -0
  26. package/dist/local-storage/services/StorageNative.js +51 -12
  27. package/dist/logger/BaseLogger.js +4 -0
  28. package/dist/main.d.ts +3 -3
  29. package/dist/main.js +2 -2
  30. package/dist/push-notification/services/PushNotificationNative.js +182 -68
  31. package/package.json +21 -1
package/BuildNo.txt CHANGED
@@ -1 +1 @@
1
- R-0.000.0045
1
+ R-0.000.0047
@@ -1,11 +1,20 @@
1
1
  import { IDatabaseAdapter } from "./types";
2
2
  /**
3
3
  * DatabaseManager - Manages native database operations
4
- * - iOS/Android/Windows: Uses @op-engineering/op-sqlite
4
+ * - React Native CLI: Uses @op-engineering/op-sqlite
5
+ * - Expo: Uses expo-sqlite
5
6
  */
6
7
  export declare class DatabaseManager {
7
8
  /**
8
9
  * Get the database adapter implementation
9
10
  */
10
11
  static getDatabaseAdapter(): IDatabaseAdapter;
12
+ /**
13
+ * Manually override the database adapter
14
+ */
15
+ static setDatabaseAdapter(adapter: {
16
+ getAdapter(): IDatabaseAdapter;
17
+ }): void;
11
18
  }
19
+ export { DatabaseExpo } from "./services/DatabaseExpo";
20
+ export { DatabaseNative } from "./services/DatabaseNative";
@@ -1,8 +1,20 @@
1
1
  import { DatabaseNative } from "./services/DatabaseNative";
2
- const dbImpl = new DatabaseNative();
2
+ import { DatabaseExpo } from "./services/DatabaseExpo";
3
+ function resolveAdapter() {
4
+ if (DatabaseNative.isAvailable()) {
5
+ return new DatabaseNative();
6
+ }
7
+ if (DatabaseExpo.isAvailable()) {
8
+ return new DatabaseExpo();
9
+ }
10
+ // Default fallback
11
+ return new DatabaseNative();
12
+ }
13
+ let dbImpl = resolveAdapter();
3
14
  /**
4
15
  * DatabaseManager - Manages native database operations
5
- * - iOS/Android/Windows: Uses @op-engineering/op-sqlite
16
+ * - React Native CLI: Uses @op-engineering/op-sqlite
17
+ * - Expo: Uses expo-sqlite
6
18
  */
7
19
  export class DatabaseManager {
8
20
  /**
@@ -11,4 +23,12 @@ export class DatabaseManager {
11
23
  static getDatabaseAdapter() {
12
24
  return dbImpl.getAdapter();
13
25
  }
26
+ /**
27
+ * Manually override the database adapter
28
+ */
29
+ static setDatabaseAdapter(adapter) {
30
+ dbImpl = adapter;
31
+ }
14
32
  }
33
+ export { DatabaseExpo } from "./services/DatabaseExpo";
34
+ export { DatabaseNative } from "./services/DatabaseNative";
@@ -8,4 +8,11 @@ export declare class DatabaseManager {
8
8
  * Get the database adapter implementation
9
9
  */
10
10
  static getDatabaseAdapter(): IDatabaseAdapter;
11
+ /**
12
+ * Manually override the database adapter
13
+ */
14
+ static setDatabaseAdapter(adapter: {
15
+ getAdapter(): IDatabaseAdapter;
16
+ }): void;
11
17
  }
18
+ export { DatabaseWeb } from "./services/DatabaseWeb";
@@ -1,5 +1,5 @@
1
1
  import { DatabaseWeb } from "./services/DatabaseWeb";
2
- const dbImpl = new DatabaseWeb();
2
+ let dbImpl = new DatabaseWeb();
3
3
  /**
4
4
  * DatabaseManager - Manages web database operations
5
5
  * - Web: Uses Browser/WebSQL/IndexedDB/UnviredDB via sql.js
@@ -11,4 +11,11 @@ export class DatabaseManager {
11
11
  static getDatabaseAdapter() {
12
12
  return dbImpl.getAdapter();
13
13
  }
14
+ /**
15
+ * Manually override the database adapter
16
+ */
17
+ static setDatabaseAdapter(adapter) {
18
+ dbImpl = adapter;
19
+ }
14
20
  }
21
+ export { DatabaseWeb } from "./services/DatabaseWeb";
@@ -3,4 +3,7 @@
3
3
  */
4
4
  export { DatabaseManager } from './DatabaseManager';
5
5
  export { Database, createDatabase } from './Database';
6
+ export { DatabaseNative } from './services/DatabaseNative';
7
+ export { DatabaseExpo } from './services/DatabaseExpo';
8
+ export { DatabaseWeb } from './services/DatabaseWeb';
6
9
  export type { IDatabaseAdapter, DatabaseOptions, ExecuteOptions, SaveWebDBOptions, ExportWebDBOptions, DeleteUserDataOptions, SuccessCallback, ErrorCallback, ResultCallback, SQLResultSet, SQLTransaction, SQLiteDatabase } from './types';
@@ -3,3 +3,6 @@
3
3
  */
4
4
  export { DatabaseManager } from './DatabaseManager';
5
5
  export { Database, createDatabase } from './Database';
6
+ export { DatabaseNative } from './services/DatabaseNative';
7
+ export { DatabaseExpo } from './services/DatabaseExpo';
8
+ export { DatabaseWeb } from './services/DatabaseWeb';
@@ -0,0 +1,14 @@
1
+ import { IDatabaseAdapter } from "../types";
2
+ /**
3
+ * DatabaseExpo - SQLite adapter for Expo environments using expo-sqlite
4
+ * Supports Expo SDK 50+ (openDatabaseSync / openDatabaseAsync) and legacy versions
5
+ */
6
+ export declare class DatabaseExpo {
7
+ private databases;
8
+ private txDepths;
9
+ static isAvailable(): boolean;
10
+ private normalizeDbName;
11
+ private getDatabase;
12
+ private executeRaw;
13
+ getAdapter(): IDatabaseAdapter;
14
+ }
@@ -0,0 +1,284 @@
1
+ let expoSqlite = null;
2
+ try {
3
+ expoSqlite = require("expo-sqlite");
4
+ }
5
+ catch (e) {
6
+ expoSqlite = null;
7
+ }
8
+ /**
9
+ * DatabaseExpo - SQLite adapter for Expo environments using expo-sqlite
10
+ * Supports Expo SDK 50+ (openDatabaseSync / openDatabaseAsync) and legacy versions
11
+ */
12
+ export class DatabaseExpo {
13
+ constructor() {
14
+ this.databases = new Map();
15
+ this.txDepths = new Map();
16
+ }
17
+ static isAvailable() {
18
+ return (expoSqlite != null &&
19
+ (typeof expoSqlite.openDatabaseSync === "function" ||
20
+ typeof expoSqlite.openDatabaseAsync === "function" ||
21
+ typeof expoSqlite.openDatabase === "function"));
22
+ }
23
+ normalizeDbName(name) {
24
+ if (!name)
25
+ return "default.db";
26
+ return name.endsWith(".db") ? name : `${name}.db`;
27
+ }
28
+ async getDatabase(name) {
29
+ const dbKey = this.normalizeDbName(name);
30
+ if (this.databases.has(dbKey)) {
31
+ return this.databases.get(dbKey);
32
+ }
33
+ if (!expoSqlite) {
34
+ throw new Error("expo-sqlite is not installed or available");
35
+ }
36
+ let db = null;
37
+ if (typeof expoSqlite.openDatabaseSync === "function") {
38
+ db = expoSqlite.openDatabaseSync(dbKey);
39
+ }
40
+ else if (typeof expoSqlite.openDatabaseAsync === "function") {
41
+ db = await expoSqlite.openDatabaseAsync(dbKey);
42
+ }
43
+ else if (typeof expoSqlite.openDatabase === "function") {
44
+ db = expoSqlite.openDatabase(dbKey);
45
+ }
46
+ else {
47
+ throw new Error("Compatible expo-sqlite openDatabase method not found");
48
+ }
49
+ this.databases.set(dbKey, db);
50
+ return db;
51
+ }
52
+ async executeRaw(db, query, params = []) {
53
+ const trimmed = query.trim();
54
+ const isSelect = /^SELECT\b/i.test(trimmed);
55
+ if (typeof db.getAllAsync === "function" && isSelect) {
56
+ return await db.getAllAsync(query, params);
57
+ }
58
+ else if (typeof db.runAsync === "function") {
59
+ return await db.runAsync(query, params);
60
+ }
61
+ else if (typeof db.execAsync === "function") {
62
+ return await db.execAsync(query);
63
+ }
64
+ else if (typeof db.transaction === "function") {
65
+ return new Promise((resolve, reject) => {
66
+ db.transaction((tx) => {
67
+ tx.executeSql(query, params, (_, res) => resolve(res), (_, err) => reject(err));
68
+ });
69
+ });
70
+ }
71
+ throw new Error("No compatible query execution method on expo-sqlite database");
72
+ }
73
+ getAdapter() {
74
+ return {
75
+ create: async (options, successCallback, errorCallback) => {
76
+ try {
77
+ const dbName = options.name || options.userId || "default";
78
+ await this.getDatabase(dbName);
79
+ successCallback({ success: true, database: dbName });
80
+ }
81
+ catch (error) {
82
+ errorCallback(error instanceof Error ? error.message : String(error));
83
+ }
84
+ },
85
+ execute: async (options, successCallback, errorCallback) => {
86
+ var _a, _b;
87
+ try {
88
+ const dbName = options.dbName || options.userId || "default";
89
+ const params = options.params || options.args || [];
90
+ const db = await this.getDatabase(dbName);
91
+ const rawQuery = options.query || "";
92
+ const trimmedQuery = rawQuery.trim().replace(/;+$/, "").toUpperCase().replace(/\s+/g, " ");
93
+ // Intercept transaction commands to prevent "cannot start a transaction within a transaction"
94
+ if (trimmedQuery === "BEGIN" || trimmedQuery === "BEGIN TRANSACTION") {
95
+ const currentDepth = this.txDepths.get(dbName) || 0;
96
+ if (currentDepth === 0) {
97
+ this.txDepths.set(dbName, 1);
98
+ try {
99
+ await this.executeRaw(db, "BEGIN TRANSACTION;");
100
+ }
101
+ catch (txErr) {
102
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
103
+ if (msg.includes("within a transaction") || msg.includes("already in a transaction")) {
104
+ this.txDepths.set(dbName, currentDepth + 1);
105
+ }
106
+ else {
107
+ throw txErr;
108
+ }
109
+ }
110
+ }
111
+ else {
112
+ // Nested transaction on the same SQLite connection: translate to SAVEPOINT
113
+ this.txDepths.set(dbName, currentDepth + 1);
114
+ try {
115
+ await this.executeRaw(db, `SAVEPOINT trans_sp_${currentDepth};`);
116
+ }
117
+ catch (spErr) { }
118
+ }
119
+ successCallback([]);
120
+ return;
121
+ }
122
+ if (trimmedQuery === "COMMIT" || trimmedQuery === "END" || trimmedQuery === "END TRANSACTION" || trimmedQuery === "COMMIT TRANSACTION") {
123
+ const currentDepth = this.txDepths.get(dbName) || 0;
124
+ if (currentDepth > 1) {
125
+ const newDepth = currentDepth - 1;
126
+ this.txDepths.set(dbName, newDepth);
127
+ try {
128
+ await this.executeRaw(db, `RELEASE SAVEPOINT trans_sp_${newDepth};`);
129
+ }
130
+ catch (spErr) { }
131
+ }
132
+ else if (currentDepth === 1) {
133
+ this.txDepths.set(dbName, 0);
134
+ try {
135
+ await this.executeRaw(db, "COMMIT;");
136
+ }
137
+ catch (txErr) {
138
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
139
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot commit")) {
140
+ throw txErr;
141
+ }
142
+ }
143
+ }
144
+ successCallback([]);
145
+ return;
146
+ }
147
+ if (trimmedQuery === "ROLLBACK" || trimmedQuery === "ROLLBACK TRANSACTION") {
148
+ const currentDepth = this.txDepths.get(dbName) || 0;
149
+ if (currentDepth > 1) {
150
+ const newDepth = currentDepth - 1;
151
+ this.txDepths.set(dbName, newDepth);
152
+ try {
153
+ await this.executeRaw(db, `ROLLBACK TO SAVEPOINT trans_sp_${newDepth};`);
154
+ }
155
+ catch (spErr) { }
156
+ try {
157
+ await this.executeRaw(db, `RELEASE SAVEPOINT trans_sp_${newDepth};`);
158
+ }
159
+ catch (spErr) { }
160
+ }
161
+ else if (currentDepth === 1) {
162
+ this.txDepths.set(dbName, 0);
163
+ try {
164
+ await this.executeRaw(db, "ROLLBACK;");
165
+ }
166
+ catch (txErr) {
167
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
168
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot rollback")) {
169
+ throw txErr;
170
+ }
171
+ }
172
+ }
173
+ else {
174
+ this.txDepths.set(dbName, 0);
175
+ }
176
+ successCallback([]);
177
+ return;
178
+ }
179
+ const res = await this.executeRaw(db, options.query, params);
180
+ let resultToReturn = [];
181
+ if (Array.isArray(res)) {
182
+ resultToReturn = res;
183
+ }
184
+ else if (res && typeof res === "object") {
185
+ if (res.rows && typeof res.rows.length === "number") {
186
+ for (let i = 0; i < res.rows.length; i++) {
187
+ resultToReturn.push(res.rows.item ? res.rows.item(i) : res.rows[i]);
188
+ }
189
+ }
190
+ if (res.lastInsertRowId !== undefined || res.insertId !== undefined) {
191
+ resultToReturn.insertId = (_a = res.lastInsertRowId) !== null && _a !== void 0 ? _a : res.insertId;
192
+ resultToReturn.rowsAffected = (_b = res.changes) !== null && _b !== void 0 ? _b : res.rowsAffected;
193
+ }
194
+ }
195
+ successCallback(resultToReturn);
196
+ }
197
+ catch (error) {
198
+ const msg = (error && (error.message || String(error))) || "";
199
+ if (msg.includes("cannot start a transaction within a transaction")) {
200
+ const dbName = options.dbName || options.userId || "default";
201
+ const currentDepth = this.txDepths.get(dbName) || 0;
202
+ this.txDepths.set(dbName, currentDepth + 1);
203
+ successCallback([]);
204
+ return;
205
+ }
206
+ if (msg.includes("no transaction is active") || msg.includes("cannot rollback") || msg.includes("cannot commit")) {
207
+ const dbName = options.dbName || options.userId || "default";
208
+ this.txDepths.set(dbName, 0);
209
+ successCallback([]);
210
+ return;
211
+ }
212
+ errorCallback(error instanceof Error ? error.message : String(error));
213
+ }
214
+ },
215
+ executeStatementOnPath: async (dbPath, sqlQuery, callback) => {
216
+ var _a;
217
+ try {
218
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
219
+ const db = await this.getDatabase(dbName);
220
+ const res = await this.executeRaw(db, sqlQuery);
221
+ callback(Array.isArray(res) ? res : []);
222
+ }
223
+ catch (error) {
224
+ callback(error instanceof Error ? error.message : String(error));
225
+ }
226
+ },
227
+ selectFromPath: async (dbPath, sqlQuery, callback) => {
228
+ var _a;
229
+ try {
230
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
231
+ const db = await this.getDatabase(dbName);
232
+ const res = await this.executeRaw(db, sqlQuery);
233
+ callback(Array.isArray(res) ? res : []);
234
+ }
235
+ catch (error) {
236
+ callback(error instanceof Error ? error.message : String(error));
237
+ }
238
+ },
239
+ createDatabase: async (dbPath, callback) => {
240
+ var _a;
241
+ try {
242
+ const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
243
+ await this.getDatabase(dbName);
244
+ callback(true);
245
+ }
246
+ catch (error) {
247
+ callback(error instanceof Error ? error.message : String(error));
248
+ }
249
+ },
250
+ getDBFilePath: (options, callback) => {
251
+ callback(options.name);
252
+ },
253
+ saveWebDB: (options, callback, errorCallback) => {
254
+ errorCallback("saveWebDB is only available on web platform");
255
+ },
256
+ exportWebDB: (options, callback, errorCallback) => {
257
+ errorCallback("exportWebDB is only available on web platform");
258
+ },
259
+ deleteUserData: async (options, callback, errorCallback) => {
260
+ try {
261
+ const dbName = options.dbName || options.userId || "default";
262
+ const db = await this.getDatabase(dbName);
263
+ const query = options.userId
264
+ ? "DELETE FROM user_data WHERE user_id = ?"
265
+ : "DELETE FROM user_data";
266
+ const params = options.userId ? [options.userId] : [];
267
+ await this.executeRaw(db, query, params);
268
+ callback();
269
+ }
270
+ catch (error) {
271
+ errorCallback(error instanceof Error ? error.message : String(error));
272
+ }
273
+ },
274
+ getEncryptionKey: (options, successCallback, errorCallback) => {
275
+ try {
276
+ successCallback("unvired_default_key");
277
+ }
278
+ catch (error) {
279
+ errorCallback();
280
+ }
281
+ },
282
+ };
283
+ }
284
+ }
@@ -1,6 +1,8 @@
1
1
  import { IDatabaseAdapter } from "../types";
2
2
  export declare class DatabaseNative {
3
3
  private databases;
4
+ private txDepths;
5
+ static isAvailable(): boolean;
4
6
  private defaultLocation;
5
7
  private getDatabase;
6
8
  getAdapter(): IDatabaseAdapter;
@@ -1,9 +1,19 @@
1
- import { open } from '@op-engineering/op-sqlite';
1
+ let opSqlite = null;
2
+ try {
3
+ opSqlite = require('@op-engineering/op-sqlite');
4
+ }
5
+ catch (e) {
6
+ opSqlite = null;
7
+ }
2
8
  export class DatabaseNative {
3
9
  constructor() {
4
10
  this.databases = new Map();
11
+ this.txDepths = new Map();
5
12
  this.defaultLocation = "default";
6
13
  }
14
+ static isAvailable() {
15
+ return opSqlite != null && typeof opSqlite.open === 'function';
16
+ }
7
17
  getDatabase(name, location) {
8
18
  const dbKey = `${name}_${location || this.defaultLocation}`;
9
19
  if (this.databases.has(dbKey)) {
@@ -12,7 +22,10 @@ export class DatabaseNative {
12
22
  if (!name) {
13
23
  throw new Error("Database name is required");
14
24
  }
15
- const db = open({ name });
25
+ if (!DatabaseNative.isAvailable()) {
26
+ throw new Error("@op-engineering/op-sqlite is not installed or available");
27
+ }
28
+ const db = opSqlite.open({ name });
16
29
  this.databases.set(dbKey, db);
17
30
  return db;
18
31
  }
@@ -33,7 +46,95 @@ export class DatabaseNative {
33
46
  const dbName = options.dbName || options.userId;
34
47
  const params = options.params || options.args || [];
35
48
  const db = this.getDatabase(dbName);
36
- // FIX: Await the result properly
49
+ const rawQuery = options.query || "";
50
+ const trimmedQuery = rawQuery.trim().replace(/;+$/, "").toUpperCase().replace(/\s+/g, " ");
51
+ // Intercept transaction commands to prevent "cannot start a transaction within a transaction"
52
+ if (trimmedQuery === "BEGIN" || trimmedQuery === "BEGIN TRANSACTION") {
53
+ const currentDepth = this.txDepths.get(dbName) || 0;
54
+ if (currentDepth === 0) {
55
+ this.txDepths.set(dbName, 1);
56
+ try {
57
+ await db.execute("BEGIN TRANSACTION;");
58
+ }
59
+ catch (txErr) {
60
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
61
+ if (msg.includes("within a transaction") || msg.includes("already in a transaction")) {
62
+ this.txDepths.set(dbName, currentDepth + 1);
63
+ }
64
+ else {
65
+ throw txErr;
66
+ }
67
+ }
68
+ }
69
+ else {
70
+ // Nested transaction on the same SQLite connection: translate to SAVEPOINT
71
+ this.txDepths.set(dbName, currentDepth + 1);
72
+ try {
73
+ await db.execute(`SAVEPOINT trans_sp_${currentDepth};`);
74
+ }
75
+ catch (spErr) { }
76
+ }
77
+ successCallback([]);
78
+ return;
79
+ }
80
+ if (trimmedQuery === "COMMIT" || trimmedQuery === "END" || trimmedQuery === "END TRANSACTION" || trimmedQuery === "COMMIT TRANSACTION") {
81
+ const currentDepth = this.txDepths.get(dbName) || 0;
82
+ if (currentDepth > 1) {
83
+ const newDepth = currentDepth - 1;
84
+ this.txDepths.set(dbName, newDepth);
85
+ try {
86
+ await db.execute(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
87
+ }
88
+ catch (spErr) { }
89
+ }
90
+ else if (currentDepth === 1) {
91
+ this.txDepths.set(dbName, 0);
92
+ try {
93
+ await db.execute("COMMIT;");
94
+ }
95
+ catch (txErr) {
96
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
97
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot commit")) {
98
+ throw txErr;
99
+ }
100
+ }
101
+ }
102
+ successCallback([]);
103
+ return;
104
+ }
105
+ if (trimmedQuery === "ROLLBACK" || trimmedQuery === "ROLLBACK TRANSACTION") {
106
+ const currentDepth = this.txDepths.get(dbName) || 0;
107
+ if (currentDepth > 1) {
108
+ const newDepth = currentDepth - 1;
109
+ this.txDepths.set(dbName, newDepth);
110
+ try {
111
+ await db.execute(`ROLLBACK TO SAVEPOINT trans_sp_${newDepth};`);
112
+ }
113
+ catch (spErr) { }
114
+ try {
115
+ await db.execute(`RELEASE SAVEPOINT trans_sp_${newDepth};`);
116
+ }
117
+ catch (spErr) { }
118
+ }
119
+ else if (currentDepth === 1) {
120
+ this.txDepths.set(dbName, 0);
121
+ try {
122
+ await db.execute("ROLLBACK;");
123
+ }
124
+ catch (txErr) {
125
+ const msg = (txErr && (txErr.message || String(txErr))) || "";
126
+ if (!msg.includes("no transaction is active") && !msg.includes("cannot rollback")) {
127
+ throw txErr;
128
+ }
129
+ }
130
+ }
131
+ else {
132
+ this.txDepths.set(dbName, 0);
133
+ }
134
+ successCallback([]);
135
+ return;
136
+ }
137
+ // Await the result properly
37
138
  const res = await db.execute(options.query, params);
38
139
  let resultToReturn = [];
39
140
  // Cast to any to avoid TS error "Property '_array' does not exist on type 'never'"
@@ -69,6 +170,20 @@ export class DatabaseNative {
69
170
  successCallback(resultToReturn);
70
171
  }
71
172
  catch (error) {
173
+ const msg = (error && (error.message || String(error))) || "";
174
+ if (msg.includes("cannot start a transaction within a transaction")) {
175
+ const dbName = options.dbName || options.userId || "default";
176
+ const currentDepth = this.txDepths.get(dbName) || 0;
177
+ this.txDepths.set(dbName, currentDepth + 1);
178
+ successCallback([]);
179
+ return;
180
+ }
181
+ if (msg.includes("no transaction is active") || msg.includes("cannot rollback") || msg.includes("cannot commit")) {
182
+ const dbName = options.dbName || options.userId || "default";
183
+ this.txDepths.set(dbName, 0);
184
+ successCallback([]);
185
+ return;
186
+ }
72
187
  errorCallback(error instanceof Error ? error.message : String(error));
73
188
  }
74
189
  },
@@ -88,22 +203,11 @@ export class DatabaseNative {
88
203
  resultToReturn.push(r);
89
204
  }
90
205
  }
91
- else if (Array.isArray(rawRows)) {
92
- resultToReturn = rawRows;
93
- }
94
- else if (rawRows._array) {
95
- resultToReturn = rawRows._array;
96
- }
97
- }
98
- // Attach insertId if present
99
- if (rawRes && rawRes.insertId !== undefined) {
100
- resultToReturn.insertId = rawRes.insertId;
101
- resultToReturn.rowsAffected = rawRes.rowsAffected;
102
206
  }
103
207
  callback(resultToReturn);
104
208
  }
105
209
  catch (error) {
106
- callback([]);
210
+ callback(error instanceof Error ? error.message : String(error));
107
211
  }
108
212
  },
109
213
  selectFromPath: async (dbPath, sqlQuery, callback) => {
@@ -122,17 +226,11 @@ export class DatabaseNative {
122
226
  resultToReturn.push(r);
123
227
  }
124
228
  }
125
- else if (Array.isArray(rawRows)) {
126
- resultToReturn = rawRows;
127
- }
128
- else if (rawRows._array) {
129
- resultToReturn = rawRows._array;
130
- }
131
229
  }
132
230
  callback(resultToReturn);
133
231
  }
134
232
  catch (error) {
135
- callback([]);
233
+ callback(error instanceof Error ? error.message : String(error));
136
234
  }
137
235
  },
138
236
  createDatabase: async (dbPath, callback) => {
@@ -140,28 +238,20 @@ export class DatabaseNative {
140
238
  try {
141
239
  const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
142
240
  this.getDatabase(dbName);
143
- callback();
241
+ callback(true);
144
242
  }
145
243
  catch (error) {
146
- callback();
244
+ callback(error instanceof Error ? error.message : String(error));
147
245
  }
148
246
  },
149
- getDBFilePath: async (options, callback) => {
150
- callback(`${options.name}.db`);
247
+ getDBFilePath: (options, callback) => {
248
+ callback(options.name);
151
249
  },
152
- saveWebDB: async (options, callback, errorCallback) => {
153
- // Not needed for native - only for web
154
- callback({
155
- success: true,
156
- message: "Not applicable for native",
157
- });
250
+ saveWebDB: (options, callback, errorCallback) => {
251
+ errorCallback("saveWebDB is only available on web platform");
158
252
  },
159
- exportWebDB: async (options, callback, errorCallback) => {
160
- // Not needed for native - only for web
161
- callback({
162
- success: true,
163
- message: "Not applicable for native",
164
- });
253
+ exportWebDB: (options, callback, errorCallback) => {
254
+ errorCallback("exportWebDB is only available on web platform");
165
255
  },
166
256
  deleteUserData: async (options, callback, errorCallback) => {
167
257
  try {
@@ -179,9 +269,12 @@ export class DatabaseNative {
179
269
  }
180
270
  },
181
271
  getEncryptionKey: (options, successCallback, errorCallback) => {
182
- // Native encryption key logic can be implemented here if needed.
183
- // For now, return empty or trigger errorCallback depending on support.
184
- errorCallback();
272
+ try {
273
+ successCallback("unvired_default_key");
274
+ }
275
+ catch (error) {
276
+ errorCallback();
277
+ }
185
278
  },
186
279
  };
187
280
  }