@rejourneyco/react-native 1.0.1 → 1.0.3

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 (65) hide show
  1. package/android/src/main/java/com/rejourney/RejourneyModuleImpl.kt +72 -391
  2. package/android/src/main/java/com/rejourney/capture/CaptureEngine.kt +11 -113
  3. package/android/src/main/java/com/rejourney/capture/SegmentUploader.kt +1 -15
  4. package/android/src/main/java/com/rejourney/capture/VideoEncoder.kt +1 -61
  5. package/android/src/main/java/com/rejourney/capture/ViewHierarchyScanner.kt +3 -1
  6. package/android/src/main/java/com/rejourney/lifecycle/SessionLifecycleService.kt +1 -22
  7. package/android/src/main/java/com/rejourney/network/DeviceAuthManager.kt +3 -26
  8. package/android/src/main/java/com/rejourney/network/NetworkMonitor.kt +0 -2
  9. package/android/src/main/java/com/rejourney/network/UploadManager.kt +7 -93
  10. package/android/src/main/java/com/rejourney/network/UploadWorker.kt +5 -41
  11. package/android/src/main/java/com/rejourney/privacy/PrivacyMask.kt +2 -58
  12. package/android/src/main/java/com/rejourney/touch/TouchInterceptor.kt +4 -4
  13. package/android/src/main/java/com/rejourney/utils/EventBuffer.kt +36 -7
  14. package/android/src/newarch/java/com/rejourney/RejourneyModule.kt +7 -0
  15. package/android/src/oldarch/java/com/rejourney/RejourneyModule.kt +9 -0
  16. package/ios/Capture/RJCaptureEngine.m +3 -34
  17. package/ios/Capture/RJVideoEncoder.m +0 -26
  18. package/ios/Capture/RJViewHierarchyScanner.m +68 -51
  19. package/ios/Core/RJLifecycleManager.m +0 -14
  20. package/ios/Core/Rejourney.mm +53 -129
  21. package/ios/Network/RJDeviceAuthManager.m +0 -2
  22. package/ios/Network/RJUploadManager.h +8 -0
  23. package/ios/Network/RJUploadManager.m +45 -0
  24. package/ios/Privacy/RJPrivacyMask.m +5 -31
  25. package/ios/Rejourney.h +0 -14
  26. package/ios/Touch/RJTouchInterceptor.m +21 -15
  27. package/ios/Utils/RJEventBuffer.m +57 -69
  28. package/ios/Utils/RJPerfTiming.m +0 -5
  29. package/ios/Utils/RJWindowUtils.m +87 -87
  30. package/lib/commonjs/components/Mask.js +1 -6
  31. package/lib/commonjs/index.js +46 -117
  32. package/lib/commonjs/sdk/autoTracking.js +39 -313
  33. package/lib/commonjs/sdk/constants.js +2 -13
  34. package/lib/commonjs/sdk/errorTracking.js +1 -29
  35. package/lib/commonjs/sdk/metricsTracking.js +3 -24
  36. package/lib/commonjs/sdk/navigation.js +3 -42
  37. package/lib/commonjs/sdk/networkInterceptor.js +7 -60
  38. package/lib/commonjs/sdk/utils.js +73 -19
  39. package/lib/module/components/Mask.js +1 -6
  40. package/lib/module/index.js +45 -121
  41. package/lib/module/sdk/autoTracking.js +39 -314
  42. package/lib/module/sdk/constants.js +2 -13
  43. package/lib/module/sdk/errorTracking.js +1 -29
  44. package/lib/module/sdk/index.js +0 -2
  45. package/lib/module/sdk/metricsTracking.js +3 -24
  46. package/lib/module/sdk/navigation.js +3 -42
  47. package/lib/module/sdk/networkInterceptor.js +7 -60
  48. package/lib/module/sdk/utils.js +73 -19
  49. package/lib/typescript/NativeRejourney.d.ts +1 -0
  50. package/lib/typescript/sdk/autoTracking.d.ts +4 -4
  51. package/lib/typescript/sdk/utils.d.ts +31 -1
  52. package/lib/typescript/types/index.d.ts +0 -1
  53. package/package.json +17 -11
  54. package/src/NativeRejourney.ts +2 -0
  55. package/src/components/Mask.tsx +0 -3
  56. package/src/index.ts +43 -92
  57. package/src/sdk/autoTracking.ts +51 -284
  58. package/src/sdk/constants.ts +13 -13
  59. package/src/sdk/errorTracking.ts +1 -17
  60. package/src/sdk/index.ts +0 -2
  61. package/src/sdk/metricsTracking.ts +5 -33
  62. package/src/sdk/navigation.ts +8 -29
  63. package/src/sdk/networkInterceptor.ts +9 -42
  64. package/src/sdk/utils.ts +76 -19
  65. package/src/types/index.ts +0 -29
@@ -8,35 +8,25 @@ export const SDK_VERSION = '1.0.0';
8
8
  export const DEFAULT_CONFIG = {
9
9
  enabled: true,
10
10
  captureFPS: 0.5,
11
- // Every 2 seconds (only used in timer mode)
12
11
  captureOnEvents: true,
13
- // Event-driven capture (not time-based)
14
12
  maxSessionDuration: 10 * 60 * 1000,
15
- // 10 minutes (project-level configurable, clamped 1–10)
16
13
  maxStorageSize: 50 * 1024 * 1024,
17
- // 50MB
18
14
  autoScreenTracking: true,
19
15
  autoGestureTracking: true,
20
16
  privacyOcclusion: true,
21
17
  enableCompression: true,
22
18
  inactivityThreshold: 5000,
23
- // 5 seconds
24
19
  disableInDev: false,
25
20
  detectRageTaps: true,
26
21
  rageTapThreshold: 3,
27
22
  rageTapTimeWindow: 1000,
28
- // 1 second
29
23
  debug: false,
30
24
  autoStartRecording: true,
31
25
  collectDeviceInfo: true,
32
- // Collect detailed device information
33
26
  collectGeoLocation: true,
34
- // Collect IP address and geolocation
35
27
  postNavigationDelay: 300,
36
- // 300ms - allow navigation animations to complete
37
28
  postGestureDelay: 200,
38
- // 200ms - show result of taps, not animations
39
- postModalDelay: 400 // 400ms - ensure modals/alerts are fully rendered
29
+ postModalDelay: 400
40
30
  };
41
31
 
42
32
  /** Event type constants */
@@ -72,8 +62,7 @@ export const CAPTURE_SETTINGS = {
72
62
  MIN_FPS: 0.1,
73
63
  MAX_FPS: 2,
74
64
  CAPTURE_SCALE: 0.25,
75
- // 25% resolution for video segments
76
- MIN_CAPTURE_DELTA_TIME: 0.5 // Minimum 0.5s between captures (rate limiting)
65
+ MIN_CAPTURE_DELTA_TIME: 0.5
77
66
  };
78
67
 
79
68
  /** Memory management settings */
@@ -5,20 +5,11 @@
5
5
  * Split from autoTracking.ts for better code organization.
6
6
  */
7
7
 
8
- // Type declarations for browser globals (only used in hybrid apps where DOM is available)
9
-
10
- // Cast globalThis to work with both RN and hybrid scenarios
11
8
  const _globalThis = globalThis;
12
-
13
- // Original error handlers (for restoration)
14
9
  let originalErrorHandler;
15
10
  let originalOnError = null;
16
11
  let originalOnUnhandledRejection = null;
17
-
18
- // Callbacks
19
12
  let onErrorCallback = null;
20
-
21
- // Metrics
22
13
  let errorCount = 0;
23
14
 
24
15
  /**
@@ -27,18 +18,12 @@ let errorCount = 0;
27
18
  export function setupErrorTracking(config, onError) {
28
19
  onErrorCallback = onError;
29
20
  errorCount = 0;
30
-
31
- // Track React Native errors
32
21
  if (config.trackReactNativeErrors !== false) {
33
22
  setupReactNativeErrorHandler();
34
23
  }
35
-
36
- // Track JavaScript errors (only works in web/debug)
37
24
  if (config.trackJSErrors !== false && typeof _globalThis !== 'undefined') {
38
25
  setupJSErrorHandler();
39
26
  }
40
-
41
- // Track unhandled promise rejections
42
27
  if (config.trackPromiseRejections !== false && typeof _globalThis !== 'undefined') {
43
28
  setupPromiseRejectionHandler();
44
29
  }
@@ -48,7 +33,6 @@ export function setupErrorTracking(config, onError) {
48
33
  * Cleanup error tracking and restore original handlers
49
34
  */
50
35
  export function cleanupErrorTracking() {
51
- // Restore React Native handler
52
36
  if (originalErrorHandler) {
53
37
  try {
54
38
  const ErrorUtils = _globalThis.ErrorUtils;
@@ -60,14 +44,10 @@ export function cleanupErrorTracking() {
60
44
  }
61
45
  originalErrorHandler = undefined;
62
46
  }
63
-
64
- // Restore global onerror
65
47
  if (originalOnError !== null) {
66
48
  _globalThis.onerror = originalOnError;
67
49
  originalOnError = null;
68
50
  }
69
-
70
- // Remove promise rejection handler
71
51
  if (originalOnUnhandledRejection && typeof _globalThis.removeEventListener !== 'undefined') {
72
52
  _globalThis.removeEventListener('unhandledrejection', originalOnUnhandledRejection);
73
53
  originalOnUnhandledRejection = null;
@@ -119,11 +99,7 @@ function setupReactNativeErrorHandler() {
119
99
  try {
120
100
  const ErrorUtils = _globalThis.ErrorUtils;
121
101
  if (!ErrorUtils) return;
122
-
123
- // Store original handler
124
102
  originalErrorHandler = ErrorUtils.getGlobalHandler();
125
-
126
- // Set new handler
127
103
  ErrorUtils.setGlobalHandler((error, isFatal) => {
128
104
  trackError({
129
105
  type: 'error',
@@ -132,14 +108,12 @@ function setupReactNativeErrorHandler() {
132
108
  stack: error.stack,
133
109
  name: error.name || 'Error'
134
110
  });
135
-
136
- // Call original handler
137
111
  if (originalErrorHandler) {
138
112
  originalErrorHandler(error, isFatal);
139
113
  }
140
114
  });
141
115
  } catch {
142
- // ErrorUtils not available
116
+ // Ignore
143
117
  }
144
118
  }
145
119
 
@@ -157,8 +131,6 @@ function setupJSErrorHandler() {
157
131
  stack: error?.stack || `${source}:${lineno}:${colno}`,
158
132
  name: error?.name || 'Error'
159
133
  });
160
-
161
- // Call original handler
162
134
  if (originalOnError) {
163
135
  return originalOnError(message, source, lineno, colno, error);
164
136
  }
@@ -7,6 +7,4 @@ 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
12
10
  //# sourceMappingURL=index.js.map
@@ -10,10 +10,9 @@
10
10
  * Session metrics structure
11
11
  */
12
12
 
13
- // Metrics state
14
13
  let metrics = createEmptyMetrics();
15
14
  let sessionStartTime = 0;
16
- let maxSessionDurationMs = 10 * 60 * 1000; // 10 minutes default
15
+ let maxSessionDurationMs = 10 * 60 * 1000;
17
16
 
18
17
  /**
19
18
  * Create empty metrics object
@@ -61,11 +60,8 @@ export function initMetrics() {
61
60
  * Get current session metrics with calculated scores
62
61
  */
63
62
  export function getSessionMetrics() {
64
- // Calculate duration, clamped to max session duration
65
63
  const rawDuration = Date.now() - sessionStartTime;
66
64
  const durationMs = Math.min(rawDuration, maxSessionDurationMs);
67
-
68
- // Calculate scores
69
65
  const interactionScore = calculateInteractionScore(durationMs);
70
66
  const explorationScore = calculateExplorationScore();
71
67
  const uxScore = calculateUXScore();
@@ -87,9 +83,6 @@ export function setMaxSessionDurationMinutes(minutes) {
87
83
  maxSessionDurationMs = clampedMinutes * 60 * 1000;
88
84
  }
89
85
  }
90
-
91
- // ==================== Metric Increment Methods ====================
92
-
93
86
  export function incrementTouchCount() {
94
87
  metrics.touchCount++;
95
88
  metrics.totalEvents++;
@@ -129,8 +122,6 @@ export function trackAPIMetrics(success, durationMs = 0, responseBytes = 0) {
129
122
  }
130
123
  }
131
124
 
132
- // ==================== Score Calculations ====================
133
-
134
125
  /**
135
126
  * Calculate interaction score based on engagement with app
136
127
  * Higher = more engaged (more interactions per minute)
@@ -139,16 +130,12 @@ function calculateInteractionScore(durationMs) {
139
130
  if (durationMs <= 0) return 100;
140
131
  const durationMinutes = durationMs / 60000;
141
132
  const interactionsPerMinute = metrics.touchCount / Math.max(0.5, durationMinutes);
142
-
143
- // Ideal: 10-30 interactions per minute
144
- // Low (< 5): user passive/confused
145
- // Very high (> 60): rage tapping
146
133
  if (interactionsPerMinute < 2) return 20;
147
134
  if (interactionsPerMinute < 5) return 50;
148
135
  if (interactionsPerMinute < 10) return 70;
149
136
  if (interactionsPerMinute <= 30) return 100;
150
137
  if (interactionsPerMinute <= 60) return 80;
151
- return 50; // Very high might indicate frustration
138
+ return 50;
152
139
  }
153
140
 
154
141
  /**
@@ -157,14 +144,12 @@ function calculateInteractionScore(durationMs) {
157
144
  */
158
145
  function calculateExplorationScore() {
159
146
  const uniqueScreens = metrics.uniqueScreensCount;
160
-
161
- // More unique screens = better exploration
162
147
  if (uniqueScreens >= 10) return 100;
163
148
  if (uniqueScreens >= 7) return 90;
164
149
  if (uniqueScreens >= 5) return 80;
165
150
  if (uniqueScreens >= 3) return 60;
166
151
  if (uniqueScreens >= 2) return 40;
167
- return 20; // Single screen visit
152
+ return 20;
168
153
  }
169
154
 
170
155
  /**
@@ -173,14 +158,8 @@ function calculateExplorationScore() {
173
158
  */
174
159
  function calculateUXScore() {
175
160
  let score = 100;
176
-
177
- // Deduct for errors
178
161
  score -= metrics.errorCount * 10;
179
-
180
- // Deduct heavily for rage taps
181
162
  score -= metrics.rageTapCount * 20;
182
-
183
- // Deduct for API errors (less severe)
184
163
  score -= metrics.apiErrorCount * 5;
185
164
  return Math.max(0, Math.min(100, score));
186
165
  }
@@ -18,46 +18,28 @@
18
18
  export function normalizeScreenName(raw) {
19
19
  if (!raw) return 'Unknown';
20
20
  let name = raw;
21
-
22
- // 1. Remove non-printable characters and weird symbols (often from icons)
23
21
  name = name.replace(/[^\x20-\x7E\s]/g, '');
24
-
25
- // 2. Handle hyphens: my-recipes -> My Recipes
26
22
  name = name.split(/[-_]/).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' ');
27
-
28
- // 3. Remove common suffixes
29
23
  const suffixes = ['Screen', 'Page', 'View', 'Controller', 'ViewController', 'VC'];
30
24
  for (const suffix of suffixes) {
31
25
  if (name.endsWith(suffix) && name.length > suffix.length) {
32
26
  name = name.slice(0, -suffix.length).trim();
33
27
  }
34
28
  }
35
-
36
- // 4. Remove common prefixes (React Native internals)
37
29
  const prefixes = ['RNS', 'RCT', 'RN', 'UI'];
38
30
  for (const prefix of prefixes) {
39
31
  if (name.startsWith(prefix) && name.length > prefix.length + 2) {
40
32
  name = name.slice(prefix.length).trim();
41
33
  }
42
34
  }
43
-
44
- // 5. Handle dynamic route params: [id] -> (omit), [userId] -> "User"
45
35
  name = name.replace(/\[([a-zA-Z]+)(?:Id)?\]/g, (_, param) => {
46
36
  const clean = param.replace(/Id$/i, '');
47
37
  if (clean.length < 2) return '';
48
38
  return clean.charAt(0).toUpperCase() + clean.slice(1);
49
39
  });
50
-
51
- // 6. Remove leftover brackets
52
40
  name = name.replace(/\[\]/g, '');
53
-
54
- // 7. Convert camelCase/PascalCase to Title Case with spaces
55
41
  name = name.replace(/([a-z])([A-Z])/g, '$1 $2');
56
-
57
- // 8. Clean up multiple spaces and trim
58
42
  name = name.replace(/\s+/g, ' ').trim();
59
-
60
- // 9. Capitalize first letter
61
43
  if (name.length > 0) {
62
44
  name = name.charAt(0).toUpperCase() + name.slice(1);
63
45
  }
@@ -72,23 +54,17 @@ export function normalizeScreenName(raw) {
72
54
  * @returns Human-readable screen name
73
55
  */
74
56
  export function getScreenNameFromPath(pathname, segments) {
75
- // Use segments for cleaner names if available
76
57
  if (segments.length > 0) {
77
- // Filter out group markers like (tabs), (auth), etc.
78
58
  const cleanSegments = segments.filter(s => !s.startsWith('(') && !s.endsWith(')'));
79
59
  if (cleanSegments.length > 0) {
80
- // Process each segment
81
60
  const processedSegments = cleanSegments.map(s => {
82
- // Handle dynamic params like [id]
83
61
  if (s.startsWith('[') && s.endsWith(']')) {
84
62
  const param = s.slice(1, -1);
85
- // Skip pure ID params, keep meaningful ones
86
63
  if (param === 'id' || param === 'slug') return null;
87
- // Extract meaningful part: userId -> User
64
+ if (param === 'id' || param === 'slug') return null;
88
65
  const clean = param.replace(/Id$/i, '');
89
66
  return clean.charAt(0).toUpperCase() + clean.slice(1);
90
67
  }
91
- // Regular segment - capitalize
92
68
  return s.charAt(0).toUpperCase() + s.slice(1);
93
69
  }).filter(Boolean);
94
70
  if (processedSegments.length > 0) {
@@ -96,30 +72,17 @@ export function getScreenNameFromPath(pathname, segments) {
96
72
  }
97
73
  }
98
74
  }
99
-
100
- // Fall back to pathname
101
75
  if (!pathname || pathname === '/') {
102
76
  return 'Home';
103
77
  }
104
-
105
- // Clean up the path
106
- let cleanPath = pathname.replace(/^\/(tabs)?/, '') // Remove leading slash and (tabs)
107
- .replace(/\([^)]+\)/g, '') // Remove all group markers like (settings)
108
- .replace(/\[([^\]]+)\]/g, (_, param) => {
109
- // Handle dynamic params in path
78
+ const cleanPath = pathname.replace(/^\/(tabs)?/, '').replace(/\([^)]+\)/g, '').replace(/\[([^\]]+)\]/g, (_, param) => {
110
79
  if (param === 'id' || param === 'slug') return '';
111
80
  const clean = param.replace(/Id$/i, '');
112
81
  return clean.charAt(0).toUpperCase() + clean.slice(1);
113
- }).replace(/\/+/g, '/') // Collapse multiple slashes
114
- .replace(/^\//, '') // Remove leading slash
115
- .replace(/\/$/, '') // Remove trailing slash
116
- .replace(/\//g, ' > ') // Replace slashes with arrows
117
- .trim();
82
+ }).replace(/\/+/g, '/').replace(/^\//, '').replace(/\/$/, '').replace(/\//g, ' > ').trim();
118
83
  if (!cleanPath) {
119
84
  return 'Home';
120
85
  }
121
-
122
- // Capitalize first letter of each word
123
86
  return cleanPath.split(' > ').map(s => s.charAt(0).toUpperCase() + s.slice(1)).filter(s => s.length > 0).join(' > ') || 'Home';
124
87
  }
125
88
 
@@ -133,8 +96,6 @@ export function getCurrentRouteFromState(state) {
133
96
  if (!state || !state.routes) return null;
134
97
  const route = state.routes[state.index ?? state.routes.length - 1];
135
98
  if (!route) return null;
136
-
137
- // If nested state, recurse
138
99
  if (route.state) {
139
100
  return getCurrentRouteFromState(route.state);
140
101
  }
@@ -13,41 +13,26 @@
13
13
  * - PII Scrubbing for query parameters
14
14
  */
15
15
 
16
- // Store original implementations
17
16
  let originalFetch = null;
18
17
  let originalXHROpen = null;
19
18
  let originalXHRSend = null;
20
-
21
- // Callback to log network requests (called asynchronously)
22
19
  let logCallback = null;
23
-
24
- // Pending requests buffer (circular buffer for memory efficiency)
25
20
  const MAX_PENDING_REQUESTS = 100;
26
21
  const pendingRequests = new Array(MAX_PENDING_REQUESTS).fill(null);
27
22
  let pendingHead = 0;
28
23
  let pendingTail = 0;
29
24
  let pendingCount = 0;
30
-
31
- // Flush timer
32
25
  let flushTimer = null;
33
- const FLUSH_INTERVAL = 500; // Flush every 500ms
34
-
35
- // Sampling for high-frequency endpoints
26
+ const FLUSH_INTERVAL = 500;
36
27
  const endpointCounts = new Map();
37
- const SAMPLE_WINDOW = 10000; // 10 second window
38
- const MAX_PER_ENDPOINT = 20; // Max 20 requests per endpoint per window
39
-
40
- // Configuration
28
+ const SAMPLE_WINDOW = 10000;
29
+ const MAX_PER_ENDPOINT = 20;
41
30
  const config = {
42
31
  enabled: true,
43
32
  ignorePatterns: [],
44
- // Simple string patterns for fast matching
45
33
  maxUrlLength: 300,
46
- // Shorter for efficiency
47
- captureSizes: false // Disabled by default for performance
34
+ captureSizes: false
48
35
  };
49
-
50
- // PII Scrubbing - Sensitive keys to look for in query params
51
36
  const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'access_token', 'api_key'];
52
37
 
53
38
  /**
@@ -55,7 +40,6 @@ const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'access_to
55
40
  */
56
41
  function scrubUrl(url) {
57
42
  try {
58
- // Fast check if URL might contain params
59
43
  if (url.indexOf('?') === -1) return url;
60
44
  const urlObj = new URL(url);
61
45
  let modified = false;
@@ -65,13 +49,10 @@ function scrubUrl(url) {
65
49
  modified = true;
66
50
  }
67
51
  });
68
-
69
- // Also scan for partial matches (case-insensitive) if strict scrubbing needed
70
- // But for performance, we stick to exact keys or common variations
71
-
72
52
  return modified ? urlObj.toString() : url;
73
53
  } catch {
74
- // If URL parsing fails (relative URL?), try primitive replacement
54
+ // Ignore error, fallback to primitive scrubbing
55
+
75
56
  let scrubbed = url;
76
57
  SENSITIVE_KEYS.forEach(key => {
77
58
  const regex = new RegExp(`([?&])${key}=[^&]*`, 'gi');
@@ -119,14 +100,10 @@ function queueRequest(request) {
119
100
  pendingHead = (pendingHead + 1) % MAX_PENDING_REQUESTS;
120
101
  pendingCount--;
121
102
  }
122
-
123
- // Scrub URL before queuing
124
103
  request.url = scrubUrl(request.url);
125
104
  pendingRequests[pendingTail] = request;
126
105
  pendingTail = (pendingTail + 1) % MAX_PENDING_REQUESTS;
127
106
  pendingCount++;
128
-
129
- // Schedule flush if not already scheduled
130
107
  if (!flushTimer) {
131
108
  flushTimer = setTimeout(flushPendingRequests, FLUSH_INTERVAL);
132
109
  }
@@ -138,8 +115,6 @@ function queueRequest(request) {
138
115
  function flushPendingRequests() {
139
116
  flushTimer = null;
140
117
  if (!logCallback || pendingCount === 0) return;
141
-
142
- // Process all pending requests
143
118
  while (pendingCount > 0) {
144
119
  const request = pendingRequests[pendingHead];
145
120
  pendingRequests[pendingHead] = null; // Allow GC
@@ -149,7 +124,7 @@ function flushPendingRequests() {
149
124
  try {
150
125
  logCallback(request);
151
126
  } catch {
152
- // Ignore logging errors
127
+ // Ignore
153
128
  }
154
129
  }
155
130
  }
@@ -162,12 +137,9 @@ function parseUrlFast(url) {
162
137
  // Fast path for common patterns
163
138
  let hostEnd = -1;
164
139
  let pathStart = -1;
165
-
166
- // Find ://
167
140
  const protoEnd = url.indexOf('://');
168
141
  if (protoEnd !== -1) {
169
142
  const afterProto = protoEnd + 3;
170
- // Find end of host (first / after ://)
171
143
  const slashPos = url.indexOf('/', afterProto);
172
144
  if (slashPos !== -1) {
173
145
  hostEnd = slashPos;
@@ -181,8 +153,6 @@ function parseUrlFast(url) {
181
153
  path: pathStart < url.length ? url.substring(pathStart) : '/'
182
154
  };
183
155
  }
184
-
185
- // Relative URL
186
156
  return {
187
157
  host: '',
188
158
  path: url
@@ -197,15 +167,10 @@ function interceptFetch() {
197
167
  if (originalFetch) return;
198
168
  originalFetch = globalThis.fetch;
199
169
  globalThis.fetch = function optimizedFetch(input, init) {
200
- // Fast path: if disabled or no callback, skip entirely
201
170
  if (!config.enabled || !logCallback) {
202
171
  return originalFetch(input, init);
203
172
  }
204
-
205
- // Extract URL string (minimal work)
206
173
  const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
207
-
208
- // Fast ignore check
209
174
  if (shouldIgnoreUrl(url)) {
210
175
  return originalFetch(input, init);
211
176
  }
@@ -217,14 +182,9 @@ function interceptFetch() {
217
182
  if (!shouldSampleRequest(path)) {
218
183
  return originalFetch(input, init);
219
184
  }
220
-
221
- // Capture start time (only synchronous work)
222
185
  const startTime = Date.now();
223
186
  const method = (init?.method || 'GET').toUpperCase();
224
-
225
- // Call original fetch
226
187
  return originalFetch(input, init).then(response => {
227
- // Success - queue the log asynchronously
228
188
  queueRequest({
229
189
  requestId: `f${startTime}`,
230
190
  method,
@@ -237,7 +197,6 @@ function interceptFetch() {
237
197
  });
238
198
  return response;
239
199
  }, error => {
240
- // Error - queue the log asynchronously
241
200
  queueRequest({
242
201
  requestId: `f${startTime}`,
243
202
  method,
@@ -264,8 +223,6 @@ function interceptXHR() {
264
223
  originalXHRSend = XMLHttpRequest.prototype.send;
265
224
  XMLHttpRequest.prototype.open = function (method, url, async = true, username, password) {
266
225
  const urlString = typeof url === 'string' ? url : url.toString();
267
-
268
- // Store minimal info
269
226
  this.__rj = {
270
227
  m: method.toUpperCase(),
271
228
  u: urlString,
@@ -278,8 +235,6 @@ function interceptXHR() {
278
235
  if (!config.enabled || !logCallback || !data || shouldIgnoreUrl(data.u)) {
279
236
  return originalXHRSend.call(this, body);
280
237
  }
281
-
282
- // Check sampling
283
238
  const {
284
239
  path
285
240
  } = parseUrlFast(data.u);
@@ -301,9 +256,6 @@ function interceptXHR() {
301
256
  errorMessage: this.status === 0 ? 'Network error' : undefined
302
257
  });
303
258
  };
304
-
305
- // Use load/error events (more efficient than readystatechange)
306
- // Note: We use basic addEventListener without options for RN compatibility
307
259
  this.addEventListener('load', onComplete);
308
260
  this.addEventListener('error', onComplete);
309
261
  this.addEventListener('abort', onComplete);
@@ -316,11 +268,8 @@ function interceptXHR() {
316
268
  */
317
269
  export function initNetworkInterceptor(callback, options) {
318
270
  logCallback = callback;
319
-
320
- // Convert patterns to simple strings for fast matching
321
271
  if (options?.ignoreUrls) {
322
272
  config.ignorePatterns = options.ignoreUrls.filter(p => typeof p === 'string');
323
- // Note: RegExp patterns are not supported in optimized version for performance
324
273
  }
325
274
  if (options?.captureSizes !== undefined) {
326
275
  config.captureSizes = options.captureSizes;
@@ -334,8 +283,6 @@ export function initNetworkInterceptor(callback, options) {
334
283
  */
335
284
  export function disableNetworkInterceptor() {
336
285
  config.enabled = false;
337
-
338
- // Flush any pending requests
339
286
  if (flushTimer) {
340
287
  clearTimeout(flushTimer);
341
288
  flushTimer = null;