react-native-debug-toolkit 2.2.0 → 2.3.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/README.md +5 -8
- package/README.zh-CN.md +5 -8
- package/lib/commonjs/features/network/index.js +4 -10
- package/lib/commonjs/features/network/index.js.map +1 -1
- package/lib/commonjs/features/network/networkInterceptor.js +158 -203
- package/lib/commonjs/features/network/networkInterceptor.js.map +1 -1
- package/lib/module/features/network/index.js +5 -11
- package/lib/module/features/network/index.js.map +1 -1
- package/lib/module/features/network/networkInterceptor.js +157 -202
- package/lib/module/features/network/networkInterceptor.js.map +1 -1
- package/lib/typescript/src/features/network/index.d.ts +0 -4
- package/lib/typescript/src/features/network/index.d.ts.map +1 -1
- package/lib/typescript/src/features/network/networkInterceptor.d.ts +1 -14
- package/lib/typescript/src/features/network/networkInterceptor.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/features/network/index.ts +5 -16
- package/src/features/network/networkInterceptor.ts +212 -237
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ A dev-only floating debug panel for React Native — inspect network, console, s
|
|
|
11
11
|

|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
- **Network** — Auto-intercepts fetch
|
|
14
|
+
- **Network** — Auto-intercepts React Native XHR transport, including fetch and axios in the default adapter, inspect requests & responses, copy as cURL
|
|
15
15
|
- **Console** — Capture `console.log / info / warn / error`
|
|
16
16
|
- **Zustand** — Log state transitions via middleware
|
|
17
17
|
- **Navigation** — Track route changes
|
|
@@ -56,7 +56,7 @@ function App() {
|
|
|
56
56
|
|
|
57
57
|
A floating debug button appears in dev mode. Tap to open the panel, tap × or swipe down to close.
|
|
58
58
|
|
|
59
|
-
Network
|
|
59
|
+
Network, console, navigation, zustand, track, and clipboard are enabled by default. Network capture hooks React Native's XHR transport, so fetch and axios requests using the default adapter are captured automatically.
|
|
60
60
|
|
|
61
61
|
Disable specific features:
|
|
62
62
|
|
|
@@ -122,19 +122,16 @@ import { addTrackLog } from 'react-native-debug-toolkit';
|
|
|
122
122
|
addTrackLog({ eventName: 'button_click', buttonId: 'submit' });
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
### Network
|
|
125
|
+
### Network Options
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
import axios from 'axios';
|
|
129
|
-
|
|
130
|
-
const api = axios.create({ baseURL: 'https://api.example.com' });
|
|
127
|
+
React Native fetch and axios traffic is captured automatically through the XHR transport layer.
|
|
131
128
|
|
|
129
|
+
```tsx
|
|
132
130
|
<DebugView
|
|
133
131
|
features={{
|
|
134
132
|
network: {
|
|
135
133
|
maxLogs: 100,
|
|
136
134
|
blacklist: ['/analytics', /\/healthcheck$/],
|
|
137
|
-
axiosInstance: api,
|
|
138
135
|
},
|
|
139
136
|
}}
|
|
140
137
|
>
|
package/README.zh-CN.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|

|
|
12
12
|
## 功能
|
|
13
13
|
|
|
14
|
-
- **Network** — 自动拦截 fetch
|
|
14
|
+
- **Network** — 自动拦截 React Native XHR 传输层,默认覆盖 fetch 和使用默认 adapter 的 axios,可查看请求与响应并复制为 cURL
|
|
15
15
|
- **Console** — 捕获 `console.log / info / warn / error`
|
|
16
16
|
- **Zustand** — 通过中间件记录状态变化
|
|
17
17
|
- **Navigation** — 追踪路由切换
|
|
@@ -56,7 +56,7 @@ function App() {
|
|
|
56
56
|
|
|
57
57
|
开发模式下出现浮动调试按钮。点击打开面板,点击 × 或下滑关闭。
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
网络、控制台、导航、Zustand、埋点和剪贴板默认启用。Network 会拦截 React Native 的 XHR 传输层,因此使用默认 adapter 的 fetch 和 axios 请求会自动被捕获。
|
|
60
60
|
|
|
61
61
|
禁用特定功能:
|
|
62
62
|
|
|
@@ -122,19 +122,16 @@ import { addTrackLog } from 'react-native-debug-toolkit';
|
|
|
122
122
|
addTrackLog({ eventName: 'button_click', buttonId: 'submit' });
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
###
|
|
125
|
+
### 网络配置
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
import axios from 'axios';
|
|
129
|
-
|
|
130
|
-
const api = axios.create({ baseURL: 'https://api.example.com' });
|
|
127
|
+
React Native fetch 和 axios 流量会通过 XHR 传输层自动捕获。
|
|
131
128
|
|
|
129
|
+
```tsx
|
|
132
130
|
<DebugView
|
|
133
131
|
features={{
|
|
134
132
|
network: {
|
|
135
133
|
maxLogs: 100,
|
|
136
134
|
blacklist: ['/analytics', /\/healthcheck$/],
|
|
137
|
-
axiosInstance: api,
|
|
138
135
|
},
|
|
139
136
|
}}
|
|
140
137
|
>
|
|
@@ -39,8 +39,7 @@ const createNetworkFeature = config => {
|
|
|
39
39
|
});
|
|
40
40
|
let initialized = false;
|
|
41
41
|
let unsubscribeLogs = null;
|
|
42
|
-
let
|
|
43
|
-
let stopAxiosFn = null;
|
|
42
|
+
let stopXhrFn = null;
|
|
44
43
|
const handleLog = entry => {
|
|
45
44
|
if (isUrlBlacklisted(entry.request.url, blacklist)) {
|
|
46
45
|
return;
|
|
@@ -59,10 +58,7 @@ const createNetworkFeature = config => {
|
|
|
59
58
|
return;
|
|
60
59
|
}
|
|
61
60
|
unsubscribeLogs = networkChannel.subscribe(handleLog);
|
|
62
|
-
|
|
63
|
-
if (config?.axiosInstance) {
|
|
64
|
-
stopAxiosFn = (0, _networkInterceptor.startAxios)(config.axiosInstance, emitNetworkLog);
|
|
65
|
-
}
|
|
61
|
+
stopXhrFn = (0, _networkInterceptor.startXMLHttpRequest)(emitNetworkLog);
|
|
66
62
|
initialized = true;
|
|
67
63
|
},
|
|
68
64
|
getSnapshot: () => logStore.getData(),
|
|
@@ -76,10 +72,8 @@ const createNetworkFeature = config => {
|
|
|
76
72
|
_urlRewriterRegistry.urlRewriter.set(null);
|
|
77
73
|
unsubscribeLogs?.();
|
|
78
74
|
unsubscribeLogs = null;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
stopAxiosFn?.();
|
|
82
|
-
stopAxiosFn = null;
|
|
75
|
+
stopXhrFn?.();
|
|
76
|
+
stopXhrFn = null;
|
|
83
77
|
logStore.clear();
|
|
84
78
|
initialized = false;
|
|
85
79
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_NetworkLogTab","require","_createEventChannel","_createPersistedObservableStore","_debugPreferences","_urlRewriterRegistry","_networkInterceptor","isUrlBlacklisted","url","blacklist","some","pattern","RegExp","test","includes","networkChannel","createEventChannel","emitNetworkLog","entry","emit","DEFAULT_MAX_LOGS","createNetworkFeature","config","maxLogs","logStore","createPersistedObservableStore","storageKey","KEYS","networkLogs","maxPersist","initialized","unsubscribeLogs","
|
|
1
|
+
{"version":3,"names":["_NetworkLogTab","require","_createEventChannel","_createPersistedObservableStore","_debugPreferences","_urlRewriterRegistry","_networkInterceptor","isUrlBlacklisted","url","blacklist","some","pattern","RegExp","test","includes","networkChannel","createEventChannel","emitNetworkLog","entry","emit","DEFAULT_MAX_LOGS","createNetworkFeature","config","maxLogs","logStore","createPersistedObservableStore","storageKey","KEYS","networkLogs","maxPersist","initialized","unsubscribeLogs","stopXhrFn","handleLog","request","push","id","nextId","name","label","renderContent","NetworkLogTab","setup","subscribe","startXMLHttpRequest","getSnapshot","getData","clear","cleanup","urlRewriter","set","listener","exports","_resetNetworkForTesting","resetInterceptors"],"sourceRoot":"../../../../src","sources":["features/network/index.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,14 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.resetInterceptors = resetInterceptors;
|
|
7
|
-
exports.
|
|
8
|
-
exports.startFetch = startFetch;
|
|
7
|
+
exports.startXMLHttpRequest = startXMLHttpRequest;
|
|
9
8
|
var _urlRewriterRegistry = require("../../utils/urlRewriterRegistry");
|
|
10
|
-
// Intercepts
|
|
11
|
-
//
|
|
12
|
-
// avoiding the unreliable XHR response interception in React Native.
|
|
13
|
-
|
|
14
|
-
// ─── Minimal axios interface (no hard dependency) ──────
|
|
9
|
+
// Intercepts React Native's XMLHttpRequest transport layer.
|
|
10
|
+
// RN fetch and axios (default adapter) both go through XHR — one hook captures everything.
|
|
15
11
|
|
|
16
12
|
// ─── Shared helpers ────────────────────────────────────
|
|
17
13
|
|
|
@@ -26,236 +22,195 @@ function rewriteUrl(url) {
|
|
|
26
22
|
return url;
|
|
27
23
|
}
|
|
28
24
|
}
|
|
29
|
-
function
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
if (typeof headers.forEach === 'function') {
|
|
35
|
-
headers.forEach((value, key) => {
|
|
36
|
-
result[key] = value;
|
|
37
|
-
});
|
|
38
|
-
return result;
|
|
25
|
+
function parseRawHeaders(rawHeaders) {
|
|
26
|
+
if (!rawHeaders) {
|
|
27
|
+
return undefined;
|
|
39
28
|
}
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
const headers = {};
|
|
30
|
+
rawHeaders.trim().split(/[\r\n]+/).forEach(line => {
|
|
31
|
+
const separatorIndex = line.indexOf(':');
|
|
32
|
+
if (separatorIndex <= 0) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const key = line.slice(0, separatorIndex).trim();
|
|
36
|
+
const value = line.slice(separatorIndex + 1).trim();
|
|
37
|
+
if (key) {
|
|
38
|
+
headers[key] = value;
|
|
39
|
+
}
|
|
42
40
|
});
|
|
43
|
-
return
|
|
44
|
-
}
|
|
45
|
-
function getRequestSnapshot(input, init) {
|
|
46
|
-
const request = input instanceof Request ? input : null;
|
|
47
|
-
return {
|
|
48
|
-
url: typeof input === 'string' ? input : request?.url ?? String(input),
|
|
49
|
-
method: (init?.method || request?.method || 'GET').toUpperCase(),
|
|
50
|
-
headers: init?.headers ? headersToObject(init.headers) : request?.headers ? headersToObject(request.headers) : undefined,
|
|
51
|
-
body: init?.body
|
|
52
|
-
};
|
|
41
|
+
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
53
42
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (!raw) {
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
43
|
+
function parseBodyText(raw) {
|
|
44
|
+
if (!raw) return undefined;
|
|
59
45
|
try {
|
|
60
46
|
return JSON.parse(raw);
|
|
61
47
|
} catch {
|
|
62
48
|
return raw;
|
|
63
49
|
}
|
|
64
50
|
}
|
|
65
|
-
function
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// AxiosHeaders instance
|
|
70
|
-
if (typeof headers.forEach === 'function') {
|
|
71
|
-
const result = {};
|
|
72
|
-
headers.forEach((value, key) => {
|
|
73
|
-
result[key] = value;
|
|
74
|
-
});
|
|
75
|
-
return Object.keys(result).length > 0 ? result : undefined;
|
|
76
|
-
}
|
|
77
|
-
// Plain object
|
|
78
|
-
const result = {};
|
|
79
|
-
const obj = headers;
|
|
80
|
-
for (const key of Object.keys(obj)) {
|
|
81
|
-
const val = obj[key];
|
|
82
|
-
if (typeof val === 'string') {
|
|
83
|
-
result[key] = val;
|
|
84
|
-
}
|
|
51
|
+
function normalizeXhrResponseBody(xhr) {
|
|
52
|
+
const text = safeRead(() => xhr.responseText);
|
|
53
|
+
if (typeof text === 'string' && text) {
|
|
54
|
+
return parseBodyText(text);
|
|
85
55
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const base = config.baseURL ?? '';
|
|
90
|
-
const url = config.url ?? '';
|
|
91
|
-
if (!base || url.startsWith('http')) {
|
|
92
|
-
return url;
|
|
56
|
+
const response = safeRead(() => xhr.response);
|
|
57
|
+
if (response != null) {
|
|
58
|
+
return response;
|
|
93
59
|
}
|
|
94
|
-
return
|
|
60
|
+
return undefined;
|
|
95
61
|
}
|
|
96
62
|
|
|
97
|
-
// ───
|
|
63
|
+
// ─── XMLHttpRequest interceptor ───────────────────────
|
|
98
64
|
|
|
99
|
-
let
|
|
100
|
-
let
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
65
|
+
let originalXMLHttpRequest = null;
|
|
66
|
+
let originalXhrOpen = null;
|
|
67
|
+
let originalXhrSend = null;
|
|
68
|
+
let originalXhrSetRequestHeader = null;
|
|
69
|
+
let xhrRefCount = 0;
|
|
70
|
+
const pendingXhrRequests = new WeakMap();
|
|
71
|
+
function safeRead(read) {
|
|
72
|
+
try {
|
|
73
|
+
return read();
|
|
74
|
+
} catch {
|
|
75
|
+
return undefined;
|
|
106
76
|
}
|
|
107
77
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
78
|
+
function getGlobalXMLHttpRequest() {
|
|
79
|
+
return globalThis.XMLHttpRequest;
|
|
80
|
+
}
|
|
81
|
+
function getXhrResponseHeaders(xhr) {
|
|
82
|
+
const rawHeaders = safeRead(() => xhr.getAllResponseHeaders?.());
|
|
83
|
+
const parsedHeaders = parseRawHeaders(rawHeaders);
|
|
84
|
+
if (parsedHeaders) {
|
|
85
|
+
return parsedHeaders;
|
|
114
86
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
87
|
+
const headers = xhr.responseHeaders;
|
|
88
|
+
if (!headers) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
return Object.keys(headers).length > 0 ? headers : undefined;
|
|
92
|
+
}
|
|
93
|
+
function stopXMLHttpRequest() {
|
|
94
|
+
xhrRefCount = Math.max(0, xhrRefCount - 1);
|
|
95
|
+
if (xhrRefCount > 0 || !originalXMLHttpRequest) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const CurrentXMLHttpRequest = getGlobalXMLHttpRequest();
|
|
99
|
+
if (CurrentXMLHttpRequest) {
|
|
100
|
+
if (originalXhrOpen) {
|
|
101
|
+
CurrentXMLHttpRequest.prototype.open = originalXhrOpen;
|
|
125
102
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const response = await originalFetch.call(globalThis, rewrittenInput, init);
|
|
129
|
-
const duration = Date.now() - startTime;
|
|
130
|
-
try {
|
|
131
|
-
const data = await parseResponseBody(response);
|
|
132
|
-
emit({
|
|
133
|
-
timestamp: startTime,
|
|
134
|
-
duration,
|
|
135
|
-
request,
|
|
136
|
-
response: {
|
|
137
|
-
status: response.status,
|
|
138
|
-
statusText: response.statusText,
|
|
139
|
-
data
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
} catch {
|
|
143
|
-
emit({
|
|
144
|
-
timestamp: startTime,
|
|
145
|
-
duration,
|
|
146
|
-
request,
|
|
147
|
-
response: {
|
|
148
|
-
status: response.status,
|
|
149
|
-
statusText: response.statusText
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
return response;
|
|
154
|
-
} catch (error) {
|
|
155
|
-
emit({
|
|
156
|
-
timestamp: startTime,
|
|
157
|
-
duration: Date.now() - startTime,
|
|
158
|
-
request,
|
|
159
|
-
error: error instanceof Error ? error.message : String(error)
|
|
160
|
-
});
|
|
161
|
-
throw error;
|
|
103
|
+
if (originalXhrSend) {
|
|
104
|
+
CurrentXMLHttpRequest.prototype.send = originalXhrSend;
|
|
162
105
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
106
|
+
if (originalXhrSetRequestHeader) {
|
|
107
|
+
CurrentXMLHttpRequest.prototype.setRequestHeader = originalXhrSetRequestHeader;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
originalXMLHttpRequest = null;
|
|
111
|
+
originalXhrOpen = null;
|
|
112
|
+
originalXhrSend = null;
|
|
113
|
+
originalXhrSetRequestHeader = null;
|
|
167
114
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
115
|
+
function startXMLHttpRequest(emit) {
|
|
116
|
+
const CurrentXMLHttpRequest = getGlobalXMLHttpRequest();
|
|
117
|
+
if (!CurrentXMLHttpRequest) {
|
|
118
|
+
return () => {};
|
|
119
|
+
}
|
|
120
|
+
xhrRefCount += 1;
|
|
121
|
+
if (originalXMLHttpRequest) {
|
|
122
|
+
return () => {
|
|
123
|
+
stopXMLHttpRequest();
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
originalXMLHttpRequest = CurrentXMLHttpRequest;
|
|
127
|
+
originalXhrOpen = CurrentXMLHttpRequest.prototype.open;
|
|
128
|
+
originalXhrSend = CurrentXMLHttpRequest.prototype.send;
|
|
129
|
+
originalXhrSetRequestHeader = CurrentXMLHttpRequest.prototype.setRequestHeader;
|
|
130
|
+
CurrentXMLHttpRequest.prototype.open = function interceptedOpen(method, url, ...args) {
|
|
131
|
+
const rewrittenUrl = _urlRewriterRegistry.urlRewriter.get() ? rewriteUrl(url) : url;
|
|
132
|
+
pendingXhrRequests.set(this, {
|
|
133
|
+
method: (method || 'GET').toUpperCase(),
|
|
134
|
+
url: rewrittenUrl,
|
|
135
|
+
headers: {},
|
|
136
|
+
timestamp: Date.now()
|
|
181
137
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
config.baseURL = undefined;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
138
|
+
return originalXhrOpen.call(this, method, rewrittenUrl, ...args);
|
|
139
|
+
};
|
|
140
|
+
CurrentXMLHttpRequest.prototype.setRequestHeader = function interceptedSetRequestHeader(header, value) {
|
|
141
|
+
const state = pendingXhrRequests.get(this);
|
|
142
|
+
if (state) {
|
|
143
|
+
state.headers[header] = value;
|
|
191
144
|
}
|
|
192
|
-
return
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
response: {
|
|
210
|
-
status: response.status,
|
|
211
|
-
statusText: response.statusText,
|
|
212
|
-
headers: normalizeAxiosHeaders(response.headers),
|
|
213
|
-
data: response.data,
|
|
214
|
-
success: response.status >= 200 && response.status < 300
|
|
145
|
+
return originalXhrSetRequestHeader.call(this, header, value);
|
|
146
|
+
};
|
|
147
|
+
CurrentXMLHttpRequest.prototype.send = function interceptedSend(body) {
|
|
148
|
+
const that = this;
|
|
149
|
+
const state = pendingXhrRequests.get(that) ?? {
|
|
150
|
+
method: 'GET',
|
|
151
|
+
url: '',
|
|
152
|
+
headers: {},
|
|
153
|
+
timestamp: Date.now()
|
|
154
|
+
};
|
|
155
|
+
state.body = body;
|
|
156
|
+
state.timestamp = Date.now();
|
|
157
|
+
pendingXhrRequests.set(that, state);
|
|
158
|
+
const complete = () => {
|
|
159
|
+
const currentState = pendingXhrRequests.get(that);
|
|
160
|
+
if (!currentState || currentState.completed) {
|
|
161
|
+
return;
|
|
215
162
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
},
|
|
219
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
220
|
-
error => {
|
|
221
|
-
const config = error.config;
|
|
222
|
-
const pending = config ? pendingAxiosRequests.get(config) : undefined;
|
|
223
|
-
const startTime = pending?.timestamp ?? Date.now();
|
|
224
|
-
if (config) {
|
|
163
|
+
currentState.completed = true;
|
|
164
|
+
const headers = getXhrResponseHeaders(that);
|
|
225
165
|
emit({
|
|
226
|
-
timestamp:
|
|
227
|
-
duration: Date.now() -
|
|
166
|
+
timestamp: currentState.timestamp,
|
|
167
|
+
duration: Date.now() - currentState.timestamp,
|
|
228
168
|
request: {
|
|
229
|
-
url:
|
|
230
|
-
method:
|
|
231
|
-
headers:
|
|
232
|
-
body:
|
|
169
|
+
url: currentState.url,
|
|
170
|
+
method: currentState.method,
|
|
171
|
+
headers: Object.keys(currentState.headers).length > 0 ? currentState.headers : undefined,
|
|
172
|
+
body: currentState.body
|
|
173
|
+
},
|
|
174
|
+
response: {
|
|
175
|
+
status: that.status,
|
|
176
|
+
statusText: that.statusText,
|
|
177
|
+
headers,
|
|
178
|
+
data: normalizeXhrResponseBody(that),
|
|
179
|
+
success: that.status >= 200 && that.status < 300
|
|
233
180
|
},
|
|
234
|
-
|
|
235
|
-
status: error.response.status,
|
|
236
|
-
statusText: error.response.statusText,
|
|
237
|
-
headers: normalizeAxiosHeaders(error.response.headers),
|
|
238
|
-
data: error.response.data,
|
|
239
|
-
success: false
|
|
240
|
-
} : undefined,
|
|
241
|
-
error: error.message ?? String(error)
|
|
181
|
+
error: currentState.error
|
|
242
182
|
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
|
|
183
|
+
};
|
|
184
|
+
const markError = message => {
|
|
185
|
+
const currentState = pendingXhrRequests.get(that);
|
|
186
|
+
if (currentState) {
|
|
187
|
+
currentState.error = message;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
that.addEventListener('error', () => {
|
|
191
|
+
markError('Network Error');
|
|
192
|
+
});
|
|
193
|
+
that.addEventListener('timeout', () => {
|
|
194
|
+
markError('Timeout');
|
|
195
|
+
});
|
|
196
|
+
that.addEventListener('abort', () => {
|
|
197
|
+
markError('Aborted');
|
|
198
|
+
});
|
|
199
|
+
that.addEventListener('loadend', complete);
|
|
200
|
+
return originalXhrSend.call(that, body);
|
|
201
|
+
};
|
|
246
202
|
return () => {
|
|
247
|
-
|
|
248
|
-
axiosInstance.interceptors.response.eject(responseInterceptorId);
|
|
203
|
+
stopXMLHttpRequest();
|
|
249
204
|
};
|
|
250
205
|
}
|
|
251
206
|
|
|
252
207
|
// ─── Cleanup ───────────────────────────────────────────
|
|
253
208
|
|
|
254
209
|
function resetInterceptors() {
|
|
255
|
-
if (
|
|
256
|
-
|
|
257
|
-
|
|
210
|
+
if (originalXMLHttpRequest) {
|
|
211
|
+
xhrRefCount = 1;
|
|
212
|
+
stopXMLHttpRequest();
|
|
258
213
|
}
|
|
259
|
-
|
|
214
|
+
xhrRefCount = 0;
|
|
260
215
|
}
|
|
261
216
|
//# sourceMappingURL=networkInterceptor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_urlRewriterRegistry","require","rewriteUrl","url","rewriter","urlRewriter","get","
|
|
1
|
+
{"version":3,"names":["_urlRewriterRegistry","require","rewriteUrl","url","rewriter","urlRewriter","get","parseRawHeaders","rawHeaders","undefined","headers","trim","split","forEach","line","separatorIndex","indexOf","key","slice","value","Object","keys","length","parseBodyText","raw","JSON","parse","normalizeXhrResponseBody","xhr","text","safeRead","responseText","response","originalXMLHttpRequest","originalXhrOpen","originalXhrSend","originalXhrSetRequestHeader","xhrRefCount","pendingXhrRequests","WeakMap","read","getGlobalXMLHttpRequest","globalThis","XMLHttpRequest","getXhrResponseHeaders","getAllResponseHeaders","parsedHeaders","responseHeaders","stopXMLHttpRequest","Math","max","CurrentXMLHttpRequest","prototype","open","send","setRequestHeader","startXMLHttpRequest","emit","interceptedOpen","method","args","rewrittenUrl","set","toUpperCase","timestamp","Date","now","call","interceptedSetRequestHeader","header","state","interceptedSend","body","that","complete","currentState","completed","duration","request","status","statusText","data","success","error","markError","message","addEventListener","resetInterceptors"],"sourceRoot":"../../../../src","sources":["features/network/networkInterceptor.ts"],"mappings":"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","ignoreList":[]}
|