@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,401 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network Interceptor for Rejourney - Optimized Version
|
|
3
|
+
*
|
|
4
|
+
* Automatically intercepts fetch() and XMLHttpRequest to log API calls.
|
|
5
|
+
*
|
|
6
|
+
* PERFORMANCE OPTIMIZATIONS:
|
|
7
|
+
* - Minimal synchronous overhead (just captures timing, no processing)
|
|
8
|
+
* - Batched async logging (doesn't block requests)
|
|
9
|
+
* - Circular buffer with max size limit
|
|
10
|
+
* - Sampling for high-frequency endpoints
|
|
11
|
+
* - No string allocations in hot path
|
|
12
|
+
* - Lazy URL parsing
|
|
13
|
+
* - PII Scrubbing for query parameters
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
// Store original implementations
|
|
17
|
+
let originalFetch = null;
|
|
18
|
+
let originalXHROpen = null;
|
|
19
|
+
let originalXHRSend = null;
|
|
20
|
+
|
|
21
|
+
// Callback to log network requests (called asynchronously)
|
|
22
|
+
let logCallback = null;
|
|
23
|
+
|
|
24
|
+
// Pending requests buffer (circular buffer for memory efficiency)
|
|
25
|
+
const MAX_PENDING_REQUESTS = 100;
|
|
26
|
+
const pendingRequests = new Array(MAX_PENDING_REQUESTS).fill(null);
|
|
27
|
+
let pendingHead = 0;
|
|
28
|
+
let pendingTail = 0;
|
|
29
|
+
let pendingCount = 0;
|
|
30
|
+
|
|
31
|
+
// Flush timer
|
|
32
|
+
let flushTimer = null;
|
|
33
|
+
const FLUSH_INTERVAL = 500; // Flush every 500ms
|
|
34
|
+
|
|
35
|
+
// Sampling for high-frequency endpoints
|
|
36
|
+
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
|
|
41
|
+
const config = {
|
|
42
|
+
enabled: true,
|
|
43
|
+
ignorePatterns: [],
|
|
44
|
+
// Simple string patterns for fast matching
|
|
45
|
+
maxUrlLength: 300,
|
|
46
|
+
// Shorter for efficiency
|
|
47
|
+
captureSizes: false // Disabled by default for performance
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// PII Scrubbing - Sensitive keys to look for in query params
|
|
51
|
+
const SENSITIVE_KEYS = ['token', 'key', 'secret', 'password', 'auth', 'access_token', 'api_key'];
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Scrub sensitive data from URL
|
|
55
|
+
*/
|
|
56
|
+
function scrubUrl(url) {
|
|
57
|
+
try {
|
|
58
|
+
// Fast check if URL might contain params
|
|
59
|
+
if (url.indexOf('?') === -1) return url;
|
|
60
|
+
const urlObj = new URL(url);
|
|
61
|
+
let modified = false;
|
|
62
|
+
SENSITIVE_KEYS.forEach(key => {
|
|
63
|
+
if (urlObj.searchParams.has(key)) {
|
|
64
|
+
urlObj.searchParams.set(key, '[REDACTED]');
|
|
65
|
+
modified = true;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
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
|
+
return modified ? urlObj.toString() : url;
|
|
73
|
+
} catch {
|
|
74
|
+
// If URL parsing fails (relative URL?), try primitive replacement
|
|
75
|
+
let scrubbed = url;
|
|
76
|
+
SENSITIVE_KEYS.forEach(key => {
|
|
77
|
+
const regex = new RegExp(`([?&])${key}=[^&]*`, 'gi');
|
|
78
|
+
scrubbed = scrubbed.replace(regex, `$1${key}=[REDACTED]`);
|
|
79
|
+
});
|
|
80
|
+
return scrubbed;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Fast check if URL should be ignored (no regex for speed)
|
|
86
|
+
*/
|
|
87
|
+
function shouldIgnoreUrl(url) {
|
|
88
|
+
const patterns = config.ignorePatterns;
|
|
89
|
+
for (let i = 0; i < patterns.length; i++) {
|
|
90
|
+
const pattern = patterns[i];
|
|
91
|
+
if (pattern && url.indexOf(pattern) !== -1) return true;
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Check if we should sample this request (rate limiting per endpoint)
|
|
98
|
+
*/
|
|
99
|
+
function shouldSampleRequest(urlPath) {
|
|
100
|
+
const now = Date.now();
|
|
101
|
+
let entry = endpointCounts.get(urlPath);
|
|
102
|
+
if (!entry || now - entry.lastReset > SAMPLE_WINDOW) {
|
|
103
|
+
entry = {
|
|
104
|
+
count: 0,
|
|
105
|
+
lastReset: now
|
|
106
|
+
};
|
|
107
|
+
endpointCounts.set(urlPath, entry);
|
|
108
|
+
}
|
|
109
|
+
entry.count++;
|
|
110
|
+
return entry.count <= MAX_PER_ENDPOINT;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Add request to pending buffer (non-blocking)
|
|
115
|
+
*/
|
|
116
|
+
function queueRequest(request) {
|
|
117
|
+
if (pendingCount >= MAX_PENDING_REQUESTS) {
|
|
118
|
+
// Buffer full, drop oldest
|
|
119
|
+
pendingHead = (pendingHead + 1) % MAX_PENDING_REQUESTS;
|
|
120
|
+
pendingCount--;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Scrub URL before queuing
|
|
124
|
+
request.url = scrubUrl(request.url);
|
|
125
|
+
pendingRequests[pendingTail] = request;
|
|
126
|
+
pendingTail = (pendingTail + 1) % MAX_PENDING_REQUESTS;
|
|
127
|
+
pendingCount++;
|
|
128
|
+
|
|
129
|
+
// Schedule flush if not already scheduled
|
|
130
|
+
if (!flushTimer) {
|
|
131
|
+
flushTimer = setTimeout(flushPendingRequests, FLUSH_INTERVAL);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Flush pending requests to callback
|
|
137
|
+
*/
|
|
138
|
+
function flushPendingRequests() {
|
|
139
|
+
flushTimer = null;
|
|
140
|
+
if (!logCallback || pendingCount === 0) return;
|
|
141
|
+
|
|
142
|
+
// Process all pending requests
|
|
143
|
+
while (pendingCount > 0) {
|
|
144
|
+
const request = pendingRequests[pendingHead];
|
|
145
|
+
pendingRequests[pendingHead] = null; // Allow GC
|
|
146
|
+
pendingHead = (pendingHead + 1) % MAX_PENDING_REQUESTS;
|
|
147
|
+
pendingCount--;
|
|
148
|
+
if (request) {
|
|
149
|
+
try {
|
|
150
|
+
logCallback(request);
|
|
151
|
+
} catch {
|
|
152
|
+
// Ignore logging errors
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Parse URL efficiently (only extract what we need)
|
|
160
|
+
*/
|
|
161
|
+
function parseUrlFast(url) {
|
|
162
|
+
// Fast path for common patterns
|
|
163
|
+
let hostEnd = -1;
|
|
164
|
+
let pathStart = -1;
|
|
165
|
+
|
|
166
|
+
// Find ://
|
|
167
|
+
const protoEnd = url.indexOf('://');
|
|
168
|
+
if (protoEnd !== -1) {
|
|
169
|
+
const afterProto = protoEnd + 3;
|
|
170
|
+
// Find end of host (first / after ://)
|
|
171
|
+
const slashPos = url.indexOf('/', afterProto);
|
|
172
|
+
if (slashPos !== -1) {
|
|
173
|
+
hostEnd = slashPos;
|
|
174
|
+
pathStart = slashPos;
|
|
175
|
+
} else {
|
|
176
|
+
hostEnd = url.length;
|
|
177
|
+
pathStart = url.length;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
host: url.substring(afterProto, hostEnd),
|
|
181
|
+
path: pathStart < url.length ? url.substring(pathStart) : '/'
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Relative URL
|
|
186
|
+
return {
|
|
187
|
+
host: '',
|
|
188
|
+
path: url
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Intercept fetch - minimal overhead version
|
|
194
|
+
*/
|
|
195
|
+
function interceptFetch() {
|
|
196
|
+
if (typeof globalThis.fetch === 'undefined') return;
|
|
197
|
+
if (originalFetch) return;
|
|
198
|
+
originalFetch = globalThis.fetch;
|
|
199
|
+
globalThis.fetch = function optimizedFetch(input, init) {
|
|
200
|
+
// Fast path: if disabled or no callback, skip entirely
|
|
201
|
+
if (!config.enabled || !logCallback) {
|
|
202
|
+
return originalFetch(input, init);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Extract URL string (minimal work)
|
|
206
|
+
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
|
|
207
|
+
|
|
208
|
+
// Fast ignore check
|
|
209
|
+
if (shouldIgnoreUrl(url)) {
|
|
210
|
+
return originalFetch(input, init);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Parse URL and check sampling
|
|
214
|
+
const {
|
|
215
|
+
path
|
|
216
|
+
} = parseUrlFast(url);
|
|
217
|
+
if (!shouldSampleRequest(path)) {
|
|
218
|
+
return originalFetch(input, init);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Capture start time (only synchronous work)
|
|
222
|
+
const startTime = Date.now();
|
|
223
|
+
const method = (init?.method || 'GET').toUpperCase();
|
|
224
|
+
|
|
225
|
+
// Call original fetch
|
|
226
|
+
return originalFetch(input, init).then(response => {
|
|
227
|
+
// Success - queue the log asynchronously
|
|
228
|
+
queueRequest({
|
|
229
|
+
requestId: `f${startTime}`,
|
|
230
|
+
method,
|
|
231
|
+
url: url.length > config.maxUrlLength ? url.substring(0, config.maxUrlLength) : url,
|
|
232
|
+
statusCode: response.status,
|
|
233
|
+
duration: Date.now() - startTime,
|
|
234
|
+
startTimestamp: startTime,
|
|
235
|
+
endTimestamp: Date.now(),
|
|
236
|
+
success: response.ok
|
|
237
|
+
});
|
|
238
|
+
return response;
|
|
239
|
+
}, error => {
|
|
240
|
+
// Error - queue the log asynchronously
|
|
241
|
+
queueRequest({
|
|
242
|
+
requestId: `f${startTime}`,
|
|
243
|
+
method,
|
|
244
|
+
url: url.length > config.maxUrlLength ? url.substring(0, config.maxUrlLength) : url,
|
|
245
|
+
statusCode: 0,
|
|
246
|
+
duration: Date.now() - startTime,
|
|
247
|
+
startTimestamp: startTime,
|
|
248
|
+
endTimestamp: Date.now(),
|
|
249
|
+
success: false,
|
|
250
|
+
errorMessage: error?.message || 'Network error'
|
|
251
|
+
});
|
|
252
|
+
throw error;
|
|
253
|
+
});
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Intercept XMLHttpRequest - minimal overhead version
|
|
259
|
+
*/
|
|
260
|
+
function interceptXHR() {
|
|
261
|
+
if (typeof XMLHttpRequest === 'undefined') return;
|
|
262
|
+
if (originalXHROpen) return;
|
|
263
|
+
originalXHROpen = XMLHttpRequest.prototype.open;
|
|
264
|
+
originalXHRSend = XMLHttpRequest.prototype.send;
|
|
265
|
+
XMLHttpRequest.prototype.open = function (method, url, async = true, username, password) {
|
|
266
|
+
const urlString = typeof url === 'string' ? url : url.toString();
|
|
267
|
+
|
|
268
|
+
// Store minimal info
|
|
269
|
+
this.__rj = {
|
|
270
|
+
m: method.toUpperCase(),
|
|
271
|
+
u: urlString,
|
|
272
|
+
t: 0
|
|
273
|
+
};
|
|
274
|
+
return originalXHROpen.call(this, method, urlString, async, username, password);
|
|
275
|
+
};
|
|
276
|
+
XMLHttpRequest.prototype.send = function (body) {
|
|
277
|
+
const data = this.__rj;
|
|
278
|
+
if (!config.enabled || !logCallback || !data || shouldIgnoreUrl(data.u)) {
|
|
279
|
+
return originalXHRSend.call(this, body);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Check sampling
|
|
283
|
+
const {
|
|
284
|
+
path
|
|
285
|
+
} = parseUrlFast(data.u);
|
|
286
|
+
if (!shouldSampleRequest(path)) {
|
|
287
|
+
return originalXHRSend.call(this, body);
|
|
288
|
+
}
|
|
289
|
+
data.t = Date.now();
|
|
290
|
+
const onComplete = () => {
|
|
291
|
+
const endTime = Date.now();
|
|
292
|
+
queueRequest({
|
|
293
|
+
requestId: `x${data.t}`,
|
|
294
|
+
method: data.m,
|
|
295
|
+
url: data.u.length > config.maxUrlLength ? data.u.substring(0, config.maxUrlLength) : data.u,
|
|
296
|
+
statusCode: this.status,
|
|
297
|
+
duration: endTime - data.t,
|
|
298
|
+
startTimestamp: data.t,
|
|
299
|
+
endTimestamp: endTime,
|
|
300
|
+
success: this.status >= 200 && this.status < 400,
|
|
301
|
+
errorMessage: this.status === 0 ? 'Network error' : undefined
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
// Use load/error events (more efficient than readystatechange)
|
|
306
|
+
// Note: We use basic addEventListener without options for RN compatibility
|
|
307
|
+
this.addEventListener('load', onComplete);
|
|
308
|
+
this.addEventListener('error', onComplete);
|
|
309
|
+
this.addEventListener('abort', onComplete);
|
|
310
|
+
return originalXHRSend.call(this, body);
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Initialize network interception
|
|
316
|
+
*/
|
|
317
|
+
export function initNetworkInterceptor(callback, options) {
|
|
318
|
+
logCallback = callback;
|
|
319
|
+
|
|
320
|
+
// Convert patterns to simple strings for fast matching
|
|
321
|
+
if (options?.ignoreUrls) {
|
|
322
|
+
config.ignorePatterns = options.ignoreUrls.filter(p => typeof p === 'string');
|
|
323
|
+
// Note: RegExp patterns are not supported in optimized version for performance
|
|
324
|
+
}
|
|
325
|
+
if (options?.captureSizes !== undefined) {
|
|
326
|
+
config.captureSizes = options.captureSizes;
|
|
327
|
+
}
|
|
328
|
+
interceptFetch();
|
|
329
|
+
interceptXHR();
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Disable network interception
|
|
334
|
+
*/
|
|
335
|
+
export function disableNetworkInterceptor() {
|
|
336
|
+
config.enabled = false;
|
|
337
|
+
|
|
338
|
+
// Flush any pending requests
|
|
339
|
+
if (flushTimer) {
|
|
340
|
+
clearTimeout(flushTimer);
|
|
341
|
+
flushTimer = null;
|
|
342
|
+
}
|
|
343
|
+
flushPendingRequests();
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Re-enable network interception
|
|
348
|
+
*/
|
|
349
|
+
export function enableNetworkInterceptor() {
|
|
350
|
+
config.enabled = true;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Force flush pending requests (call before app termination)
|
|
355
|
+
*/
|
|
356
|
+
export function flushNetworkRequests() {
|
|
357
|
+
if (flushTimer) {
|
|
358
|
+
clearTimeout(flushTimer);
|
|
359
|
+
flushTimer = null;
|
|
360
|
+
}
|
|
361
|
+
flushPendingRequests();
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Restore original fetch and XHR
|
|
366
|
+
*/
|
|
367
|
+
export function restoreNetworkInterceptor() {
|
|
368
|
+
if (originalFetch) {
|
|
369
|
+
globalThis.fetch = originalFetch;
|
|
370
|
+
originalFetch = null;
|
|
371
|
+
}
|
|
372
|
+
if (originalXHROpen && originalXHRSend) {
|
|
373
|
+
XMLHttpRequest.prototype.open = originalXHROpen;
|
|
374
|
+
XMLHttpRequest.prototype.send = originalXHRSend;
|
|
375
|
+
originalXHROpen = null;
|
|
376
|
+
originalXHRSend = null;
|
|
377
|
+
}
|
|
378
|
+
logCallback = null;
|
|
379
|
+
|
|
380
|
+
// Clear state
|
|
381
|
+
pendingHead = 0;
|
|
382
|
+
pendingTail = 0;
|
|
383
|
+
pendingCount = 0;
|
|
384
|
+
endpointCounts.clear();
|
|
385
|
+
if (flushTimer) {
|
|
386
|
+
clearTimeout(flushTimer);
|
|
387
|
+
flushTimer = null;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Get stats for debugging
|
|
393
|
+
*/
|
|
394
|
+
export function getNetworkInterceptorStats() {
|
|
395
|
+
return {
|
|
396
|
+
pendingCount,
|
|
397
|
+
endpointCount: endpointCounts.size,
|
|
398
|
+
enabled: config.enabled
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=networkInterceptor.js.map
|