@rejourneyco/react-native 1.0.0 → 1.0.2

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 (49) hide show
  1. package/README.md +29 -0
  2. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +47 -30
  3. package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +25 -1
  4. package/android/src/main/java/com/rejourney/capture/CaptureHeuristics.kt +70 -32
  5. package/android/src/main/java/com/rejourney/core/Constants.kt +4 -4
  6. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +14 -0
  7. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +9 -0
  8. package/ios/Capture/RJCaptureEngine.m +72 -34
  9. package/ios/Capture/RJCaptureHeuristics.h +7 -5
  10. package/ios/Capture/RJCaptureHeuristics.m +138 -112
  11. package/ios/Capture/RJVideoEncoder.m +0 -26
  12. package/ios/Core/Rejourney.mm +64 -102
  13. package/ios/Utils/RJPerfTiming.m +0 -5
  14. package/ios/Utils/RJWindowUtils.m +0 -1
  15. package/lib/commonjs/components/Mask.js +1 -6
  16. package/lib/commonjs/index.js +12 -101
  17. package/lib/commonjs/sdk/autoTracking.js +55 -353
  18. package/lib/commonjs/sdk/constants.js +2 -13
  19. package/lib/commonjs/sdk/errorTracking.js +1 -29
  20. package/lib/commonjs/sdk/metricsTracking.js +3 -24
  21. package/lib/commonjs/sdk/navigation.js +3 -42
  22. package/lib/commonjs/sdk/networkInterceptor.js +7 -49
  23. package/lib/commonjs/sdk/utils.js +0 -5
  24. package/lib/module/components/Mask.js +1 -6
  25. package/lib/module/index.js +11 -105
  26. package/lib/module/sdk/autoTracking.js +55 -354
  27. package/lib/module/sdk/constants.js +2 -13
  28. package/lib/module/sdk/errorTracking.js +1 -29
  29. package/lib/module/sdk/index.js +0 -2
  30. package/lib/module/sdk/metricsTracking.js +3 -24
  31. package/lib/module/sdk/navigation.js +3 -42
  32. package/lib/module/sdk/networkInterceptor.js +7 -49
  33. package/lib/module/sdk/utils.js +0 -5
  34. package/lib/typescript/NativeRejourney.d.ts +2 -0
  35. package/lib/typescript/sdk/autoTracking.d.ts +5 -6
  36. package/lib/typescript/types/index.d.ts +0 -1
  37. package/package.json +11 -3
  38. package/src/NativeRejourney.ts +4 -0
  39. package/src/components/Mask.tsx +0 -3
  40. package/src/index.ts +11 -88
  41. package/src/sdk/autoTracking.ts +72 -331
  42. package/src/sdk/constants.ts +13 -13
  43. package/src/sdk/errorTracking.ts +1 -17
  44. package/src/sdk/index.ts +0 -2
  45. package/src/sdk/metricsTracking.ts +5 -33
  46. package/src/sdk/navigation.ts +8 -29
  47. package/src/sdk/networkInterceptor.ts +9 -33
  48. package/src/sdk/utils.ts +0 -5
  49. package/src/types/index.ts +0 -29
@@ -7,26 +7,26 @@ export const SDK_VERSION = '1.0.0';
7
7
  /** Default configuration values */
8
8
  export const DEFAULT_CONFIG = {
9
9
  enabled: true,
10
- captureFPS: 0.5, // Every 2 seconds (only used in timer mode)
11
- captureOnEvents: true, // Event-driven capture (not time-based)
12
- maxSessionDuration: 10 * 60 * 1000, // 10 minutes (project-level configurable, clamped 1–10)
13
- maxStorageSize: 50 * 1024 * 1024, // 50MB
10
+ captureFPS: 0.5,
11
+ captureOnEvents: true,
12
+ maxSessionDuration: 10 * 60 * 1000,
13
+ maxStorageSize: 50 * 1024 * 1024,
14
14
  autoScreenTracking: true,
15
15
  autoGestureTracking: true,
16
16
  privacyOcclusion: true,
17
17
  enableCompression: true,
18
- inactivityThreshold: 5000, // 5 seconds
18
+ inactivityThreshold: 5000,
19
19
  disableInDev: false,
20
20
  detectRageTaps: true,
21
21
  rageTapThreshold: 3,
22
- rageTapTimeWindow: 1000, // 1 second
22
+ rageTapTimeWindow: 1000,
23
23
  debug: false,
24
24
  autoStartRecording: true,
25
- collectDeviceInfo: true, // Collect detailed device information
26
- collectGeoLocation: true, // Collect IP address and geolocation
27
- postNavigationDelay: 300, // 300ms - allow navigation animations to complete
28
- postGestureDelay: 200, // 200ms - show result of taps, not animations
29
- postModalDelay: 400, // 400ms - ensure modals/alerts are fully rendered
25
+ collectDeviceInfo: true,
26
+ collectGeoLocation: true,
27
+ postNavigationDelay: 300,
28
+ postGestureDelay: 200,
29
+ postModalDelay: 400,
30
30
  } as const;
31
31
 
32
32
  /** Event type constants */
@@ -61,8 +61,8 @@ export const CAPTURE_SETTINGS = {
61
61
  DEFAULT_FPS: 0.5,
62
62
  MIN_FPS: 0.1,
63
63
  MAX_FPS: 2,
64
- CAPTURE_SCALE: 0.25, // 25% resolution for video segments
65
- MIN_CAPTURE_DELTA_TIME: 0.5, // Minimum 0.5s between captures (rate limiting)
64
+ CAPTURE_SCALE: 0.25,
65
+ MIN_CAPTURE_DELTA_TIME: 0.5,
66
66
  } as const;
67
67
 
68
68
  /** Memory management settings */
@@ -7,7 +7,6 @@
7
7
 
8
8
  import type { ErrorEvent } from '../types';
9
9
 
10
- // Type declarations for browser globals (only used in hybrid apps where DOM is available)
11
10
  type OnErrorEventHandler = ((
12
11
  event: Event | string,
13
12
  source?: string,
@@ -21,7 +20,6 @@ interface PromiseRejectionEvent {
21
20
  promise?: Promise<any>;
22
21
  }
23
22
 
24
- // Cast globalThis to work with both RN and hybrid scenarios
25
23
  const _globalThis = globalThis as typeof globalThis & {
26
24
  onerror?: OnErrorEventHandler;
27
25
  addEventListener?: (type: string, handler: (event: any) => void) => void;
@@ -32,15 +30,11 @@ const _globalThis = globalThis as typeof globalThis & {
32
30
  };
33
31
  };
34
32
 
35
- // Original error handlers (for restoration)
36
33
  let originalErrorHandler: ((error: Error, isFatal: boolean) => void) | undefined;
37
34
  let originalOnError: OnErrorEventHandler | null = null;
38
35
  let originalOnUnhandledRejection: ((event: PromiseRejectionEvent) => void) | null = null;
39
-
40
- // Callbacks
41
36
  let onErrorCallback: ((error: ErrorEvent) => void) | null = null;
42
37
 
43
- // Metrics
44
38
  let errorCount = 0;
45
39
 
46
40
  /**
@@ -57,17 +51,14 @@ export function setupErrorTracking(
57
51
  onErrorCallback = onError;
58
52
  errorCount = 0;
59
53
 
60
- // Track React Native errors
61
54
  if (config.trackReactNativeErrors !== false) {
62
55
  setupReactNativeErrorHandler();
63
56
  }
64
57
 
65
- // Track JavaScript errors (only works in web/debug)
66
58
  if (config.trackJSErrors !== false && typeof _globalThis !== 'undefined') {
67
59
  setupJSErrorHandler();
68
60
  }
69
61
 
70
- // Track unhandled promise rejections
71
62
  if (config.trackPromiseRejections !== false && typeof _globalThis !== 'undefined') {
72
63
  setupPromiseRejectionHandler();
73
64
  }
@@ -77,7 +68,6 @@ export function setupErrorTracking(
77
68
  * Cleanup error tracking and restore original handlers
78
69
  */
79
70
  export function cleanupErrorTracking(): void {
80
- // Restore React Native handler
81
71
  if (originalErrorHandler) {
82
72
  try {
83
73
  const ErrorUtils = _globalThis.ErrorUtils;
@@ -90,13 +80,11 @@ export function cleanupErrorTracking(): void {
90
80
  originalErrorHandler = undefined;
91
81
  }
92
82
 
93
- // Restore global onerror
94
83
  if (originalOnError !== null) {
95
84
  _globalThis.onerror = originalOnError;
96
85
  originalOnError = null;
97
86
  }
98
87
 
99
- // Remove promise rejection handler
100
88
  if (originalOnUnhandledRejection && typeof _globalThis.removeEventListener !== 'undefined') {
101
89
  _globalThis.removeEventListener!('unhandledrejection', originalOnUnhandledRejection);
102
90
  originalOnUnhandledRejection = null;
@@ -155,10 +143,8 @@ function setupReactNativeErrorHandler(): void {
155
143
  const ErrorUtils = _globalThis.ErrorUtils;
156
144
  if (!ErrorUtils) return;
157
145
 
158
- // Store original handler
159
146
  originalErrorHandler = ErrorUtils.getGlobalHandler();
160
147
 
161
- // Set new handler
162
148
  ErrorUtils.setGlobalHandler((error: Error, isFatal: boolean) => {
163
149
  trackError({
164
150
  type: 'error',
@@ -168,13 +154,12 @@ function setupReactNativeErrorHandler(): void {
168
154
  name: error.name || 'Error',
169
155
  });
170
156
 
171
- // Call original handler
172
157
  if (originalErrorHandler) {
173
158
  originalErrorHandler(error, isFatal);
174
159
  }
175
160
  });
176
161
  } catch {
177
- // ErrorUtils not available
162
+ // Ignore
178
163
  }
179
164
  }
180
165
 
@@ -200,7 +185,6 @@ function setupJSErrorHandler(): void {
200
185
  name: error?.name || 'Error',
201
186
  });
202
187
 
203
- // Call original handler
204
188
  if (originalOnError) {
205
189
  return originalOnError(message, source, lineno, colno, error);
206
190
  }
package/src/sdk/index.ts CHANGED
@@ -7,5 +7,3 @@ export * from './constants';
7
7
  export * from './utils';
8
8
  export * from './autoTracking';
9
9
  export * from './networkInterceptor';
10
- // Note: errorTracking and metricsTracking are internal modules
11
- // Their exports are re-exported through autoTracking for backward compatibility
@@ -10,41 +10,29 @@
10
10
  * Session metrics structure
11
11
  */
12
12
  export interface SessionMetrics {
13
- // Core counts
14
13
  totalEvents: number;
15
14
  touchCount: number;
16
15
  scrollCount: number;
17
16
  gestureCount: number;
18
17
  inputCount: number;
19
18
  navigationCount: number;
20
-
21
- // Issue tracking
22
19
  errorCount: number;
23
20
  rageTapCount: number;
24
-
25
- // API metrics
26
21
  apiSuccessCount: number;
27
22
  apiErrorCount: number;
28
23
  apiTotalCount: number;
29
-
30
- // Network timing (for avg calculation)
31
- netTotalDurationMs: number; // Sum of all API durations
32
- netTotalBytes: number; // Sum of all response bytes
33
-
34
- // Screen tracking for funnels
24
+ netTotalDurationMs: number;
25
+ netTotalBytes: number;
35
26
  screensVisited: string[];
36
27
  uniqueScreensCount: number;
37
-
38
- // Scores (0-100)
39
28
  interactionScore: number;
40
29
  explorationScore: number;
41
30
  uxScore: number;
42
31
  }
43
32
 
44
- // Metrics state
45
33
  let metrics: SessionMetrics = createEmptyMetrics();
46
34
  let sessionStartTime = 0;
47
- let maxSessionDurationMs = 10 * 60 * 1000; // 10 minutes default
35
+ let maxSessionDurationMs = 10 * 60 * 1000;
48
36
 
49
37
  /**
50
38
  * Create empty metrics object
@@ -92,11 +80,9 @@ export function initMetrics(): void {
92
80
  * Get current session metrics with calculated scores
93
81
  */
94
82
  export function getSessionMetrics(): SessionMetrics {
95
- // Calculate duration, clamped to max session duration
96
83
  const rawDuration = Date.now() - sessionStartTime;
97
84
  const durationMs = Math.min(rawDuration, maxSessionDurationMs);
98
85
 
99
- // Calculate scores
100
86
  const interactionScore = calculateInteractionScore(durationMs);
101
87
  const explorationScore = calculateExplorationScore();
102
88
  const uxScore = calculateUXScore();
@@ -120,8 +106,6 @@ export function setMaxSessionDurationMinutes(minutes?: number): void {
120
106
  }
121
107
  }
122
108
 
123
- // ==================== Metric Increment Methods ====================
124
-
125
109
  export function incrementTouchCount(): void {
126
110
  metrics.touchCount++;
127
111
  metrics.totalEvents++;
@@ -173,8 +157,6 @@ export function trackAPIMetrics(
173
157
  }
174
158
  }
175
159
 
176
- // ==================== Score Calculations ====================
177
-
178
160
  /**
179
161
  * Calculate interaction score based on engagement with app
180
162
  * Higher = more engaged (more interactions per minute)
@@ -185,15 +167,12 @@ function calculateInteractionScore(durationMs: number): number {
185
167
  const durationMinutes = durationMs / 60000;
186
168
  const interactionsPerMinute = metrics.touchCount / Math.max(0.5, durationMinutes);
187
169
 
188
- // Ideal: 10-30 interactions per minute
189
- // Low (< 5): user passive/confused
190
- // Very high (> 60): rage tapping
191
170
  if (interactionsPerMinute < 2) return 20;
192
171
  if (interactionsPerMinute < 5) return 50;
193
172
  if (interactionsPerMinute < 10) return 70;
194
173
  if (interactionsPerMinute <= 30) return 100;
195
174
  if (interactionsPerMinute <= 60) return 80;
196
- return 50; // Very high might indicate frustration
175
+ return 50;
197
176
  }
198
177
 
199
178
  /**
@@ -203,13 +182,12 @@ function calculateInteractionScore(durationMs: number): number {
203
182
  function calculateExplorationScore(): number {
204
183
  const uniqueScreens = metrics.uniqueScreensCount;
205
184
 
206
- // More unique screens = better exploration
207
185
  if (uniqueScreens >= 10) return 100;
208
186
  if (uniqueScreens >= 7) return 90;
209
187
  if (uniqueScreens >= 5) return 80;
210
188
  if (uniqueScreens >= 3) return 60;
211
189
  if (uniqueScreens >= 2) return 40;
212
- return 20; // Single screen visit
190
+ return 20;
213
191
  }
214
192
 
215
193
  /**
@@ -219,14 +197,8 @@ function calculateExplorationScore(): number {
219
197
  function calculateUXScore(): number {
220
198
  let score = 100;
221
199
 
222
- // Deduct for errors
223
200
  score -= metrics.errorCount * 10;
224
-
225
- // Deduct heavily for rage taps
226
201
  score -= metrics.rageTapCount * 20;
227
-
228
- // Deduct for API errors (less severe)
229
202
  score -= metrics.apiErrorCount * 5;
230
-
231
203
  return Math.max(0, Math.min(100, score));
232
204
  }
@@ -20,15 +20,12 @@ export function normalizeScreenName(raw: string): string {
20
20
 
21
21
  let name = raw;
22
22
 
23
- // 1. Remove non-printable characters and weird symbols (often from icons)
24
23
  name = name.replace(/[^\x20-\x7E\s]/g, '');
25
24
 
26
- // 2. Handle hyphens: my-recipes -> My Recipes
27
25
  name = name.split(/[-_]/).map(word =>
28
26
  word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
29
27
  ).join(' ');
30
28
 
31
- // 3. Remove common suffixes
32
29
  const suffixes = ['Screen', 'Page', 'View', 'Controller', 'ViewController', 'VC'];
33
30
  for (const suffix of suffixes) {
34
31
  if (name.endsWith(suffix) && name.length > suffix.length) {
@@ -36,7 +33,6 @@ export function normalizeScreenName(raw: string): string {
36
33
  }
37
34
  }
38
35
 
39
- // 4. Remove common prefixes (React Native internals)
40
36
  const prefixes = ['RNS', 'RCT', 'RN', 'UI'];
41
37
  for (const prefix of prefixes) {
42
38
  if (name.startsWith(prefix) && name.length > prefix.length + 2) {
@@ -44,23 +40,18 @@ export function normalizeScreenName(raw: string): string {
44
40
  }
45
41
  }
46
42
 
47
- // 5. Handle dynamic route params: [id] -> (omit), [userId] -> "User"
48
43
  name = name.replace(/\[([a-zA-Z]+)(?:Id)?\]/g, (_, param) => {
49
44
  const clean = param.replace(/Id$/i, '');
50
45
  if (clean.length < 2) return '';
51
46
  return clean.charAt(0).toUpperCase() + clean.slice(1);
52
47
  });
53
48
 
54
- // 6. Remove leftover brackets
55
49
  name = name.replace(/\[\]/g, '');
56
50
 
57
- // 7. Convert camelCase/PascalCase to Title Case with spaces
58
51
  name = name.replace(/([a-z])([A-Z])/g, '$1 $2');
59
52
 
60
- // 8. Clean up multiple spaces and trim
61
53
  name = name.replace(/\s+/g, ' ').trim();
62
54
 
63
- // 9. Capitalize first letter
64
55
  if (name.length > 0) {
65
56
  name = name.charAt(0).toUpperCase() + name.slice(1);
66
57
  }
@@ -76,24 +67,18 @@ export function normalizeScreenName(raw: string): string {
76
67
  * @returns Human-readable screen name
77
68
  */
78
69
  export function getScreenNameFromPath(pathname: string, segments: string[]): string {
79
- // Use segments for cleaner names if available
80
70
  if (segments.length > 0) {
81
- // Filter out group markers like (tabs), (auth), etc.
82
71
  const cleanSegments = segments.filter(s => !s.startsWith('(') && !s.endsWith(')'));
83
72
 
84
73
  if (cleanSegments.length > 0) {
85
- // Process each segment
86
74
  const processedSegments = cleanSegments.map(s => {
87
- // Handle dynamic params like [id]
88
75
  if (s.startsWith('[') && s.endsWith(']')) {
89
76
  const param = s.slice(1, -1);
90
- // Skip pure ID params, keep meaningful ones
91
77
  if (param === 'id' || param === 'slug') return null;
92
- // Extract meaningful part: userId -> User
78
+ if (param === 'id' || param === 'slug') return null;
93
79
  const clean = param.replace(/Id$/i, '');
94
80
  return clean.charAt(0).toUpperCase() + clean.slice(1);
95
81
  }
96
- // Regular segment - capitalize
97
82
  return s.charAt(0).toUpperCase() + s.slice(1);
98
83
  }).filter(Boolean);
99
84
 
@@ -103,32 +88,27 @@ export function getScreenNameFromPath(pathname: string, segments: string[]): str
103
88
  }
104
89
  }
105
90
 
106
- // Fall back to pathname
107
91
  if (!pathname || pathname === '/') {
108
92
  return 'Home';
109
93
  }
110
-
111
- // Clean up the path
112
- let cleanPath = pathname
113
- .replace(/^\/(tabs)?/, '') // Remove leading slash and (tabs)
114
- .replace(/\([^)]+\)/g, '') // Remove all group markers like (settings)
94
+ const cleanPath = pathname
95
+ .replace(/^\/(tabs)?/, '')
96
+ .replace(/\([^)]+\)/g, '')
115
97
  .replace(/\[([^\]]+)\]/g, (_, param) => {
116
- // Handle dynamic params in path
117
98
  if (param === 'id' || param === 'slug') return '';
118
99
  const clean = param.replace(/Id$/i, '');
119
100
  return clean.charAt(0).toUpperCase() + clean.slice(1);
120
101
  })
121
- .replace(/\/+/g, '/') // Collapse multiple slashes
122
- .replace(/^\//, '') // Remove leading slash
123
- .replace(/\/$/, '') // Remove trailing slash
124
- .replace(/\//g, ' > ') // Replace slashes with arrows
102
+ .replace(/\/+/g, '/')
103
+ .replace(/^\//, '')
104
+ .replace(/\/$/, '')
105
+ .replace(/\//g, ' > ')
125
106
  .trim();
126
107
 
127
108
  if (!cleanPath) {
128
109
  return 'Home';
129
110
  }
130
111
 
131
- // Capitalize first letter of each word
132
112
  return cleanPath
133
113
  .split(' > ')
134
114
  .map(s => s.charAt(0).toUpperCase() + s.slice(1))
@@ -148,7 +128,6 @@ export function getCurrentRouteFromState(state: any): string | null {
148
128
  const route = state.routes[state.index ?? state.routes.length - 1];
149
129
  if (!route) return null;
150
130
 
151
- // If nested state, recurse
152
131
  if (route.state) {
153
132
  return getCurrentRouteFromState(route.state);
154
133
  }
@@ -15,39 +15,32 @@
15
15
 
16
16
  import type { NetworkRequestParams } from '../types';
17
17
 
18
- // Store original implementations
19
18
  let originalFetch: typeof fetch | null = null;
20
19
  let originalXHROpen: typeof XMLHttpRequest.prototype.open | null = null;
21
20
  let originalXHRSend: typeof XMLHttpRequest.prototype.send | null = null;
22
21
 
23
- // Callback to log network requests (called asynchronously)
24
22
  let logCallback: ((request: NetworkRequestParams) => void) | null = null;
25
23
 
26
- // Pending requests buffer (circular buffer for memory efficiency)
27
24
  const MAX_PENDING_REQUESTS = 100;
28
25
  const pendingRequests: (NetworkRequestParams | null)[] = new Array(MAX_PENDING_REQUESTS).fill(null);
29
26
  let pendingHead = 0;
30
27
  let pendingTail = 0;
31
28
  let pendingCount = 0;
32
29
 
33
- // Flush timer
34
30
  let flushTimer: ReturnType<typeof setTimeout> | null = null;
35
- const FLUSH_INTERVAL = 500; // Flush every 500ms
31
+ const FLUSH_INTERVAL = 500;
36
32
 
37
- // Sampling for high-frequency endpoints
38
33
  const endpointCounts = new Map<string, { count: number; lastReset: number }>();
39
- const SAMPLE_WINDOW = 10000; // 10 second window
40
- const MAX_PER_ENDPOINT = 20; // Max 20 requests per endpoint per window
34
+ const SAMPLE_WINDOW = 10000;
35
+ const MAX_PER_ENDPOINT = 20;
41
36
 
42
- // Configuration
43
37
  const config = {
44
38
  enabled: true,
45
- ignorePatterns: [] as string[], // Simple string patterns for fast matching
46
- maxUrlLength: 300, // Shorter for efficiency
47
- captureSizes: false, // Disabled by default for performance
39
+ ignorePatterns: [] as string[],
40
+ maxUrlLength: 300,
41
+ captureSizes: false,
48
42
  };
49
43
 
50
- // PII Scrubbing - Sensitive keys to look for in query params
51
44
  const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'access_token', 'api_key'];
52
45
 
53
46
  /**
@@ -55,7 +48,6 @@ const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'access_to
55
48
  */
56
49
  function scrubUrl(url: string): string {
57
50
  try {
58
- // Fast check if URL might contain params
59
51
  if (url.indexOf('?') === -1) return url;
60
52
 
61
53
  const urlObj = new URL(url);
@@ -68,12 +60,10 @@ function scrubUrl(url: string): string {
68
60
  }
69
61
  });
70
62
 
71
- // Also scan for partial matches (case-insensitive) if strict scrubbing needed
72
- // But for performance, we stick to exact keys or common variations
73
-
74
63
  return modified ? urlObj.toString() : url;
75
64
  } catch {
76
- // If URL parsing fails (relative URL?), try primitive replacement
65
+ // Ignore error, fallback to primitive scrubbing
66
+
77
67
  let scrubbed = url;
78
68
  SENSITIVE_KEYS.forEach(key => {
79
69
  const regex = new RegExp(`([?&])${key}=[^&]*`, 'gi');
@@ -121,14 +111,12 @@ function queueRequest(request: NetworkRequestParams): void {
121
111
  pendingCount--;
122
112
  }
123
113
 
124
- // Scrub URL before queuing
125
114
  request.url = scrubUrl(request.url);
126
115
 
127
116
  pendingRequests[pendingTail] = request;
128
117
  pendingTail = (pendingTail + 1) % MAX_PENDING_REQUESTS;
129
118
  pendingCount++;
130
119
 
131
- // Schedule flush if not already scheduled
132
120
  if (!flushTimer) {
133
121
  flushTimer = setTimeout(flushPendingRequests, FLUSH_INTERVAL);
134
122
  }
@@ -153,7 +141,7 @@ function flushPendingRequests(): void {
153
141
  try {
154
142
  logCallback(request);
155
143
  } catch {
156
- // Ignore logging errors
144
+ // Ignore
157
145
  }
158
146
  }
159
147
  }
@@ -167,11 +155,9 @@ function parseUrlFast(url: string): { host: string; path: string } {
167
155
  let hostEnd = -1;
168
156
  let pathStart = -1;
169
157
 
170
- // Find ://
171
158
  const protoEnd = url.indexOf('://');
172
159
  if (protoEnd !== -1) {
173
160
  const afterProto = protoEnd + 3;
174
- // Find end of host (first / after ://)
175
161
  const slashPos = url.indexOf('/', afterProto);
176
162
  if (slashPos !== -1) {
177
163
  hostEnd = slashPos;
@@ -187,7 +173,6 @@ function parseUrlFast(url: string): { host: string; path: string } {
187
173
  };
188
174
  }
189
175
 
190
- // Relative URL
191
176
  return { host: '', path: url };
192
177
  }
193
178
 
@@ -204,19 +189,16 @@ function interceptFetch(): void {
204
189
  input: RequestInfo | URL,
205
190
  init?: RequestInit
206
191
  ): Promise<Response> {
207
- // Fast path: if disabled or no callback, skip entirely
208
192
  if (!config.enabled || !logCallback) {
209
193
  return originalFetch!(input, init);
210
194
  }
211
195
 
212
- // Extract URL string (minimal work)
213
196
  const url = typeof input === 'string'
214
197
  ? input
215
198
  : input instanceof URL
216
199
  ? input.href
217
200
  : (input as Request).url;
218
201
 
219
- // Fast ignore check
220
202
  if (shouldIgnoreUrl(url)) {
221
203
  return originalFetch!(input, init);
222
204
  }
@@ -248,7 +230,6 @@ function interceptFetch(): void {
248
230
  return response;
249
231
  },
250
232
  (error) => {
251
- // Error - queue the log asynchronously
252
233
  queueRequest({
253
234
  requestId: `f${startTime}`,
254
235
  method,
@@ -285,7 +266,6 @@ function interceptXHR(): void {
285
266
  ): void {
286
267
  const urlString = typeof url === 'string' ? url : url.toString();
287
268
 
288
- // Store minimal info
289
269
  (this as any).__rj = {
290
270
  m: method.toUpperCase(),
291
271
  u: urlString,
@@ -325,8 +305,6 @@ function interceptXHR(): void {
325
305
  });
326
306
  };
327
307
 
328
- // Use load/error events (more efficient than readystatechange)
329
- // Note: We use basic addEventListener without options for RN compatibility
330
308
  this.addEventListener('load', onComplete);
331
309
  this.addEventListener('error', onComplete);
332
310
  this.addEventListener('abort', onComplete);
@@ -347,11 +325,9 @@ export function initNetworkInterceptor(
347
325
  ): void {
348
326
  logCallback = callback;
349
327
 
350
- // Convert patterns to simple strings for fast matching
351
328
  if (options?.ignoreUrls) {
352
329
  config.ignorePatterns = options.ignoreUrls
353
330
  .filter((p): p is string => typeof p === 'string');
354
- // Note: RegExp patterns are not supported in optimized version for performance
355
331
  }
356
332
 
357
333
  if (options?.captureSizes !== undefined) {
package/src/sdk/utils.ts CHANGED
@@ -302,11 +302,6 @@ class Logger {
302
302
  }
303
303
  }
304
304
 
305
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
306
- // Lifecycle Logs - Industry standard minimal logging
307
- // These are the only logs integrators will see in debug builds
308
- // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
309
-
310
305
  /**
311
306
  * Log SDK initialization success.
312
307
  * Only shown in development builds - this is the minimal "SDK started" log.
@@ -104,10 +104,6 @@ export interface RejourneyConfig {
104
104
  networkCaptureSizes?: boolean;
105
105
  }
106
106
 
107
- // ============================================================================
108
- // Event Types
109
- // ============================================================================
110
-
111
107
  export type GestureType =
112
108
  | 'tap'
113
109
  | 'double_tap'
@@ -293,10 +289,6 @@ export interface ErrorEvent {
293
289
  name?: string;
294
290
  }
295
291
 
296
- // ============================================================================
297
- // Network Request Types (API Call Tracking)
298
- // ============================================================================
299
-
300
292
  export interface NetworkRequestEvent {
301
293
  type: 'network_request';
302
294
  /** Unique request ID for correlating request/response */
@@ -355,10 +347,6 @@ export type SessionEvent =
355
347
  | ErrorEvent
356
348
  | NetworkRequestEvent;
357
349
 
358
- // ============================================================================
359
- // Session Types
360
- // ============================================================================
361
-
362
350
  export interface GeoLocation {
363
351
  /** IP address */
364
352
  ip: string;
@@ -451,14 +439,9 @@ export interface SessionSummary {
451
439
  videoSegmentCount?: number;
452
440
  storageSize: number;
453
441
  isComplete: boolean;
454
- /** Path to session data file */
455
442
  filePath: string;
456
443
  }
457
444
 
458
- // ============================================================================
459
- // Replay Types
460
- // ============================================================================
461
-
462
445
  export interface ReplayState {
463
446
  /** Current playback position in ms from session start */
464
447
  currentTime: number;
@@ -507,10 +490,6 @@ export interface ReplayProps {
507
490
  style?: object;
508
491
  }
509
492
 
510
- // ============================================================================
511
- // Native Module Types
512
- // ============================================================================
513
-
514
493
  export interface RejourneyNativeModule {
515
494
  /** Initialize the native SDK */
516
495
  initialize(config: RejourneyConfig): Promise<void>;
@@ -540,10 +519,6 @@ export interface RejourneyNativeModule {
540
519
  getStorageUsage(): Promise<{ used: number; max: number }>;
541
520
  }
542
521
 
543
- // ============================================================================
544
- // API Types
545
- // ============================================================================
546
-
547
522
  export interface RejourneyAPI {
548
523
  /** SDK version */
549
524
  readonly version: string;
@@ -704,10 +679,6 @@ export interface NetworkRequestParams {
704
679
  success?: boolean;
705
680
  }
706
681
 
707
- // ============================================================================
708
- // Hook Types
709
- // ============================================================================
710
-
711
682
  export interface UseRejourneyResult {
712
683
  /** Whether SDK is initialized */
713
684
  isInitialized: boolean;