@multiplayer-app/session-recorder-react-native 0.0.1 → 1.0.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 (228) hide show
  1. package/README.md +708 -83
  2. package/SessionRecorderNative.podspec +26 -0
  3. package/android/build.gradle +34 -0
  4. package/copy-react-native-dist.sh +34 -16
  5. package/dist/components/ScreenRecorderView/ScreenRecorderView.js +1 -1
  6. package/dist/components/ScreenRecorderView/ScreenRecorderView.js.map +1 -1
  7. package/dist/components/SessionRecorderWidget/ErrorBanner.d.ts +7 -0
  8. package/dist/components/SessionRecorderWidget/ErrorBanner.js +1 -0
  9. package/dist/components/SessionRecorderWidget/ErrorBanner.js.map +1 -0
  10. package/dist/components/SessionRecorderWidget/FinalPopover.d.ts +12 -0
  11. package/dist/components/SessionRecorderWidget/FinalPopover.js +1 -0
  12. package/dist/components/SessionRecorderWidget/FinalPopover.js.map +1 -0
  13. package/dist/components/SessionRecorderWidget/FloatingButton.d.ts +8 -0
  14. package/dist/components/SessionRecorderWidget/FloatingButton.js +1 -0
  15. package/dist/components/SessionRecorderWidget/FloatingButton.js.map +1 -0
  16. package/dist/components/SessionRecorderWidget/InitialPopover.d.ts +16 -0
  17. package/dist/components/SessionRecorderWidget/InitialPopover.js +1 -0
  18. package/dist/components/SessionRecorderWidget/InitialPopover.js.map +1 -0
  19. package/dist/components/SessionRecorderWidget/ModalContainer.d.ts +8 -0
  20. package/dist/components/SessionRecorderWidget/ModalContainer.js +1 -0
  21. package/dist/components/SessionRecorderWidget/ModalContainer.js.map +1 -0
  22. package/dist/components/SessionRecorderWidget/ModalHeader.d.ts +6 -0
  23. package/dist/components/SessionRecorderWidget/ModalHeader.js +1 -0
  24. package/dist/components/SessionRecorderWidget/ModalHeader.js.map +1 -0
  25. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.d.ts +5 -0
  26. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js +1 -0
  27. package/dist/components/SessionRecorderWidget/SessionRecorderWidget.js.map +1 -0
  28. package/dist/components/SessionRecorderWidget/icons.d.ts +11 -0
  29. package/dist/components/SessionRecorderWidget/icons.js +1 -0
  30. package/dist/components/SessionRecorderWidget/icons.js.map +1 -0
  31. package/dist/components/SessionRecorderWidget/index.d.ts +2 -0
  32. package/dist/components/SessionRecorderWidget/index.js +1 -0
  33. package/dist/components/SessionRecorderWidget/index.js.map +1 -0
  34. package/dist/components/SessionRecorderWidget/styles.d.ts +165 -0
  35. package/dist/components/SessionRecorderWidget/styles.js +1 -0
  36. package/dist/components/SessionRecorderWidget/styles.js.map +1 -0
  37. package/dist/components/index.d.ts +2 -1
  38. package/dist/components/index.js +1 -1
  39. package/dist/components/index.js.map +1 -1
  40. package/dist/config/constants.js +1 -1
  41. package/dist/config/constants.js.map +1 -1
  42. package/dist/config/defaults.d.ts +4 -4
  43. package/dist/config/defaults.js +1 -1
  44. package/dist/config/defaults.js.map +1 -1
  45. package/dist/config/masking.d.ts +2 -2
  46. package/dist/config/masking.js +1 -1
  47. package/dist/config/masking.js.map +1 -1
  48. package/dist/config/session-recorder.js +1 -1
  49. package/dist/config/session-recorder.js.map +1 -1
  50. package/dist/config/validators.d.ts +1 -1
  51. package/dist/config/validators.js +1 -1
  52. package/dist/config/validators.js.map +1 -1
  53. package/dist/config/widget.d.ts +9 -0
  54. package/dist/config/widget.js +1 -0
  55. package/dist/config/widget.js.map +1 -0
  56. package/dist/context/SessionRecorderContext.d.ts +12 -3
  57. package/dist/context/SessionRecorderContext.js +1 -1
  58. package/dist/context/SessionRecorderContext.js.map +1 -1
  59. package/dist/context/SessionRecorderStore.d.ts +12 -0
  60. package/dist/context/SessionRecorderStore.js +1 -0
  61. package/dist/context/SessionRecorderStore.js.map +1 -0
  62. package/dist/context/useSessionRecorderStore.d.ts +8 -0
  63. package/dist/context/useSessionRecorderStore.js +1 -0
  64. package/dist/context/useSessionRecorderStore.js.map +1 -0
  65. package/dist/context/useStoreSelector.d.ts +4 -0
  66. package/dist/context/useStoreSelector.js +1 -0
  67. package/dist/context/useStoreSelector.js.map +1 -0
  68. package/dist/index.d.ts +1 -1
  69. package/dist/index.js +1 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/native/GestureRecorderNative.d.ts +57 -0
  72. package/dist/native/GestureRecorderNative.js +1 -0
  73. package/dist/native/GestureRecorderNative.js.map +1 -0
  74. package/dist/native/SessionRecorderNative.d.ts +33 -0
  75. package/dist/native/SessionRecorderNative.js +1 -0
  76. package/dist/native/SessionRecorderNative.js.map +1 -0
  77. package/dist/native/index.d.ts +2 -0
  78. package/dist/native/index.js +1 -0
  79. package/dist/native/index.js.map +1 -0
  80. package/dist/otel/index.js +1 -1
  81. package/dist/otel/index.js.map +1 -1
  82. package/dist/patch/xhr.js +1 -1
  83. package/dist/patch/xhr.js.map +1 -1
  84. package/dist/recorder/eventExporter.d.ts +4 -1
  85. package/dist/recorder/eventExporter.js +1 -1
  86. package/dist/recorder/eventExporter.js.map +1 -1
  87. package/dist/recorder/gestureRecorder.d.ts +28 -62
  88. package/dist/recorder/gestureRecorder.js +1 -1
  89. package/dist/recorder/gestureRecorder.js.map +1 -1
  90. package/dist/recorder/index.d.ts +2 -0
  91. package/dist/recorder/index.js +1 -1
  92. package/dist/recorder/index.js.map +1 -1
  93. package/dist/recorder/navigationTracker.d.ts +4 -19
  94. package/dist/recorder/navigationTracker.js +1 -1
  95. package/dist/recorder/navigationTracker.js.map +1 -1
  96. package/dist/recorder/screenRecorder.d.ts +11 -5
  97. package/dist/recorder/screenRecorder.js +1 -1
  98. package/dist/recorder/screenRecorder.js.map +1 -1
  99. package/dist/services/api.service.d.ts +12 -3
  100. package/dist/services/api.service.js +1 -1
  101. package/dist/services/api.service.js.map +1 -1
  102. package/dist/services/network.service.d.ts +46 -0
  103. package/dist/services/network.service.js +1 -0
  104. package/dist/services/network.service.js.map +1 -0
  105. package/dist/services/screenMaskingService.d.ts +47 -0
  106. package/dist/services/screenMaskingService.js +1 -0
  107. package/dist/services/screenMaskingService.js.map +1 -0
  108. package/dist/services/storage.service.d.ts +18 -2
  109. package/dist/services/storage.service.js +1 -1
  110. package/dist/services/storage.service.js.map +1 -1
  111. package/dist/session-recorder.d.ts +18 -33
  112. package/dist/session-recorder.js +1 -1
  113. package/dist/session-recorder.js.map +1 -1
  114. package/dist/types/configs.d.ts +85 -0
  115. package/dist/types/configs.js +1 -0
  116. package/dist/types/configs.js.map +1 -0
  117. package/dist/types/index.d.ts +1 -0
  118. package/dist/types/index.js +1 -1
  119. package/dist/types/index.js.map +1 -1
  120. package/dist/types/session-recorder.d.ts +105 -132
  121. package/dist/types/session-recorder.js +1 -1
  122. package/dist/types/session-recorder.js.map +1 -1
  123. package/dist/utils/constants.optional.d.ts +21 -0
  124. package/dist/utils/constants.optional.expo.d.ts +3 -0
  125. package/dist/utils/constants.optional.expo.js +1 -0
  126. package/dist/utils/constants.optional.expo.js.map +1 -0
  127. package/dist/utils/constants.optional.js +1 -0
  128. package/dist/utils/constants.optional.js.map +1 -0
  129. package/dist/utils/createStore.d.ts +8 -0
  130. package/dist/utils/createStore.js +1 -0
  131. package/dist/utils/createStore.js.map +1 -0
  132. package/dist/utils/logger.d.ts +2 -7
  133. package/dist/utils/logger.js +1 -1
  134. package/dist/utils/logger.js.map +1 -1
  135. package/dist/utils/platform.d.ts +11 -0
  136. package/dist/utils/platform.js +1 -1
  137. package/dist/utils/platform.js.map +1 -1
  138. package/dist/utils/rrweb-events.d.ts +4 -3
  139. package/dist/utils/rrweb-events.js +1 -1
  140. package/dist/utils/rrweb-events.js.map +1 -1
  141. package/dist/utils/session.d.ts +2 -1
  142. package/dist/utils/session.js +1 -1
  143. package/dist/utils/session.js.map +1 -1
  144. package/dist/utils/shallowEqual.d.ts +1 -0
  145. package/dist/utils/shallowEqual.js +1 -0
  146. package/dist/utils/shallowEqual.js.map +1 -0
  147. package/dist/version.d.ts +1 -1
  148. package/dist/version.js +1 -1
  149. package/ios/GestureRecorderNative.m +21 -0
  150. package/ios/GestureRecorderNative.swift +316 -0
  151. package/ios/SessionRecorderNative.m +17 -0
  152. package/ios/SessionRecorderNative.podspec +26 -0
  153. package/ios/SessionRecorderNative.swift +599 -0
  154. package/package.json +15 -16
  155. package/react-native.config.js +12 -0
  156. package/RRWEB_INTEGRATION.md +0 -336
  157. package/VIEWSHOT_INTEGRATION_TEST.md +0 -123
  158. package/babel.config.js +0 -13
  159. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.d.ts +0 -6
  160. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js +0 -1
  161. package/dist/components/GestureCaptureWrapper/GestureCaptureWrapper.js.map +0 -1
  162. package/dist/components/GestureCaptureWrapper/index.d.ts +0 -1
  163. package/dist/components/GestureCaptureWrapper/index.js +0 -1
  164. package/dist/components/GestureCaptureWrapper/index.js.map +0 -1
  165. package/dist/components/GestureCaptureWrapper.d.ts +0 -6
  166. package/dist/components/GestureCaptureWrapper.js +0 -1
  167. package/dist/components/GestureCaptureWrapper.js.map +0 -1
  168. package/dist/expo.d.ts +0 -7
  169. package/dist/expo.js +0 -1
  170. package/dist/expo.js.map +0 -1
  171. package/dist/otel/instrumentations/gestureInstrumentation.d.ts +0 -15
  172. package/dist/otel/instrumentations/gestureInstrumentation.js +0 -1
  173. package/dist/otel/instrumentations/gestureInstrumentation.js.map +0 -1
  174. package/dist/otel/instrumentations/reactNativeInstrumentation.d.ts +0 -8
  175. package/dist/otel/instrumentations/reactNativeInstrumentation.js +0 -1
  176. package/dist/otel/instrumentations/reactNativeInstrumentation.js.map +0 -1
  177. package/dist/otel/instrumentations/reactNavigationInstrumentation.d.ts +0 -13
  178. package/dist/otel/instrumentations/reactNavigationInstrumentation.js +0 -1
  179. package/dist/otel/instrumentations/reactNavigationInstrumentation.js.map +0 -1
  180. package/dist/recorder/gestureHandlerRecorder.d.ts +0 -19
  181. package/dist/recorder/gestureHandlerRecorder.js +0 -1
  182. package/dist/recorder/gestureHandlerRecorder.js.map +0 -1
  183. package/dist/types/rrweb.d.ts +0 -118
  184. package/dist/types/rrweb.js +0 -1
  185. package/dist/types/rrweb.js.map +0 -1
  186. package/scripts/generate-app-metadata.js +0 -173
  187. package/src/components/GestureCaptureWrapper/GestureCaptureWrapper.tsx +0 -86
  188. package/src/components/GestureCaptureWrapper/index.ts +0 -1
  189. package/src/components/ScreenRecorderView/ScreenRecorderView.tsx +0 -72
  190. package/src/components/ScreenRecorderView/index.ts +0 -1
  191. package/src/components/index.ts +0 -1
  192. package/src/config/constants.ts +0 -60
  193. package/src/config/defaults.ts +0 -82
  194. package/src/config/index.ts +0 -6
  195. package/src/config/masking.ts +0 -27
  196. package/src/config/session-recorder.ts +0 -55
  197. package/src/config/validators.ts +0 -31
  198. package/src/context/SessionRecorderContext.tsx +0 -75
  199. package/src/expo.ts +0 -11
  200. package/src/index.ts +0 -17
  201. package/src/otel/helpers.ts +0 -275
  202. package/src/otel/index.ts +0 -138
  203. package/src/otel/instrumentations/index.ts +0 -115
  204. package/src/patch/index.ts +0 -1
  205. package/src/patch/xhr.ts +0 -142
  206. package/src/recorder/eventExporter.ts +0 -141
  207. package/src/recorder/gestureRecorder.ts +0 -498
  208. package/src/recorder/index.ts +0 -179
  209. package/src/recorder/navigationTracker.ts +0 -449
  210. package/src/recorder/screenRecorder.ts +0 -498
  211. package/src/services/api.service.ts +0 -203
  212. package/src/services/storage.service.ts +0 -158
  213. package/src/session-recorder.ts +0 -600
  214. package/src/types/expo.d.ts +0 -23
  215. package/src/types/index.ts +0 -28
  216. package/src/types/session-recorder.ts +0 -423
  217. package/src/types/session.ts +0 -65
  218. package/src/utils/app-metadata.ts +0 -31
  219. package/src/utils/index.ts +0 -8
  220. package/src/utils/logger.ts +0 -225
  221. package/src/utils/platform.ts +0 -384
  222. package/src/utils/request-utils.ts +0 -61
  223. package/src/utils/rrweb-events.ts +0 -309
  224. package/src/utils/session.ts +0 -18
  225. package/src/utils/time.ts +0 -17
  226. package/src/utils/type-utils.ts +0 -75
  227. package/src/version.ts +0 -1
  228. package/tsconfig.json +0 -24
@@ -1,449 +0,0 @@
1
- import { NavigationEvent, RecorderConfig } from '../types'
2
- import { trace, SpanStatusCode } from '@opentelemetry/api'
3
- import { logger } from '../utils'
4
-
5
- export class NavigationTracker {
6
- private config?: RecorderConfig
7
- private isRecording = false
8
- private navigationRef: any = null
9
- private events: NavigationEvent[] = []
10
- private navigationListeners: Map<string, any> = new Map()
11
- private currentRoute: string | null = null
12
- private navigationStack: string[] = []
13
- private navigationStartTime: number = 0
14
-
15
- init(config: RecorderConfig): void {
16
- this.config = config
17
- }
18
-
19
- setNavigationRef(ref: any): void {
20
- this.navigationRef = ref
21
- if (this.isRecording) {
22
- this._setupNavigationListener()
23
- }
24
- }
25
-
26
- start(): void {
27
- logger.info('NavigationTracker', 'Navigation tracking started')
28
- this.isRecording = true
29
- this.events = []
30
- this.navigationStack = []
31
- this.navigationStartTime = Date.now()
32
- this._setupNavigationListener()
33
- // Navigation tracking started
34
- }
35
-
36
- stop(): void {
37
- this.isRecording = false
38
- this._removeNavigationListener()
39
- // Navigation tracking stopped
40
- }
41
-
42
- pause(): void {
43
- this.isRecording = false
44
- }
45
-
46
- resume(): void {
47
- this.isRecording = true
48
- this._setupNavigationListener()
49
- }
50
-
51
- private _setupNavigationListener(): void {
52
- if (!this.navigationRef) {
53
- // Navigation ref not set - silently continue
54
- return
55
- }
56
-
57
- try {
58
- // Listen to navigation state changes
59
- const stateListener = this.navigationRef.addListener('state', (e: any) => {
60
- this._recordNavigationEvent('state_change', e.data)
61
- })
62
-
63
- // Listen to focus events
64
- const focusListener = this.navigationRef.addListener('focus', (e: any) => {
65
- this._recordNavigationEvent('focus', e.data)
66
- })
67
-
68
- // Listen to blur events
69
- const blurListener = this.navigationRef.addListener('blur', (e: any) => {
70
- this._recordNavigationEvent('blur', e.data)
71
- })
72
-
73
- // Listen to beforeRemove events
74
- const beforeRemoveListener = this.navigationRef.addListener('beforeRemove', (e: any) => {
75
- this._recordNavigationEvent('beforeRemove', e.data)
76
- })
77
-
78
- // Store listeners for cleanup
79
- this.navigationListeners.set('state', stateListener)
80
- this.navigationListeners.set('focus', focusListener)
81
- this.navigationListeners.set('blur', blurListener)
82
- this.navigationListeners.set('beforeRemove', beforeRemoveListener)
83
-
84
- // Navigation listeners setup complete
85
- } catch (error) {
86
- // Failed to setup navigation listeners - silently continue
87
- }
88
- }
89
-
90
- private _removeNavigationListener(): void {
91
- try {
92
- // Remove all listeners
93
- this.navigationListeners.forEach((listener, key) => {
94
- if (listener && typeof listener.remove === 'function') {
95
- listener.remove()
96
- }
97
- })
98
- this.navigationListeners.clear()
99
- // Navigation listeners removed
100
- } catch (error) {
101
- // Failed to remove navigation listeners - silently continue
102
- }
103
- }
104
-
105
- private _recordNavigationEvent(eventType: string, data: any): void {
106
- if (!this.isRecording) return
107
-
108
- const event: NavigationEvent = {
109
- type: 'navigate', // Default type
110
- timestamp: Date.now(),
111
- metadata: {
112
- eventType,
113
- navigationDuration: Date.now() - this.navigationStartTime,
114
- stackDepth: this.navigationStack.length,
115
- },
116
- }
117
-
118
- if (data) {
119
- if (data.routeName) {
120
- event.routeName = data.routeName
121
- this._updateNavigationStack(data.routeName, eventType)
122
- }
123
- if (data.params) {
124
- event.params = data.params
125
- }
126
- if (data.key) {
127
- event.metadata!.routeKey = data.key
128
- }
129
- }
130
-
131
- this.events.push(event)
132
- this._sendEvent(event)
133
- this._recordOpenTelemetrySpan(event)
134
- }
135
-
136
-
137
-
138
- private _updateNavigationStack(routeName: string, eventType: string): void {
139
- if (eventType === 'focus' || eventType === 'state_change') {
140
- if (this.currentRoute !== routeName) {
141
- this.currentRoute = routeName
142
- this.navigationStack.push(routeName)
143
- }
144
- } else if (eventType === 'blur' || eventType === 'beforeRemove') {
145
- const index = this.navigationStack.indexOf(routeName)
146
- if (index > -1) {
147
- this.navigationStack.splice(index, 1)
148
- }
149
- }
150
- }
151
-
152
- private _sendEvent(event: NavigationEvent): void {
153
- // Navigation event recorded
154
- }
155
-
156
- private _recordOpenTelemetrySpan(event: NavigationEvent): void {
157
- try {
158
- const span = trace.getTracer('navigation').startSpan(`Navigation.${event.type}`, {
159
- attributes: {
160
- 'navigation.system': 'ReactNavigation',
161
- 'navigation.operation': event.type,
162
- 'navigation.type': event.type,
163
- 'navigation.timestamp': event.timestamp,
164
- 'navigation.platform': 'react-native',
165
- },
166
- })
167
-
168
- if (event.routeName) {
169
- span.setAttribute('navigation.route_name', event.routeName)
170
- }
171
- if (event.params) {
172
- span.setAttribute('navigation.params', JSON.stringify(event.params))
173
- }
174
- if (event.metadata) {
175
- Object.entries(event.metadata).forEach(([key, value]) => {
176
- span.setAttribute(`navigation.metadata.${key}`, String(value))
177
- })
178
- }
179
-
180
- span.setStatus({ code: SpanStatusCode.OK })
181
- span.end()
182
- } catch (error) {
183
- // Failed to record OpenTelemetry span for navigation - silently continue
184
- }
185
- }
186
-
187
- // Public methods for manual event recording
188
- recordNavigate(routeName: string, params?: Record<string, any>): void {
189
- const event: NavigationEvent = {
190
- type: 'navigate',
191
- timestamp: Date.now(),
192
- routeName,
193
- params,
194
- metadata: {
195
- navigationDuration: Date.now() - this.navigationStartTime,
196
- stackDepth: this.navigationStack.length,
197
- manual: true,
198
- },
199
- }
200
-
201
- this._updateNavigationStack(routeName, 'focus')
202
- this._recordEvent(event)
203
- }
204
-
205
- recordGoBack(): void {
206
- const event: NavigationEvent = {
207
- type: 'goBack',
208
- timestamp: Date.now(),
209
- metadata: {
210
- navigationDuration: Date.now() - this.navigationStartTime,
211
- stackDepth: this.navigationStack.length,
212
- manual: true,
213
- },
214
- }
215
-
216
- this._recordEvent(event)
217
- }
218
-
219
- recordReset(routes: any[]): void {
220
- const event: NavigationEvent = {
221
- type: 'reset',
222
- timestamp: Date.now(),
223
- metadata: {
224
- navigationDuration: Date.now() - this.navigationStartTime,
225
- routesCount: routes.length,
226
- manual: true,
227
- },
228
- }
229
-
230
- // Update navigation stack
231
- this.navigationStack = routes.map(route => route.name || route.routeName)
232
- if (routes.length > 0) {
233
- this.currentRoute = routes[0].name || routes[0].routeName
234
- }
235
-
236
- this._recordEvent(event)
237
- this._recordEvent(event)
238
- }
239
-
240
- private _recordEvent(event: NavigationEvent): void {
241
- if (!this.isRecording) return
242
-
243
- this.events.push(event)
244
- this._sendEvent(event)
245
- this._recordOpenTelemetrySpan(event)
246
- }
247
-
248
- // Advanced navigation tracking methods
249
- recordDeepLink(url: string, params?: Record<string, any>): void {
250
- const event: NavigationEvent = {
251
- type: 'navigate',
252
- timestamp: Date.now(),
253
- routeName: 'deepLink',
254
- params: { url, ...params },
255
- metadata: {
256
- navigationDuration: Date.now() - this.navigationStartTime,
257
- stackDepth: this.navigationStack.length,
258
- deepLink: true,
259
- },
260
- }
261
-
262
- this._recordEvent(event)
263
- this._recordEvent(event)
264
- }
265
-
266
- recordTabChange(tabName: string, tabIndex: number): void {
267
- const event: NavigationEvent = {
268
- type: 'navigate',
269
- timestamp: Date.now(),
270
- routeName: tabName,
271
- params: { tabIndex },
272
- metadata: {
273
- navigationDuration: Date.now() - this.navigationStartTime,
274
- stackDepth: this.navigationStack.length,
275
- tabChange: true,
276
- tabIndex,
277
- },
278
- }
279
-
280
- this._recordEvent(event)
281
- this._recordEvent(event)
282
- }
283
-
284
- recordModalOpen(modalName: string, params?: Record<string, any>): void {
285
- const event: NavigationEvent = {
286
- type: 'navigate',
287
- timestamp: Date.now(),
288
- routeName: modalName,
289
- params,
290
- metadata: {
291
- navigationDuration: Date.now() - this.navigationStartTime,
292
- stackDepth: this.navigationStack.length,
293
- modal: true,
294
- },
295
- }
296
-
297
- this._recordEvent(event)
298
- this._recordEvent(event)
299
- }
300
-
301
- recordModalClose(modalName: string): void {
302
- const event: NavigationEvent = {
303
- type: 'goBack',
304
- timestamp: Date.now(),
305
- routeName: modalName,
306
- metadata: {
307
- navigationDuration: Date.now() - this.navigationStartTime,
308
- stackDepth: this.navigationStack.length,
309
- modal: true,
310
- modalClose: true,
311
- },
312
- }
313
-
314
- this._recordEvent(event)
315
- this._recordEvent(event)
316
- }
317
-
318
- recordStackPush(routeName: string, params?: Record<string, any>): void {
319
- const event: NavigationEvent = {
320
- type: 'navigate',
321
- timestamp: Date.now(),
322
- routeName,
323
- params,
324
- metadata: {
325
- navigationDuration: Date.now() - this.navigationStartTime,
326
- stackDepth: this.navigationStack.length,
327
- stackOperation: 'push',
328
- },
329
- }
330
-
331
- this._recordEvent(event)
332
- this._recordEvent(event)
333
- }
334
-
335
- recordStackPop(routeName?: string): void {
336
- const event: NavigationEvent = {
337
- type: 'goBack',
338
- timestamp: Date.now(),
339
- routeName,
340
- metadata: {
341
- navigationDuration: Date.now() - this.navigationStartTime,
342
- stackDepth: this.navigationStack.length,
343
- stackOperation: 'pop',
344
- },
345
- }
346
-
347
- this._recordEvent(event)
348
- this._recordEvent(event)
349
- }
350
-
351
- // Performance monitoring
352
- recordNavigationPerformance(routeName: string, loadTime: number): void {
353
- const event: NavigationEvent = {
354
- type: 'navigate',
355
- timestamp: Date.now(),
356
- routeName,
357
- metadata: {
358
- navigationDuration: Date.now() - this.navigationStartTime,
359
- stackDepth: this.navigationStack.length,
360
- performance: 'monitoring',
361
- loadTime,
362
- },
363
- }
364
-
365
- this._recordEvent(event)
366
- this._recordEvent(event)
367
- }
368
-
369
- // Error tracking
370
- recordNavigationError(error: Error, routeName?: string): void {
371
- const event: NavigationEvent = {
372
- type: 'navigate',
373
- timestamp: Date.now(),
374
- routeName,
375
- metadata: {
376
- navigationDuration: Date.now() - this.navigationStartTime,
377
- stackDepth: this.navigationStack.length,
378
- error: true,
379
- errorType: error.name,
380
- errorMessage: error.message,
381
- },
382
- }
383
-
384
- this._recordEvent(event)
385
- this._recordEvent(event)
386
-
387
- // Also record as OpenTelemetry error span
388
- try {
389
- const span = trace.getTracer('navigation').startSpan('Navigation.error', {
390
- attributes: {
391
- 'navigation.system': 'ReactNavigation',
392
- 'navigation.error': true,
393
- 'navigation.error.type': error.name,
394
- 'navigation.error.message': error.message,
395
- 'navigation.route_name': routeName || 'unknown',
396
- 'navigation.timestamp': Date.now(),
397
- },
398
- })
399
-
400
- span.setStatus({ code: SpanStatusCode.ERROR, message: error.message })
401
- span.recordException(error)
402
- span.end()
403
- } catch (spanError) {
404
- // Failed to record error span - silently continue
405
- }
406
- }
407
-
408
- // Get current navigation state
409
- getCurrentRoute(): string | null {
410
- return this.currentRoute
411
- }
412
-
413
- getNavigationStack(): string[] {
414
- return [...this.navigationStack]
415
- }
416
-
417
- getNavigationDepth(): number {
418
- return this.navigationStack.length
419
- }
420
-
421
- // Get recorded events
422
- getEvents(): NavigationEvent[] {
423
- return [...this.events]
424
- }
425
-
426
- // Clear events
427
- clearEvents(): void {
428
- this.events = []
429
- }
430
-
431
- // Get navigation statistics
432
- getNavigationStats(): Record<string, number> {
433
- const stats: Record<string, number> = {}
434
- this.events.forEach(event => {
435
- stats[event.type] = (stats[event.type] || 0) + 1
436
- })
437
- return stats
438
- }
439
-
440
- // Get recording status
441
- isRecordingEnabled(): boolean {
442
- return this.isRecording
443
- }
444
-
445
- // Get navigation duration
446
- getNavigationDuration(): number {
447
- return Date.now() - this.navigationStartTime
448
- }
449
- }