@multiplayer-app/session-recorder-react-native 0.0.1-alpha.1 → 0.0.1-alpha.10

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 (234) hide show
  1. package/RRWEB_INTEGRATION.md +336 -0
  2. package/VIEWSHOT_INTEGRATION_TEST.md +123 -0
  3. package/copy-react-native-dist.sh +38 -0
  4. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.d.ts +6 -0
  5. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js +1 -0
  6. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js.map +1 -0
  7. package/dist/components/GestureCaptureWrapper/index.d.ts +1 -0
  8. package/dist/components/GestureCaptureWrapper/index.js +1 -0
  9. package/dist/components/GestureCaptureWrapper/index.js.map +1 -0
  10. package/dist/components/GestureCaptureWrapper.d.ts +6 -0
  11. package/dist/components/GestureCaptureWrapper.js +1 -0
  12. package/dist/components/GestureCaptureWrapper.js.map +1 -0
  13. package/dist/components/ScreenRecorderView/ScreenRecorderView.d.ts +5 -0
  14. package/dist/components/ScreenRecorderView/ScreenRecorderView.js +1 -0
  15. package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -0
  16. package/dist/components/ScreenRecorderView/index.d.ts +1 -0
  17. package/dist/components/ScreenRecorderView/index.js +1 -0
  18. package/dist/components/ScreenRecorderView/index.js.map +1 -0
  19. package/dist/components/index.d.ts +1 -0
  20. package/dist/components/index.js +1 -0
  21. package/dist/components/index.js.map +1 -0
  22. package/dist/config/constants.d.ts +18 -0
  23. package/dist/config/constants.js +1 -0
  24. package/dist/config/constants.js.map +1 -0
  25. package/dist/config/defaults.d.ts +4 -0
  26. package/dist/config/defaults.js +1 -0
  27. package/dist/config/defaults.js.map +1 -0
  28. package/dist/config/index.d.ts +5 -0
  29. package/dist/config/index.js +1 -0
  30. package/dist/config/index.js.map +1 -0
  31. package/dist/config/masking.d.ts +2 -30
  32. package/dist/config/masking.js +1 -1
  33. package/dist/config/masking.js.map +1 -1
  34. package/dist/config/session-recorder.d.ts +2 -0
  35. package/dist/config/session-recorder.js +1 -0
  36. package/dist/config/session-recorder.js.map +1 -0
  37. package/dist/config/validators.d.ts +10 -0
  38. package/dist/config/validators.js +1 -0
  39. package/dist/config/validators.js.map +1 -0
  40. package/dist/context/SessionRecorderContext.d.ts +12 -0
  41. package/dist/context/SessionRecorderContext.js +1 -0
  42. package/dist/context/SessionRecorderContext.js.map +1 -0
  43. package/dist/expo.d.ts +5 -9
  44. package/dist/expo.js +1 -1
  45. package/dist/expo.js.map +1 -1
  46. package/dist/index.d.ts +6 -10
  47. package/dist/index.js +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/otel/helpers.d.ts +45 -3
  50. package/dist/otel/helpers.js +1 -1
  51. package/dist/otel/helpers.js.map +1 -1
  52. package/dist/otel/index.d.ts +4 -25
  53. package/dist/otel/index.js +1 -1
  54. package/dist/otel/index.js.map +1 -1
  55. package/dist/otel/instrumentations/gestureInstrumentation.js +1 -1
  56. package/dist/otel/instrumentations/gestureInstrumentation.js.map +1 -1
  57. package/dist/otel/instrumentations/index.d.ts +3 -4
  58. package/dist/otel/instrumentations/index.js +1 -1
  59. package/dist/otel/instrumentations/index.js.map +1 -1
  60. package/dist/otel/instrumentations/reactNativeInstrumentation.js +1 -1
  61. package/dist/otel/instrumentations/reactNativeInstrumentation.js.map +1 -1
  62. package/dist/otel/instrumentations/reactNavigationInstrumentation.d.ts +1 -0
  63. package/dist/otel/instrumentations/reactNavigationInstrumentation.js +1 -1
  64. package/dist/otel/instrumentations/reactNavigationInstrumentation.js.map +1 -1
  65. package/dist/patch/index.d.ts +1 -0
  66. package/dist/patch/index.js +1 -0
  67. package/dist/patch/index.js.map +1 -0
  68. package/dist/patch/xhr.d.ts +2 -0
  69. package/dist/patch/xhr.js +1 -0
  70. package/dist/patch/xhr.js.map +1 -0
  71. package/dist/recorder/eventExporter.d.ts +21 -0
  72. package/dist/recorder/eventExporter.js +1 -0
  73. package/dist/recorder/eventExporter.js.map +1 -0
  74. package/dist/recorder/gestureHandlerRecorder.d.ts +19 -0
  75. package/dist/recorder/gestureHandlerRecorder.js +1 -0
  76. package/dist/recorder/gestureHandlerRecorder.js.map +1 -0
  77. package/dist/recorder/gestureRecorder.d.ts +68 -11
  78. package/dist/recorder/gestureRecorder.js +1 -1
  79. package/dist/recorder/gestureRecorder.js.map +1 -1
  80. package/dist/recorder/index.d.ts +60 -6
  81. package/dist/recorder/index.js +1 -1
  82. package/dist/recorder/index.js.map +1 -1
  83. package/dist/recorder/navigationTracker.js +1 -1
  84. package/dist/recorder/navigationTracker.js.map +1 -1
  85. package/dist/recorder/screenRecorder.d.ts +79 -10
  86. package/dist/recorder/screenRecorder.js +1 -1
  87. package/dist/recorder/screenRecorder.js.map +1 -1
  88. package/dist/services/api.service.d.ts +62 -10
  89. package/dist/services/api.service.js +1 -1
  90. package/dist/services/api.service.js.map +1 -1
  91. package/dist/services/storage.service.d.ts +23 -16
  92. package/dist/services/storage.service.js +1 -1
  93. package/dist/services/storage.service.js.map +1 -1
  94. package/dist/session-recorder.d.ts +166 -0
  95. package/dist/session-recorder.js +1 -0
  96. package/dist/session-recorder.js.map +1 -0
  97. package/dist/types/index.d.ts +15 -76
  98. package/dist/types/index.js +1 -1
  99. package/dist/types/index.js.map +1 -1
  100. package/dist/types/rrweb.d.ts +118 -0
  101. package/dist/types/rrweb.js +1 -0
  102. package/dist/types/rrweb.js.map +1 -0
  103. package/dist/types/session-recorder.d.ts +366 -0
  104. package/dist/types/session-recorder.js +1 -0
  105. package/dist/types/session-recorder.js.map +1 -0
  106. package/dist/types/session.d.ts +59 -0
  107. package/dist/types/session.js +1 -0
  108. package/dist/types/session.js.map +1 -0
  109. package/dist/utils/app-metadata.d.ts +16 -0
  110. package/dist/utils/app-metadata.js +1 -0
  111. package/dist/utils/app-metadata.js.map +1 -0
  112. package/dist/utils/index.d.ts +7 -0
  113. package/dist/utils/index.js +1 -0
  114. package/dist/utils/index.js.map +1 -0
  115. package/dist/utils/logger.d.ts +112 -0
  116. package/dist/utils/logger.js +1 -0
  117. package/dist/utils/logger.js.map +1 -0
  118. package/dist/utils/platform.d.ts +37 -0
  119. package/dist/utils/platform.js +1 -1
  120. package/dist/utils/platform.js.map +1 -1
  121. package/dist/utils/request-utils.d.ts +21 -0
  122. package/dist/utils/request-utils.js +1 -0
  123. package/dist/utils/request-utils.js.map +1 -0
  124. package/dist/utils/rrweb-events.d.ts +65 -0
  125. package/dist/utils/rrweb-events.js +1 -0
  126. package/dist/utils/rrweb-events.js.map +1 -0
  127. package/dist/utils/session.d.ts +5 -0
  128. package/dist/utils/session.js +1 -0
  129. package/dist/utils/session.js.map +1 -0
  130. package/dist/utils/time.d.ts +4 -0
  131. package/dist/utils/time.js +1 -0
  132. package/dist/utils/time.js.map +1 -0
  133. package/dist/utils/type-utils.d.ts +16 -0
  134. package/dist/utils/type-utils.js +1 -0
  135. package/dist/utils/type-utils.js.map +1 -0
  136. package/dist/version.d.ts +1 -1
  137. package/dist/version.js +1 -1
  138. package/dist/version.js.map +1 -1
  139. package/docs/AUTO_METADATA_DETECTION.md +108 -0
  140. package/package.json +10 -9
  141. package/scripts/generate-app-metadata.js +173 -0
  142. package/src/components/GestureCaptureWrapper/GestureCaptureWrapper.tsx +86 -0
  143. package/src/components/GestureCaptureWrapper/index.ts +1 -0
  144. package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +72 -0
  145. package/src/components/ScreenRecorderView/index.ts +1 -0
  146. package/src/components/index.ts +1 -0
  147. package/src/config/constants.ts +60 -0
  148. package/src/config/defaults.ts +82 -0
  149. package/src/config/index.ts +6 -0
  150. package/src/config/masking.ts +10 -61
  151. package/src/config/session-recorder.ts +55 -0
  152. package/src/config/validators.ts +31 -0
  153. package/src/context/SessionRecorderContext.tsx +75 -0
  154. package/src/expo.ts +7 -37
  155. package/src/index.ts +14 -17
  156. package/src/otel/helpers.ts +265 -11
  157. package/src/otel/index.ts +37 -247
  158. package/src/otel/instrumentations/index.ts +82 -53
  159. package/src/patch/index.ts +1 -0
  160. package/src/patch/xhr.ts +142 -0
  161. package/src/recorder/eventExporter.ts +141 -0
  162. package/src/recorder/gestureRecorder.ts +194 -125
  163. package/src/recorder/index.ts +132 -24
  164. package/src/recorder/navigationTracker.ts +12 -10
  165. package/src/recorder/screenRecorder.ts +242 -155
  166. package/src/services/api.service.ts +170 -45
  167. package/src/services/storage.service.ts +102 -74
  168. package/src/session-recorder.ts +600 -0
  169. package/src/types/index.ts +19 -79
  170. package/src/types/session-recorder.ts +423 -0
  171. package/src/types/session.ts +65 -0
  172. package/src/utils/app-metadata.ts +31 -0
  173. package/src/utils/index.ts +8 -0
  174. package/src/utils/logger.ts +225 -0
  175. package/src/utils/platform.ts +321 -6
  176. package/src/utils/request-utils.ts +61 -0
  177. package/src/utils/rrweb-events.ts +309 -0
  178. package/src/utils/session.ts +18 -0
  179. package/src/utils/time.ts +17 -0
  180. package/src/utils/type-utils.ts +75 -0
  181. package/src/version.ts +1 -1
  182. package/dist/sessionRecorder.d.ts +0 -54
  183. package/dist/sessionRecorder.js +0 -1
  184. package/dist/sessionRecorder.js.map +0 -1
  185. package/examples/sample-expo-app/README.md +0 -142
  186. package/examples/sample-expo-app/app/(tabs)/_layout.tsx +0 -60
  187. package/examples/sample-expo-app/app/(tabs)/explore.tsx +0 -110
  188. package/examples/sample-expo-app/app/(tabs)/index.tsx +0 -125
  189. package/examples/sample-expo-app/app/(tabs)/posts.tsx +0 -96
  190. package/examples/sample-expo-app/app/(tabs)/users.tsx +0 -131
  191. package/examples/sample-expo-app/app/+not-found.tsx +0 -32
  192. package/examples/sample-expo-app/app/_layout.tsx +0 -53
  193. package/examples/sample-expo-app/app/post/[id].tsx +0 -199
  194. package/examples/sample-expo-app/app/user/[id].tsx +0 -270
  195. package/examples/sample-expo-app/app.json +0 -42
  196. package/examples/sample-expo-app/assets/fonts/SpaceMono-Regular.ttf +0 -0
  197. package/examples/sample-expo-app/assets/images/adaptive-icon.png +0 -0
  198. package/examples/sample-expo-app/assets/images/favicon.png +0 -0
  199. package/examples/sample-expo-app/assets/images/icon.png +0 -0
  200. package/examples/sample-expo-app/assets/images/partial-react-logo.png +0 -0
  201. package/examples/sample-expo-app/assets/images/react-logo.png +0 -0
  202. package/examples/sample-expo-app/assets/images/react-logo@2x.png +0 -0
  203. package/examples/sample-expo-app/assets/images/react-logo@3x.png +0 -0
  204. package/examples/sample-expo-app/assets/images/splash-icon.png +0 -0
  205. package/examples/sample-expo-app/components/Collapsible.tsx +0 -45
  206. package/examples/sample-expo-app/components/ErrorView.tsx +0 -52
  207. package/examples/sample-expo-app/components/ExternalLink.tsx +0 -24
  208. package/examples/sample-expo-app/components/HapticTab.tsx +0 -18
  209. package/examples/sample-expo-app/components/HelloWave.tsx +0 -40
  210. package/examples/sample-expo-app/components/LoadingSpinner.tsx +0 -34
  211. package/examples/sample-expo-app/components/ParallaxScrollView.tsx +0 -82
  212. package/examples/sample-expo-app/components/ThemedText.tsx +0 -60
  213. package/examples/sample-expo-app/components/ThemedView.tsx +0 -14
  214. package/examples/sample-expo-app/components/ui/IconSymbol.ios.tsx +0 -32
  215. package/examples/sample-expo-app/components/ui/IconSymbol.tsx +0 -41
  216. package/examples/sample-expo-app/components/ui/TabBarBackground.ios.tsx +0 -19
  217. package/examples/sample-expo-app/components/ui/TabBarBackground.tsx +0 -6
  218. package/examples/sample-expo-app/constants/Colors.ts +0 -26
  219. package/examples/sample-expo-app/eslint.config.js +0 -10
  220. package/examples/sample-expo-app/hooks/useApi.ts +0 -41
  221. package/examples/sample-expo-app/hooks/useColorScheme.ts +0 -1
  222. package/examples/sample-expo-app/hooks/useColorScheme.web.ts +0 -21
  223. package/examples/sample-expo-app/hooks/useThemeColor.ts +0 -21
  224. package/examples/sample-expo-app/metro.config.js +0 -26
  225. package/examples/sample-expo-app/package-lock.json +0 -26296
  226. package/examples/sample-expo-app/package.json +0 -59
  227. package/examples/sample-expo-app/scripts/reset-project.js +0 -112
  228. package/examples/sample-expo-app/services/api.ts +0 -98
  229. package/examples/sample-expo-app/tsconfig.json +0 -17
  230. package/examples/sample-expo-app/utils/navigation.ts +0 -19
  231. package/src/otel/instrumentations/gestureInstrumentation.ts +0 -141
  232. package/src/otel/instrumentations/reactNativeInstrumentation.ts +0 -164
  233. package/src/otel/instrumentations/reactNavigationInstrumentation.ts +0 -114
  234. package/src/sessionRecorder.ts +0 -367
@@ -1,78 +1,203 @@
1
- import { ISession, SessionRecorderOptions } from '../types'
2
-
3
- // Type definitions for fetch API
4
- type RequestInit = {
5
- method?: string
6
- headers?: Record<string, string>
7
- body?: string
8
- signal?: AbortSignal
9
- }
1
+ import { SessionRecorderOptions, IResourceAttributes, ISessionAttributes } from '../types'
10
2
 
11
3
  export interface StartSessionRequest {
12
- application: string
13
- version: string
14
- environment: string
15
- metadata?: Record<string, any>
4
+ name?: string
5
+ stoppedAt?: string | number
6
+ sessionAttributes?: ISessionAttributes
7
+ resourceAttributes?: IResourceAttributes
8
+ debugSessionData?: Record<string, any>
16
9
  }
17
10
 
18
11
  export interface StopSessionRequest {
19
- sessionId: string
20
- comment?: string
12
+ sessionAttributes?: ISessionAttributes
13
+ stoppedAt: string | number
21
14
  }
22
15
 
23
16
  export class ApiService {
24
17
  private config?: SessionRecorderOptions
25
18
  private baseUrl: string = 'https://api.multiplayer.app'
26
19
 
20
+ constructor() {
21
+ this.config = {
22
+ apiKey: '',
23
+ apiBaseUrl: '',
24
+ exporterEndpoint: '',
25
+ version: '',
26
+ application: '',
27
+ environment: '',
28
+ } as SessionRecorderOptions
29
+ }
30
+
27
31
  init(config: SessionRecorderOptions): void {
28
- this.config = config
32
+
33
+ this.config = {
34
+ ...this.config,
35
+ ...config,
36
+ }
29
37
  if (config.apiBaseUrl) {
30
38
  this.baseUrl = config.apiBaseUrl
31
39
  }
32
40
  }
33
41
 
34
- private async makeRequest<T>(
35
- endpoint: string,
36
- options: RequestInit = {},
37
- ): Promise<T> {
38
- if (!this.config?.apiKey) {
39
- throw new Error('API key not configured')
42
+ /**
43
+ * Update the API service configuration
44
+ * @param config - Partial configuration to update
45
+ */
46
+ public updateConfigs(config: Partial<SessionRecorderOptions>) {
47
+ if (this.config) {
48
+ this.config = { ...this.config, ...config }
40
49
  }
50
+ }
41
51
 
42
- const url = `${this.baseUrl}${endpoint}`
43
- const response = await fetch(url, {
44
- ...options,
52
+ /**
53
+ * Make a request to the session debugger API
54
+ * @param path - API endpoint path (relative to the base URL)
55
+ * @param method - HTTP method (GET, POST, PATCH, etc.)
56
+ * @param body - request payload
57
+ * @param signal - AbortSignal to set request's signal
58
+ */
59
+ private async makeRequest(
60
+ path: string,
61
+ method: string,
62
+ body?: any,
63
+ signal?: AbortSignal,
64
+ ): Promise<any> {
65
+ const url = `${this.baseUrl}/v0/radar${path}`
66
+ const params = {
67
+ method,
68
+ body: body ? JSON.stringify(body) : null,
45
69
  headers: {
46
70
  'Content-Type': 'application/json',
47
- 'Authorization': `Bearer ${this.config.apiKey}`,
48
- ...options.headers,
71
+ ...(this.config?.apiKey && { 'X-Api-Key': this.config.apiKey }),
49
72
  },
50
- })
73
+ }
74
+
75
+ try {
76
+ const response = await fetch(url, {
77
+ ...params,
78
+ signal,
79
+ })
80
+
81
+ if (!response.ok) {
82
+ throw new Error('Network response was not ok: ' + response.statusText)
83
+ }
51
84
 
52
- if (!response.ok) {
53
- throw new Error(`API request failed: ${response.statusText}`)
85
+ if (response.status === 204) {
86
+ return null
87
+ }
88
+
89
+ return await response.json()
90
+ } catch (error: any) {
91
+ if (error?.name === 'AbortError') {
92
+ throw new Error('Request aborted')
93
+ }
94
+ throw new Error('Error making request: ' + error.message)
54
95
  }
96
+ }
97
+
98
+ /**
99
+ * Start a new debug session
100
+ * @param request - Session start request data
101
+ * @param signal - Optional AbortSignal for request cancellation
102
+ */
103
+ async startSession(
104
+ request: StartSessionRequest,
105
+ signal?: AbortSignal,
106
+ ): Promise<any> {
107
+ return this.makeRequest(
108
+ '/debug-sessions/start',
109
+ 'POST',
110
+ request,
111
+ signal,
112
+ )
113
+ }
114
+
115
+ /**
116
+ * Stop an active debug session
117
+ * @param sessionId - ID of the session to stop
118
+ * @param request - Session stop request data
119
+ */
120
+ async stopSession(
121
+ sessionId: string,
122
+ request: StopSessionRequest,
123
+ ): Promise<any> {
124
+ return this.makeRequest(
125
+ `/debug-sessions/${sessionId}/stop`,
126
+ 'PATCH',
127
+ request,
128
+ )
129
+ }
130
+
131
+ /**
132
+ * Cancel an active debug session
133
+ * @param sessionId - ID of the session to cancel
134
+ */
135
+ async cancelSession(sessionId: string): Promise<any> {
136
+ return this.makeRequest(
137
+ `/debug-sessions/${sessionId}/cancel`,
138
+ 'DELETE',
139
+ )
140
+ }
55
141
 
56
- return response.json()
142
+ /**
143
+ * Start a new continuous debug session
144
+ * @param request - Session start request data
145
+ * @param signal - Optional AbortSignal for request cancellation
146
+ */
147
+ async startContinuousDebugSession(
148
+ request: StartSessionRequest,
149
+ signal?: AbortSignal,
150
+ ): Promise<any> {
151
+ return this.makeRequest(
152
+ '/continuous-debug-sessions/start',
153
+ 'POST',
154
+ request,
155
+ signal,
156
+ )
57
157
  }
58
158
 
59
- async startSession(request: StartSessionRequest): Promise<ISession> {
60
- return this.makeRequest<ISession>('/sessions', {
61
- method: 'POST',
62
- body: JSON.stringify(request),
63
- })
159
+ /**
160
+ * Save a continuous debug session
161
+ * @param sessionId - ID of the session to save
162
+ * @param request - Session save request data
163
+ * @param signal - Optional AbortSignal for request cancellation
164
+ */
165
+ async saveContinuousDebugSession(
166
+ sessionId: string,
167
+ request: StartSessionRequest,
168
+ signal?: AbortSignal,
169
+ ): Promise<any> {
170
+ return this.makeRequest(
171
+ `/continuous-debug-sessions/${sessionId}/save`,
172
+ 'POST',
173
+ request,
174
+ signal,
175
+ )
64
176
  }
65
177
 
66
- async stopSession(request: StopSessionRequest): Promise<void> {
67
- return this.makeRequest<void>(`/sessions/${request.sessionId}/stop`, {
68
- method: 'POST',
69
- body: JSON.stringify({ comment: request.comment }),
70
- })
178
+ /**
179
+ * Stop an active continuous debug session
180
+ * @param sessionId - ID of the session to stop
181
+ */
182
+ async stopContinuousDebugSession(sessionId: string): Promise<any> {
183
+ return this.makeRequest(
184
+ `/continuous-debug-sessions/${sessionId}/cancel`,
185
+ 'DELETE',
186
+ )
71
187
  }
72
188
 
73
- async saveSession(sessionId: string): Promise<ISession> {
74
- return this.makeRequest<ISession>(`/sessions/${sessionId}/save`, {
75
- method: 'POST',
76
- })
189
+ /**
190
+ * Check debug session should be started remotely
191
+ */
192
+ async checkRemoteSession(
193
+ requestBody: StartSessionRequest,
194
+ signal?: AbortSignal,
195
+ ): Promise<{ state: 'START' | 'STOP' }> {
196
+ return this.makeRequest(
197
+ '/remote-debug-session/check',
198
+ 'POST',
199
+ requestBody,
200
+ signal,
201
+ )
77
202
  }
78
203
  }
@@ -1,6 +1,13 @@
1
1
  import AsyncStorage from '@react-native-async-storage/async-storage'
2
- import { ISession, SessionState } from '../types'
3
2
  import { SessionType } from '@multiplayer-app/session-recorder-common'
3
+ import { ISession, SessionState } from '../types'
4
+
5
+ interface CacheData {
6
+ sessionId: string | null
7
+ sessionType: SessionType | null
8
+ sessionState: SessionState | null
9
+ sessionObject: ISession | null
10
+ }
4
11
 
5
12
  export class StorageService {
6
13
  private static readonly SESSION_ID_KEY = 'session_id'
@@ -8,123 +15,144 @@ export class StorageService {
8
15
  private static readonly SESSION_STATE_KEY = 'session_state'
9
16
  private static readonly SESSION_OBJECT_KEY = 'session_object'
10
17
 
11
- async saveSessionId(sessionId: string): Promise<void> {
12
- try {
13
- await AsyncStorage.setItem(StorageService.SESSION_ID_KEY, sessionId)
14
- } catch (error) {
15
- console.error('Failed to save session ID:', error)
16
- throw error
17
- }
18
+ private static cache: CacheData = {
19
+ sessionId: null,
20
+ sessionType: null,
21
+ sessionState: null,
22
+ sessionObject: null,
23
+ }
24
+
25
+ private static cacheInitialized = false
26
+
27
+ constructor() {
28
+ StorageService.initialize()
18
29
  }
19
30
 
20
- async getSessionId(): Promise<string | null> {
31
+ private static async initializeCache(): Promise<void> {
32
+ if (StorageService.cacheInitialized) return
33
+
21
34
  try {
22
- return await AsyncStorage.getItem(StorageService.SESSION_ID_KEY)
35
+ const [sessionId, sessionType, sessionState, sessionObject] = await Promise.all([
36
+ AsyncStorage.getItem(StorageService.SESSION_ID_KEY),
37
+ AsyncStorage.getItem(StorageService.SESSION_TYPE_KEY),
38
+ AsyncStorage.getItem(StorageService.SESSION_STATE_KEY),
39
+ AsyncStorage.getItem(StorageService.SESSION_OBJECT_KEY),
40
+ ])
41
+
42
+ StorageService.cache = {
43
+ sessionId,
44
+ sessionType: sessionType as SessionType | null,
45
+ sessionState: sessionState as SessionState | null,
46
+ sessionObject: sessionObject ? JSON.parse(sessionObject) : null,
47
+ }
48
+ StorageService.cacheInitialized = true
23
49
  } catch (error) {
24
- console.error('Failed to get session ID:', error)
25
- return null
50
+ // Failed to initialize cache - silently continue
51
+ StorageService.cacheInitialized = true // Mark as initialized to prevent retries
26
52
  }
27
53
  }
28
54
 
29
- async saveSessionType(sessionType: SessionType): Promise<void> {
55
+ saveSessionId(sessionId: string): void {
30
56
  try {
31
- await AsyncStorage.setItem(StorageService.SESSION_TYPE_KEY, sessionType)
57
+ StorageService.cache.sessionId = sessionId
58
+ AsyncStorage.setItem(StorageService.SESSION_ID_KEY, sessionId).catch(error => {
59
+ // Failed to persist session ID - silently continue
60
+ })
32
61
  } catch (error) {
33
- console.error('Failed to save session type:', error)
62
+ // Failed to save session ID - silently continue
34
63
  throw error
35
64
  }
36
65
  }
37
66
 
38
- async getSessionType(): Promise<SessionType | null> {
39
- try {
40
- const type = await AsyncStorage.getItem(StorageService.SESSION_TYPE_KEY)
41
- return type as SessionType | null
42
- } catch (error) {
43
- console.error('Failed to get session type:', error)
44
- return null
45
- }
67
+ getSessionId(): string | null {
68
+ return StorageService.cache.sessionId
46
69
  }
47
70
 
48
- async saveSessionState(state: SessionState): Promise<void> {
71
+ saveSessionType(sessionType: SessionType): void {
49
72
  try {
50
- await AsyncStorage.setItem(StorageService.SESSION_STATE_KEY, state)
73
+ StorageService.cache.sessionType = sessionType
74
+ AsyncStorage.setItem(StorageService.SESSION_TYPE_KEY, sessionType).catch(error => {
75
+ // Failed to persist session type - silently continue
76
+ })
51
77
  } catch (error) {
52
- console.error('Failed to save session state:', error)
78
+ // Failed to save session type - silently continue
53
79
  throw error
54
80
  }
55
81
  }
56
82
 
57
- async getSessionState(): Promise<SessionState | null> {
58
- try {
59
- const state = await AsyncStorage.getItem(StorageService.SESSION_STATE_KEY)
60
- return state as SessionState | null
61
- } catch (error) {
62
- console.error('Failed to get session state:', error)
63
- return null
64
- }
83
+ getSessionType(): SessionType | null {
84
+ return StorageService.cache.sessionType
65
85
  }
66
86
 
67
- async saveSessionObject(session: ISession): Promise<void> {
87
+ saveSessionState(state: SessionState): void {
68
88
  try {
69
- await AsyncStorage.setItem(StorageService.SESSION_OBJECT_KEY, JSON.stringify(session))
89
+ StorageService.cache.sessionState = state
90
+
91
+ AsyncStorage.setItem(StorageService.SESSION_STATE_KEY, state).catch(error => {
92
+ // Failed to persist session state - silently continue
93
+ })
70
94
  } catch (error) {
71
- console.error('Failed to save session object:', error)
95
+ // Failed to save session state - silently continue
72
96
  throw error
73
97
  }
74
98
  }
75
99
 
76
- async getSessionObject(): Promise<ISession | null> {
100
+ getSessionState(): SessionState | null {
101
+ return StorageService.cache.sessionState
102
+ }
103
+
104
+ saveSessionObject(session: ISession): void {
77
105
  try {
78
- const sessionData = await AsyncStorage.getItem(StorageService.SESSION_OBJECT_KEY)
79
- return sessionData ? JSON.parse(sessionData) : null
106
+ StorageService.cache.sessionObject = session
107
+ AsyncStorage.setItem(StorageService.SESSION_OBJECT_KEY, JSON.stringify(session)).catch(error => {
108
+ // Failed to persist session object - silently continue
109
+ })
80
110
  } catch (error) {
81
- console.error('Failed to get session object:', error)
82
- return null
111
+ // Failed to save session object - silently continue
112
+ throw error
83
113
  }
84
114
  }
85
115
 
86
- async clearSessionData(): Promise<void> {
116
+ getSessionObject(): ISession | null {
117
+ return StorageService.cache.sessionObject
118
+ }
119
+
120
+ clearSessionData(): void {
87
121
  try {
88
- await AsyncStorage.multiRemove([
122
+ // Clear cache immediately
123
+ StorageService.cache = {
124
+ sessionId: null,
125
+ sessionType: null,
126
+ sessionState: null,
127
+ sessionObject: null,
128
+ }
129
+
130
+ // Clear persistent storage asynchronously
131
+ AsyncStorage.multiRemove([
89
132
  StorageService.SESSION_ID_KEY,
90
133
  StorageService.SESSION_TYPE_KEY,
91
134
  StorageService.SESSION_STATE_KEY,
92
135
  StorageService.SESSION_OBJECT_KEY,
93
- ])
136
+ ]).catch(error => {
137
+ // Failed to clear session data from storage - silently continue
138
+ })
94
139
  } catch (error) {
95
- console.error('Failed to clear session data:', error)
140
+ // Failed to clear session data - silently continue
96
141
  throw error
97
142
  }
98
143
  }
99
144
 
100
- async getAllSessionData(): Promise<{
101
- sessionId: string | null
102
- sessionType: SessionType | null
103
- sessionState: SessionState | null
104
- sessionObject: ISession | null
105
- }> {
106
- try {
107
- const [sessionId, sessionType, sessionState, sessionObject] = await Promise.all([
108
- this.getSessionId(),
109
- this.getSessionType(),
110
- this.getSessionState(),
111
- this.getSessionObject(),
112
- ])
113
-
114
- return {
115
- sessionId,
116
- sessionType,
117
- sessionState,
118
- sessionObject,
119
- }
120
- } catch (error) {
121
- console.error('Failed to get all session data:', error)
122
- return {
123
- sessionId: null,
124
- sessionType: null,
125
- sessionState: null,
126
- sessionObject: null,
127
- }
145
+ getAllSessionData(): CacheData {
146
+ return {
147
+ sessionId: StorageService.cache.sessionId,
148
+ sessionType: StorageService.cache.sessionType,
149
+ sessionState: StorageService.cache.sessionState,
150
+ sessionObject: StorageService.cache.sessionObject,
128
151
  }
129
152
  }
153
+
154
+ // Initialize cache on first use - call this method when the service is first used
155
+ static async initialize(): Promise<void> {
156
+ await StorageService.initializeCache()
157
+ }
130
158
  }