@savers_app/react-native-sdk 1.1.0

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 (197) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +508 -0
  3. package/lib/module/@types/@react-native-async-storage__async-storage.d.js +2 -0
  4. package/lib/module/@types/@react-native-async-storage__async-storage.d.js.map +1 -0
  5. package/lib/module/@types/@react-native-community__geolocation.d.js +2 -0
  6. package/lib/module/@types/@react-native-community__geolocation.d.js.map +1 -0
  7. package/lib/module/@types/react-native-aes-gcm-crypto.d.js +2 -0
  8. package/lib/module/@types/react-native-aes-gcm-crypto.d.js.map +1 -0
  9. package/lib/module/@types/react-native-device-info.d.js +2 -0
  10. package/lib/module/@types/react-native-device-info.d.js.map +1 -0
  11. package/lib/module/core/runtime.js +67 -0
  12. package/lib/module/core/runtime.js.map +1 -0
  13. package/lib/module/data/models/apiResponse.js +19 -0
  14. package/lib/module/data/models/apiResponse.js.map +1 -0
  15. package/lib/module/data/models/onboardingModel.js +67 -0
  16. package/lib/module/data/models/onboardingModel.js.map +1 -0
  17. package/lib/module/data/network/apiClient.js +109 -0
  18. package/lib/module/data/network/apiClient.js.map +1 -0
  19. package/lib/module/data/network/apiEndpoints.js +6 -0
  20. package/lib/module/data/network/apiEndpoints.js.map +1 -0
  21. package/lib/module/data/network/apiExceptionHandler.js +16 -0
  22. package/lib/module/data/network/apiExceptionHandler.js.map +1 -0
  23. package/lib/module/data/network/apiRepository.js +70 -0
  24. package/lib/module/data/network/apiRepository.js.map +1 -0
  25. package/lib/module/data/network/apiService.js +66 -0
  26. package/lib/module/data/network/apiService.js.map +1 -0
  27. package/lib/module/data/network/dataTypeUtils.js +77 -0
  28. package/lib/module/data/network/dataTypeUtils.js.map +1 -0
  29. package/lib/module/data/network/interceptors/authInterceptor.js +69 -0
  30. package/lib/module/data/network/interceptors/authInterceptor.js.map +1 -0
  31. package/lib/module/data/network/interceptors/errorInterceptor.js +15 -0
  32. package/lib/module/data/network/interceptors/errorInterceptor.js.map +1 -0
  33. package/lib/module/data/network/interceptors/loggingInterceptor.js +17 -0
  34. package/lib/module/data/network/interceptors/loggingInterceptor.js.map +1 -0
  35. package/lib/module/data/network/interceptors/networkInterceptor.js +22 -0
  36. package/lib/module/data/network/interceptors/networkInterceptor.js.map +1 -0
  37. package/lib/module/data/network/interceptors/retryInterceptor.js +22 -0
  38. package/lib/module/data/network/interceptors/retryInterceptor.js.map +1 -0
  39. package/lib/module/data/storage/asyncStorageManager.js +50 -0
  40. package/lib/module/data/storage/asyncStorageManager.js.map +1 -0
  41. package/lib/module/data/storage/deviceIdManager.js +45 -0
  42. package/lib/module/data/storage/deviceIdManager.js.map +1 -0
  43. package/lib/module/data/storage/keysManager.js +70 -0
  44. package/lib/module/data/storage/keysManager.js.map +1 -0
  45. package/lib/module/data/storage/locationManager.js +30 -0
  46. package/lib/module/data/storage/locationManager.js.map +1 -0
  47. package/lib/module/data/storage/sessionManager.js +12 -0
  48. package/lib/module/data/storage/sessionManager.js.map +1 -0
  49. package/lib/module/data/storage/storageKeys.js +7 -0
  50. package/lib/module/data/storage/storageKeys.js.map +1 -0
  51. package/lib/module/data/storage/storageManager.js +76 -0
  52. package/lib/module/data/storage/storageManager.js.map +1 -0
  53. package/lib/module/index.js +20 -0
  54. package/lib/module/index.js.map +1 -0
  55. package/lib/module/package.json +1 -0
  56. package/lib/module/services/device/location.js +47 -0
  57. package/lib/module/services/device/location.js.map +1 -0
  58. package/lib/module/services/navigation/dialPad.js +29 -0
  59. package/lib/module/services/navigation/dialPad.js.map +1 -0
  60. package/lib/module/services/navigation/goBackNavigation.js +22 -0
  61. package/lib/module/services/navigation/goBackNavigation.js.map +1 -0
  62. package/lib/module/services/navigation/openBrowser.js +8 -0
  63. package/lib/module/services/navigation/openBrowser.js.map +1 -0
  64. package/lib/module/services/navigation/openMap.js +26 -0
  65. package/lib/module/services/navigation/openMap.js.map +1 -0
  66. package/lib/module/services/permissions/permissionManager.js +28 -0
  67. package/lib/module/services/permissions/permissionManager.js.map +1 -0
  68. package/lib/module/services/url/urlGenerator.js +90 -0
  69. package/lib/module/services/url/urlGenerator.js.map +1 -0
  70. package/lib/module/services/webview/messageHandler.js +69 -0
  71. package/lib/module/services/webview/messageHandler.js.map +1 -0
  72. package/lib/module/utils/dependencyManager.js +51 -0
  73. package/lib/module/utils/dependencyManager.js.map +1 -0
  74. package/lib/module/utils/encryption.js +43 -0
  75. package/lib/module/utils/encryption.js.map +1 -0
  76. package/lib/module/utils/errors.js +9 -0
  77. package/lib/module/utils/errors.js.map +1 -0
  78. package/lib/module/utils/logger.js +14 -0
  79. package/lib/module/utils/logger.js.map +1 -0
  80. package/lib/module/utils/platformManager.js +14 -0
  81. package/lib/module/utils/platformManager.js.map +1 -0
  82. package/lib/module/utils/validator.js +26 -0
  83. package/lib/module/utils/validator.js.map +1 -0
  84. package/lib/typescript/package.json +1 -0
  85. package/lib/typescript/src/core/runtime.d.ts +10 -0
  86. package/lib/typescript/src/core/runtime.d.ts.map +1 -0
  87. package/lib/typescript/src/data/models/apiResponse.d.ts +9 -0
  88. package/lib/typescript/src/data/models/apiResponse.d.ts.map +1 -0
  89. package/lib/typescript/src/data/models/onboardingModel.d.ts +24 -0
  90. package/lib/typescript/src/data/models/onboardingModel.d.ts.map +1 -0
  91. package/lib/typescript/src/data/network/apiClient.d.ts +17 -0
  92. package/lib/typescript/src/data/network/apiClient.d.ts.map +1 -0
  93. package/lib/typescript/src/data/network/apiEndpoints.d.ts +4 -0
  94. package/lib/typescript/src/data/network/apiEndpoints.d.ts.map +1 -0
  95. package/lib/typescript/src/data/network/apiExceptionHandler.d.ts +3 -0
  96. package/lib/typescript/src/data/network/apiExceptionHandler.d.ts.map +1 -0
  97. package/lib/typescript/src/data/network/apiRepository.d.ts +19 -0
  98. package/lib/typescript/src/data/network/apiRepository.d.ts.map +1 -0
  99. package/lib/typescript/src/data/network/apiService.d.ts +19 -0
  100. package/lib/typescript/src/data/network/apiService.d.ts.map +1 -0
  101. package/lib/typescript/src/data/network/dataTypeUtils.d.ts +10 -0
  102. package/lib/typescript/src/data/network/dataTypeUtils.d.ts.map +1 -0
  103. package/lib/typescript/src/data/network/interceptors/authInterceptor.d.ts +13 -0
  104. package/lib/typescript/src/data/network/interceptors/authInterceptor.d.ts.map +1 -0
  105. package/lib/typescript/src/data/network/interceptors/errorInterceptor.d.ts +4 -0
  106. package/lib/typescript/src/data/network/interceptors/errorInterceptor.d.ts.map +1 -0
  107. package/lib/typescript/src/data/network/interceptors/loggingInterceptor.d.ts +5 -0
  108. package/lib/typescript/src/data/network/interceptors/loggingInterceptor.d.ts.map +1 -0
  109. package/lib/typescript/src/data/network/interceptors/networkInterceptor.d.ts +4 -0
  110. package/lib/typescript/src/data/network/interceptors/networkInterceptor.d.ts.map +1 -0
  111. package/lib/typescript/src/data/network/interceptors/retryInterceptor.d.ts +7 -0
  112. package/lib/typescript/src/data/network/interceptors/retryInterceptor.d.ts.map +1 -0
  113. package/lib/typescript/src/data/storage/asyncStorageManager.d.ts +13 -0
  114. package/lib/typescript/src/data/storage/asyncStorageManager.d.ts.map +1 -0
  115. package/lib/typescript/src/data/storage/deviceIdManager.d.ts +2 -0
  116. package/lib/typescript/src/data/storage/deviceIdManager.d.ts.map +1 -0
  117. package/lib/typescript/src/data/storage/keysManager.d.ts +29 -0
  118. package/lib/typescript/src/data/storage/keysManager.d.ts.map +1 -0
  119. package/lib/typescript/src/data/storage/locationManager.d.ts +21 -0
  120. package/lib/typescript/src/data/storage/locationManager.d.ts.map +1 -0
  121. package/lib/typescript/src/data/storage/sessionManager.d.ts +3 -0
  122. package/lib/typescript/src/data/storage/sessionManager.d.ts.map +1 -0
  123. package/lib/typescript/src/data/storage/storageKeys.d.ts +5 -0
  124. package/lib/typescript/src/data/storage/storageKeys.d.ts.map +1 -0
  125. package/lib/typescript/src/data/storage/storageManager.d.ts +16 -0
  126. package/lib/typescript/src/data/storage/storageManager.d.ts.map +1 -0
  127. package/lib/typescript/src/index.d.ts +18 -0
  128. package/lib/typescript/src/index.d.ts.map +1 -0
  129. package/lib/typescript/src/services/device/location.d.ts +8 -0
  130. package/lib/typescript/src/services/device/location.d.ts.map +1 -0
  131. package/lib/typescript/src/services/navigation/dialPad.d.ts +3 -0
  132. package/lib/typescript/src/services/navigation/dialPad.d.ts.map +1 -0
  133. package/lib/typescript/src/services/navigation/goBackNavigation.d.ts +4 -0
  134. package/lib/typescript/src/services/navigation/goBackNavigation.d.ts.map +1 -0
  135. package/lib/typescript/src/services/navigation/openBrowser.d.ts +2 -0
  136. package/lib/typescript/src/services/navigation/openBrowser.d.ts.map +1 -0
  137. package/lib/typescript/src/services/navigation/openMap.d.ts +2 -0
  138. package/lib/typescript/src/services/navigation/openMap.d.ts.map +1 -0
  139. package/lib/typescript/src/services/permissions/permissionManager.d.ts +4 -0
  140. package/lib/typescript/src/services/permissions/permissionManager.d.ts.map +1 -0
  141. package/lib/typescript/src/services/url/urlGenerator.d.ts +43 -0
  142. package/lib/typescript/src/services/url/urlGenerator.d.ts.map +1 -0
  143. package/lib/typescript/src/services/webview/messageHandler.d.ts +2 -0
  144. package/lib/typescript/src/services/webview/messageHandler.d.ts.map +1 -0
  145. package/lib/typescript/src/utils/dependencyManager.d.ts +31 -0
  146. package/lib/typescript/src/utils/dependencyManager.d.ts.map +1 -0
  147. package/lib/typescript/src/utils/encryption.d.ts +5 -0
  148. package/lib/typescript/src/utils/encryption.d.ts.map +1 -0
  149. package/lib/typescript/src/utils/errors.d.ts +4 -0
  150. package/lib/typescript/src/utils/errors.d.ts.map +1 -0
  151. package/lib/typescript/src/utils/logger.d.ts +6 -0
  152. package/lib/typescript/src/utils/logger.d.ts.map +1 -0
  153. package/lib/typescript/src/utils/platformManager.d.ts +4 -0
  154. package/lib/typescript/src/utils/platformManager.d.ts.map +1 -0
  155. package/lib/typescript/src/utils/validator.d.ts +4 -0
  156. package/lib/typescript/src/utils/validator.d.ts.map +1 -0
  157. package/package.json +176 -0
  158. package/src/@types/@react-native-async-storage__async-storage.d.ts +7 -0
  159. package/src/@types/@react-native-community__geolocation.d.ts +18 -0
  160. package/src/@types/react-native-aes-gcm-crypto.d.ts +22 -0
  161. package/src/@types/react-native-device-info.d.ts +3 -0
  162. package/src/core/runtime.ts +80 -0
  163. package/src/data/models/apiResponse.ts +28 -0
  164. package/src/data/models/onboardingModel.ts +99 -0
  165. package/src/data/network/apiClient.ts +148 -0
  166. package/src/data/network/apiEndpoints.ts +3 -0
  167. package/src/data/network/apiExceptionHandler.ts +16 -0
  168. package/src/data/network/apiRepository.ts +106 -0
  169. package/src/data/network/apiService.ts +72 -0
  170. package/src/data/network/dataTypeUtils.ts +78 -0
  171. package/src/data/network/interceptors/authInterceptor.ts +77 -0
  172. package/src/data/network/interceptors/errorInterceptor.ts +13 -0
  173. package/src/data/network/interceptors/loggingInterceptor.ts +16 -0
  174. package/src/data/network/interceptors/networkInterceptor.ts +20 -0
  175. package/src/data/network/interceptors/retryInterceptor.ts +24 -0
  176. package/src/data/storage/asyncStorageManager.ts +56 -0
  177. package/src/data/storage/deviceIdManager.ts +46 -0
  178. package/src/data/storage/keysManager.ts +89 -0
  179. package/src/data/storage/locationManager.ts +39 -0
  180. package/src/data/storage/sessionManager.ts +11 -0
  181. package/src/data/storage/storageKeys.ts +4 -0
  182. package/src/data/storage/storageManager.ts +83 -0
  183. package/src/index.tsx +17 -0
  184. package/src/services/device/location.ts +51 -0
  185. package/src/services/navigation/dialPad.ts +39 -0
  186. package/src/services/navigation/goBackNavigation.ts +22 -0
  187. package/src/services/navigation/openBrowser.ts +6 -0
  188. package/src/services/navigation/openMap.ts +39 -0
  189. package/src/services/permissions/permissionManager.ts +33 -0
  190. package/src/services/url/urlGenerator.ts +132 -0
  191. package/src/services/webview/messageHandler.ts +48 -0
  192. package/src/utils/dependencyManager.ts +82 -0
  193. package/src/utils/encryption.ts +58 -0
  194. package/src/utils/errors.ts +6 -0
  195. package/src/utils/logger.ts +11 -0
  196. package/src/utils/platformManager.ts +14 -0
  197. package/src/utils/validator.ts +29 -0
@@ -0,0 +1,77 @@
1
+ /* eslint-disable no-unreachable */
2
+
3
+ // Utilities
4
+ import { logger } from '../../../utils/logger';
5
+
6
+ export class AuthInterceptor {
7
+ private static readonly oauthSubIdKey = 'oauthSubId';
8
+ private static readonly bodyMethods = new Set(['POST', 'PUT', 'PATCH']);
9
+ private static readonly excludedApis = new Set<string>();
10
+
11
+ async onRequest(options: any): Promise<any> {
12
+ try {
13
+ if (this.shouldExcludeApi(options.url)) {
14
+ return options;
15
+ }
16
+
17
+ const userId = await this.getCurrentUserId();
18
+ if (userId) {
19
+ this.addAuthenticationData(options, userId);
20
+ }
21
+ } catch (e) {
22
+ logger.error('AuthInterceptor error:', e);
23
+ }
24
+
25
+ return options;
26
+ }
27
+
28
+ private addAuthenticationData(options: any, userId: string) {
29
+ const method = (options.method || 'GET').toUpperCase();
30
+
31
+ if (AuthInterceptor.bodyMethods.has(method)) {
32
+ this.addToQueryParametersAndBody(options, userId);
33
+ } else {
34
+ this.addToQueryParameters(options, userId);
35
+ }
36
+ }
37
+
38
+ private addToQueryParameters(options: any, userId: string) {
39
+ options.params = options.params || {};
40
+ options.params[AuthInterceptor.oauthSubIdKey] = userId;
41
+ }
42
+
43
+ private addToQueryParametersAndBody(options: any, userId: string) {
44
+ this.addToQueryParameters(options, userId);
45
+ this.addToRequestBody(options, userId);
46
+ }
47
+
48
+ private addToRequestBody(options: any, userId: string) {
49
+ if (options.body instanceof FormData) {
50
+ options.body.append(AuthInterceptor.oauthSubIdKey, userId);
51
+ } else if (typeof options.body === 'object' && options.body !== null) {
52
+ options.body[AuthInterceptor.oauthSubIdKey] = userId;
53
+ }
54
+ }
55
+
56
+ private shouldExcludeApi(apiPath: string): boolean {
57
+ if (!apiPath) return false;
58
+ for (const excludedPath of AuthInterceptor.excludedApis) {
59
+ if (apiPath.includes(excludedPath)) {
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ }
65
+
66
+ private async getCurrentUserId(): Promise<string | null> {
67
+ try {
68
+ // Placeholder for Keycloak integration
69
+ // const currentUser = KeycloakWebViewManager.instance.currentUser;
70
+ // return currentUser?.email;
71
+ return null;
72
+ } catch (e) {
73
+ logger.error('Failed to get current user ID:', e);
74
+ return null;
75
+ }
76
+ }
77
+ }
@@ -0,0 +1,13 @@
1
+ // Utilities / Helpers
2
+ import { getErrorMessage } from '../apiExceptionHandler';
3
+
4
+ export class ErrorInterceptor {
5
+ onError(err: any, handler: any) {
6
+ const unifiedMessage = getErrorMessage(err?.status, err?.type);
7
+ const newError = {
8
+ ...err,
9
+ error: unifiedMessage,
10
+ };
11
+ handler.reject(newError);
12
+ }
13
+ }
@@ -0,0 +1,16 @@
1
+ // Utilities
2
+ import { logger } from '../../../utils/logger';
3
+
4
+ export class LoggingInterceptor {
5
+ onRequest(options: any) {
6
+ logger.info(`➡️ [REQUEST] ${options.method} ${options.url}`);
7
+ logger.info('Headers:', options.headers);
8
+ logger.info('Body:', options.body);
9
+ return options;
10
+ }
11
+
12
+ onResponse(response: any) {
13
+ logger.info(`✅ [RESPONSE] ${response.status}:`, response.data);
14
+ return response;
15
+ }
16
+ }
@@ -0,0 +1,20 @@
1
+ // Third-party libraries
2
+ import NetInfo from '@react-native-community/netinfo';
3
+
4
+ // Utilities / Helpers
5
+ import { noInternetError } from '../apiExceptionHandler';
6
+
7
+ export class NetworkInterceptor {
8
+ async onRequest(options: any): Promise<any> {
9
+ const state = await NetInfo.fetch();
10
+ if (!state.isConnected) {
11
+ throw {
12
+ requestOptions: options,
13
+ type: 'connectionError',
14
+ error: noInternetError(),
15
+ message: noInternetError(), // Unified message
16
+ };
17
+ }
18
+ return options;
19
+ }
20
+ }
@@ -0,0 +1,24 @@
1
+ export class RetryInterceptor {
2
+ private readonly retries: number;
3
+
4
+ constructor(retries: number = 1) {
5
+ this.retries = retries;
6
+ }
7
+
8
+ async onError(err: any, handler: any): Promise<any> {
9
+ const attempt = err.config?.retry_attempt ?? 0;
10
+
11
+ if (attempt < this.retries && this.shouldRetry(err)) {
12
+ // Retry logic implementation depends on the HTTP client (axios/fetch)
13
+ // This is a placeholder for the logic
14
+ return handler.next(err);
15
+ }
16
+ return handler.next(err);
17
+ }
18
+
19
+ private shouldRetry(err: any): boolean {
20
+ // Check for timeout or network errors
21
+ // Placeholder logic
22
+ return err.code === 'ECONNABORTED' || err.message?.includes('timeout');
23
+ }
24
+ }
@@ -0,0 +1,56 @@
1
+ // Utilities / Helpers
2
+ import { resolveNativeDependencies } from '../../utils/dependencyManager';
3
+
4
+ function ensureStorage() {
5
+ const { AsyncStorage } = resolveNativeDependencies();
6
+ if (!AsyncStorage) throw new Error('ASYNC_STORAGE_NOT_AVAILABLE');
7
+ return AsyncStorage as any;
8
+ }
9
+
10
+ export async function storageGet(key: string): Promise<string | null> {
11
+ const storage = ensureStorage();
12
+ return storage.getItem(key);
13
+ }
14
+
15
+ export async function storageSet(key: string, value: string): Promise<void> {
16
+ const storage = ensureStorage();
17
+ await storage.setItem(key, value);
18
+ }
19
+
20
+ export async function storageRemove(key: string): Promise<void> {
21
+ const storage = ensureStorage();
22
+ if (typeof storage.removeItem === 'function') {
23
+ await storage.removeItem(key);
24
+ return;
25
+ }
26
+ throw new Error('ASYNC_STORAGE_REMOVE_NOT_SUPPORTED');
27
+ }
28
+
29
+ export async function storageGetJSON<T>(key: string): Promise<T | undefined> {
30
+ const raw = await storageGet(key);
31
+ if (!raw) return undefined;
32
+ try {
33
+ return JSON.parse(raw) as T;
34
+ } catch {
35
+ return undefined;
36
+ }
37
+ }
38
+
39
+ export async function storageSetJSON(
40
+ key: string,
41
+ value: unknown
42
+ ): Promise<void> {
43
+ await storageSet(key, JSON.stringify(value));
44
+ }
45
+
46
+ export function createStorageNamespace(ns: string) {
47
+ const prefix = ns ? `${ns}:` : '';
48
+ return {
49
+ get: (key: string) => storageGet(prefix + key),
50
+ set: (key: string, value: string) => storageSet(prefix + key, value),
51
+ remove: (key: string) => storageRemove(prefix + key),
52
+ getJSON: <T>(key: string) => storageGetJSON<T>(prefix + key),
53
+ setJSON: (key: string, value: unknown) =>
54
+ storageSetJSON(prefix + key, value),
55
+ };
56
+ }
@@ -0,0 +1,46 @@
1
+ // Storage Utilities
2
+ import { storageGet, storageSet } from './asyncStorageManager';
3
+ import { SDK_DEVICE_ID } from './storageKeys';
4
+
5
+ // Utilities / Helpers
6
+ import { resolveNativeDependencies } from '../../utils/dependencyManager';
7
+
8
+ let cachedDeviceId: string | null = null;
9
+
10
+ async function getFromStorage(): Promise<string | null> {
11
+ const key = SDK_DEVICE_ID;
12
+ try {
13
+ const existing = await storageGet(key);
14
+ return existing ?? null;
15
+ } catch {
16
+ return null;
17
+ }
18
+ }
19
+
20
+ async function saveToStorage(id: string): Promise<void> {
21
+ const key = SDK_DEVICE_ID;
22
+ try {
23
+ await storageSet(key, id);
24
+ } catch {}
25
+ }
26
+
27
+ export async function getDeviceId(): Promise<string> {
28
+ if (cachedDeviceId) return cachedDeviceId;
29
+ const stored = await getFromStorage();
30
+ if (stored) {
31
+ cachedDeviceId = stored;
32
+ return stored;
33
+ }
34
+ try {
35
+ const { DeviceInfo } = resolveNativeDependencies();
36
+ if (DeviceInfo?.getUniqueId) {
37
+ const uniqueId = await DeviceInfo.getUniqueId();
38
+ cachedDeviceId = uniqueId;
39
+ await saveToStorage(uniqueId);
40
+ return uniqueId;
41
+ }
42
+ } catch {}
43
+ throw new Error(
44
+ 'DEVICE_ID_UNAVAILABLE: install react-native-device-info or provide a custom id'
45
+ );
46
+ }
@@ -0,0 +1,89 @@
1
+ class KeysManager {
2
+ private apiKey: string | null = null;
3
+ private encryptionKey: string | null = null;
4
+ private pRefCode: string | null = null;
5
+ private authMode: string | null = null;
6
+
7
+ setApiKey(apiKey: string): void {
8
+ this.apiKey = apiKey;
9
+ }
10
+
11
+ getApiKey(): string | null {
12
+ return this.apiKey ?? null;
13
+ }
14
+
15
+ setEncryptionKey(encryptionKey: string): void {
16
+ this.encryptionKey = encryptionKey;
17
+ }
18
+
19
+ getEncryptionKey(): string | null {
20
+ return this.encryptionKey ?? null;
21
+ }
22
+
23
+ setPRefCode(pRefCode: string): void {
24
+ this.pRefCode = pRefCode;
25
+ }
26
+
27
+ getPRefCode(): string | null {
28
+ return this.pRefCode ?? null;
29
+ }
30
+
31
+ setAuthMode(authMode: string): void {
32
+ this.authMode = authMode;
33
+ }
34
+
35
+ getAuthMode(): string | null {
36
+ return this.authMode ?? null;
37
+ }
38
+ }
39
+
40
+ export const keysManager = new KeysManager();
41
+
42
+ export const setApiKey = async (apiKey: string): Promise<void> => {
43
+ keysManager.setApiKey(apiKey);
44
+ };
45
+
46
+ export async function getApiKey(): Promise<string> {
47
+ return keysManager.getApiKey() ?? '-';
48
+ }
49
+
50
+ export const setEncryptionKey = async (
51
+ encryptionKey: string
52
+ ): Promise<void> => {
53
+ keysManager.setEncryptionKey(encryptionKey);
54
+ };
55
+ export async function getEncryptionKey(): Promise<string> {
56
+ return keysManager.getEncryptionKey() ?? '-';
57
+ }
58
+
59
+ export function getApiKeySync(): string | null {
60
+ return keysManager.getApiKey();
61
+ }
62
+
63
+ export function getEncryptionKeySync(): string | null {
64
+ return keysManager.getEncryptionKey();
65
+ }
66
+
67
+ export const setPRefCode = async (pRefCode: string): Promise<void> => {
68
+ keysManager.setPRefCode(pRefCode);
69
+ };
70
+
71
+ export async function getPRefCode(): Promise<string> {
72
+ return keysManager.getPRefCode() ?? '-';
73
+ }
74
+
75
+ export function getPRefCodeSync(): string | null {
76
+ return keysManager.getPRefCode();
77
+ }
78
+
79
+ export const setAuthMode = async (authMode: string): Promise<void> => {
80
+ keysManager.setAuthMode(authMode);
81
+ };
82
+
83
+ export async function getAuthMode(): Promise<string> {
84
+ return keysManager.getAuthMode() ?? '-';
85
+ }
86
+
87
+ export function getAuthModeSync(): string | null {
88
+ return keysManager.getAuthMode();
89
+ }
@@ -0,0 +1,39 @@
1
+ class LocationManager {
2
+ private lat: number | null = null;
3
+ private lng: number | null = null;
4
+
5
+ setCoordinates(lat: number, lng: number): void {
6
+ this.lat = lat;
7
+ this.lng = lng;
8
+ }
9
+
10
+ getCoordinates(): { lat: number; lng: number } | null {
11
+ if (this.lat === null || this.lng === null) {
12
+ return null;
13
+ }
14
+ return { lat: this.lat, lng: this.lng };
15
+ }
16
+ }
17
+
18
+ export const locationManager = new LocationManager();
19
+
20
+ export const setLocationCoordinates = async (
21
+ lat: number,
22
+ lng: number
23
+ ): Promise<void> => {
24
+ locationManager.setCoordinates(lat, lng);
25
+ };
26
+
27
+ export async function getLocationCoordinates(): Promise<{
28
+ lat: number;
29
+ lng: number;
30
+ } | null> {
31
+ return locationManager.getCoordinates();
32
+ }
33
+
34
+ export function getLocationCoordinatesSync(): {
35
+ lat: number;
36
+ lng: number;
37
+ } | null {
38
+ return locationManager.getCoordinates();
39
+ }
@@ -0,0 +1,11 @@
1
+ // Storage Utilities
2
+ import { storageSet, storageGet } from './asyncStorageManager';
3
+ import { SDK_SESSION_ID } from './storageKeys';
4
+
5
+ export const setSessionId = async (sessionId: string) => {
6
+ await storageSet(SDK_SESSION_ID, sessionId);
7
+ };
8
+
9
+ export const getSessionId = async (): Promise<string | null> => {
10
+ return storageGet(SDK_SESSION_ID);
11
+ };
@@ -0,0 +1,4 @@
1
+ export const SAVERS_API_KEY = 'SAVERS_API_KEY';
2
+ export const SAVERS_ENCRYPTION_KEY = 'SAVERS_ENCRYPTION_KEY';
3
+ export const SDK_SESSION_ID = 'SDK_SESSION_ID';
4
+ export const SDK_DEVICE_ID = 'SDK_DEVICE_ID';
@@ -0,0 +1,83 @@
1
+ // Storage Utilities
2
+ import { storageGet, storageSet, storageRemove } from './asyncStorageManager';
3
+
4
+ const cachePrefix = 'cache_';
5
+
6
+ const userIdKey = 'userId';
7
+ const isOnboardingSkipedKey = 'isOnboardingSkipedKey';
8
+ const isAuthSkipedKey = 'isAuthSkipedKey';
9
+ const authSkippedTimestampKey = 'authSkippedTimestamp';
10
+ const userSelectedLocationKey = 'userSelectedLocation';
11
+ const browsingModeKey = 'browsingMode';
12
+
13
+ export const StorageKeys = {
14
+ userId: userIdKey,
15
+ isOnboardingSkiped: isOnboardingSkipedKey,
16
+ isAuthSkiped: isAuthSkipedKey,
17
+ authSkippedTimestamp: authSkippedTimestampKey,
18
+ userSelectedLocation: userSelectedLocationKey,
19
+ browsingMode: browsingModeKey,
20
+ };
21
+
22
+ export async function save(key: string, value: any): Promise<void> {
23
+ const fullKey = cachePrefix + key;
24
+ let dataToSave: string;
25
+ if (typeof value === 'string') {
26
+ dataToSave = value;
27
+ } else {
28
+ try {
29
+ dataToSave = JSON.stringify(value);
30
+ } catch {
31
+ dataToSave = String(value);
32
+ }
33
+ }
34
+ await storageSet(fullKey, dataToSave);
35
+ }
36
+
37
+ export async function get(key: string): Promise<any> {
38
+ const fullKey = cachePrefix + key;
39
+ const raw = await storageGet(fullKey);
40
+ if (raw === null) return null;
41
+ if (raw.startsWith('{') || raw.startsWith('[')) {
42
+ try {
43
+ return JSON.parse(raw);
44
+ } catch {
45
+ return raw;
46
+ }
47
+ }
48
+ return raw;
49
+ }
50
+
51
+ export async function clear(key: string): Promise<void> {
52
+ const fullKey = cachePrefix + key;
53
+ await storageRemove(fullKey);
54
+ }
55
+
56
+ export async function clearAll(): Promise<void> {
57
+ // Not supported by asyncStorageManager wrapper yet, would need extension.
58
+ // For now, we'll leave it as a TODO or implement using low level if exposed,
59
+ // but better to remove direct dependency on @react-native-async-storage/async-storage
60
+ // to support the unified approach.
61
+ // However, asyncStorageManager hides the implementation.
62
+ // Let's rely on the fact that clearAll was mainly for cache.
63
+ console.warn('clearAll not fully supported in unified storage yet');
64
+ }
65
+
66
+ export async function saveAuthSkippedTime(): Promise<void> {
67
+ const timestamp = new Date().toISOString();
68
+ await save(authSkippedTimestampKey, timestamp);
69
+ }
70
+
71
+ export async function getAuthSkippedTime(): Promise<Date | null> {
72
+ const data = await get(authSkippedTimestampKey);
73
+ if (typeof data === 'string') {
74
+ try {
75
+ return new Date(data);
76
+ } catch {}
77
+ }
78
+ return null;
79
+ }
80
+
81
+ export async function clearAuthSkippedTime(): Promise<void> {
82
+ await clear(authSkippedTimestampKey);
83
+ }
package/src/index.tsx ADDED
@@ -0,0 +1,17 @@
1
+ export * from './services/navigation/openMap';
2
+ export * from './services/navigation/goBackNavigation';
3
+ export * from './services/permissions/permissionManager';
4
+ export * from './utils/platformManager';
5
+ export * from './utils/errors';
6
+ export * from './utils/logger';
7
+ export * from './utils/validator';
8
+ export * from './services/webview/messageHandler';
9
+ export * from './data/storage/deviceIdManager';
10
+ export * from './services/navigation/dialPad';
11
+ export * from './services/navigation/openBrowser';
12
+ export * from './data/storage/sessionManager';
13
+ export * from './services/url/urlGenerator';
14
+ export * from './data/network/apiService';
15
+ export * from './core/runtime';
16
+ export * from './data/storage/keysManager';
17
+ export * from './data/storage/locationManager';
@@ -0,0 +1,51 @@
1
+ // Platform Utilities
2
+ import { isAndroid } from '../../utils/platformManager';
3
+ import { resolveNativeDependencies } from '../../utils/dependencyManager';
4
+
5
+ // Permissions
6
+ import { ensureLocationPermission } from '../permissions/permissionManager';
7
+
8
+ export type DeviceLocation = { lat: number; lng: number };
9
+
10
+ let locationProvider: (() => Promise<DeviceLocation | undefined>) | undefined;
11
+
12
+ export function setLocationProvider(
13
+ provider: () => Promise<DeviceLocation | undefined>
14
+ ): void {
15
+ locationProvider = provider;
16
+ }
17
+
18
+ export const fetchLocation = async (): Promise<DeviceLocation> => {
19
+ const { Geolocation } = resolveNativeDependencies();
20
+ if (!Geolocation) {
21
+ throw new Error(
22
+ 'GEOLOCATION_NOT_LINKED: install and link @react-native-community/geolocation'
23
+ );
24
+ }
25
+ return new Promise((resolve, reject) => {
26
+ Geolocation.getCurrentPosition(
27
+ (pos: { coords: { latitude: number; longitude: number } }) =>
28
+ resolve({ lat: pos.coords.latitude, lng: pos.coords.longitude }),
29
+ (err: unknown) => reject(err),
30
+ { enableHighAccuracy: true, timeout: 10000 }
31
+ );
32
+ });
33
+ };
34
+
35
+ export async function getDeviceLocation(): Promise<DeviceLocation | undefined> {
36
+ if (locationProvider) {
37
+ return locationProvider();
38
+ }
39
+ if (isAndroid()) {
40
+ const granted = await ensureLocationPermission();
41
+ if (!granted) {
42
+ throw new Error('LOCATION_PERMISSION_DENIED');
43
+ }
44
+ }
45
+ try {
46
+ const loc = await fetchLocation();
47
+ return loc;
48
+ } catch {
49
+ throw new Error('LOCATION_UNAVAILABLE');
50
+ }
51
+ }
@@ -0,0 +1,39 @@
1
+ // React Native Core
2
+ import { Linking, Platform } from 'react-native';
3
+
4
+ // Utilities / Validators
5
+ import { isValidPhoneNumber } from '../../utils/validator';
6
+
7
+ export const callPhone = async (phone: string): Promise<void> => {
8
+ if (!isValidPhoneNumber(phone)) {
9
+ throw new Error('INVALID_PHONE_NUMBER');
10
+ }
11
+
12
+ const url =
13
+ Platform.OS === 'ios'
14
+ ? `telprompt:${phone}` // iOS preferred
15
+ : `tel:${phone}`;
16
+
17
+ try {
18
+ await Linking.openURL(url);
19
+ } catch {
20
+ throw new Error('CALL_NOT_SUPPORTED');
21
+ }
22
+ };
23
+
24
+ export async function openDialPad(phone?: string): Promise<void> {
25
+ const url =
26
+ Platform.OS === 'ios'
27
+ ? phone
28
+ ? `telprompt:${phone}`
29
+ : 'tel:' // open empty dial pad
30
+ : phone
31
+ ? `tel:${phone}`
32
+ : 'tel:';
33
+
34
+ try {
35
+ await Linking.openURL(url);
36
+ } catch {
37
+ throw new Error('DIAL_PAD_NOT_SUPPORTED');
38
+ }
39
+ }
@@ -0,0 +1,22 @@
1
+ // React Native Core
2
+ import { BackHandler, Platform } from 'react-native';
3
+
4
+ // Navigation / Routing
5
+ import { createNavigationContainerRef } from '@react-navigation/native';
6
+
7
+ export const navigationRef = createNavigationContainerRef();
8
+
9
+ export function closeCurrentScreen(): boolean {
10
+ if (navigationRef.isReady() && navigationRef.canGoBack()) {
11
+ navigationRef.goBack();
12
+ return true;
13
+ }
14
+ return false;
15
+ }
16
+
17
+ export function closeCurrentScreenSafe(): void {
18
+ const closed = closeCurrentScreen();
19
+ if (!closed && Platform.OS === 'android') {
20
+ BackHandler.exitApp();
21
+ }
22
+ }
@@ -0,0 +1,6 @@
1
+ // React Native Core
2
+ import { Linking } from 'react-native';
3
+
4
+ export async function openBrowser(url: string): Promise<void> {
5
+ await Linking.openURL(url);
6
+ }
@@ -0,0 +1,39 @@
1
+ // React Native Core
2
+ import { Linking } from 'react-native';
3
+
4
+ // Utilities / Helpers
5
+ import { isMapAppAvailable, isValidCoordinates } from '../../utils/validator';
6
+
7
+ // Platform / Environment helpers
8
+ import { isIOS } from '../../utils/platformManager';
9
+
10
+ export async function openMap(
11
+ lat: number,
12
+ lng: number,
13
+ label?: string
14
+ ): Promise<void> {
15
+ if (!isValidCoordinates(lat, lng)) {
16
+ throw new Error('INVALID_COORDINATES');
17
+ }
18
+
19
+ const iosUrl = `maps:0,0?q=${encodeURIComponent(label ?? '')}@${lat},${lng}`;
20
+ const androidUrl = `geo:0,0?q=${lat},${lng}${
21
+ label ? `(${encodeURIComponent(label)})` : ''
22
+ }`;
23
+ const deepLink = isIOS() ? iosUrl : androidUrl;
24
+
25
+ const available = await isMapAppAvailable();
26
+ if (available) {
27
+ await Linking.openURL(deepLink);
28
+ return;
29
+ }
30
+
31
+ const browserUrl = isIOS()
32
+ ? `https://maps.apple.com/?q=${encodeURIComponent(
33
+ label ?? ''
34
+ )}&ll=${lat},${lng}`
35
+ : `https://www.google.com/maps/search/?api=1&query=${lat},${lng}${
36
+ label ? `&query_place_id=${encodeURIComponent(label)}` : ''
37
+ }`;
38
+ await Linking.openURL(browserUrl);
39
+ }