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

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
@@ -5,6 +5,7 @@ import { IDatabaseAdapter } from "../types";
5
5
  */
6
6
  export declare class DatabaseWeb {
7
7
  private databases;
8
+ private txDepths;
8
9
  private defaultLocation;
9
10
  private getDatabase;
10
11
  private persistDatabase;
@@ -46,6 +46,7 @@ function getSqlJs() {
46
46
  export class DatabaseWeb {
47
47
  constructor() {
48
48
  this.databases = new Map();
49
+ this.txDepths = new Map();
49
50
  this.defaultLocation = "default";
50
51
  }
51
52
  async getDatabase(name, location) {
@@ -106,7 +107,94 @@ export class DatabaseWeb {
106
107
  const dbName = (options.dbName || options.userId || "default");
107
108
  const params = options.params || options.args || [];
108
109
  const db = await this.getDatabase(dbName);
109
- const trimmedQuery = options.query.trim();
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
+ }
110
198
  const isSelect = /^SELECT\b/i.test(trimmedQuery);
111
199
  let resultToReturn = [];
112
200
  if (isSelect) {
@@ -138,11 +226,29 @@ export class DatabaseWeb {
138
226
  catch (e) { }
139
227
  resultToReturn.insertId = insertId;
140
228
  resultToReturn.rowsAffected = rowsAffected;
141
- this.persistDatabase(dbName);
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
+ }
142
234
  }
143
235
  successCallback(resultToReturn);
144
236
  }
145
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
+ }
146
252
  errorCallback(error instanceof Error ? error.message : String(error));
147
253
  }
148
254
  },
@@ -173,6 +279,7 @@ export class DatabaseWeb {
173
279
  callback(resultToReturn);
174
280
  }
175
281
  catch (error) {
282
+ console.error("[DatabaseWeb] executeStatementOnPath error:", error);
176
283
  callback([]);
177
284
  }
178
285
  },
@@ -190,6 +297,7 @@ export class DatabaseWeb {
190
297
  callback(resultToReturn);
191
298
  }
192
299
  catch (error) {
300
+ console.error("[DatabaseWeb] selectFromPath error:", error);
193
301
  callback([]);
194
302
  }
195
303
  },
@@ -201,32 +309,35 @@ export class DatabaseWeb {
201
309
  callback();
202
310
  }
203
311
  catch (error) {
312
+ console.error("[DatabaseWeb] createDatabase error:", error);
204
313
  callback();
205
314
  }
206
315
  },
207
- getDBFilePath: async (options, callback) => {
208
- callback(`${options.name || options.userId || "default"}.db`);
316
+ getDBFilePath: (options, callback) => {
317
+ callback(options.name);
209
318
  },
210
- saveWebDB: async (options, callback, errorCallback) => {
319
+ saveWebDB: (options, callback, errorCallback) => {
211
320
  try {
212
- const dbName = options.dbName || options.userId || "default";
213
- const db = await this.getDatabase(dbName);
214
- const data = db.export();
215
- if (typeof localStorage !== "undefined") {
216
- localStorage.setItem(`__sqlite_${dbName}`, JSON.stringify(Array.from(data)));
217
- }
218
- callback({ success: true });
321
+ const dbName = (options.dbName || "default");
322
+ this.persistDatabase(dbName);
323
+ callback({ success: true, message: "Database saved to localStorage" });
219
324
  }
220
325
  catch (error) {
221
326
  errorCallback(error instanceof Error ? error.message : String(error));
222
327
  }
223
328
  },
224
- exportWebDB: async (options, callback, errorCallback) => {
329
+ exportWebDB: (options, callback, errorCallback) => {
225
330
  try {
226
- const dbName = options.dbName || options.userId || "default";
227
- const db = await this.getDatabase(dbName);
228
- const data = db.export();
229
- callback({ success: true, data: Array.from(data) });
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
+ }
230
341
  }
231
342
  catch (error) {
232
343
  errorCallback(error instanceof Error ? error.message : String(error));
@@ -234,22 +345,10 @@ export class DatabaseWeb {
234
345
  },
235
346
  deleteUserData: async (options, callback, errorCallback) => {
236
347
  try {
237
- const dbName = options.dbName || options.userId;
238
- if (dbName) {
239
- const dbKey = `${dbName}_${this.defaultLocation}`;
240
- if (this.databases.has(dbKey)) {
241
- const db = this.databases.get(dbKey);
242
- try {
243
- db === null || db === void 0 ? void 0 : db.close();
244
- }
245
- catch (e) { }
246
- this.databases.delete(dbKey);
247
- }
248
- if (typeof localStorage !== "undefined") {
249
- localStorage.removeItem(`__sqlite_${dbName}`);
250
- localStorage.removeItem(`__unvired_db_${dbName}`);
251
- }
252
- }
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);
253
352
  callback();
254
353
  }
255
354
  catch (error) {
@@ -257,7 +356,12 @@ export class DatabaseWeb {
257
356
  }
258
357
  },
259
358
  getEncryptionKey: (options, successCallback, errorCallback) => {
260
- successCallback("");
359
+ try {
360
+ successCallback("unvired_default_key");
361
+ }
362
+ catch (error) {
363
+ errorCallback();
364
+ }
261
365
  },
262
366
  };
263
367
  }
@@ -7,6 +7,20 @@ try {
7
7
  catch (e) {
8
8
  RNDeviceInfo = null;
9
9
  }
10
+ let ExpoDevice = null;
11
+ let ExpoApplication = null;
12
+ try {
13
+ ExpoDevice = require("expo-device");
14
+ }
15
+ catch (e) {
16
+ ExpoDevice = null;
17
+ }
18
+ try {
19
+ ExpoApplication = require("expo-application");
20
+ }
21
+ catch (e) {
22
+ ExpoApplication = null;
23
+ }
10
24
  export class DeviceInfoNative {
11
25
  getDeviceInfo() {
12
26
  try {
@@ -24,6 +38,21 @@ export class DeviceInfoNative {
24
38
  deviceType: RNDeviceInfo.getDeviceType ? RNDeviceInfo.getDeviceType() : "Handset",
25
39
  };
26
40
  }
41
+ if (ExpoDevice || ExpoApplication) {
42
+ const isTablet = (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.deviceType) === 2;
43
+ return {
44
+ platform: Platform.OS,
45
+ model: (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.modelName) || "Unknown",
46
+ version: Platform.Version ? Platform.Version.toString() : "1.0",
47
+ isMobile: Platform.OS === "ios" || Platform.OS === "android",
48
+ manufacturer: (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.manufacturer) || "Unknown",
49
+ uuid: (ExpoApplication === null || ExpoApplication === void 0 ? void 0 : ExpoApplication.getAndroidId) ? ExpoApplication.getAndroidId() : ((ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.osBuildId) || "default-uuid"),
50
+ deviceId: (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.osBuildId) || (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.modelName) || "default-id",
51
+ deviceName: (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.deviceName) || "Device",
52
+ brand: (ExpoDevice === null || ExpoDevice === void 0 ? void 0 : ExpoDevice.brand) || "Unknown",
53
+ deviceType: isTablet ? "Tablet" : "Handset",
54
+ };
55
+ }
27
56
  }
28
57
  catch (error) {
29
58
  console.warn("Error getting native device info:", error);
@@ -58,7 +87,13 @@ export class DeviceInfoNative {
58
87
  }
59
88
  async isTablet() {
60
89
  try {
61
- return RNDeviceInfo && RNDeviceInfo.isTablet ? await RNDeviceInfo.isTablet() : false;
90
+ if (RNDeviceInfo && RNDeviceInfo.isTablet) {
91
+ return await RNDeviceInfo.isTablet();
92
+ }
93
+ if (ExpoDevice) {
94
+ return ExpoDevice.deviceType === 2; // Expo DeviceType.TABLET === 2
95
+ }
96
+ return false;
62
97
  }
63
98
  catch (error) {
64
99
  return false;
@@ -66,7 +101,13 @@ export class DeviceInfoNative {
66
101
  }
67
102
  async getAppVersion() {
68
103
  try {
69
- return RNDeviceInfo && RNDeviceInfo.getVersion ? await RNDeviceInfo.getVersion() : "1.0.0";
104
+ if (RNDeviceInfo && RNDeviceInfo.getVersion) {
105
+ return await RNDeviceInfo.getVersion();
106
+ }
107
+ if (ExpoApplication && ExpoApplication.nativeApplicationVersion) {
108
+ return ExpoApplication.nativeApplicationVersion;
109
+ }
110
+ return "1.0.0";
70
111
  }
71
112
  catch (error) {
72
113
  return "1.0.0";
@@ -74,7 +115,13 @@ export class DeviceInfoNative {
74
115
  }
75
116
  async getBuildNumber() {
76
117
  try {
77
- return RNDeviceInfo && RNDeviceInfo.getBuildNumber ? await RNDeviceInfo.getBuildNumber() : "1";
118
+ if (RNDeviceInfo && RNDeviceInfo.getBuildNumber) {
119
+ return await RNDeviceInfo.getBuildNumber();
120
+ }
121
+ if (ExpoApplication && ExpoApplication.nativeBuildVersion) {
122
+ return String(ExpoApplication.nativeBuildVersion);
123
+ }
124
+ return "1";
78
125
  }
79
126
  catch (error) {
80
127
  return "1";
@@ -41,11 +41,20 @@ export interface IFileSystem {
41
41
  }
42
42
  /**
43
43
  * FileSystem class
44
- * Handles file system operations for React Native
45
- * - iOS/Android/Windows: Uses react-native-fs
46
- * - Web: Limited functionality (not supported)
44
+ * Handles file system operations for React Native & Expo
45
+ * - iOS/Android CLI: Uses react-native-fs
46
+ * - Expo: Uses expo-file-system
47
+ * - Web: Limited functionality
47
48
  */
48
49
  export declare class FileSystem {
50
+ /**
51
+ * Manually override the active file system adapter
52
+ */
53
+ static setFileSystemAdapter(adapter: IFileSystem): void;
54
+ /**
55
+ * Get the currently active file system adapter
56
+ */
57
+ static getFileSystemAdapter(): IFileSystem;
49
58
  /**
50
59
  * Get document directory path
51
60
  */
@@ -1,15 +1,42 @@
1
1
  import { Platform } from 'react-native';
2
2
  import { FileSystemNative } from './services/FileSystemNative';
3
+ import { FileSystemExpo } from './services/FileSystemExpo';
3
4
  import { FileSystemWeb } from './services/FileSystemWeb';
4
- // Select file system implementation based on platform
5
- const fsImpl = Platform.OS === 'web' ? new FileSystemWeb() : new FileSystemNative();
5
+ function resolveFileSystemImpl() {
6
+ if (Platform.OS === 'web') {
7
+ return new FileSystemWeb();
8
+ }
9
+ if (FileSystemNative.isAvailable()) {
10
+ return new FileSystemNative();
11
+ }
12
+ if (FileSystemExpo.isAvailable()) {
13
+ return new FileSystemExpo();
14
+ }
15
+ // Default fallback
16
+ return new FileSystemExpo();
17
+ }
18
+ // Select file system implementation based on platform and available modules
19
+ let fsImpl = resolveFileSystemImpl();
6
20
  /**
7
21
  * FileSystem class
8
- * Handles file system operations for React Native
9
- * - iOS/Android/Windows: Uses react-native-fs
10
- * - Web: Limited functionality (not supported)
22
+ * Handles file system operations for React Native & Expo
23
+ * - iOS/Android CLI: Uses react-native-fs
24
+ * - Expo: Uses expo-file-system
25
+ * - Web: Limited functionality
11
26
  */
12
27
  export class FileSystem {
28
+ /**
29
+ * Manually override the active file system adapter
30
+ */
31
+ static setFileSystemAdapter(adapter) {
32
+ fsImpl = adapter;
33
+ }
34
+ /**
35
+ * Get the currently active file system adapter
36
+ */
37
+ static getFileSystemAdapter() {
38
+ return fsImpl;
39
+ }
13
40
  /**
14
41
  * Get document directory path
15
42
  */
@@ -33,7 +60,8 @@ export class FileSystem {
33
60
  */
34
61
  static async getFolderBasedOnUserId(userId) {
35
62
  try {
36
- return await fsImpl.getFolderBasedOnUserId(userId);
63
+ const folder = await fsImpl.getFolderBasedOnUserId(userId);
64
+ return folder.endsWith('/') ? folder : `${folder}/`;
37
65
  }
38
66
  catch (error) {
39
67
  console.error('Error getting user folder:', error);
@@ -1,3 +1,6 @@
1
1
  export { FileSystem } from './FileSystem';
2
- export type { IFileEntry, IDirectoryReader } from './FileSystem';
2
+ export { FileSystemNative } from './services/FileSystemNative';
3
+ export { FileSystemExpo } from './services/FileSystemExpo';
4
+ export { FileSystemWeb } from './services/FileSystemWeb';
5
+ export type { IFileEntry, IDirectoryReader, IFileSystem, FileSystemEncoding } from './FileSystem';
3
6
  export { default } from './FileSystem';
@@ -1,3 +1,6 @@
1
1
  // File System module exports
2
2
  export { FileSystem } from './FileSystem';
3
+ export { FileSystemNative } from './services/FileSystemNative';
4
+ export { FileSystemExpo } from './services/FileSystemExpo';
5
+ export { FileSystemWeb } from './services/FileSystemWeb';
3
6
  export { default } from './FileSystem';
@@ -0,0 +1,22 @@
1
+ import type { IFileEntry, IFileSystem, FileSystemEncoding } from '../FileSystem';
2
+ /**
3
+ * FileSystem implementation for Expo using expo-file-system
4
+ */
5
+ export declare class FileSystemExpo implements IFileSystem {
6
+ static isAvailable(): boolean;
7
+ private normalizeEncoding;
8
+ private getDocDir;
9
+ getDocumentDirectory(): string;
10
+ resolveLocalFileSystemURL(url: string): Promise<IFileEntry>;
11
+ getFolderBasedOnUserId(userId: string): Promise<string>;
12
+ deleteUserFolder(userId: string): Promise<void>;
13
+ createDirectory(path: string): Promise<void>;
14
+ readFile(path: string, encoding?: FileSystemEncoding): Promise<string>;
15
+ writeFile(path: string, content: string, encoding?: FileSystemEncoding): Promise<void>;
16
+ deleteFile(path: string): Promise<void>;
17
+ exists(path: string): Promise<boolean>;
18
+ stat(path: string): Promise<any>;
19
+ readDir(path: string): Promise<any[]>;
20
+ copyFile(source: string, destination: string): Promise<void>;
21
+ moveFile(source: string, destination: string): Promise<void>;
22
+ }