@onairos/react-native 3.1.16 → 3.1.17

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 (198) hide show
  1. package/README.md +404 -0
  2. package/lib/commonjs/assets/images/Checkbox.svg +3 -3
  3. package/lib/commonjs/assets/images/EnochE.svg +19 -19
  4. package/lib/commonjs/assets/images/Personalityprofile.svg +3 -3
  5. package/lib/commonjs/assets/images/Personalitytraits.svg +3 -3
  6. package/lib/commonjs/assets/images/Userpreferences.svg +3 -3
  7. package/lib/commonjs/assets/images/arrow.svg +20 -20
  8. package/lib/commonjs/assets/images/basicproficon.svg +43 -43
  9. package/lib/commonjs/assets/images/basicprofile.svg +3 -3
  10. package/lib/commonjs/assets/images/checkmark.svg +4 -4
  11. package/lib/commonjs/assets/images/contentanalysis.svg +3 -3
  12. package/lib/commonjs/assets/images/contenticon.svg +23 -23
  13. package/lib/commonjs/assets/images/personalityicon.svg +18 -18
  14. package/lib/commonjs/assets/images/x-close.svg +3 -3
  15. package/lib/commonjs/components/OnairosButton.js +290 -0
  16. package/lib/commonjs/components/OnairosButton.js.map +1 -0
  17. package/lib/commonjs/components/OnairosSignInButton.js +30 -8
  18. package/lib/commonjs/components/OnairosSignInButton.js.map +1 -1
  19. package/lib/commonjs/components/UniversalOnboarding.js +4 -4
  20. package/lib/commonjs/config/api.js +2 -2
  21. package/lib/commonjs/hooks/useConnections.js +6 -6
  22. package/lib/commonjs/hooks/useUserConnections.js +10 -10
  23. package/lib/commonjs/index.js +9 -10
  24. package/lib/commonjs/index.js.map +1 -1
  25. package/lib/commonjs/services/apiClient.js +35 -35
  26. package/lib/commonjs/services/apiKeyService.js +99 -99
  27. package/lib/commonjs/services/authService.js +82 -82
  28. package/lib/commonjs/services/biometricPinService.js +10 -10
  29. package/lib/commonjs/services/connectedAccountsService.js +32 -32
  30. package/lib/commonjs/services/googleAuthService.js +15 -15
  31. package/lib/commonjs/services/imageCompressionService.js +15 -15
  32. package/lib/commonjs/services/jwtStorageService.js +59 -59
  33. package/lib/commonjs/services/mobileTrainingService.js +14 -14
  34. package/lib/commonjs/services/pinEncryptionService.js +10 -10
  35. package/lib/commonjs/services/pinStorageUtils.js +15 -15
  36. package/lib/commonjs/services/platformAuthService.js +47 -47
  37. package/lib/commonjs/services/storageService.js +31 -31
  38. package/lib/commonjs/services/trainingApiHelpers.js +33 -33
  39. package/lib/commonjs/services/userConnectionsService.js +24 -24
  40. package/lib/commonjs/utils/Portal.js +4 -4
  41. package/lib/commonjs/utils/api.js +24 -24
  42. package/lib/commonjs/utils/auth.js +18 -18
  43. package/lib/commonjs/utils/crypto.js +13 -13
  44. package/lib/commonjs/utils/encryption.js +12 -12
  45. package/lib/commonjs/utils/eventUtils.js +52 -52
  46. package/lib/commonjs/utils/programmaticFlow.js +16 -16
  47. package/lib/commonjs/utils/retryHelper.js +27 -27
  48. package/lib/module/assets/images/Checkbox.svg +3 -3
  49. package/lib/module/assets/images/EnochE.svg +19 -19
  50. package/lib/module/assets/images/Personalityprofile.svg +3 -3
  51. package/lib/module/assets/images/Personalitytraits.svg +3 -3
  52. package/lib/module/assets/images/Userpreferences.svg +3 -3
  53. package/lib/module/assets/images/arrow.svg +20 -20
  54. package/lib/module/assets/images/basicproficon.svg +43 -43
  55. package/lib/module/assets/images/basicprofile.svg +3 -3
  56. package/lib/module/assets/images/checkmark.svg +4 -4
  57. package/lib/module/assets/images/contentanalysis.svg +3 -3
  58. package/lib/module/assets/images/contenticon.svg +23 -23
  59. package/lib/module/assets/images/personalityicon.svg +18 -18
  60. package/lib/module/assets/images/x-close.svg +3 -3
  61. package/lib/module/components/OnairosButton.js +282 -0
  62. package/lib/module/components/OnairosButton.js.map +1 -0
  63. package/lib/module/components/OnairosSignInButton.js +30 -8
  64. package/lib/module/components/OnairosSignInButton.js.map +1 -1
  65. package/lib/module/components/UniversalOnboarding.js +4 -4
  66. package/lib/module/config/api.js +2 -2
  67. package/lib/module/hooks/useConnections.js +6 -6
  68. package/lib/module/hooks/useUserConnections.js +10 -10
  69. package/lib/module/index.js +8 -10
  70. package/lib/module/index.js.map +1 -1
  71. package/lib/module/services/apiClient.js +35 -35
  72. package/lib/module/services/apiKeyService.js +99 -99
  73. package/lib/module/services/authService.js +82 -82
  74. package/lib/module/services/biometricPinService.js +10 -10
  75. package/lib/module/services/connectedAccountsService.js +32 -32
  76. package/lib/module/services/googleAuthService.js +15 -15
  77. package/lib/module/services/imageCompressionService.js +15 -15
  78. package/lib/module/services/jwtStorageService.js +59 -59
  79. package/lib/module/services/mobileTrainingService.js +14 -14
  80. package/lib/module/services/pinEncryptionService.js +10 -10
  81. package/lib/module/services/pinStorageUtils.js +15 -15
  82. package/lib/module/services/platformAuthService.js +47 -47
  83. package/lib/module/services/storageService.js +31 -31
  84. package/lib/module/services/trainingApiHelpers.js +33 -33
  85. package/lib/module/services/userConnectionsService.js +24 -24
  86. package/lib/module/utils/Portal.js +4 -4
  87. package/lib/module/utils/api.js +24 -24
  88. package/lib/module/utils/auth.js +18 -18
  89. package/lib/module/utils/crypto.js +13 -13
  90. package/lib/module/utils/encryption.js +12 -12
  91. package/lib/module/utils/eventUtils.js +52 -52
  92. package/lib/module/utils/programmaticFlow.js +16 -16
  93. package/lib/module/utils/retryHelper.js +27 -27
  94. package/lib/typescript/components/OnairosButton.d.ts +37 -0
  95. package/lib/typescript/components/OnairosButton.d.ts.map +1 -0
  96. package/lib/typescript/components/OnairosSignInButton.d.ts +2 -1
  97. package/lib/typescript/components/OnairosSignInButton.d.ts.map +1 -1
  98. package/lib/typescript/index.d.ts +3 -4
  99. package/lib/typescript/index.d.ts.map +1 -1
  100. package/package.json +163 -163
  101. package/src/api/index.ts +151 -151
  102. package/src/assets/images/Checkbox.svg +3 -3
  103. package/src/assets/images/EnochE.svg +19 -19
  104. package/src/assets/images/Personalityprofile.svg +3 -3
  105. package/src/assets/images/Personalitytraits.svg +3 -3
  106. package/src/assets/images/Userpreferences.svg +3 -3
  107. package/src/assets/images/arrow.svg +20 -20
  108. package/src/assets/images/basicproficon.svg +43 -43
  109. package/src/assets/images/basicprofile.svg +3 -3
  110. package/src/assets/images/checkmark.svg +4 -4
  111. package/src/assets/images/contentanalysis.svg +3 -3
  112. package/src/assets/images/contenticon.svg +23 -23
  113. package/src/assets/images/personalityicon.svg +18 -18
  114. package/src/assets/images/x-close.svg +3 -3
  115. package/src/components/BodyText.tsx +33 -33
  116. package/src/components/BrandMark.tsx +62 -62
  117. package/src/components/CodeInput.tsx +32 -32
  118. package/src/components/DataRequestScreen.tsx +355 -355
  119. package/src/components/EmailInput.tsx +31 -31
  120. package/src/components/EmailVerificationModal.tsx +363 -363
  121. package/src/components/ExistingUserDataConfirmation.tsx +506 -506
  122. package/src/components/GoogleButton.tsx +55 -55
  123. package/src/components/HeadingGroup.tsx +49 -49
  124. package/src/components/ModalHeader.tsx +125 -125
  125. package/src/components/ModalSheet.tsx +57 -57
  126. package/src/components/Onairos.tsx +422 -422
  127. package/src/components/OnairosButton.tsx +339 -0
  128. package/src/components/OnairosSignInButton.tsx +30 -10
  129. package/src/components/Overlay.tsx +506 -506
  130. package/src/components/PersonaImage.tsx +79 -79
  131. package/src/components/PersonaLoadingScreen.tsx +201 -201
  132. package/src/components/PersonalizationConsentScreen.tsx +410 -410
  133. package/src/components/PinCreationScreen.tsx +492 -492
  134. package/src/components/PinInput.tsx +555 -555
  135. package/src/components/PlatformConnectorsStep.tsx +891 -891
  136. package/src/components/PlatformList.tsx +144 -144
  137. package/src/components/PlatformToggle.tsx +226 -226
  138. package/src/components/PrimaryButton.tsx +213 -213
  139. package/src/components/SignInMatchAnimation.tsx +225 -225
  140. package/src/components/SignInStep.tsx +217 -217
  141. package/src/components/TrainingModal.tsx +1047 -1047
  142. package/src/components/UniversalOnboarding.tsx +2887 -2887
  143. package/src/components/VerificationStep.tsx +198 -198
  144. package/src/components/WelcomeScreen.tsx +473 -473
  145. package/src/components/icons/Basicproficon.tsx +30 -30
  146. package/src/components/icons/Basicprofile.tsx +17 -17
  147. package/src/components/icons/Checkbox.tsx +17 -17
  148. package/src/components/icons/Checkmark.tsx +24 -24
  149. package/src/components/icons/Contentanalysis.tsx +17 -17
  150. package/src/components/icons/Contenticon.tsx +30 -30
  151. package/src/components/icons/EnochE.tsx +39 -39
  152. package/src/components/icons/Personalityicon.tsx +22 -22
  153. package/src/components/icons/Personalityprofile.tsx +17 -17
  154. package/src/components/icons/Personalitytraits.tsx +17 -17
  155. package/src/components/icons/Userpreferences.tsx +17 -17
  156. package/src/components/icons/index.ts +12 -12
  157. package/src/components/onboarding/OAuthWebView.tsx +232 -232
  158. package/src/config/api.ts +25 -25
  159. package/src/context/AuthContext.tsx +393 -393
  160. package/src/hooks/useConnectedAccounts.ts +138 -138
  161. package/src/hooks/useConnections.ts +161 -161
  162. package/src/hooks/useCredentials.ts +174 -174
  163. package/src/hooks/useUserConnections.ts +165 -165
  164. package/src/index.js +14 -0
  165. package/src/index.ts +94 -96
  166. package/src/services/apiClient.ts +336 -336
  167. package/src/services/apiKeyService.ts +919 -919
  168. package/src/services/authService.ts +1008 -1008
  169. package/src/services/biometricPinService.ts +192 -192
  170. package/src/services/connectedAccountsService.ts +289 -289
  171. package/src/services/googleAuthService.ts +279 -279
  172. package/src/services/imageCompressionService.ts +302 -302
  173. package/src/services/jwtStorageService.ts +256 -256
  174. package/src/services/mobileTrainingService.ts +203 -203
  175. package/src/services/pinEncryptionService.ts +75 -75
  176. package/src/services/pinStorageUtils.ts +96 -96
  177. package/src/services/platformAuthService.ts +1346 -1346
  178. package/src/services/storageService.ts +451 -451
  179. package/src/services/trainingApiHelpers.ts +66 -66
  180. package/src/services/userConnectionsService.ts +556 -556
  181. package/src/services/youtubeMigrationService.ts +453 -453
  182. package/src/theme/index.ts +239 -239
  183. package/src/types/ambient.d.ts +28 -28
  184. package/src/types/index.ts +265 -265
  185. package/src/types/node-fix.d.ts +18 -18
  186. package/src/types/node-override.d.ts +23 -23
  187. package/src/types/opacity.d.ts +15 -15
  188. package/src/types/types.d.ts +17 -17
  189. package/src/utils/Portal.tsx +82 -82
  190. package/src/utils/api.js +111 -111
  191. package/src/utils/auth.js +103 -103
  192. package/src/utils/crypto.js +59 -59
  193. package/src/utils/encryption.ts +68 -68
  194. package/src/utils/eventUtils.ts +302 -302
  195. package/src/utils/haptics.ts +58 -58
  196. package/src/utils/imagePreloader.ts +2 -2
  197. package/src/utils/programmaticFlow.ts +112 -112
  198. package/src/utils/retryHelper.ts +274 -274
@@ -1,257 +1,257 @@
1
- import AsyncStorage from '@react-native-async-storage/async-storage';
2
- import { Buffer } from 'buffer';
3
-
4
- /**
5
- * JWT Token Storage Service - CORRECTED APPROACH
6
- * Manages 3 DISTINCT JWT token types for different route families
7
- *
8
- * TOKEN TYPES:
9
- * 1. Enoch JWT (enoch_token) - For /enoch/*, /api/auth/*, /mobile-training/enoch
10
- * 2. Onairos JWT (onairos_jwt_token) - For /youtube/*, /gmail/*, social connections
11
- * 3. Auth Token (auth_token) - For context-specific auth flows
12
- */
13
-
14
- export enum TokenType {
15
- ENOCH = 'enoch_token',
16
- ONAIROS = 'onairos_jwt_token',
17
- AUTH = 'auth_token'
18
- }
19
-
20
- /**
21
- * Route-based token mapping
22
- * Determines which token type to use for which routes
23
- */
24
- export const getTokenTypeForRoute = (route: string): TokenType => {
25
- const cleanRoute = route.toLowerCase();
26
-
27
- // Enoch routes - use Enoch JWT
28
- if (cleanRoute.includes('/enoch/') ||
29
- cleanRoute.includes('/api/auth/') ||
30
- cleanRoute.includes('/mobile-training/enoch')) {
31
- return TokenType.ENOCH;
32
- }
33
-
34
- // Onairos routes - use Onairos JWT
35
- if (cleanRoute.includes('/youtube/') ||
36
- cleanRoute.includes('/gmail/') ||
37
- cleanRoute.includes('/connectedaccounts') ||
38
- cleanRoute.includes('/social/')) {
39
- return TokenType.ONAIROS;
40
- }
41
-
42
- // Default to auth token for other routes
43
- return TokenType.AUTH;
44
- };
45
-
46
- /**
47
- * Store JWT token of specific type
48
- * @param tokenType - Type of token to store
49
- * @param token - JWT token to store
50
- * @returns Promise<boolean> - Success status
51
- */
52
- export const storeJWT = async (tokenType: TokenType, token: string): Promise<boolean> => {
53
- try {
54
- if (!token || token.trim() === '') {
55
- console.warn(`⚠️ [JWT Storage] Attempted to store empty/null ${tokenType} token`);
56
- return false;
57
- }
58
-
59
- // Validate JWT format (should have 3 parts separated by dots)
60
- const parts = token.split('.');
61
- if (parts.length !== 3) {
62
- console.warn(`⚠️ [JWT Storage] Invalid JWT format for ${tokenType} - token should have 3 parts`);
63
- return false;
64
- }
65
-
66
- await AsyncStorage.setItem(tokenType, token);
67
- console.log(`✅ [JWT Storage] ${tokenType} token stored successfully`);
68
- return true;
69
- } catch (error) {
70
- console.error(`❌ [JWT Storage] Failed to store ${tokenType} token:`, error);
71
- return false;
72
- }
73
- };
74
-
75
- /**
76
- * Retrieve JWT token of specific type
77
- * @param tokenType - Type of token to retrieve
78
- * @returns Promise<string | null> - JWT token or null if not found
79
- */
80
- export const getJWT = async (tokenType: TokenType): Promise<string | null> => {
81
- try {
82
- const token = await AsyncStorage.getItem(tokenType);
83
-
84
- if (!token) {
85
- console.log(`📭 [JWT Storage] No ${tokenType} token found in storage`);
86
- return null;
87
- }
88
-
89
- // Validate JWT format
90
- if (!isValidJWTFormat(token)) {
91
- console.warn(`⚠️ [JWT Storage] Invalid JWT format found for ${tokenType}, removing`);
92
- await clearJWT(tokenType);
93
- return null;
94
- }
95
-
96
- console.log(`🔐 [JWT Storage] ${tokenType} token retrieved successfully`);
97
- return token;
98
- } catch (error) {
99
- console.error(`❌ [JWT Storage] Failed to retrieve ${tokenType} token:`, error);
100
- return null;
101
- }
102
- };
103
-
104
- /**
105
- * Get JWT token for specific route
106
- * @param route - API route to get token for
107
- * @returns Promise<string | null> - Appropriate JWT token or null
108
- */
109
- export const getJWTForRoute = async (route: string): Promise<string | null> => {
110
- const tokenType = getTokenTypeForRoute(route);
111
- const token = await getJWT(tokenType);
112
-
113
- if (token) {
114
- console.log(`🎯 [JWT Storage] Using ${tokenType} token for route: ${route}`);
115
- } else {
116
- console.warn(`⚠️ [JWT Storage] No ${tokenType} token available for route: ${route}`);
117
- }
118
-
119
- return token;
120
- };
121
-
122
- /**
123
- * Clear JWT token of specific type
124
- * @param tokenType - Type of token to clear
125
- * @returns Promise<boolean> - Success status
126
- */
127
- export const clearJWT = async (tokenType: TokenType): Promise<boolean> => {
128
- try {
129
- await AsyncStorage.removeItem(tokenType);
130
- console.log(`✅ [JWT Storage] ${tokenType} token cleared successfully`);
131
- return true;
132
- } catch (error) {
133
- console.error(`❌ [JWT Storage] Failed to clear ${tokenType} token:`, error);
134
- return false;
135
- }
136
- };
137
-
138
- /**
139
- * Clear all JWT tokens
140
- * @returns Promise<boolean> - Success status
141
- */
142
- export const clearAllJWT = async (): Promise<boolean> => {
143
- try {
144
- await Promise.all([
145
- clearJWT(TokenType.ENOCH),
146
- clearJWT(TokenType.ONAIROS),
147
- clearJWT(TokenType.AUTH)
148
- ]);
149
- console.log('✅ [JWT Storage] All JWT tokens cleared successfully');
150
- return true;
151
- } catch (error) {
152
- console.error('❌ [JWT Storage] Failed to clear all JWT tokens:', error);
153
- return false;
154
- }
155
- };
156
-
157
- /**
158
- * Replace JWT token after verification - route-aware
159
- * @param tokenType - Type of token being replaced
160
- * @param newToken - New JWT token from verification response
161
- * @returns Promise<boolean> - Success status
162
- */
163
- export const replaceJWTAfterVerification = async (tokenType: TokenType, newToken: string): Promise<boolean> => {
164
- try {
165
- console.log(`🔄 [JWT Storage] Replacing ${tokenType} token after verification`);
166
-
167
- if (!newToken || !isValidJWTFormat(newToken)) {
168
- console.error(`❌ [JWT Storage] Invalid ${tokenType} token provided for replacement`);
169
- return false;
170
- }
171
-
172
- // Clear old token first, then store new one
173
- await clearJWT(tokenType);
174
- const stored = await storeJWT(tokenType, newToken);
175
-
176
- if (stored) {
177
- console.log(`✅ [JWT Storage] ${tokenType} token successfully replaced after verification`);
178
- }
179
-
180
- return stored;
181
- } catch (error) {
182
- console.error(`❌ [JWT Storage] Failed to replace ${tokenType} token after verification:`, error);
183
- return false;
184
- }
185
- };
186
-
187
- /**
188
- * Store Enoch JWT token (from email verification)
189
- * @param token - Enoch JWT token
190
- * @returns Promise<boolean> - Success status
191
- */
192
- export const storeEnochJWT = async (token: string): Promise<boolean> => {
193
- return await storeJWT(TokenType.ENOCH, token);
194
- };
195
-
196
- /**
197
- * Store Onairos JWT token (from sign-in/registration)
198
- * @param token - Onairos JWT token
199
- * @returns Promise<boolean> - Success status
200
- */
201
- export const storeOnairosJWT = async (token: string): Promise<boolean> => {
202
- return await storeJWT(TokenType.ONAIROS, token);
203
- };
204
-
205
- /**
206
- * Store Auth token (for context-specific flows)
207
- * @param token - Auth token
208
- * @returns Promise<boolean> - Success status
209
- */
210
- export const storeAuthToken = async (token: string): Promise<boolean> => {
211
- return await storeJWT(TokenType.AUTH, token);
212
- };
213
-
214
- /**
215
- * Validate JWT format
216
- * @param token - Token to validate
217
- * @returns boolean - True if valid JWT format
218
- */
219
- const isValidJWTFormat = (token: string): boolean => {
220
- if (!token || token.length < 20) return false;
221
-
222
- // Check if it's an email address (invalid JWT)
223
- if (token.includes('@') && token.includes('.') && !token.includes('Bearer') && token.length < 100) {
224
- return false;
225
- }
226
-
227
- // Check if it has JWT structure (3 parts separated by dots)
228
- const tokenParts = token.split('.');
229
- if (tokenParts.length !== 3) return false;
230
-
231
- // Additional validation - JWT should be longer than 50 characters typically
232
- if (token.length < 50) return false;
233
-
234
- return true;
235
- };
236
-
237
- /**
238
- * Check if JWT token of specific type exists and is valid
239
- * @param tokenType - Type of token to check
240
- * @returns Promise<boolean> - True if valid token exists
241
- */
242
- export const hasValidJWT = async (tokenType: TokenType): Promise<boolean> => {
243
- const token = await getJWT(tokenType);
244
- return token !== null;
245
- };
246
-
247
- /**
248
- * Get all available tokens (for debugging)
249
- * @returns Promise<Record<TokenType, string | null>> - All tokens
250
- */
251
- export const getAllTokens = async (): Promise<Record<TokenType, string | null>> => {
252
- return {
253
- [TokenType.ENOCH]: await getJWT(TokenType.ENOCH),
254
- [TokenType.ONAIROS]: await getJWT(TokenType.ONAIROS),
255
- [TokenType.AUTH]: await getJWT(TokenType.AUTH)
256
- };
1
+ import AsyncStorage from '@react-native-async-storage/async-storage';
2
+ import { Buffer } from 'buffer';
3
+
4
+ /**
5
+ * JWT Token Storage Service - CORRECTED APPROACH
6
+ * Manages 3 DISTINCT JWT token types for different route families
7
+ *
8
+ * TOKEN TYPES:
9
+ * 1. Enoch JWT (enoch_token) - For /enoch/*, /api/auth/*, /mobile-training/enoch
10
+ * 2. Onairos JWT (onairos_jwt_token) - For /youtube/*, /gmail/*, social connections
11
+ * 3. Auth Token (auth_token) - For context-specific auth flows
12
+ */
13
+
14
+ export enum TokenType {
15
+ ENOCH = 'enoch_token',
16
+ ONAIROS = 'onairos_jwt_token',
17
+ AUTH = 'auth_token'
18
+ }
19
+
20
+ /**
21
+ * Route-based token mapping
22
+ * Determines which token type to use for which routes
23
+ */
24
+ export const getTokenTypeForRoute = (route: string): TokenType => {
25
+ const cleanRoute = route.toLowerCase();
26
+
27
+ // Enoch routes - use Enoch JWT
28
+ if (cleanRoute.includes('/enoch/') ||
29
+ cleanRoute.includes('/api/auth/') ||
30
+ cleanRoute.includes('/mobile-training/enoch')) {
31
+ return TokenType.ENOCH;
32
+ }
33
+
34
+ // Onairos routes - use Onairos JWT
35
+ if (cleanRoute.includes('/youtube/') ||
36
+ cleanRoute.includes('/gmail/') ||
37
+ cleanRoute.includes('/connectedaccounts') ||
38
+ cleanRoute.includes('/social/')) {
39
+ return TokenType.ONAIROS;
40
+ }
41
+
42
+ // Default to auth token for other routes
43
+ return TokenType.AUTH;
44
+ };
45
+
46
+ /**
47
+ * Store JWT token of specific type
48
+ * @param tokenType - Type of token to store
49
+ * @param token - JWT token to store
50
+ * @returns Promise<boolean> - Success status
51
+ */
52
+ export const storeJWT = async (tokenType: TokenType, token: string): Promise<boolean> => {
53
+ try {
54
+ if (!token || token.trim() === '') {
55
+ console.warn(`⚠️ [JWT Storage] Attempted to store empty/null ${tokenType} token`);
56
+ return false;
57
+ }
58
+
59
+ // Validate JWT format (should have 3 parts separated by dots)
60
+ const parts = token.split('.');
61
+ if (parts.length !== 3) {
62
+ console.warn(`⚠️ [JWT Storage] Invalid JWT format for ${tokenType} - token should have 3 parts`);
63
+ return false;
64
+ }
65
+
66
+ await AsyncStorage.setItem(tokenType, token);
67
+ console.log(`✅ [JWT Storage] ${tokenType} token stored successfully`);
68
+ return true;
69
+ } catch (error) {
70
+ console.error(`❌ [JWT Storage] Failed to store ${tokenType} token:`, error);
71
+ return false;
72
+ }
73
+ };
74
+
75
+ /**
76
+ * Retrieve JWT token of specific type
77
+ * @param tokenType - Type of token to retrieve
78
+ * @returns Promise<string | null> - JWT token or null if not found
79
+ */
80
+ export const getJWT = async (tokenType: TokenType): Promise<string | null> => {
81
+ try {
82
+ const token = await AsyncStorage.getItem(tokenType);
83
+
84
+ if (!token) {
85
+ console.log(`📭 [JWT Storage] No ${tokenType} token found in storage`);
86
+ return null;
87
+ }
88
+
89
+ // Validate JWT format
90
+ if (!isValidJWTFormat(token)) {
91
+ console.warn(`⚠️ [JWT Storage] Invalid JWT format found for ${tokenType}, removing`);
92
+ await clearJWT(tokenType);
93
+ return null;
94
+ }
95
+
96
+ console.log(`🔐 [JWT Storage] ${tokenType} token retrieved successfully`);
97
+ return token;
98
+ } catch (error) {
99
+ console.error(`❌ [JWT Storage] Failed to retrieve ${tokenType} token:`, error);
100
+ return null;
101
+ }
102
+ };
103
+
104
+ /**
105
+ * Get JWT token for specific route
106
+ * @param route - API route to get token for
107
+ * @returns Promise<string | null> - Appropriate JWT token or null
108
+ */
109
+ export const getJWTForRoute = async (route: string): Promise<string | null> => {
110
+ const tokenType = getTokenTypeForRoute(route);
111
+ const token = await getJWT(tokenType);
112
+
113
+ if (token) {
114
+ console.log(`🎯 [JWT Storage] Using ${tokenType} token for route: ${route}`);
115
+ } else {
116
+ console.warn(`⚠️ [JWT Storage] No ${tokenType} token available for route: ${route}`);
117
+ }
118
+
119
+ return token;
120
+ };
121
+
122
+ /**
123
+ * Clear JWT token of specific type
124
+ * @param tokenType - Type of token to clear
125
+ * @returns Promise<boolean> - Success status
126
+ */
127
+ export const clearJWT = async (tokenType: TokenType): Promise<boolean> => {
128
+ try {
129
+ await AsyncStorage.removeItem(tokenType);
130
+ console.log(`✅ [JWT Storage] ${tokenType} token cleared successfully`);
131
+ return true;
132
+ } catch (error) {
133
+ console.error(`❌ [JWT Storage] Failed to clear ${tokenType} token:`, error);
134
+ return false;
135
+ }
136
+ };
137
+
138
+ /**
139
+ * Clear all JWT tokens
140
+ * @returns Promise<boolean> - Success status
141
+ */
142
+ export const clearAllJWT = async (): Promise<boolean> => {
143
+ try {
144
+ await Promise.all([
145
+ clearJWT(TokenType.ENOCH),
146
+ clearJWT(TokenType.ONAIROS),
147
+ clearJWT(TokenType.AUTH)
148
+ ]);
149
+ console.log('✅ [JWT Storage] All JWT tokens cleared successfully');
150
+ return true;
151
+ } catch (error) {
152
+ console.error('❌ [JWT Storage] Failed to clear all JWT tokens:', error);
153
+ return false;
154
+ }
155
+ };
156
+
157
+ /**
158
+ * Replace JWT token after verification - route-aware
159
+ * @param tokenType - Type of token being replaced
160
+ * @param newToken - New JWT token from verification response
161
+ * @returns Promise<boolean> - Success status
162
+ */
163
+ export const replaceJWTAfterVerification = async (tokenType: TokenType, newToken: string): Promise<boolean> => {
164
+ try {
165
+ console.log(`🔄 [JWT Storage] Replacing ${tokenType} token after verification`);
166
+
167
+ if (!newToken || !isValidJWTFormat(newToken)) {
168
+ console.error(`❌ [JWT Storage] Invalid ${tokenType} token provided for replacement`);
169
+ return false;
170
+ }
171
+
172
+ // Clear old token first, then store new one
173
+ await clearJWT(tokenType);
174
+ const stored = await storeJWT(tokenType, newToken);
175
+
176
+ if (stored) {
177
+ console.log(`✅ [JWT Storage] ${tokenType} token successfully replaced after verification`);
178
+ }
179
+
180
+ return stored;
181
+ } catch (error) {
182
+ console.error(`❌ [JWT Storage] Failed to replace ${tokenType} token after verification:`, error);
183
+ return false;
184
+ }
185
+ };
186
+
187
+ /**
188
+ * Store Enoch JWT token (from email verification)
189
+ * @param token - Enoch JWT token
190
+ * @returns Promise<boolean> - Success status
191
+ */
192
+ export const storeEnochJWT = async (token: string): Promise<boolean> => {
193
+ return await storeJWT(TokenType.ENOCH, token);
194
+ };
195
+
196
+ /**
197
+ * Store Onairos JWT token (from sign-in/registration)
198
+ * @param token - Onairos JWT token
199
+ * @returns Promise<boolean> - Success status
200
+ */
201
+ export const storeOnairosJWT = async (token: string): Promise<boolean> => {
202
+ return await storeJWT(TokenType.ONAIROS, token);
203
+ };
204
+
205
+ /**
206
+ * Store Auth token (for context-specific flows)
207
+ * @param token - Auth token
208
+ * @returns Promise<boolean> - Success status
209
+ */
210
+ export const storeAuthToken = async (token: string): Promise<boolean> => {
211
+ return await storeJWT(TokenType.AUTH, token);
212
+ };
213
+
214
+ /**
215
+ * Validate JWT format
216
+ * @param token - Token to validate
217
+ * @returns boolean - True if valid JWT format
218
+ */
219
+ const isValidJWTFormat = (token: string): boolean => {
220
+ if (!token || token.length < 20) return false;
221
+
222
+ // Check if it's an email address (invalid JWT)
223
+ if (token.includes('@') && token.includes('.') && !token.includes('Bearer') && token.length < 100) {
224
+ return false;
225
+ }
226
+
227
+ // Check if it has JWT structure (3 parts separated by dots)
228
+ const tokenParts = token.split('.');
229
+ if (tokenParts.length !== 3) return false;
230
+
231
+ // Additional validation - JWT should be longer than 50 characters typically
232
+ if (token.length < 50) return false;
233
+
234
+ return true;
235
+ };
236
+
237
+ /**
238
+ * Check if JWT token of specific type exists and is valid
239
+ * @param tokenType - Type of token to check
240
+ * @returns Promise<boolean> - True if valid token exists
241
+ */
242
+ export const hasValidJWT = async (tokenType: TokenType): Promise<boolean> => {
243
+ const token = await getJWT(tokenType);
244
+ return token !== null;
245
+ };
246
+
247
+ /**
248
+ * Get all available tokens (for debugging)
249
+ * @returns Promise<Record<TokenType, string | null>> - All tokens
250
+ */
251
+ export const getAllTokens = async (): Promise<Record<TokenType, string | null>> => {
252
+ return {
253
+ [TokenType.ENOCH]: await getJWT(TokenType.ENOCH),
254
+ [TokenType.ONAIROS]: await getJWT(TokenType.ONAIROS),
255
+ [TokenType.AUTH]: await getJWT(TokenType.AUTH)
256
+ };
257
257
  };