@unvired/react-native-unvired-sdk 0.0.15 → 0.0.20

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.0015
1
+ R-0.000.0020
package/README.md CHANGED
@@ -116,7 +116,7 @@ npm install @unvired/react-native-unvired-sdk
116
116
  ### Install Peer Dependencies
117
117
 
118
118
  ```bash
119
- npm install react-native-device-info @dr.pogodin/react-native-fs react-native-sqlite-storage @react-native-async-storage/async-storage
119
+ npm install react-native-device-info react-native-fs @op-engineering/op-sqlite @react-native-async-storage/async-storage react-native-zip-archive
120
120
  ```
121
121
 
122
122
  ### Optional: Push Notifications
@@ -1,7 +1,7 @@
1
1
  import { IDatabaseAdapter } from './types';
2
2
  /**
3
3
  * DatabaseManager - Manages database operations across platforms
4
- * - iOS/Android/Windows: Uses react-native-sqlite-storage
4
+ * - iOS/Android/Windows: Uses @op-engineering/op-sqlite
5
5
  * - Web: Uses WebSQL
6
6
  */
7
7
  export declare class DatabaseManager {
@@ -5,7 +5,7 @@ import { DatabaseWeb } from './services/DatabaseWeb';
5
5
  const dbImpl = Platform.OS === 'web' ? new DatabaseWeb() : new DatabaseNative();
6
6
  /**
7
7
  * DatabaseManager - Manages database operations across platforms
8
- * - iOS/Android/Windows: Uses react-native-sqlite-storage
8
+ * - iOS/Android/Windows: Uses @op-engineering/op-sqlite
9
9
  * - Web: Uses WebSQL
10
10
  */
11
11
  export class DatabaseManager {
@@ -3,6 +3,5 @@ export declare class DatabaseNative {
3
3
  private databases;
4
4
  private defaultLocation;
5
5
  private getDatabase;
6
- private resultSetToArray;
7
6
  getAdapter(): IDatabaseAdapter;
8
7
  }
@@ -1,33 +1,27 @@
1
- import SQLite from "react-native-sqlite-storage";
2
- SQLite.enablePromise(true);
3
- SQLite.DEBUG(false);
1
+ import { open } from '@op-engineering/op-sqlite';
4
2
  export class DatabaseNative {
5
3
  constructor() {
6
4
  this.databases = new Map();
7
5
  this.defaultLocation = "default";
8
6
  }
9
- async getDatabase(name, location) {
7
+ getDatabase(name, location) {
10
8
  const dbKey = `${name}_${location || this.defaultLocation}`;
11
9
  if (this.databases.has(dbKey)) {
12
10
  return this.databases.get(dbKey);
13
11
  }
14
- const dbLocation = (location || this.defaultLocation);
15
- const db = await SQLite.openDatabase({ name, location: dbLocation });
12
+ // @op-engineering/op-sqlite open function
13
+ // We treat location as mainly advisory since op-sqlite defaults to valid paths.
14
+ // If strict paths are needed, we would need to construct absolute path using FS.
15
+ // For now, we rely on the name.
16
+ const db = open({ name });
16
17
  this.databases.set(dbKey, db);
17
18
  return db;
18
19
  }
19
- resultSetToArray(resultSet) {
20
- const results = [];
21
- for (let i = 0; i < resultSet.rows.length; i++) {
22
- results.push(resultSet.rows.item(i));
23
- }
24
- return results;
25
- }
26
20
  getAdapter() {
27
21
  return {
28
22
  create: async (options, successCallback, errorCallback) => {
29
23
  try {
30
- await this.getDatabase(options.name, options.location);
24
+ this.getDatabase(options.name, options.location);
31
25
  successCallback({ success: true, database: options.name });
32
26
  }
33
27
  catch (error) {
@@ -35,61 +29,43 @@ export class DatabaseNative {
35
29
  }
36
30
  },
37
31
  execute: async (options, successCallback, errorCallback) => {
32
+ var _a;
38
33
  try {
39
- const db = await this.getDatabase(options.dbName);
40
- const results = await new Promise((resolve, reject) => {
41
- db.transaction((tx) => {
42
- tx.executeSql(options.query, options.params || [], (_, resultSet) => {
43
- resolve(this.resultSetToArray(resultSet));
44
- }, (_, error) => {
45
- reject(error);
46
- return false;
47
- });
48
- });
49
- });
50
- successCallback(results);
34
+ const db = this.getDatabase(options.dbName);
35
+ const res = db.execute(options.query, options.params);
36
+ // op-sqlite v15+ returns rows as an array natively in most configurations
37
+ // Check for _array for backward compatibility with some bridges or older habits
38
+ // @ts-ignore
39
+ const rows = ((_a = res.rows) === null || _a === void 0 ? void 0 : _a._array) || res.rows || [];
40
+ successCallback(rows);
51
41
  }
52
42
  catch (error) {
53
43
  errorCallback(error instanceof Error ? error.message : String(error));
54
44
  }
55
45
  },
56
46
  executeStatementOnPath: async (dbPath, sqlQuery, callback) => {
57
- var _a;
47
+ var _a, _b;
58
48
  try {
59
49
  const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
60
- const db = await this.getDatabase(dbName);
61
- const results = await new Promise((resolve) => {
62
- db.transaction((tx) => {
63
- tx.executeSql(sqlQuery, [], (_, resultSet) => {
64
- resolve(this.resultSetToArray(resultSet));
65
- }, () => {
66
- resolve([]);
67
- return false;
68
- });
69
- });
70
- });
71
- callback(results);
50
+ const db = this.getDatabase(dbName);
51
+ const res = db.execute(sqlQuery);
52
+ // @ts-ignore
53
+ const rows = ((_b = res.rows) === null || _b === void 0 ? void 0 : _b._array) || res.rows || [];
54
+ callback(rows);
72
55
  }
73
56
  catch (error) {
74
57
  callback([]);
75
58
  }
76
59
  },
77
60
  selectFromPath: async (dbPath, sqlQuery, callback) => {
78
- var _a;
61
+ var _a, _b;
79
62
  try {
80
63
  const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
81
- const db = await this.getDatabase(dbName);
82
- const results = await new Promise((resolve) => {
83
- db.readTransaction((tx) => {
84
- tx.executeSql(sqlQuery, [], (_, resultSet) => {
85
- resolve(this.resultSetToArray(resultSet));
86
- }, () => {
87
- resolve([]);
88
- return false;
89
- });
90
- });
91
- });
92
- callback(results);
64
+ const db = this.getDatabase(dbName);
65
+ const res = db.execute(sqlQuery);
66
+ // @ts-ignore
67
+ const rows = ((_b = res.rows) === null || _b === void 0 ? void 0 : _b._array) || res.rows || [];
68
+ callback(rows);
93
69
  }
94
70
  catch (error) {
95
71
  callback([]);
@@ -99,7 +75,7 @@ export class DatabaseNative {
99
75
  var _a;
100
76
  try {
101
77
  const dbName = ((_a = dbPath.split("/").pop()) === null || _a === void 0 ? void 0 : _a.replace(".db", "")) || "default";
102
- await this.getDatabase(dbName);
78
+ this.getDatabase(dbName);
103
79
  callback();
104
80
  }
105
81
  catch (error) {
@@ -125,19 +101,12 @@ export class DatabaseNative {
125
101
  },
126
102
  deleteUserData: async (options, callback, errorCallback) => {
127
103
  try {
128
- const db = await this.getDatabase(options.dbName);
129
- await new Promise((resolve, reject) => {
130
- db.transaction((tx) => {
131
- const query = options.userId
132
- ? "DELETE FROM user_data WHERE user_id = ?"
133
- : "DELETE FROM user_data";
134
- const params = options.userId ? [options.userId] : [];
135
- tx.executeSql(query, params, () => resolve(), (_, error) => {
136
- reject(error);
137
- return false;
138
- });
139
- });
140
- });
104
+ const db = this.getDatabase(options.dbName);
105
+ const query = options.userId
106
+ ? "DELETE FROM user_data WHERE user_id = ?"
107
+ : "DELETE FROM user_data";
108
+ const params = options.userId ? [options.userId] : [];
109
+ db.execute(query, params);
141
110
  callback();
142
111
  }
143
112
  catch (error) {
@@ -2,7 +2,7 @@ import { IFileEntry, FileSystemEncoding } from './FileSystem.types';
2
2
  /**
3
3
  * FileSystem class
4
4
  * Handles file system operations for React Native
5
- * - iOS/Android/Windows: Uses @dr.pogodin/react-native-fs
5
+ * - iOS/Android/Windows: Uses react-native-fs
6
6
  * - Web: Limited functionality (not supported)
7
7
  */
8
8
  export declare class FileSystem {
@@ -6,7 +6,7 @@ const fsImpl = Platform.OS === 'web' ? new FileSystemWeb() : new FileSystemNativ
6
6
  /**
7
7
  * FileSystem class
8
8
  * Handles file system operations for React Native
9
- * - iOS/Android/Windows: Uses @dr.pogodin/react-native-fs
9
+ * - iOS/Android/Windows: Uses react-native-fs
10
10
  * - Web: Limited functionality (not supported)
11
11
  */
12
12
  export class FileSystem {
@@ -1,4 +1,17 @@
1
1
  import { IFileEntry, IDirectoryReader } from './FileSystem.types';
2
+ /**
3
+ * DirectoryReader implementation for React Native
4
+ * Wraps RNFS.readDir to match the Cordova DirectoryReader interface
5
+ */
6
+ export declare class RNDirectoryReader implements IDirectoryReader {
7
+ private dirPath;
8
+ constructor(dirPath: string);
9
+ readEntries(callback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
10
+ }
11
+ /**
12
+ * FileEntry implementation for React Native
13
+ * Wraps react-native-fs to match the Cordova FileEntry interface
14
+ */
2
15
  export declare class RNFileEntry implements IFileEntry {
3
16
  isFile: boolean;
4
17
  isDirectory: boolean;
@@ -6,21 +19,37 @@ export declare class RNFileEntry implements IFileEntry {
6
19
  fullPath: string;
7
20
  nativeURL: string;
8
21
  filesystem: any;
9
- constructor(isFile: boolean, isDirectory: boolean, name: string, fullPath: string, nativeURL: string, filesystem?: any);
10
- remove(successCallback: () => void, errorCallback: (error: any) => void): void;
11
- removeRecursively(successCallback: () => void, errorCallback: (error: any) => void): void;
22
+ constructor(path: string, isDirectory?: boolean);
23
+ /**
24
+ * Remove a file or empty directory
25
+ */
26
+ remove(callback: () => void, errorCallback: (error: any) => void): void;
27
+ /**
28
+ * Remove a directory and all its contents recursively
29
+ */
30
+ removeRecursively(callback: () => void, errorCallback: (error: any) => void): void;
31
+ /**
32
+ * Create a directory reader for reading directory contents
33
+ */
12
34
  createReader(): IDirectoryReader;
35
+ /**
36
+ * Get or create a subdirectory
37
+ */
13
38
  getDirectory(path: string, options: {
14
39
  create: boolean;
15
- }, successCallback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
40
+ }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
41
+ /**
42
+ * Get or create a file
43
+ */
16
44
  getFile(path: string, options: {
17
45
  create: boolean;
18
- }, successCallback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
46
+ }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
47
+ /**
48
+ * Get file metadata
49
+ */
19
50
  file(callback: (file: any) => void, errorCallback: (error: any) => void): void;
51
+ /**
52
+ * Create a file writer for writing to the file
53
+ */
20
54
  createWriter(callback: (writer: any) => void, errorCallback: (error: any) => void): void;
21
55
  }
22
- export declare class RNDirectoryReader implements IDirectoryReader {
23
- private localPath;
24
- constructor(localPath: string);
25
- readEntries(successCallback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
26
- }
@@ -1,114 +1,179 @@
1
- import * as RNFS from '@dr.pogodin/react-native-fs';
1
+ import * as RNFS from 'react-native-fs';
2
+ /**
3
+ * DirectoryReader implementation for React Native
4
+ * Wraps RNFS.readDir to match the Cordova DirectoryReader interface
5
+ */
6
+ export class RNDirectoryReader {
7
+ constructor(dirPath) {
8
+ this.dirPath = dirPath;
9
+ }
10
+ readEntries(callback, errorCallback) {
11
+ RNFS.readDir(this.dirPath)
12
+ .then(items => {
13
+ const entries = items.map(item => new RNFileEntry(item.path, item.isDirectory()));
14
+ callback(entries);
15
+ })
16
+ .catch(errorCallback);
17
+ }
18
+ }
19
+ /**
20
+ * FileEntry implementation for React Native
21
+ * Wraps react-native-fs to match the Cordova FileEntry interface
22
+ */
2
23
  export class RNFileEntry {
3
- constructor(isFile, isDirectory, name, fullPath, nativeURL, filesystem = null) {
4
- this.isFile = isFile;
24
+ constructor(path, isDirectory = false) {
25
+ this.fullPath = path;
26
+ this.nativeURL = `file://${path}`;
5
27
  this.isDirectory = isDirectory;
6
- this.name = name;
7
- this.fullPath = fullPath;
8
- this.nativeURL = nativeURL;
9
- this.filesystem = filesystem;
28
+ this.isFile = !isDirectory;
29
+ this.name = path.split('/').pop() || '';
30
+ this.filesystem = null;
10
31
  }
11
- remove(successCallback, errorCallback) {
32
+ /**
33
+ * Remove a file or empty directory
34
+ */
35
+ remove(callback, errorCallback) {
12
36
  RNFS.unlink(this.fullPath)
13
- .then(() => successCallback())
14
- .catch((err) => errorCallback(err));
37
+ .then(() => callback())
38
+ .catch(errorCallback);
15
39
  }
16
- removeRecursively(successCallback, errorCallback) {
17
- this.remove(successCallback, errorCallback);
40
+ /**
41
+ * Remove a directory and all its contents recursively
42
+ */
43
+ removeRecursively(callback, errorCallback) {
44
+ // RNFS.unlink works recursively for directories
45
+ RNFS.unlink(this.fullPath)
46
+ .then(() => callback())
47
+ .catch(errorCallback);
18
48
  }
49
+ /**
50
+ * Create a directory reader for reading directory contents
51
+ */
19
52
  createReader() {
20
53
  return new RNDirectoryReader(this.fullPath);
21
54
  }
22
- getDirectory(path, options, successCallback, errorCallback) {
23
- const newPath = this.fullPath + (this.fullPath.endsWith('/') ? '' : '/') + path;
24
- const newNativeURL = "file://" + newPath;
25
- if (options.create) {
26
- RNFS.mkdir(newPath).then(() => {
27
- successCallback(new RNFileEntry(false, true, path, newPath, newNativeURL));
28
- }).catch(errorCallback);
29
- }
30
- else {
31
- RNFS.stat(newPath).then(stat => {
32
- if (stat.isDirectory()) {
33
- successCallback(new RNFileEntry(false, true, path, newPath, newNativeURL));
34
- }
35
- else {
36
- errorCallback("Not a directory");
37
- }
38
- }).catch(errorCallback);
39
- }
55
+ /**
56
+ * Get or create a subdirectory
57
+ */
58
+ getDirectory(path, options, callback, errorCallback) {
59
+ const dirPath = `${this.fullPath}/${path}`;
60
+ RNFS.exists(dirPath)
61
+ .then(exists => {
62
+ if (exists) {
63
+ return RNFS.stat(dirPath).then(stats => {
64
+ if (stats.isDirectory()) {
65
+ callback(new RNFileEntry(dirPath, true));
66
+ }
67
+ else {
68
+ errorCallback(new Error('Path exists but is not a directory'));
69
+ }
70
+ });
71
+ }
72
+ else if (options.create) {
73
+ return RNFS.mkdir(dirPath).then(() => {
74
+ callback(new RNFileEntry(dirPath, true));
75
+ });
76
+ }
77
+ else {
78
+ errorCallback(new Error('Directory does not exist'));
79
+ }
80
+ })
81
+ .catch(errorCallback);
40
82
  }
41
- getFile(path, options, successCallback, errorCallback) {
42
- const newPath = this.fullPath + (this.fullPath.endsWith('/') ? '' : '/') + path;
43
- const newNativeURL = "file://" + newPath;
44
- if (options.create) {
45
- RNFS.exists(newPath).then(exists => {
46
- if (exists) {
47
- successCallback(new RNFileEntry(true, false, path, newPath, newNativeURL));
48
- }
49
- else {
50
- RNFS.writeFile(newPath, '', 'utf8').then(() => {
51
- successCallback(new RNFileEntry(true, false, path, newPath, newNativeURL));
52
- }).catch(errorCallback);
53
- }
54
- }).catch(errorCallback);
55
- }
56
- else {
57
- RNFS.stat(newPath).then(stat => {
58
- if (stat.isFile()) {
59
- successCallback(new RNFileEntry(true, false, path, newPath, newNativeURL));
60
- }
61
- else {
62
- errorCallback("Not a file");
63
- }
64
- }).catch(errorCallback);
65
- }
83
+ /**
84
+ * Get or create a file
85
+ */
86
+ getFile(path, options, callback, errorCallback) {
87
+ const filePath = `${this.fullPath}/${path}`;
88
+ RNFS.exists(filePath)
89
+ .then(exists => {
90
+ if (exists) {
91
+ return RNFS.stat(filePath).then(stats => {
92
+ if (!stats.isDirectory()) {
93
+ callback(new RNFileEntry(filePath, false));
94
+ }
95
+ else {
96
+ errorCallback(new Error('Path exists but is a directory'));
97
+ }
98
+ });
99
+ }
100
+ else if (options.create) {
101
+ // Create empty file
102
+ return RNFS.writeFile(filePath, '', 'utf8').then(() => {
103
+ callback(new RNFileEntry(filePath, false));
104
+ });
105
+ }
106
+ else {
107
+ errorCallback(new Error('File does not exist'));
108
+ }
109
+ })
110
+ .catch(errorCallback);
66
111
  }
112
+ /**
113
+ * Get file metadata
114
+ */
67
115
  file(callback, errorCallback) {
68
- RNFS.stat(this.fullPath).then(stat => {
69
- const file = {
70
- name: stat.name,
71
- localURL: "file://" + stat.path,
72
- type: "",
73
- lastModified: stat.mtime ? new Date(stat.mtime).getTime() : 0,
74
- lastModifiedDate: stat.mtime,
75
- size: stat.size,
76
- start: 0,
77
- end: stat.size,
78
- slice: () => { }
116
+ RNFS.stat(this.fullPath)
117
+ .then(stats => {
118
+ // Create a File-like object with metadata
119
+ const fileObject = {
120
+ name: this.fullPath.split('/').pop() || '',
121
+ size: stats.size,
122
+ type: '', // RNFS doesn't provide MIME type directly
123
+ lastModified: new Date(stats.mtime).getTime(),
124
+ lastModifiedDate: new Date(stats.mtime),
125
+ path: this.fullPath,
79
126
  };
80
- callback(file);
81
- }).catch(errorCallback);
127
+ callback(fileObject);
128
+ })
129
+ .catch(errorCallback);
82
130
  }
131
+ /**
132
+ * Create a file writer for writing to the file
133
+ */
83
134
  createWriter(callback, errorCallback) {
135
+ // Create a FileWriter-like object
84
136
  const writer = {
137
+ filePath: this.fullPath,
85
138
  write: (data) => {
86
- RNFS.writeFile(this.fullPath, data, 'utf8')
139
+ return RNFS.writeFile(this.fullPath, data, 'utf8')
87
140
  .then(() => { if (writer.onwriteend)
88
141
  writer.onwriteend(); })
89
142
  .catch((err) => { if (writer.onerror)
90
143
  writer.onerror(err); });
91
144
  },
92
- seek: () => { },
93
- truncate: () => { },
145
+ append: (data) => {
146
+ return RNFS.appendFile(this.fullPath, data, 'utf8')
147
+ .then(() => { if (writer.onwriteend)
148
+ writer.onwriteend(); })
149
+ .catch((err) => { if (writer.onerror)
150
+ writer.onerror(err); });
151
+ },
152
+ truncate: (size) => {
153
+ // Read file, truncate content, and write back
154
+ return RNFS.readFile(this.fullPath, 'utf8')
155
+ .then(content => {
156
+ const truncated = content.substring(0, size);
157
+ return RNFS.writeFile(this.fullPath, truncated, 'utf8')
158
+ .then(() => { if (writer.onwriteend)
159
+ writer.onwriteend(); });
160
+ })
161
+ .catch((err) => { if (writer.onerror)
162
+ writer.onerror(err); });
163
+ },
164
+ seek: (offset) => {
165
+ // Not directly supported in RNFS
166
+ // This would need to be implemented with read/write operations
167
+ return Promise.resolve();
168
+ },
94
169
  onwriteend: null,
95
170
  onerror: null
96
171
  };
97
- callback(writer);
98
- }
99
- }
100
- export class RNDirectoryReader {
101
- constructor(localPath) {
102
- this.localPath = localPath;
103
- }
104
- readEntries(successCallback, errorCallback) {
105
- RNFS.readDir(this.localPath)
106
- .then((result) => {
107
- const entries = result.map(fileStat => {
108
- return new RNFileEntry(fileStat.isFile(), fileStat.isDirectory(), fileStat.name || fileStat.path.split('/').pop() || '', fileStat.path, "file://" + fileStat.path);
109
- });
110
- successCallback(entries);
111
- })
112
- .catch((err) => errorCallback(err));
172
+ try {
173
+ callback(writer);
174
+ }
175
+ catch (error) {
176
+ errorCallback(error);
177
+ }
113
178
  }
114
179
  }
@@ -1,4 +1,4 @@
1
- import * as RNFS from '@dr.pogodin/react-native-fs';
1
+ import * as RNFS from 'react-native-fs';
2
2
  import { IFileEntry, IFileSystem, FileSystemEncoding } from '../FileSystem.types';
3
3
  export declare class FileSystemNative implements IFileSystem {
4
4
  getDocumentDirectory(): string;
@@ -10,8 +10,8 @@ export declare class FileSystemNative implements IFileSystem {
10
10
  writeFile(path: string, content: string, encoding?: FileSystemEncoding): Promise<void>;
11
11
  deleteFile(path: string): Promise<void>;
12
12
  exists(path: string): Promise<boolean>;
13
- stat(path: string): Promise<RNFS.StatResultT>;
14
- readDir(path: string): Promise<RNFS.ReadDirResItemT[]>;
13
+ stat(path: string): Promise<RNFS.StatResult>;
14
+ readDir(path: string): Promise<RNFS.ReadDirItem[]>;
15
15
  copyFile(source: string, destination: string): Promise<void>;
16
16
  moveFile(source: string, destination: string): Promise<void>;
17
17
  }
@@ -1,35 +1,52 @@
1
- import * as RNFS from '@dr.pogodin/react-native-fs';
1
+ import * as RNFS from 'react-native-fs';
2
2
  import { RNFileEntry } from '../RNFileEntry';
3
3
  export class FileSystemNative {
4
4
  getDocumentDirectory() {
5
5
  return RNFS.DocumentDirectoryPath;
6
6
  }
7
7
  async resolveLocalFileSystemURL(url) {
8
- let normalizedPath = url;
9
- if (normalizedPath.startsWith('file://')) {
10
- normalizedPath = normalizedPath.substring(7);
11
- }
12
- const exists = await RNFS.exists(normalizedPath);
13
- if (!exists) {
14
- throw new Error(`File or directory does not exist: ${normalizedPath}`);
15
- }
16
- const stat = await RNFS.stat(normalizedPath);
17
- const fileName = stat.name || normalizedPath.split('/').pop() || 'unknown';
18
- return new RNFileEntry(stat.isFile(), stat.isDirectory(), fileName, stat.path, `file://${stat.path}`);
8
+ return new Promise((resolve, reject) => {
9
+ // Remove file:// prefix if present
10
+ const path = url.replace('file://', '');
11
+ RNFS.exists(path)
12
+ .then(exists => {
13
+ if (!exists) {
14
+ reject(new Error(`Path does not exist: ${path}`));
15
+ return;
16
+ }
17
+ return RNFS.stat(path).then(stats => {
18
+ resolve(new RNFileEntry(path, stats.isDirectory()));
19
+ });
20
+ })
21
+ .catch(reject);
22
+ });
19
23
  }
20
24
  async getFolderBasedOnUserId(userId) {
21
- const userFolder = `${RNFS.DocumentDirectoryPath}/users/${userId}`;
22
- const exists = await RNFS.exists(userFolder);
23
- if (!exists) {
24
- await RNFS.mkdir(userFolder, { NSURLIsExcludedFromBackupKey: true });
25
+ const userPath = `${RNFS.DocumentDirectoryPath}/${userId}`;
26
+ try {
27
+ const exists = await RNFS.exists(userPath);
28
+ if (!exists) {
29
+ // Create the directory if it doesn't exist
30
+ await RNFS.mkdir(userPath);
31
+ }
32
+ // Return the native URL format
33
+ return `file://${userPath}`;
34
+ }
35
+ catch (error) {
36
+ throw new Error(`Failed to get/create folder for user ${userId}: ${error}`);
25
37
  }
26
- return userFolder;
27
38
  }
28
39
  async deleteUserFolder(userId) {
29
- const userFolder = `${RNFS.DocumentDirectoryPath}/users/${userId}`;
30
- const exists = await RNFS.exists(userFolder);
31
- if (exists) {
32
- await RNFS.unlink(userFolder);
40
+ const userPath = `${RNFS.DocumentDirectoryPath}/${userId}`;
41
+ try {
42
+ const exists = await RNFS.exists(userPath);
43
+ if (exists) {
44
+ // RNFS.unlink removes directories recursively
45
+ await RNFS.unlink(userPath);
46
+ }
47
+ }
48
+ catch (error) {
49
+ throw new Error(`Failed to delete folder for user ${userId}: ${error}`);
33
50
  }
34
51
  }
35
52
  async createDirectory(path) {
@@ -4,14 +4,14 @@ import { Platform } from 'react-native';
4
4
  let RNFS = null;
5
5
  let zip = null;
6
6
  try {
7
- RNFS = require('@dr.pogodin/react-native-fs');
7
+ RNFS = require('react-native-fs');
8
8
  if (!RNFS || !RNFS.DocumentDirectoryPath) {
9
- console.error('❌ @dr.pogodin/react-native-fs is not properly linked. Please run: cd ios && pod install (iOS) or rebuild your Android app.');
9
+ console.error('❌ react-native-fs is not properly linked. Please run: cd ios && pod install (iOS) or rebuild your Android app.');
10
10
  RNFS = null;
11
11
  }
12
12
  }
13
13
  catch (e) {
14
- console.error('❌ @dr.pogodin/react-native-fs module not found. Please install: npm install @dr.pogodin/react-native-fs');
14
+ console.error('❌ react-native-fs module not found. Please install: npm install react-native-fs');
15
15
  }
16
16
  try {
17
17
  const zipModule = require('react-native-zip-archive');
@@ -2,14 +2,14 @@ import * as pako from 'pako';
2
2
  // Import with null safety
3
3
  let RNFS = null;
4
4
  try {
5
- RNFS = require('@dr.pogodin/react-native-fs');
5
+ RNFS = require('react-native-fs');
6
6
  if (!RNFS || !RNFS.DocumentDirectoryPath) {
7
- console.error('❌ @dr.pogodin/react-native-fs is not properly linked.');
7
+ console.error('❌ react-native-fs is not properly linked.');
8
8
  RNFS = null;
9
9
  }
10
10
  }
11
11
  catch (e) {
12
- console.error('❌ @dr.pogodin/react-native-fs module not found.');
12
+ console.error('❌ react-native-fs module not found.');
13
13
  }
14
14
  export class LoggerWindows {
15
15
  constructor() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unvired/react-native-unvired-sdk",
3
- "version": "0.0.15",
3
+ "version": "0.0.20",
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",
@@ -24,32 +24,64 @@
24
24
  "author": "Unvired",
25
25
  "license": "UNLICENSED",
26
26
  "peerDependencies": {
27
- "@dr.pogodin/react-native-fs": "^2.36.2",
27
+ "react": "19.2.0",
28
+ "react-native": "0.83.1",
29
+ "react-native-fs": "^2.20.0",
30
+ "react-native-device-info": "^15.0.1",
31
+ "@op-engineering/op-sqlite": "^15.2.5",
32
+ "react-native-zip-archive": "^7.0.2",
28
33
  "@react-native-firebase/messaging": "^21.8.1",
29
- "react": ">=16.8.0",
30
- "react-native": ">=0.60.0",
31
- "react-native-device-info": "^14.1.1",
32
- "react-native-sqlite-storage": "^6.0.1",
33
- "react-native-zip-archive": "^7.0.2"
34
+ "@react-native-async-storage/async-storage": "^2.2.0"
34
35
  },
35
36
  "peerDependenciesMeta": {
36
37
  "@react-native-firebase/messaging": {
37
38
  "optional": true
39
+ },
40
+ "@op-engineering/op-sqlite": {
41
+ "optional": true
42
+ },
43
+ "react-native-zip-archive": {
44
+ "optional": true
45
+ },
46
+ "@react-native-async-storage/async-storage": {
47
+ "optional": true
48
+ },
49
+ "react-native-device-info": {
50
+ "optional": true
51
+ },
52
+ "react-native-fs": {
53
+ "optional": true
54
+ },
55
+ "react": {
56
+ "optional": true
57
+ },
58
+ "react-native": {
59
+ "optional": true
38
60
  }
39
61
  },
40
62
  "devDependencies": {
41
- "@types/react": "^18.0.0",
42
- "@types/react-native": "^0.72.0",
43
- "@types/react-native-sqlite-storage": "^6.0.5",
63
+ "@types/pako": "^2.0.4",
64
+ "@types/react": ">=19.0.0",
65
+ "@types/react-native": "^0.73.0",
44
66
  "@types/sql.js": "^1.4.9",
45
67
  "eslint": "^8.0.0",
46
68
  "jest": "^29.0.0",
47
69
  "prettier": "^3.0.0",
48
- "typescript": "^5.0.0"
70
+ "typescript": "^5.0.0",
71
+ "react": "19.2.0",
72
+ "react-native": "0.83.1",
73
+ "@react-native-firebase/app": "21.14.0"
74
+ },
75
+ "engines": {
76
+ "node": ">=22.0.0"
49
77
  },
50
78
  "dependencies": {
79
+ "react-native-fs": "^2.20.0",
80
+ "@op-engineering/op-sqlite": "^15.2.5",
81
+ "react-native-zip-archive": "^7.0.2",
51
82
  "@react-native-async-storage/async-storage": "^2.2.0",
52
- "@types/pako": "^2.0.4",
83
+ "react-native-device-info": "^15.0.1",
84
+ "@react-native-firebase/messaging": "^21.8.1",
53
85
  "pako": "^2.1.0",
54
86
  "sql.js": "^1.10.3"
55
87
  },
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Platform Adapter Interface
3
+ *
4
+ * This interface abstracts platform-specific functionality so that the core SDK
5
+ * can work with both Cordova and React Native platforms.
6
+ */
7
+
8
+ export enum DatabaseType {
9
+ FrameworkDb = 'FrameworkDb',
10
+ AppDb = 'AppDb'
11
+ }
12
+
13
+ export interface IDeviceInfo {
14
+ platform: string;
15
+ model: string;
16
+ version: string;
17
+ isMobile: boolean;
18
+ }
19
+
20
+ export interface IFileEntry {
21
+ fullPath: string;
22
+ nativeURL: string;
23
+ isDirectory?: boolean;
24
+ remove(callback: () => void, errorCallback: (error: any) => void): void;
25
+ removeRecursively(callback: () => void, errorCallback: (error: any) => void): void;
26
+ createReader(): IDirectoryReader;
27
+ getDirectory?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
28
+ getFile?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
29
+ file?(callback: (file: File) => void, errorCallback: (error: any) => void): void;
30
+ createWriter?(callback: (writer: any) => void, errorCallback: (error: any) => void): void;
31
+ }
32
+
33
+ export interface IDirectoryReader {
34
+ readEntries(callback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
35
+ }
36
+
37
+ export interface IDatabaseAdapter {
38
+ create(options: { userId: string }, successCallback: (result: any) => void, errorCallback: (error: any) => void): void;
39
+ execute(options: any, successCallback: (result: any) => void, errorCallback: (error: any) => void): void;
40
+ executeStatementOnPath(dbPath: string, sqlQuery: string, callback: (result: any) => void): void;
41
+ selectFromPath(dbPath: string, sqlQuery: string, callback: (result: any) => void): void;
42
+ createDatabase(dbPath: string, callback: () => void): void;
43
+ getDBFilePath(options: { dbType: string }, callback: (path: string) => void): void;
44
+ saveWebDB(options: { userId: string }, callback: (result: any) => void, errorCallback: (error: any) => void): void;
45
+ exportWebDB(options: { userId: string }, callback: (result: any) => void, errorCallback: (error: any) => void): void;
46
+ deleteUserData(options: { userId: string }, callback: () => void, errorCallback: (error: any) => void): void;
47
+ }
48
+
49
+ export interface IPushNotificationAdapter {
50
+ requestPermission(options?: { forceShow: boolean }): Promise<void>;
51
+ getToken(): Promise<string>;
52
+ onTokenRefresh(callback: (token: string) => void): void;
53
+ onMessage(callback: (payload: any) => void): void;
54
+ onBackgroundMessage(callback: (payload: any) => void): void;
55
+ }
56
+
57
+ export interface ILoggerAdapter {
58
+ logDebug(sourceClass: string, method: string, message: string): void;
59
+ logError(sourceClass: string, method: string, message: string): void;
60
+ logInfo(sourceClass: string, method: string, message: string): void;
61
+ setLogLevel(logLevel: string): void;
62
+ getLogFileURL(): Promise<string>;
63
+ getLogFileContent(): Promise<string>;
64
+ getBackupLogFileContent(): Promise<string>;
65
+ clearLogFile(): void;
66
+ }
67
+
68
+ export interface IStorageAdapter {
69
+ getItem(key: string): void;
70
+ setItem(key: string, value: string): void;
71
+ removeItem(key: string): void;
72
+ clear(): void;
73
+ }
74
+
75
+
76
+
77
+ export interface ILocalStorageAdapter {
78
+ getItem(key: string): void;
79
+ setItem(key: string, value: string): void;
80
+ removeItem(key: string): void;
81
+ clear(): void;
82
+ }
83
+ /**
84
+ * Main Platform Adapter Interface
85
+ */
86
+ export interface PlatformInterface {
87
+ // Device Information
88
+ getDeviceInfo(): Promise<IDeviceInfo>;
89
+ getPlatform(): string;
90
+ getFrontendType(): string;
91
+ getDocumentDirectory(): string;
92
+
93
+ // File System Operations
94
+ resolveLocalFileSystemURL(url: string): Promise<IFileEntry>;
95
+ getFolderBasedOnUserId(userId: string): Promise<string>;
96
+ deleteUserFolder(userId: string): Promise<void>;
97
+
98
+ // Database Operations
99
+ getDatabaseAdapter(): IDatabaseAdapter;
100
+
101
+ // Push Notifications
102
+ getPushNotificationAdapter(): IPushNotificationAdapter | null;
103
+
104
+ // Logging
105
+ getLoggerAdapter(): ILoggerAdapter;
106
+
107
+ // Storage
108
+ getStorageAdapter(): IStorageAdapter;
109
+ }
@@ -0,0 +1,208 @@
1
+ import RNFS from 'react-native-fs';
2
+ export interface IDirectoryReader {
3
+ readEntries(callback: (entries: IFileEntry[]) => void, errorCallback: (error: any) => void): void;
4
+ }
5
+
6
+ export interface IFileEntry {
7
+ fullPath: string;
8
+ nativeURL: string;
9
+ isDirectory?: boolean;
10
+ remove(callback: () => void, errorCallback: (error: any) => void): void;
11
+ removeRecursively(callback: () => void, errorCallback: (error: any) => void): void;
12
+ createReader(): IDirectoryReader;
13
+ getDirectory?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
14
+ getFile?(path: string, options: { create: boolean }, callback: (entry: IFileEntry) => void, errorCallback: (error: any) => void): void;
15
+ file?(callback: (file: File) => void, errorCallback: (error: any) => void): void;
16
+ createWriter?(callback: (writer: any) => void, errorCallback: (error: any) => void): void;
17
+ }
18
+ /**
19
+ * DirectoryReader implementation for React Native
20
+ * Wraps RNFS.readDir to match the Cordova DirectoryReader interface
21
+ */
22
+ export class ReactNativeDirectoryReader implements IDirectoryReader {
23
+ private dirPath: string;
24
+
25
+ constructor(dirPath: string) {
26
+ this.dirPath = dirPath;
27
+ }
28
+
29
+ readEntries(
30
+ callback: (entries: IFileEntry[]) => void,
31
+ errorCallback: (error: any) => void
32
+ ): void {
33
+ RNFS.readDir(this.dirPath)
34
+ .then(items => {
35
+ const entries = items.map(item =>
36
+ new ReactNativeFileEntry(item.path, item.isDirectory())
37
+ );
38
+ callback(entries);
39
+ })
40
+ .catch(errorCallback);
41
+ }
42
+ }
43
+
44
+ /**
45
+ * FileEntry implementation for React Native
46
+ * Wraps react-native-fs to match the Cordova FileEntry interface
47
+ */
48
+ export class ReactNativeFileEntry implements IFileEntry {
49
+ fullPath: string;
50
+ nativeURL: string;
51
+ isDirectory?: boolean;
52
+
53
+ constructor(path: string, isDirectory: boolean = false) {
54
+ this.fullPath = path;
55
+ this.nativeURL = `file://${path}`;
56
+ this.isDirectory = isDirectory;
57
+ }
58
+
59
+ /**
60
+ * Remove a file or empty directory
61
+ */
62
+ remove(callback: () => void, errorCallback: (error: any) => void): void {
63
+ RNFS.unlink(this.fullPath)
64
+ .then(() => callback())
65
+ .catch(errorCallback);
66
+ }
67
+
68
+ /**
69
+ * Remove a directory and all its contents recursively
70
+ */
71
+ removeRecursively(callback: () => void, errorCallback: (error: any) => void): void {
72
+ // RNFS.unlink works recursively for directories
73
+ RNFS.unlink(this.fullPath)
74
+ .then(() => callback())
75
+ .catch(errorCallback);
76
+ }
77
+
78
+ /**
79
+ * Create a directory reader for reading directory contents
80
+ */
81
+ createReader(): IDirectoryReader {
82
+ return new ReactNativeDirectoryReader(this.fullPath);
83
+ }
84
+
85
+ /**
86
+ * Get or create a subdirectory
87
+ */
88
+ getDirectory(
89
+ path: string,
90
+ options: { create: boolean },
91
+ callback: (entry: IFileEntry) => void,
92
+ errorCallback: (error: any) => void
93
+ ): void {
94
+ const dirPath = `${this.fullPath}/${path}`;
95
+
96
+ RNFS.exists(dirPath)
97
+ .then(exists => {
98
+ if (exists) {
99
+ return RNFS.stat(dirPath).then(stats => {
100
+ if (stats.isDirectory()) {
101
+ callback(new ReactNativeFileEntry(dirPath, true));
102
+ } else {
103
+ errorCallback(new Error('Path exists but is not a directory'));
104
+ }
105
+ });
106
+ } else if (options.create) {
107
+ return RNFS.mkdir(dirPath).then(() => {
108
+ callback(new ReactNativeFileEntry(dirPath, true));
109
+ });
110
+ } else {
111
+ errorCallback(new Error('Directory does not exist'));
112
+ }
113
+ })
114
+ .catch(errorCallback);
115
+ }
116
+
117
+ /**
118
+ * Get or create a file
119
+ */
120
+ getFile(
121
+ path: string,
122
+ options: { create: boolean },
123
+ callback: (entry: IFileEntry) => void,
124
+ errorCallback: (error: any) => void
125
+ ): void {
126
+ const filePath = `${this.fullPath}/${path}`;
127
+
128
+ RNFS.exists(filePath)
129
+ .then(exists => {
130
+ if (exists) {
131
+ return RNFS.stat(filePath).then(stats => {
132
+ if (!stats.isDirectory()) {
133
+ callback(new ReactNativeFileEntry(filePath, false));
134
+ } else {
135
+ errorCallback(new Error('Path exists but is a directory'));
136
+ }
137
+ });
138
+ } else if (options.create) {
139
+ // Create empty file
140
+ return RNFS.writeFile(filePath, '', 'utf8').then(() => {
141
+ callback(new ReactNativeFileEntry(filePath, false));
142
+ });
143
+ } else {
144
+ errorCallback(new Error('File does not exist'));
145
+ }
146
+ })
147
+ .catch(errorCallback);
148
+ }
149
+
150
+ /**
151
+ * Get file metadata
152
+ */
153
+ file(callback: (file: File) => void, errorCallback: (error: any) => void): void {
154
+ RNFS.stat(this.fullPath)
155
+ .then(stats => {
156
+ // Create a File-like object with metadata
157
+ const fileObject: any = {
158
+ name: this.fullPath.split('/').pop() || '',
159
+ size: stats.size,
160
+ type: '', // RNFS doesn't provide MIME type directly
161
+ lastModified: new Date(stats.mtime).getTime(),
162
+ lastModifiedDate: new Date(stats.mtime),
163
+ path: this.fullPath,
164
+ };
165
+ callback(fileObject as File);
166
+ })
167
+ .catch(errorCallback);
168
+ }
169
+
170
+ /**
171
+ * Create a file writer for writing to the file
172
+ */
173
+ createWriter(callback: (writer: any) => void, errorCallback: (error: any) => void): void {
174
+ // Create a FileWriter-like object
175
+ const writer = {
176
+ filePath: this.fullPath,
177
+
178
+ write: (data: string) => {
179
+ return RNFS.writeFile(this.fullPath, data, 'utf8');
180
+ },
181
+
182
+ append: (data: string) => {
183
+ return RNFS.appendFile(this.fullPath, data, 'utf8');
184
+ },
185
+
186
+ truncate: (size: number) => {
187
+ // Read file, truncate content, and write back
188
+ return RNFS.readFile(this.fullPath, 'utf8')
189
+ .then(content => {
190
+ const truncated = content.substring(0, size);
191
+ return RNFS.writeFile(this.fullPath, truncated, 'utf8');
192
+ });
193
+ },
194
+
195
+ seek: (offset: number) => {
196
+ // Not directly supported in RNFS
197
+ // This would need to be implemented with read/write operations
198
+ return Promise.resolve();
199
+ }
200
+ };
201
+
202
+ try {
203
+ callback(writer);
204
+ } catch (error) {
205
+ errorCallback(error);
206
+ }
207
+ }
208
+ }
@@ -1,5 +1,7 @@
1
1
  import { PlatformInterface, IDeviceInfo, IFileEntry, IDatabaseAdapter, IPushNotificationAdapter, ILoggerAdapter, DatabaseType } from './PlatformInterface';
2
- import { logger, LogLevel } from '@unvired/react-native-unvired-sdk';
2
+ import { logger, LogLevel } from '../src/logger';
3
+ import { RNFileEntry } from '../src/file-system/RNFileEntry';
4
+ import { FileSystem } from '../src/file-system/FileSystem';
3
5
  export class ReactNativePlatformAdapter implements PlatformInterface {
4
6
 
5
7
  getDeviceInfo(): IDeviceInfo {
@@ -24,22 +26,20 @@ export class ReactNativePlatformAdapter implements PlatformInterface {
24
26
  }
25
27
 
26
28
  getDocumentDirectory(): string {
27
- // TODO: Implement document directory retrieval
28
- return "";
29
+ // Return the document directory path for React Native
30
+ return FileSystem.getDocumentDirectory();
29
31
  }
30
32
 
31
33
  resolveLocalFileSystemURL(url: string): Promise<IFileEntry> {
32
- // TODO: Implement local file system URL resolution
33
- return Promise.resolve({} as IFileEntry);
34
+ return FileSystem.resolveLocalFileSystemURL(url);
34
35
  }
35
36
 
36
37
  async getFolderBasedOnUserId(userId: string): Promise<string> {
37
- // TODO: Implement folder retrieval based on user ID
38
- return "";
38
+ return FileSystem.getFolderBasedOnUserId(userId);
39
39
  }
40
40
 
41
41
  async deleteUserFolder(userId: string): Promise<void> {
42
- // TODO: Implement user folder deletion
42
+ return FileSystem.deleteUserFolder(userId);
43
43
  }
44
44
 
45
45
  getDatabaseAdapter(): IDatabaseAdapter {
@@ -139,7 +139,8 @@ export class ReactNativePlatformAdapter implements PlatformInterface {
139
139
  },
140
140
  getBackupLogFileContent: async () => {
141
141
  // TODO: Implement backup log file content retrieval
142
- return logger.getBackupLogFileContent();
142
+ const content = await logger.getBackupLogFileContent();
143
+ return content || '';
143
144
  },
144
145
  clearLogFile: async () => {
145
146
  // TODO: Implement log file clearing