@rejourneyco/react-native 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.
- package/android/build.gradle.kts +135 -0
- package/android/consumer-rules.pro +10 -0
- package/android/proguard-rules.pro +1 -0
- package/android/src/main/AndroidManifest.xml +15 -0
- package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +2981 -0
- package/android/src/main/java/com/rejourney/capture/ANRHandler.kt +206 -0
- package/android/src/main/java/com/rejourney/capture/ActivityTracker.kt +98 -0
- package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +1553 -0
- package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +375 -0
- package/android/src/main/java/com/rejourney/capture/CrashHandler.kt +153 -0
- package/android/src/main/java/com/rejourney/capture/MotionEvent.kt +215 -0
- package/android/src/main/java/com/rejourney/capture/SegmentUploader.kt +512 -0
- package/android/src/main/java/com/rejourney/capture/VideoEncoder.kt +773 -0
- package/android/src/main/java/com/rejourney/capture/ViewHierarchyScanner.kt +633 -0
- package/android/src/main/java/com/rejourney/capture/ViewSerializer.kt +286 -0
- package/android/src/main/java/com/rejourney/core/Constants.kt +117 -0
- package/android/src/main/java/com/rejourney/core/Logger.kt +93 -0
- package/android/src/main/java/com/rejourney/core/Types.kt +124 -0
- package/android/src/main/java/com/rejourney/lifecycle/SessionLifecycleService.kt +162 -0
- package/android/src/main/java/com/rejourney/network/DeviceAuthManager.kt +747 -0
- package/android/src/main/java/com/rejourney/network/HttpClientProvider.kt +16 -0
- package/android/src/main/java/com/rejourney/network/NetworkMonitor.kt +272 -0
- package/android/src/main/java/com/rejourney/network/UploadManager.kt +1363 -0
- package/android/src/main/java/com/rejourney/network/UploadWorker.kt +492 -0
- package/android/src/main/java/com/rejourney/privacy/PrivacyMask.kt +645 -0
- package/android/src/main/java/com/rejourney/touch/GestureClassifier.kt +233 -0
- package/android/src/main/java/com/rejourney/touch/KeyboardTracker.kt +158 -0
- package/android/src/main/java/com/rejourney/touch/TextInputTracker.kt +181 -0
- package/android/src/main/java/com/rejourney/touch/TouchInterceptor.kt +591 -0
- package/android/src/main/java/com/rejourney/utils/EventBuffer.kt +284 -0
- package/android/src/main/java/com/rejourney/utils/OEMDetector.kt +154 -0
- package/android/src/main/java/com/rejourney/utils/PerfTiming.kt +235 -0
- package/android/src/main/java/com/rejourney/utils/Telemetry.kt +297 -0
- package/android/src/main/java/com/rejourney/utils/WindowUtils.kt +84 -0
- package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +187 -0
- package/android/src/newarch/java/com/rejourney/RejourneyPackage.kt +40 -0
- package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +218 -0
- package/android/src/oldarch/java/com/rejourney/RejourneyPackage.kt +23 -0
- package/ios/Capture/RJANRHandler.h +42 -0
- package/ios/Capture/RJANRHandler.m +328 -0
- package/ios/Capture/RJCaptureEngine.h +275 -0
- package/ios/Capture/RJCaptureEngine.m +2062 -0
- package/ios/Capture/RJCaptureHeuristics.h +80 -0
- package/ios/Capture/RJCaptureHeuristics.m +903 -0
- package/ios/Capture/RJCrashHandler.h +46 -0
- package/ios/Capture/RJCrashHandler.m +313 -0
- package/ios/Capture/RJMotionEvent.h +183 -0
- package/ios/Capture/RJMotionEvent.m +183 -0
- package/ios/Capture/RJPerformanceManager.h +100 -0
- package/ios/Capture/RJPerformanceManager.m +373 -0
- package/ios/Capture/RJPixelBufferDownscaler.h +42 -0
- package/ios/Capture/RJPixelBufferDownscaler.m +85 -0
- package/ios/Capture/RJSegmentUploader.h +146 -0
- package/ios/Capture/RJSegmentUploader.m +778 -0
- package/ios/Capture/RJVideoEncoder.h +247 -0
- package/ios/Capture/RJVideoEncoder.m +1036 -0
- package/ios/Capture/RJViewControllerTracker.h +73 -0
- package/ios/Capture/RJViewControllerTracker.m +508 -0
- package/ios/Capture/RJViewHierarchyScanner.h +215 -0
- package/ios/Capture/RJViewHierarchyScanner.m +1464 -0
- package/ios/Capture/RJViewSerializer.h +119 -0
- package/ios/Capture/RJViewSerializer.m +498 -0
- package/ios/Core/RJConstants.h +124 -0
- package/ios/Core/RJConstants.m +88 -0
- package/ios/Core/RJLifecycleManager.h +85 -0
- package/ios/Core/RJLifecycleManager.m +308 -0
- package/ios/Core/RJLogger.h +61 -0
- package/ios/Core/RJLogger.m +211 -0
- package/ios/Core/RJTypes.h +176 -0
- package/ios/Core/RJTypes.m +66 -0
- package/ios/Core/Rejourney.h +64 -0
- package/ios/Core/Rejourney.mm +2495 -0
- package/ios/Network/RJDeviceAuthManager.h +94 -0
- package/ios/Network/RJDeviceAuthManager.m +967 -0
- package/ios/Network/RJNetworkMonitor.h +68 -0
- package/ios/Network/RJNetworkMonitor.m +267 -0
- package/ios/Network/RJRetryManager.h +73 -0
- package/ios/Network/RJRetryManager.m +325 -0
- package/ios/Network/RJUploadManager.h +267 -0
- package/ios/Network/RJUploadManager.m +2296 -0
- package/ios/Privacy/RJPrivacyMask.h +163 -0
- package/ios/Privacy/RJPrivacyMask.m +922 -0
- package/ios/Rejourney.h +63 -0
- package/ios/Touch/RJGestureClassifier.h +130 -0
- package/ios/Touch/RJGestureClassifier.m +333 -0
- package/ios/Touch/RJTouchInterceptor.h +169 -0
- package/ios/Touch/RJTouchInterceptor.m +772 -0
- package/ios/Utils/RJEventBuffer.h +112 -0
- package/ios/Utils/RJEventBuffer.m +358 -0
- package/ios/Utils/RJGzipUtils.h +33 -0
- package/ios/Utils/RJGzipUtils.m +89 -0
- package/ios/Utils/RJKeychainManager.h +48 -0
- package/ios/Utils/RJKeychainManager.m +111 -0
- package/ios/Utils/RJPerfTiming.h +209 -0
- package/ios/Utils/RJPerfTiming.m +264 -0
- package/ios/Utils/RJTelemetry.h +92 -0
- package/ios/Utils/RJTelemetry.m +320 -0
- package/ios/Utils/RJWindowUtils.h +66 -0
- package/ios/Utils/RJWindowUtils.m +133 -0
- package/lib/commonjs/NativeRejourney.js +40 -0
- package/lib/commonjs/components/Mask.js +79 -0
- package/lib/commonjs/index.js +1381 -0
- package/lib/commonjs/sdk/autoTracking.js +1259 -0
- package/lib/commonjs/sdk/constants.js +151 -0
- package/lib/commonjs/sdk/errorTracking.js +199 -0
- package/lib/commonjs/sdk/index.js +50 -0
- package/lib/commonjs/sdk/metricsTracking.js +204 -0
- package/lib/commonjs/sdk/navigation.js +151 -0
- package/lib/commonjs/sdk/networkInterceptor.js +412 -0
- package/lib/commonjs/sdk/utils.js +363 -0
- package/lib/commonjs/types/expo-router.d.js +2 -0
- package/lib/commonjs/types/index.js +2 -0
- package/lib/module/NativeRejourney.js +38 -0
- package/lib/module/components/Mask.js +72 -0
- package/lib/module/index.js +1284 -0
- package/lib/module/sdk/autoTracking.js +1233 -0
- package/lib/module/sdk/constants.js +145 -0
- package/lib/module/sdk/errorTracking.js +189 -0
- package/lib/module/sdk/index.js +12 -0
- package/lib/module/sdk/metricsTracking.js +187 -0
- package/lib/module/sdk/navigation.js +143 -0
- package/lib/module/sdk/networkInterceptor.js +401 -0
- package/lib/module/sdk/utils.js +342 -0
- package/lib/module/types/expo-router.d.js +2 -0
- package/lib/module/types/index.js +2 -0
- package/lib/typescript/NativeRejourney.d.ts +147 -0
- package/lib/typescript/components/Mask.d.ts +39 -0
- package/lib/typescript/index.d.ts +117 -0
- package/lib/typescript/sdk/autoTracking.d.ts +204 -0
- package/lib/typescript/sdk/constants.d.ts +120 -0
- package/lib/typescript/sdk/errorTracking.d.ts +32 -0
- package/lib/typescript/sdk/index.d.ts +9 -0
- package/lib/typescript/sdk/metricsTracking.d.ts +58 -0
- package/lib/typescript/sdk/navigation.d.ts +33 -0
- package/lib/typescript/sdk/networkInterceptor.d.ts +47 -0
- package/lib/typescript/sdk/utils.d.ts +148 -0
- package/lib/typescript/types/index.d.ts +624 -0
- package/package.json +102 -0
- package/rejourney.podspec +21 -0
- package/src/NativeRejourney.ts +165 -0
- package/src/components/Mask.tsx +80 -0
- package/src/index.ts +1459 -0
- package/src/sdk/autoTracking.ts +1373 -0
- package/src/sdk/constants.ts +134 -0
- package/src/sdk/errorTracking.ts +231 -0
- package/src/sdk/index.ts +11 -0
- package/src/sdk/metricsTracking.ts +232 -0
- package/src/sdk/navigation.ts +157 -0
- package/src/sdk/networkInterceptor.ts +440 -0
- package/src/sdk/utils.ts +369 -0
- package/src/types/expo-router.d.ts +7 -0
- package/src/types/index.ts +739 -0
|
@@ -0,0 +1,739 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rejourney SDK Types
|
|
3
|
+
* Session recording and replay for React Native
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Configuration Types
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
export interface RejourneyConfig {
|
|
11
|
+
/**
|
|
12
|
+
* Public route key for authentication (required)
|
|
13
|
+
* Get this from your Rejourney dashboard at https://rejourney.co
|
|
14
|
+
* @example 'pk_live_xxxxxxxxxxxx'
|
|
15
|
+
*/
|
|
16
|
+
publicRouteKey?: string;
|
|
17
|
+
/** Project ID (UUID) required for ingest + auth */
|
|
18
|
+
projectId?: string;
|
|
19
|
+
/** iOS bundle identifier (for verification) */
|
|
20
|
+
bundleId?: string;
|
|
21
|
+
/** Android package name (for verification) */
|
|
22
|
+
packageName?: string;
|
|
23
|
+
|
|
24
|
+
/** Enable or disable recording (default: true) */
|
|
25
|
+
enabled?: boolean;
|
|
26
|
+
/** Video capture FPS (default: 2 = capture every 500ms) */
|
|
27
|
+
captureFPS?: number;
|
|
28
|
+
/** Maximum session duration in milliseconds (default: 30 minutes) */
|
|
29
|
+
maxSessionDuration?: number;
|
|
30
|
+
/** Maximum storage size in bytes (default: 50MB) */
|
|
31
|
+
maxStorageSize?: number;
|
|
32
|
+
/** Enable automatic screen name detection with React Navigation (default: true) */
|
|
33
|
+
autoScreenTracking?: boolean;
|
|
34
|
+
/** Enable automatic gesture detection (default: true) */
|
|
35
|
+
autoGestureTracking?: boolean;
|
|
36
|
+
/** Enable privacy occlusion for text inputs (default: true) */
|
|
37
|
+
privacyOcclusion?: boolean;
|
|
38
|
+
/** Enable compression for stored sessions (default: true) */
|
|
39
|
+
enableCompression?: boolean;
|
|
40
|
+
/** Skip captures during inactivity longer than this (ms) (default: 5000) */
|
|
41
|
+
inactivityThreshold?: number;
|
|
42
|
+
/** Disable recording in development mode (default: false) */
|
|
43
|
+
disableInDev?: boolean;
|
|
44
|
+
/** Enable rage tap detection (default: true) */
|
|
45
|
+
detectRageTaps?: boolean;
|
|
46
|
+
/** Rage tap threshold - number of taps in quick succession (default: 3) */
|
|
47
|
+
rageTapThreshold?: number;
|
|
48
|
+
/** Rage tap time window in ms (default: 1000) */
|
|
49
|
+
rageTapTimeWindow?: number;
|
|
50
|
+
/** Enable debug logging (default: false) */
|
|
51
|
+
debug?: boolean;
|
|
52
|
+
autoStartRecording?: boolean;
|
|
53
|
+
/** API URL for session uploads (default: https://api.rejourney.co) */
|
|
54
|
+
apiUrl?: string;
|
|
55
|
+
/** Collect detailed device information (default: true) */
|
|
56
|
+
collectDeviceInfo?: boolean;
|
|
57
|
+
/** Collect IP address and geolocation data (default: true) */
|
|
58
|
+
collectGeoLocation?: boolean;
|
|
59
|
+
/** Delay after navigation before capturing (ms) - allows animations to complete (default: 300) */
|
|
60
|
+
postNavigationDelay?: number;
|
|
61
|
+
/** Delay after gestures/taps before capturing (ms) - shows result not animation (default: 200) */
|
|
62
|
+
postGestureDelay?: number;
|
|
63
|
+
/** Delay after modals/alerts before capturing (ms) - ensures full render (default: 400) */
|
|
64
|
+
postModalDelay?: number;
|
|
65
|
+
|
|
66
|
+
// ========================================================================
|
|
67
|
+
// Authentication Callbacks
|
|
68
|
+
// ========================================================================
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Callback fired when device authentication fails with a security error.
|
|
72
|
+
* This occurs when:
|
|
73
|
+
* - Bundle ID mismatch (403): App's bundle ID doesn't match project configuration
|
|
74
|
+
* - Project not found (404): Invalid project key
|
|
75
|
+
*
|
|
76
|
+
* When this fires, recording is automatically stopped to prevent data accumulation.
|
|
77
|
+
* Use this to notify users or log the issue.
|
|
78
|
+
*
|
|
79
|
+
* @param error - Error details including code, message, and domain
|
|
80
|
+
*/
|
|
81
|
+
onAuthError?: (error: { code: number; message: string; domain: string }) => void;
|
|
82
|
+
|
|
83
|
+
// ========================================================================
|
|
84
|
+
// Network Interception Options
|
|
85
|
+
// ========================================================================
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Automatically intercept and log all network requests (fetch & XHR) (default: true)
|
|
89
|
+
* When enabled, API calls are automatically tracked without any code changes.
|
|
90
|
+
*/
|
|
91
|
+
autoTrackNetwork?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* URLs to ignore when tracking network requests.
|
|
94
|
+
* Useful for excluding analytics, logging, or other non-essential requests.
|
|
95
|
+
* Can be strings (substring match) or RegExp patterns.
|
|
96
|
+
* The dashboard URL is always ignored automatically.
|
|
97
|
+
* @example ['analytics.google.com', /\.segment\.com/]
|
|
98
|
+
*/
|
|
99
|
+
networkIgnoreUrls?: (string | RegExp)[];
|
|
100
|
+
/**
|
|
101
|
+
* Whether to capture request/response body sizes (default: true)
|
|
102
|
+
* Disable if you want minimal network tracking overhead.
|
|
103
|
+
*/
|
|
104
|
+
networkCaptureSizes?: boolean;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// Event Types
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
export type GestureType =
|
|
112
|
+
| 'tap'
|
|
113
|
+
| 'double_tap'
|
|
114
|
+
| 'long_press'
|
|
115
|
+
| 'force_touch'
|
|
116
|
+
| 'swipe_left'
|
|
117
|
+
| 'swipe_right'
|
|
118
|
+
| 'swipe_up'
|
|
119
|
+
| 'swipe_down'
|
|
120
|
+
| 'pinch'
|
|
121
|
+
| 'pinch_in'
|
|
122
|
+
| 'pinch_out'
|
|
123
|
+
| 'pan_up'
|
|
124
|
+
| 'pan_down'
|
|
125
|
+
| 'pan_left'
|
|
126
|
+
| 'pan_right'
|
|
127
|
+
| 'rotate_cw'
|
|
128
|
+
| 'rotate_ccw'
|
|
129
|
+
| 'scroll'
|
|
130
|
+
| 'scroll_up'
|
|
131
|
+
| 'scroll_down'
|
|
132
|
+
| 'two_finger_tap'
|
|
133
|
+
| 'three_finger_gesture'
|
|
134
|
+
| 'multi_touch'
|
|
135
|
+
| 'keyboard_tap'
|
|
136
|
+
| 'rage_tap';
|
|
137
|
+
|
|
138
|
+
export type EventType =
|
|
139
|
+
| 'gesture'
|
|
140
|
+
| 'screen_change'
|
|
141
|
+
| 'custom'
|
|
142
|
+
| 'app_state'
|
|
143
|
+
| 'app_lifecycle'
|
|
144
|
+
| 'keyboard_show'
|
|
145
|
+
| 'keyboard_hide'
|
|
146
|
+
| 'keyboard_typing'
|
|
147
|
+
| 'oauth_started'
|
|
148
|
+
| 'oauth_completed'
|
|
149
|
+
| 'oauth_returned'
|
|
150
|
+
| 'external_url_opened'
|
|
151
|
+
| 'session_start'
|
|
152
|
+
| 'session_timeout'
|
|
153
|
+
| 'frustration'
|
|
154
|
+
| 'error';
|
|
155
|
+
|
|
156
|
+
export interface TouchPoint {
|
|
157
|
+
x: number;
|
|
158
|
+
y: number;
|
|
159
|
+
timestamp: number;
|
|
160
|
+
/** Force/pressure of the touch (0-1, for force touch/3D Touch) */
|
|
161
|
+
force?: number;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export interface GestureEvent {
|
|
165
|
+
type: 'gesture';
|
|
166
|
+
gestureType: GestureType;
|
|
167
|
+
timestamp: number;
|
|
168
|
+
/** Touch coordinates */
|
|
169
|
+
touches: TouchPoint[];
|
|
170
|
+
/** Duration of the gesture in ms */
|
|
171
|
+
duration?: number;
|
|
172
|
+
/** Velocity for swipes */
|
|
173
|
+
velocity?: { x: number; y: number };
|
|
174
|
+
/** Scale for pinch gestures */
|
|
175
|
+
scale?: number;
|
|
176
|
+
/** Rotation angle in degrees (for rotation gestures) */
|
|
177
|
+
rotation?: number;
|
|
178
|
+
/** Max force applied (for force touch) */
|
|
179
|
+
maxForce?: number;
|
|
180
|
+
/** Number of fingers used */
|
|
181
|
+
touchCount?: number;
|
|
182
|
+
/** Target component identifier if available */
|
|
183
|
+
targetId?: string;
|
|
184
|
+
/** Accessibility label of target */
|
|
185
|
+
targetLabel?: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export interface ScreenChangeEvent {
|
|
189
|
+
type: 'screen_change';
|
|
190
|
+
timestamp: number;
|
|
191
|
+
/** Screen/route name */
|
|
192
|
+
screenName: string;
|
|
193
|
+
/** Previous screen name */
|
|
194
|
+
previousScreenName?: string;
|
|
195
|
+
/** Screen parameters */
|
|
196
|
+
params?: Record<string, unknown>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export interface CustomEvent {
|
|
200
|
+
type: 'custom';
|
|
201
|
+
timestamp: number;
|
|
202
|
+
/** Event name */
|
|
203
|
+
name: string;
|
|
204
|
+
/** Event properties */
|
|
205
|
+
properties?: Record<string, unknown>;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export interface AppStateEvent {
|
|
209
|
+
type: 'app_state';
|
|
210
|
+
timestamp: number;
|
|
211
|
+
/** App state: active, background, inactive */
|
|
212
|
+
state: 'active' | 'background' | 'inactive';
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface AppLifecycleEvent {
|
|
216
|
+
type: 'app_lifecycle';
|
|
217
|
+
timestamp: number;
|
|
218
|
+
/** Lifecycle state */
|
|
219
|
+
state: 'app_foreground' | 'app_background' | 'app_terminated';
|
|
220
|
+
/** Duration app was in background when returning to foreground (ms) */
|
|
221
|
+
backgroundDuration?: number;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export interface KeyboardEvent {
|
|
225
|
+
type: 'keyboard_show' | 'keyboard_hide';
|
|
226
|
+
timestamp: number;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export interface KeyboardTypingEvent {
|
|
230
|
+
type: 'keyboard_typing';
|
|
231
|
+
timestamp: number;
|
|
232
|
+
/** Number of key presses (content not captured for privacy) */
|
|
233
|
+
keyPressCount: number;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
export interface OAuthEvent {
|
|
237
|
+
type: 'oauth_started' | 'oauth_completed' | 'oauth_returned';
|
|
238
|
+
timestamp: number;
|
|
239
|
+
/** OAuth provider name */
|
|
240
|
+
provider?: string;
|
|
241
|
+
/** OAuth URL scheme */
|
|
242
|
+
scheme?: string;
|
|
243
|
+
/** Whether OAuth was successful (for completed event) */
|
|
244
|
+
success?: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export interface ExternalURLEvent {
|
|
248
|
+
type: 'external_url_opened';
|
|
249
|
+
timestamp: number;
|
|
250
|
+
/** URL scheme that was opened */
|
|
251
|
+
scheme: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export interface SessionTimeoutEvent {
|
|
255
|
+
type: 'session_timeout';
|
|
256
|
+
timestamp: number;
|
|
257
|
+
/** Duration app was in background (ms) */
|
|
258
|
+
backgroundDuration: number;
|
|
259
|
+
/** Timeout threshold that was exceeded (ms) */
|
|
260
|
+
timeoutThreshold: number;
|
|
261
|
+
/** Reason for the timeout */
|
|
262
|
+
reason: 'background_timeout';
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface SessionStartEvent {
|
|
266
|
+
type: 'session_start';
|
|
267
|
+
timestamp: number;
|
|
268
|
+
/** Previous session ID if this session was started due to timeout */
|
|
269
|
+
previousSessionId?: string;
|
|
270
|
+
/** Duration app was in background before new session (ms) */
|
|
271
|
+
backgroundDuration?: number;
|
|
272
|
+
/** Reason for starting new session */
|
|
273
|
+
reason?: 'resumed_after_background_timeout' | 'user_initiated' | 'auto_start';
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface FrustrationEvent {
|
|
277
|
+
type: 'frustration';
|
|
278
|
+
timestamp: number;
|
|
279
|
+
/** Frustration type */
|
|
280
|
+
frustrationKind: 'rage_tap' | 'ui_freeze' | 'error';
|
|
281
|
+
/** Additional details */
|
|
282
|
+
details?: Record<string, unknown>;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export interface ErrorEvent {
|
|
286
|
+
type: 'error';
|
|
287
|
+
timestamp: number;
|
|
288
|
+
/** Error message */
|
|
289
|
+
message: string;
|
|
290
|
+
/** Error stack trace */
|
|
291
|
+
stack?: string;
|
|
292
|
+
/** Error type/name */
|
|
293
|
+
name?: string;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ============================================================================
|
|
297
|
+
// Network Request Types (API Call Tracking)
|
|
298
|
+
// ============================================================================
|
|
299
|
+
|
|
300
|
+
export interface NetworkRequestEvent {
|
|
301
|
+
type: 'network_request';
|
|
302
|
+
/** Unique request ID for correlating request/response */
|
|
303
|
+
requestId: string;
|
|
304
|
+
/** Timestamp when request started */
|
|
305
|
+
timestamp: number;
|
|
306
|
+
/** HTTP method */
|
|
307
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
308
|
+
/** Request URL (may be truncated for efficiency) */
|
|
309
|
+
url: string;
|
|
310
|
+
/** URL path only (without domain, for grouping) */
|
|
311
|
+
urlPath: string;
|
|
312
|
+
/** URL domain/host */
|
|
313
|
+
urlHost: string;
|
|
314
|
+
/** Request headers (filtered for privacy, optional) */
|
|
315
|
+
requestHeaders?: Record<string, string>;
|
|
316
|
+
/** Request body size in bytes (not the actual body for privacy) */
|
|
317
|
+
requestBodySize?: number;
|
|
318
|
+
/** Content type of request */
|
|
319
|
+
requestContentType?: string;
|
|
320
|
+
/** HTTP status code (0 if request failed) */
|
|
321
|
+
statusCode: number;
|
|
322
|
+
/** Response headers (filtered for privacy, optional) */
|
|
323
|
+
responseHeaders?: Record<string, string>;
|
|
324
|
+
/** Response body size in bytes */
|
|
325
|
+
responseBodySize?: number;
|
|
326
|
+
/** Content type of response */
|
|
327
|
+
responseContentType?: string;
|
|
328
|
+
/** Duration of the request in ms */
|
|
329
|
+
duration: number;
|
|
330
|
+
/** Timestamp when response was received */
|
|
331
|
+
endTimestamp: number;
|
|
332
|
+
/** Whether the request succeeded (statusCode 2xx or 3xx) */
|
|
333
|
+
success: boolean;
|
|
334
|
+
/** Error message if request failed */
|
|
335
|
+
errorMessage?: string;
|
|
336
|
+
/** Whether this was a cached response */
|
|
337
|
+
cached?: boolean;
|
|
338
|
+
/** Screen where the request was initiated (if known) */
|
|
339
|
+
screenName?: string;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export type SessionEvent =
|
|
343
|
+
| GestureEvent
|
|
344
|
+
| ScreenChangeEvent
|
|
345
|
+
| CustomEvent
|
|
346
|
+
| AppStateEvent
|
|
347
|
+
| AppLifecycleEvent
|
|
348
|
+
| KeyboardEvent
|
|
349
|
+
| KeyboardTypingEvent
|
|
350
|
+
| OAuthEvent
|
|
351
|
+
| ExternalURLEvent
|
|
352
|
+
| SessionTimeoutEvent
|
|
353
|
+
| SessionStartEvent
|
|
354
|
+
| FrustrationEvent
|
|
355
|
+
| ErrorEvent
|
|
356
|
+
| NetworkRequestEvent;
|
|
357
|
+
|
|
358
|
+
// ============================================================================
|
|
359
|
+
// Session Types
|
|
360
|
+
// ============================================================================
|
|
361
|
+
|
|
362
|
+
export interface GeoLocation {
|
|
363
|
+
/** IP address */
|
|
364
|
+
ip: string;
|
|
365
|
+
/** Country name */
|
|
366
|
+
country?: string;
|
|
367
|
+
/** Country code (ISO 3166-1 alpha-2) */
|
|
368
|
+
countryCode?: string;
|
|
369
|
+
/** Region/State */
|
|
370
|
+
region?: string;
|
|
371
|
+
/** City */
|
|
372
|
+
city?: string;
|
|
373
|
+
/** Latitude */
|
|
374
|
+
latitude?: number;
|
|
375
|
+
/** Longitude */
|
|
376
|
+
longitude?: number;
|
|
377
|
+
/** Timezone */
|
|
378
|
+
timezone?: string;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
export interface DeviceInfo {
|
|
382
|
+
/** Device model */
|
|
383
|
+
model: string;
|
|
384
|
+
/** Device manufacturer */
|
|
385
|
+
manufacturer?: string;
|
|
386
|
+
/** OS name */
|
|
387
|
+
os: 'ios' | 'android';
|
|
388
|
+
/** OS version */
|
|
389
|
+
osVersion: string;
|
|
390
|
+
/** Screen width */
|
|
391
|
+
screenWidth: number;
|
|
392
|
+
/** Screen height */
|
|
393
|
+
screenHeight: number;
|
|
394
|
+
/** Pixel density */
|
|
395
|
+
pixelRatio: number;
|
|
396
|
+
/** App version */
|
|
397
|
+
appVersion?: string;
|
|
398
|
+
/** App bundle/package ID */
|
|
399
|
+
appId?: string;
|
|
400
|
+
/** Device locale */
|
|
401
|
+
locale?: string;
|
|
402
|
+
/** Device timezone */
|
|
403
|
+
timezone?: string;
|
|
404
|
+
/** Total device memory (MB) */
|
|
405
|
+
totalMemory?: number;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export interface SessionMetadata {
|
|
409
|
+
/** Unique session ID */
|
|
410
|
+
sessionId: string;
|
|
411
|
+
/** User identity if set */
|
|
412
|
+
userId?: string;
|
|
413
|
+
/** Session start timestamp */
|
|
414
|
+
startTime: number;
|
|
415
|
+
/** Session end timestamp */
|
|
416
|
+
endTime?: number;
|
|
417
|
+
/** Session duration in ms */
|
|
418
|
+
duration?: number;
|
|
419
|
+
/** Device information */
|
|
420
|
+
deviceInfo: DeviceInfo;
|
|
421
|
+
/** Geolocation information */
|
|
422
|
+
geoLocation?: GeoLocation;
|
|
423
|
+
/** Number of events in session */
|
|
424
|
+
eventCount: number;
|
|
425
|
+
/** Number of video segments */
|
|
426
|
+
videoSegmentCount?: number;
|
|
427
|
+
/** Total storage size in bytes */
|
|
428
|
+
storageSize: number;
|
|
429
|
+
/** Session tags */
|
|
430
|
+
tags?: string[];
|
|
431
|
+
/** SDK version */
|
|
432
|
+
sdkVersion: string;
|
|
433
|
+
/** Whether session is complete */
|
|
434
|
+
isComplete: boolean;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
export interface SessionData {
|
|
438
|
+
/** Session metadata */
|
|
439
|
+
metadata: SessionMetadata;
|
|
440
|
+
/** Session events */
|
|
441
|
+
events: SessionEvent[];
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export interface SessionSummary {
|
|
445
|
+
sessionId: string;
|
|
446
|
+
userId?: string;
|
|
447
|
+
startTime: number;
|
|
448
|
+
endTime?: number;
|
|
449
|
+
duration?: number;
|
|
450
|
+
eventCount: number;
|
|
451
|
+
videoSegmentCount?: number;
|
|
452
|
+
storageSize: number;
|
|
453
|
+
isComplete: boolean;
|
|
454
|
+
/** Path to session data file */
|
|
455
|
+
filePath: string;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// ============================================================================
|
|
459
|
+
// Replay Types
|
|
460
|
+
// ============================================================================
|
|
461
|
+
|
|
462
|
+
export interface ReplayState {
|
|
463
|
+
/** Current playback position in ms from session start */
|
|
464
|
+
currentTime: number;
|
|
465
|
+
/** Is currently playing */
|
|
466
|
+
isPlaying: boolean;
|
|
467
|
+
/** Playback speed multiplier */
|
|
468
|
+
speed: 0.5 | 1 | 2 | 4;
|
|
469
|
+
/** Session duration */
|
|
470
|
+
duration: number;
|
|
471
|
+
/** Current video segment time position */
|
|
472
|
+
currentVideoTime?: number;
|
|
473
|
+
/** Events at or near current time */
|
|
474
|
+
activeEvents: SessionEvent[];
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export interface ReplayControls {
|
|
478
|
+
play: () => void;
|
|
479
|
+
pause: () => void;
|
|
480
|
+
seek: (timeMs: number) => void;
|
|
481
|
+
setSpeed: (speed: 0.5 | 1 | 2 | 4) => void;
|
|
482
|
+
skipInactivity: () => void;
|
|
483
|
+
nextEvent: () => void;
|
|
484
|
+
previousEvent: () => void;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export interface ReplayProps {
|
|
488
|
+
/** Session ID to replay */
|
|
489
|
+
sessionId: string;
|
|
490
|
+
/** Auto-play on mount (default: false) */
|
|
491
|
+
autoPlay?: boolean;
|
|
492
|
+
/** Show controls (default: true) */
|
|
493
|
+
showControls?: boolean;
|
|
494
|
+
/** Show event markers on timeline (default: true) */
|
|
495
|
+
showEventMarkers?: boolean;
|
|
496
|
+
/** Show gesture overlays (default: true) */
|
|
497
|
+
showGestureOverlays?: boolean;
|
|
498
|
+
/** Initial playback speed (default: 1) */
|
|
499
|
+
initialSpeed?: 0.5 | 1 | 2 | 4;
|
|
500
|
+
/** Callback when playback ends */
|
|
501
|
+
onEnd?: () => void;
|
|
502
|
+
/** Callback when playback state changes */
|
|
503
|
+
onStateChange?: (state: ReplayState) => void;
|
|
504
|
+
/** Callback on error */
|
|
505
|
+
onError?: (error: Error) => void;
|
|
506
|
+
/** Container style */
|
|
507
|
+
style?: object;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// ============================================================================
|
|
511
|
+
// Native Module Types
|
|
512
|
+
// ============================================================================
|
|
513
|
+
|
|
514
|
+
export interface RejourneyNativeModule {
|
|
515
|
+
/** Initialize the native SDK */
|
|
516
|
+
initialize(config: RejourneyConfig): Promise<void>;
|
|
517
|
+
/** Start recording session */
|
|
518
|
+
startRecording(): Promise<string>;
|
|
519
|
+
/** Stop recording session */
|
|
520
|
+
stopRecording(): Promise<void>;
|
|
521
|
+
/** Log a gesture event */
|
|
522
|
+
logGesture(event: Omit<GestureEvent, 'type'>): Promise<void>;
|
|
523
|
+
/** Set privacy occlusion for a view */
|
|
524
|
+
setOccluded(viewTag: number, occluded: boolean): Promise<void>;
|
|
525
|
+
/** Get device info */
|
|
526
|
+
getDeviceInfo(): Promise<DeviceInfo>;
|
|
527
|
+
/** Get all sessions */
|
|
528
|
+
getSessions(): Promise<SessionSummary[]>;
|
|
529
|
+
/** Get session data */
|
|
530
|
+
getSessionData(sessionId: string): Promise<SessionData>;
|
|
531
|
+
/** Delete a session */
|
|
532
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
533
|
+
/** Delete all sessions */
|
|
534
|
+
deleteAllSessions(): Promise<void>;
|
|
535
|
+
/** Export session as shareable file */
|
|
536
|
+
exportSession(sessionId: string): Promise<string>;
|
|
537
|
+
/** Get current recording state */
|
|
538
|
+
isRecording(): Promise<boolean>;
|
|
539
|
+
/** Get storage usage */
|
|
540
|
+
getStorageUsage(): Promise<{ used: number; max: number }>;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// ============================================================================
|
|
544
|
+
// API Types
|
|
545
|
+
// ============================================================================
|
|
546
|
+
|
|
547
|
+
export interface RejourneyAPI {
|
|
548
|
+
/** SDK version */
|
|
549
|
+
readonly version: string;
|
|
550
|
+
/** Internal method to start recording session (called by startRejourney) */
|
|
551
|
+
_startSession(): Promise<boolean>;
|
|
552
|
+
/** Internal method to stop recording session (called by stopRejourney) */
|
|
553
|
+
_stopSession(): Promise<void>;
|
|
554
|
+
/** Log a custom event */
|
|
555
|
+
logEvent(name: string, properties?: Record<string, unknown>): void;
|
|
556
|
+
/** Set user identity for session correlation */
|
|
557
|
+
setUserIdentity(userId: string): void;
|
|
558
|
+
/** Clear user identity */
|
|
559
|
+
clearUserIdentity(): void;
|
|
560
|
+
/** Tag current screen */
|
|
561
|
+
tagScreen(screenName: string, params?: Record<string, unknown>): void;
|
|
562
|
+
/** Mark a view as sensitive (will be occluded in recording) */
|
|
563
|
+
setOccluded(viewRef: { current: any }, occluded?: boolean): void;
|
|
564
|
+
/** Add a tag to current session */
|
|
565
|
+
addSessionTag(tag: string): void;
|
|
566
|
+
/** Mark a visual change that should be captured */
|
|
567
|
+
markVisualChange(reason: string, importance?: 'low' | 'medium' | 'high' | 'critical'): Promise<boolean>;
|
|
568
|
+
/** Report scroll event for timeline correlation */
|
|
569
|
+
onScroll(scrollOffset: number): Promise<void>;
|
|
570
|
+
/** Notify SDK that an OAuth flow is starting */
|
|
571
|
+
onOAuthStarted(provider: string): Promise<boolean>;
|
|
572
|
+
/** Notify SDK that an OAuth flow has completed */
|
|
573
|
+
onOAuthCompleted(provider: string, success: boolean): Promise<boolean>;
|
|
574
|
+
/** Notify SDK that an external URL is being opened */
|
|
575
|
+
onExternalURLOpened(urlScheme: string): Promise<boolean>;
|
|
576
|
+
/**
|
|
577
|
+
* Log a network request for API call timeline tracking.
|
|
578
|
+
* This is a low-priority, efficient way to track API calls during session replay.
|
|
579
|
+
*
|
|
580
|
+
* @param request - Network request details
|
|
581
|
+
* @example
|
|
582
|
+
* ```typescript
|
|
583
|
+
* Rejourney.logNetworkRequest({
|
|
584
|
+
* request Id: 'req_123',
|
|
585
|
+
* method: 'POST',
|
|
586
|
+
* url: 'https://api.example.com/users',
|
|
587
|
+
* statusCode: 201,
|
|
588
|
+
* duration: 234,
|
|
589
|
+
* requestBodySize: 156,
|
|
590
|
+
* responseBodySize: 512,
|
|
591
|
+
* });
|
|
592
|
+
* ```
|
|
593
|
+
*/
|
|
594
|
+
logNetworkRequest(request: NetworkRequestParams): void;
|
|
595
|
+
/** Get all recorded sessions */
|
|
596
|
+
getSessions(): Promise<SessionSummary[]>;
|
|
597
|
+
/** Get session data for replay */
|
|
598
|
+
getSessionData(sessionId: string): Promise<SessionData>;
|
|
599
|
+
/** Delete a session */
|
|
600
|
+
deleteSession(sessionId: string): Promise<void>;
|
|
601
|
+
/** Delete all sessions */
|
|
602
|
+
deleteAllSessions(): Promise<void>;
|
|
603
|
+
/** Export session for sharing */
|
|
604
|
+
exportSession(sessionId: string): Promise<string>;
|
|
605
|
+
/** Check if currently recording */
|
|
606
|
+
isRecording(): Promise<boolean>;
|
|
607
|
+
/** Get storage usage */
|
|
608
|
+
getStorageUsage(): Promise<{ used: number; max: number }>;
|
|
609
|
+
/** Get ingest auth headers (x-ingest-token/x-device-id) if available */
|
|
610
|
+
getIngestAuthHeaders(): { 'x-ingest-token': string; 'x-device-id': string } | null;
|
|
611
|
+
/**
|
|
612
|
+
* Get SDK telemetry metrics for observability
|
|
613
|
+
* Returns metrics about SDK health including upload success rates,
|
|
614
|
+
* retry attempts, circuit breaker events, and memory pressure.
|
|
615
|
+
*/
|
|
616
|
+
getSDKMetrics(): Promise<SDKMetrics>;
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Trigger a debug ANR (Dev only)
|
|
620
|
+
* Blocks the main thread for the specified duration
|
|
621
|
+
*/
|
|
622
|
+
debugTriggerANR(durationMs: number): void;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Mask a view by its nativeID prop (will be occluded in recordings)
|
|
626
|
+
*
|
|
627
|
+
* Use this to mask any sensitive content that isn't a text input.
|
|
628
|
+
* The view must have a `nativeID` prop set.
|
|
629
|
+
*
|
|
630
|
+
* @param nativeID - The nativeID prop of the view to mask
|
|
631
|
+
* @example
|
|
632
|
+
* ```tsx
|
|
633
|
+
* // In your component
|
|
634
|
+
* <View nativeID="sensitiveCard">...</View>
|
|
635
|
+
*
|
|
636
|
+
* // To mask it
|
|
637
|
+
* Rejourney.maskView('sensitiveCard');
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
maskView(nativeID: string): void;
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Unmask a view by its nativeID prop
|
|
644
|
+
*
|
|
645
|
+
* Removes the mask from a view that was previously masked with maskView().
|
|
646
|
+
*
|
|
647
|
+
* @param nativeID - The nativeID prop of the view to unmask
|
|
648
|
+
*/
|
|
649
|
+
unmaskView(nativeID: string): void;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* SDK telemetry metrics for observability
|
|
654
|
+
*/
|
|
655
|
+
export interface SDKMetrics {
|
|
656
|
+
uploadSuccessCount: number;
|
|
657
|
+
uploadFailureCount: number;
|
|
658
|
+
retryAttemptCount: number;
|
|
659
|
+
circuitBreakerOpenCount: number;
|
|
660
|
+
memoryEvictionCount: number;
|
|
661
|
+
offlinePersistCount: number;
|
|
662
|
+
sessionStartCount: number;
|
|
663
|
+
crashCount: number;
|
|
664
|
+
uploadSuccessRate: number;
|
|
665
|
+
avgUploadDurationMs: number;
|
|
666
|
+
currentQueueDepth: number;
|
|
667
|
+
lastUploadTime: number | null;
|
|
668
|
+
lastRetryTime: number | null;
|
|
669
|
+
totalBytesUploaded: number;
|
|
670
|
+
totalBytesEvicted: number;
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Parameters for logging a network request
|
|
675
|
+
*/
|
|
676
|
+
export interface NetworkRequestParams {
|
|
677
|
+
/** Unique request ID (optional, will be auto-generated if not provided) */
|
|
678
|
+
requestId?: string;
|
|
679
|
+
/** HTTP method */
|
|
680
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
681
|
+
/** Full request URL */
|
|
682
|
+
url: string;
|
|
683
|
+
/** HTTP status code (0 if request failed/aborted) */
|
|
684
|
+
statusCode: number;
|
|
685
|
+
/** Request duration in milliseconds */
|
|
686
|
+
duration: number;
|
|
687
|
+
/** Timestamp when request started (optional, defaults to endTimestamp - duration) */
|
|
688
|
+
startTimestamp?: number;
|
|
689
|
+
/** Timestamp when response was received (optional, defaults to Date.now()) */
|
|
690
|
+
endTimestamp?: number;
|
|
691
|
+
/** Request body size in bytes (optional) */
|
|
692
|
+
requestBodySize?: number;
|
|
693
|
+
/** Response body size in bytes (optional) */
|
|
694
|
+
responseBodySize?: number;
|
|
695
|
+
/** Request content type (optional) */
|
|
696
|
+
requestContentType?: string;
|
|
697
|
+
/** Response content type (optional) */
|
|
698
|
+
responseContentType?: string;
|
|
699
|
+
/** Error message if request failed (optional) */
|
|
700
|
+
errorMessage?: string;
|
|
701
|
+
/** Whether response was from cache (optional) */
|
|
702
|
+
cached?: boolean;
|
|
703
|
+
/** Whether the request was successful (2xx/3xx status) */
|
|
704
|
+
success?: boolean;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// ============================================================================
|
|
708
|
+
// Hook Types
|
|
709
|
+
// ============================================================================
|
|
710
|
+
|
|
711
|
+
export interface UseRejourneyResult {
|
|
712
|
+
/** Whether SDK is initialized */
|
|
713
|
+
isInitialized: boolean;
|
|
714
|
+
/** Whether currently recording */
|
|
715
|
+
isRecording: boolean;
|
|
716
|
+
/** Current session ID */
|
|
717
|
+
currentSessionId: string | null;
|
|
718
|
+
/** Start recording */
|
|
719
|
+
startRecording: () => Promise<string>;
|
|
720
|
+
/** Stop recording */
|
|
721
|
+
stopRecording: () => Promise<void>;
|
|
722
|
+
/** Log custom event */
|
|
723
|
+
logEvent: (name: string, properties?: Record<string, unknown>) => void;
|
|
724
|
+
/** Error if any */
|
|
725
|
+
error: Error | null;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
export interface UseReplayResult {
|
|
729
|
+
/** Replay state */
|
|
730
|
+
state: ReplayState;
|
|
731
|
+
/** Replay controls */
|
|
732
|
+
controls: ReplayControls;
|
|
733
|
+
/** Session data */
|
|
734
|
+
session: SessionData | null;
|
|
735
|
+
/** Loading state */
|
|
736
|
+
isLoading: boolean;
|
|
737
|
+
/** Error if any */
|
|
738
|
+
error: Error | null;
|
|
739
|
+
}
|