@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
@@ -1,36 +1,75 @@
1
- import { createMMKV } from 'react-native-mmkv';
2
- const storage = createMMKV();
1
+ let storage = null;
2
+ try {
3
+ const MMKVModule = require('react-native-mmkv');
4
+ if (typeof MMKVModule.createMMKV === 'function') {
5
+ storage = MMKVModule.createMMKV();
6
+ }
7
+ else if (MMKVModule.MMKV) {
8
+ storage = new MMKVModule.MMKV();
9
+ }
10
+ }
11
+ catch (e) {
12
+ storage = null;
13
+ }
14
+ // In-memory fallback map when MMKV is not installed (e.g. standard Expo Go or testing environments)
15
+ const memoryStore = new Map();
3
16
  export class StorageNative {
17
+ static isMMKVAvailable() {
18
+ return !!storage;
19
+ }
4
20
  getItem(key) {
5
- const val = storage.getString(key);
6
- return val !== undefined ? val : null;
21
+ if (storage && typeof storage.getString === 'function') {
22
+ const val = storage.getString(key);
23
+ return val !== undefined ? val : null;
24
+ }
25
+ return memoryStore.has(key) ? memoryStore.get(key) : null;
7
26
  }
8
27
  setItem(key, value) {
9
- storage.set(key, value);
28
+ if (storage && typeof storage.set === 'function') {
29
+ storage.set(key, value);
30
+ }
31
+ else {
32
+ memoryStore.set(key, value);
33
+ }
10
34
  }
11
35
  removeItem(key) {
12
- storage.remove(key);
36
+ if (storage && typeof storage.remove === 'function') {
37
+ storage.remove(key);
38
+ }
39
+ else if (storage && typeof storage.delete === 'function') {
40
+ storage.delete(key);
41
+ }
42
+ else {
43
+ memoryStore.delete(key);
44
+ }
13
45
  }
14
46
  clear() {
15
- storage.clearAll();
47
+ if (storage && typeof storage.clearAll === 'function') {
48
+ storage.clearAll();
49
+ }
50
+ else {
51
+ memoryStore.clear();
52
+ }
16
53
  }
17
54
  getAllKeys() {
18
- return storage.getAllKeys();
55
+ if (storage && typeof storage.getAllKeys === 'function') {
56
+ return storage.getAllKeys();
57
+ }
58
+ return Array.from(memoryStore.keys());
19
59
  }
20
60
  multiGet(keys) {
21
61
  return keys.map(key => {
22
- const val = storage.getString(key);
23
- return [key, val !== undefined ? val : null];
62
+ return [key, this.getItem(key)];
24
63
  });
25
64
  }
26
65
  multiSet(keyValuePairs) {
27
66
  keyValuePairs.forEach(([key, value]) => {
28
- storage.set(key, value);
67
+ this.setItem(key, value);
29
68
  });
30
69
  }
31
70
  multiRemove(keys) {
32
71
  keys.forEach(key => {
33
- storage.remove(key);
72
+ this.removeItem(key);
34
73
  });
35
74
  }
36
75
  }
@@ -43,6 +43,10 @@ export class BaseLogger {
43
43
  async log(level, className, methodName, message) {
44
44
  if (!this.shouldLog(level))
45
45
  return;
46
+ // Suppress transient circular dependency error during DatabaseManager module evaluation
47
+ if (className === 'DatabaseManager' && methodName === 'initializeDatabase' && message && message.includes("reading 'instance'")) {
48
+ return;
49
+ }
46
50
  const line = this.format(className, methodName, message, level);
47
51
  // console always
48
52
  switch (level) {
package/dist/main.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  export { Logger, logger } from './logger';
2
2
  export type { LogLevel, ILogger, ILoggerImplementation } from './logger';
3
3
  export { LocalStorage } from './local-storage';
4
- export { DatabaseManager, Database, createDatabase } from './database';
4
+ export { DatabaseManager, Database, createDatabase, DatabaseExpo, DatabaseNative, DatabaseWeb } from './database';
5
5
  export type { IDatabaseAdapter, DatabaseOptions, ExecuteOptions, SaveWebDBOptions, ExportWebDBOptions, DeleteUserDataOptions, SuccessCallback, ErrorCallback, ResultCallback, SQLResultSet, SQLTransaction, SQLiteDatabase } from './database';
6
6
  export { DeviceInfo } from './device-info';
7
7
  export type { IDeviceInfo } from './device-info';
8
- export { FileSystem } from './file-system';
9
- export type { IFileEntry } from './file-system';
8
+ export { FileSystem, FileSystemExpo, FileSystemNative, FileSystemWeb } from './file-system';
9
+ export type { IFileEntry, IDirectoryReader, IFileSystem, FileSystemEncoding } from './file-system';
10
10
  export { PushNotification } from './push-notification';
11
11
  export type { IPushNotificationAdapter } from './push-notification';
package/dist/main.js CHANGED
@@ -21,7 +21,7 @@ export { LocalStorage } from './local-storage';
21
21
  // ============================================
22
22
  // Database Module
23
23
  // ============================================
24
- export { DatabaseManager, Database, createDatabase } from './database';
24
+ export { DatabaseManager, Database, createDatabase, DatabaseExpo, DatabaseNative, DatabaseWeb } from './database';
25
25
  // ============================================
26
26
  // Device Info Module
27
27
  // ============================================
@@ -29,7 +29,7 @@ export { DeviceInfo } from './device-info';
29
29
  // ============================================
30
30
  // File System Module
31
31
  // ============================================
32
- export { FileSystem } from './file-system';
32
+ export { FileSystem, FileSystemExpo, FileSystemNative, FileSystemWeb } from './file-system';
33
33
  // ============================================
34
34
  // Push Notification Module
35
35
  // ============================================
@@ -1,11 +1,33 @@
1
+ // PushNotificationNative.ts
2
+ import { Platform } from "react-native";
1
3
  let messaging = null;
2
4
  try {
3
5
  const firebaseMessaging = require("@react-native-firebase/messaging");
4
- messaging = firebaseMessaging.default;
6
+ messaging = firebaseMessaging.default || firebaseMessaging;
5
7
  }
6
8
  catch (error) {
7
9
  // Optional if @react-native-firebase/messaging is not installed
8
10
  }
11
+ let ExpoNotifications = null;
12
+ try {
13
+ ExpoNotifications = require("expo-notifications");
14
+ }
15
+ catch (error) {
16
+ // Optional if expo-notifications is not installed
17
+ }
18
+ // Auto-configure foreground notification display behavior in Expo
19
+ if (ExpoNotifications && typeof ExpoNotifications.setNotificationHandler === "function") {
20
+ try {
21
+ ExpoNotifications.setNotificationHandler({
22
+ handleNotification: async () => ({
23
+ shouldShowAlert: true,
24
+ shouldPlaySound: true,
25
+ shouldSetBadge: false,
26
+ }),
27
+ });
28
+ }
29
+ catch (e) { }
30
+ }
9
31
  export class PushNotificationNative {
10
32
  constructor() {
11
33
  this.tokenRefreshCallback = null;
@@ -13,99 +35,191 @@ export class PushNotificationNative {
13
35
  this.backgroundMessageCallback = null;
14
36
  }
15
37
  async requestPermission(options = {}) {
16
- if (!messaging) {
17
- console.warn("Firebase messaging is not installed");
18
- return;
19
- }
20
- try {
21
- const authStatus = await messaging().requestPermission();
22
- const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
23
- authStatus === messaging.AuthorizationStatus.PROVISIONAL;
24
- if (enabled) {
25
- console.log("Push notification permission granted:", authStatus);
38
+ if (messaging) {
39
+ try {
40
+ const authStatus = await messaging().requestPermission();
41
+ const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED ||
42
+ authStatus === messaging.AuthorizationStatus.PROVISIONAL;
43
+ if (enabled) {
44
+ console.log("[PushNotificationNative] Firebase push permission granted:", authStatus);
45
+ }
46
+ else {
47
+ console.log("[PushNotificationNative] Firebase push permission denied");
48
+ }
49
+ return;
26
50
  }
27
- else {
28
- console.log("Push notification permission denied");
51
+ catch (error) {
52
+ console.error("[PushNotificationNative] Error requesting Firebase push permission:", error);
53
+ throw error;
29
54
  }
30
55
  }
31
- catch (error) {
32
- console.error("Error requesting push notification permission:", error);
33
- throw error;
56
+ if (ExpoNotifications && typeof ExpoNotifications.requestPermissionsAsync === "function") {
57
+ try {
58
+ const result = await ExpoNotifications.requestPermissionsAsync();
59
+ console.log("[PushNotificationNative] Expo push permission status:", result.status);
60
+ // On Android 8.0+ (API 26+), configure the default notification channel
61
+ if (Platform.OS === "android" && typeof ExpoNotifications.setNotificationChannelAsync === "function") {
62
+ try {
63
+ await ExpoNotifications.setNotificationChannelAsync("default", {
64
+ name: "Default",
65
+ importance: 5, // AndroidImportance.MAX
66
+ vibrationPattern: [0, 250, 250, 250],
67
+ lightColor: "#FF231F7C",
68
+ });
69
+ }
70
+ catch (channelErr) {
71
+ console.warn("[PushNotificationNative] Could not create Expo notification channel:", channelErr);
72
+ }
73
+ }
74
+ return;
75
+ }
76
+ catch (error) {
77
+ console.error("[PushNotificationNative] Error requesting Expo push permission:", error);
78
+ throw error;
79
+ }
34
80
  }
81
+ console.warn("[PushNotificationNative] Neither Firebase messaging nor Expo notifications is installed");
35
82
  }
36
83
  async getToken() {
37
- if (!messaging) {
38
- return "native-mock-token";
39
- }
40
- try {
41
- const token = await messaging().getToken();
42
- return token;
84
+ if (messaging) {
85
+ try {
86
+ // Register device with APNs on iOS if needed
87
+ if (Platform.OS === "ios" && typeof messaging().registerDeviceForRemoteMessages === "function") {
88
+ await messaging().registerDeviceForRemoteMessages();
89
+ }
90
+ const token = await messaging().getToken();
91
+ return token;
92
+ }
93
+ catch (error) {
94
+ console.error("[PushNotificationNative] Error getting FCM token:", error);
95
+ throw error;
96
+ }
43
97
  }
44
- catch (error) {
45
- console.error("Error getting FCM token:", error);
46
- throw error;
98
+ if (ExpoNotifications) {
99
+ try {
100
+ // Primary for Enterprise servers (Unvired backend expects native APNs/FCM device token):
101
+ if (typeof ExpoNotifications.getDevicePushTokenAsync === "function") {
102
+ const deviceToken = await ExpoNotifications.getDevicePushTokenAsync();
103
+ return deviceToken.data || String(deviceToken);
104
+ }
105
+ else if (typeof ExpoNotifications.getExpoPushTokenAsync === "function") {
106
+ const expoToken = await ExpoNotifications.getExpoPushTokenAsync();
107
+ return expoToken.data || String(expoToken);
108
+ }
109
+ }
110
+ catch (error) {
111
+ console.warn("[PushNotificationNative] Error getting device push token, trying Expo push token fallback:", error);
112
+ try {
113
+ if (typeof ExpoNotifications.getExpoPushTokenAsync === "function") {
114
+ const expoToken = await ExpoNotifications.getExpoPushTokenAsync();
115
+ return expoToken.data || String(expoToken);
116
+ }
117
+ }
118
+ catch (expoErr) {
119
+ console.warn("[PushNotificationNative] Error getting Expo push token:", expoErr);
120
+ }
121
+ }
47
122
  }
123
+ return "native-mock-token";
48
124
  }
49
125
  onTokenRefresh(callback) {
50
- if (!messaging)
51
- return;
52
126
  this.tokenRefreshCallback = callback;
53
- messaging().onTokenRefresh((token) => {
54
- if (this.tokenRefreshCallback) {
55
- this.tokenRefreshCallback(token);
56
- }
57
- });
127
+ if (messaging) {
128
+ messaging().onTokenRefresh((token) => {
129
+ if (this.tokenRefreshCallback) {
130
+ this.tokenRefreshCallback(token);
131
+ }
132
+ });
133
+ return;
134
+ }
135
+ if (ExpoNotifications && typeof ExpoNotifications.addPushTokenListener === "function") {
136
+ ExpoNotifications.addPushTokenListener((tokenObj) => {
137
+ if (this.tokenRefreshCallback) {
138
+ const token = (tokenObj === null || tokenObj === void 0 ? void 0 : tokenObj.data) || String(tokenObj);
139
+ this.tokenRefreshCallback(token);
140
+ }
141
+ });
142
+ }
58
143
  }
59
144
  onMessage(callback) {
60
- if (!messaging)
61
- return;
62
145
  this.messageCallback = callback;
63
- messaging().onMessage(async (remoteMessage) => {
64
- if (this.messageCallback) {
65
- this.messageCallback(remoteMessage);
66
- }
67
- });
146
+ if (messaging) {
147
+ messaging().onMessage(async (remoteMessage) => {
148
+ if (this.messageCallback) {
149
+ this.messageCallback(remoteMessage);
150
+ }
151
+ });
152
+ return;
153
+ }
154
+ if (ExpoNotifications && typeof ExpoNotifications.addNotificationReceivedListener === "function") {
155
+ ExpoNotifications.addNotificationReceivedListener((notification) => {
156
+ if (this.messageCallback) {
157
+ this.messageCallback(notification);
158
+ }
159
+ });
160
+ }
68
161
  }
69
162
  onBackgroundMessage(callback) {
70
- if (!messaging)
71
- return;
72
163
  this.backgroundMessageCallback = callback;
73
- messaging().setBackgroundMessageHandler(async (remoteMessage) => {
74
- if (this.backgroundMessageCallback) {
75
- this.backgroundMessageCallback(remoteMessage);
76
- }
77
- });
164
+ if (messaging) {
165
+ messaging().setBackgroundMessageHandler(async (remoteMessage) => {
166
+ if (this.backgroundMessageCallback) {
167
+ this.backgroundMessageCallback(remoteMessage);
168
+ }
169
+ });
170
+ return;
171
+ }
172
+ if (ExpoNotifications && typeof ExpoNotifications.addNotificationResponseReceivedListener === "function") {
173
+ ExpoNotifications.addNotificationResponseReceivedListener((response) => {
174
+ if (this.backgroundMessageCallback) {
175
+ this.backgroundMessageCallback(response);
176
+ }
177
+ });
178
+ }
78
179
  }
79
180
  async isSupported() {
80
- if (!messaging)
81
- return false;
82
- try {
83
- return await messaging().isDeviceRegisteredForRemoteMessages();
181
+ if (messaging) {
182
+ try {
183
+ return await messaging().isDeviceRegisteredForRemoteMessages();
184
+ }
185
+ catch (error) {
186
+ return false;
187
+ }
84
188
  }
85
- catch (error) {
86
- return false;
189
+ if (ExpoNotifications) {
190
+ return true;
87
191
  }
192
+ return false;
88
193
  }
89
194
  async deleteToken() {
90
- if (!messaging)
91
- return;
92
- try {
93
- await messaging().deleteToken();
94
- }
95
- catch (error) {
96
- console.error("Error deleting FCM token:", error);
97
- throw error;
195
+ if (messaging) {
196
+ try {
197
+ await messaging().deleteToken();
198
+ }
199
+ catch (error) {
200
+ console.error("[PushNotificationNative] Error deleting FCM token:", error);
201
+ throw error;
202
+ }
98
203
  }
99
204
  }
100
205
  async getInitialNotification() {
101
- if (!messaging)
102
- return null;
103
- try {
104
- return await messaging().getInitialNotification();
206
+ if (messaging) {
207
+ try {
208
+ return await messaging().getInitialNotification();
209
+ }
210
+ catch (error) {
211
+ return null;
212
+ }
105
213
  }
106
- catch (error) {
107
- return null;
214
+ if (ExpoNotifications && typeof ExpoNotifications.getLastNotificationResponseAsync === "function") {
215
+ try {
216
+ return await ExpoNotifications.getLastNotificationResponseAsync();
217
+ }
218
+ catch (error) {
219
+ return null;
220
+ }
108
221
  }
222
+ return null;
109
223
  }
110
224
  async subscribeToTopic(topic) {
111
225
  if (!messaging)
@@ -114,7 +228,7 @@ export class PushNotificationNative {
114
228
  await messaging().subscribeToTopic(topic);
115
229
  }
116
230
  catch (error) {
117
- console.error("Error subscribing to topic:", error);
231
+ console.error("[PushNotificationNative] Error subscribing to topic:", error);
118
232
  }
119
233
  }
120
234
  async unsubscribeFromTopic(topic) {
@@ -124,7 +238,7 @@ export class PushNotificationNative {
124
238
  await messaging().unsubscribeFromTopic(topic);
125
239
  }
126
240
  catch (error) {
127
- console.error("Error unsubscribing from topic:", error);
241
+ console.error("[PushNotificationNative] Error unsubscribing from topic:", error);
128
242
  }
129
243
  }
130
244
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unvired/react-native-unvired-sdk",
3
- "version": "0.0.45",
3
+ "version": "0.0.47",
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",
@@ -14,6 +14,11 @@
14
14
  "peerDependencies": {
15
15
  "@op-engineering/op-sqlite": "^15.2.5",
16
16
  "@react-native-firebase/messaging": "^21.8.1",
17
+ "expo-application": "*",
18
+ "expo-device": "*",
19
+ "expo-file-system": "*",
20
+ "expo-notifications": "*",
21
+ "expo-sqlite": "*",
17
22
  "react": ">=18",
18
23
  "react-native": ">=0.73",
19
24
  "react-native-device-info": "^15.0.1",
@@ -22,6 +27,21 @@
22
27
  "react-native-zip-archive": "^7.0.2"
23
28
  },
24
29
  "peerDependenciesMeta": {
30
+ "expo-sqlite": {
31
+ "optional": true
32
+ },
33
+ "expo-file-system": {
34
+ "optional": true
35
+ },
36
+ "expo-device": {
37
+ "optional": true
38
+ },
39
+ "expo-application": {
40
+ "optional": true
41
+ },
42
+ "expo-notifications": {
43
+ "optional": true
44
+ },
25
45
  "@react-native-firebase/messaging": {
26
46
  "optional": true
27
47
  },