@rozenite/network-activity-plugin 1.0.0-alpha.8 → 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/README.md +2 -0
- package/dist/App.html +2 -2
- package/dist/assets/{App-R2ZMH9wJ.css → App-BrSkOkws.css} +269 -2
- package/dist/assets/{App-lNMijPJ4.js → App-C6wCDVkW.js} +17485 -10814
- package/dist/event-source.cjs +22 -0
- package/dist/event-source.js +23 -0
- package/dist/react-native.cjs +4 -1
- package/dist/react-native.js +4 -1
- package/dist/rozenite.json +1 -1
- package/dist/src/react-native/config.d.ts +20 -0
- package/dist/src/react-native/{network-inspector.d.ts → http/network-inspector.d.ts} +1 -1
- package/dist/src/react-native/http/overrides-registry.d.ts +6 -0
- package/dist/src/react-native/{xhr-interceptor.d.ts → http/xhr-interceptor.d.ts} +7 -1
- package/dist/src/react-native/sse/event-source.d.ts +2 -0
- package/dist/src/react-native/sse/sse-inspector.d.ts +9 -0
- package/dist/src/react-native/sse/sse-interceptor.d.ts +36 -0
- package/dist/src/react-native/sse/types.d.ts +6 -0
- package/dist/src/react-native/useNetworkActivityDevTools.d.ts +2 -1
- package/dist/src/react-native/utils/getBlobName.d.ts +35 -0
- package/dist/src/react-native/utils/getFormDataEntries.d.ts +18 -0
- package/dist/src/react-native/utils.d.ts +6 -0
- package/dist/src/react-native/websocket/websocket-inspector.d.ts +9 -0
- package/dist/src/react-native/websocket/websocket-interceptor.d.ts +74 -0
- package/dist/src/shared/client.d.ts +53 -6
- package/dist/src/shared/sse-events.d.ts +38 -0
- package/dist/src/shared/websocket-events.d.ts +60 -0
- package/dist/src/ui/components/Badge.d.ts +1 -1
- package/dist/src/ui/components/Button.d.ts +2 -2
- package/dist/src/ui/components/CodeBlock.d.ts +3 -0
- package/dist/src/ui/components/CodeEditor.d.ts +5 -0
- package/dist/src/ui/components/CookieCard.d.ts +7 -0
- package/dist/src/ui/components/CopyRequestDropdown.d.ts +7 -0
- package/dist/src/ui/components/DropdownMenu.d.ts +27 -0
- package/dist/src/ui/components/FilterBar.d.ts +10 -0
- package/dist/src/ui/components/JsonTreeCopyableItem.d.ts +7 -0
- package/dist/src/ui/components/KeyValueGrid.d.ts +13 -0
- package/dist/src/ui/components/OverrideResponse.d.ts +8 -0
- package/dist/src/ui/components/RequestBody.d.ts +6 -0
- package/dist/src/ui/components/RequestList.d.ts +13 -28
- package/dist/src/ui/components/ScrollArea.d.ts +3 -2
- package/dist/src/ui/components/Section.d.ts +8 -0
- package/dist/src/ui/components/Separator.d.ts +2 -1
- package/dist/src/ui/components/SidePanel.d.ts +1 -0
- package/dist/src/ui/components/Tabs.d.ts +7 -0
- package/dist/src/ui/components/Toolbar.d.ts +1 -0
- package/dist/src/ui/hooks/useCopyToClipboard.d.ts +4 -0
- package/dist/src/ui/state/derived.d.ts +5 -0
- package/dist/src/ui/state/hooks.d.ts +21 -0
- package/dist/src/ui/state/model.d.ts +103 -0
- package/dist/src/ui/state/store.d.ts +48 -0
- package/dist/src/ui/tabs/CookiesTab.d.ts +3 -6
- package/dist/src/ui/tabs/HeadersTab.d.ts +3 -15
- package/dist/src/ui/tabs/MessagesTab.d.ts +5 -0
- package/dist/src/ui/tabs/RequestTab.d.ts +2 -7
- package/dist/src/ui/tabs/ResponseTab.d.ts +2 -8
- package/dist/src/ui/tabs/SSEMessagesTab.d.ts +5 -0
- package/dist/src/ui/tabs/TimingTab.d.ts +3 -5
- package/dist/src/ui/types.d.ts +4 -1
- package/dist/src/ui/utils/assert.d.ts +1 -0
- package/dist/src/ui/utils/checkRequestBodyBinary.d.ts +2 -0
- package/dist/src/ui/utils/copyToClipboard.d.ts +1 -0
- package/dist/src/ui/utils/escapeShellArg.d.ts +1 -0
- package/dist/src/ui/utils/generateCurlCommand.d.ts +2 -0
- package/dist/src/ui/utils/generateFetchCall.d.ts +2 -0
- package/dist/src/ui/utils/generateMultipartBody.d.ts +4 -0
- package/dist/src/ui/utils/getId.d.ts +1 -0
- package/dist/src/ui/utils/getStatusColor.d.ts +1 -0
- package/dist/src/utils/applyReactNativeRequestHeadersLogic.d.ts +7 -0
- package/dist/src/utils/applyReactNativeResponseHeadersLogic.d.ts +9 -0
- package/dist/src/utils/cookieParser.d.ts +6 -0
- package/dist/src/utils/getContentTypeMimeType.d.ts +2 -0
- package/dist/src/utils/getHttpHeader.d.ts +5 -0
- package/dist/src/utils/getHttpHeaderValueAsString.d.ts +11 -0
- package/dist/src/utils/getStringSizeInBytes.d.ts +1 -0
- package/dist/src/utils/inferContentTypeFromPostData.d.ts +2 -0
- package/dist/src/utils/safeStringify.d.ts +1 -0
- package/dist/src/utils/typeChecks.d.ts +9 -0
- package/dist/useNetworkActivityDevTools.cjs +724 -40
- package/dist/useNetworkActivityDevTools.js +723 -41
- package/package.json +22 -8
- package/react-native.ts +6 -1
- package/src/react-native/config.ts +43 -0
- package/src/react-native/http/network-inspector.ts +388 -0
- package/src/react-native/http/overrides-registry.ts +32 -0
- package/src/react-native/{xhr-interceptor.ts → http/xhr-interceptor.ts} +19 -2
- package/src/react-native/{xml-request.d.ts → http/xml-request.d.ts} +1 -0
- package/src/react-native/sse/event-source.ts +25 -0
- package/src/react-native/sse/sse-inspector.ts +139 -0
- package/src/react-native/sse/sse-interceptor.ts +180 -0
- package/src/react-native/sse/types.ts +9 -0
- package/src/react-native/useNetworkActivityDevTools.ts +156 -4
- package/src/react-native/utils/getBlobName.ts +45 -0
- package/src/react-native/utils/getFormDataEntries.ts +32 -0
- package/src/react-native/utils.ts +43 -0
- package/src/react-native/websocket/websocket-inspector.ts +180 -0
- package/src/react-native/websocket/websocket-interceptor.d.ts +4 -0
- package/src/react-native/websocket/websocket-interceptor.ts +166 -0
- package/src/shared/client.ts +79 -6
- package/src/shared/sse-events.ts +47 -0
- package/src/shared/websocket-events.ts +79 -0
- package/src/ui/components/Button.tsx +1 -0
- package/src/ui/components/CodeBlock.tsx +19 -0
- package/src/ui/components/CodeEditor.tsx +26 -0
- package/src/ui/components/CookieCard.tsx +64 -0
- package/src/ui/components/CopyRequestDropdown.tsx +95 -0
- package/src/ui/components/DropdownMenu.tsx +206 -0
- package/src/ui/components/FilterBar.tsx +117 -0
- package/src/ui/components/Input.tsx +1 -1
- package/src/ui/components/JsonTree.tsx +20 -0
- package/src/ui/components/JsonTreeCopyableItem.tsx +37 -0
- package/src/ui/components/KeyValueGrid.tsx +51 -0
- package/src/ui/components/OverrideResponse.tsx +132 -0
- package/src/ui/components/RequestBody.tsx +86 -0
- package/src/ui/components/RequestList.tsx +101 -131
- package/src/ui/components/ScrollArea.tsx +1 -0
- package/src/ui/components/Section.tsx +46 -0
- package/src/ui/components/SidePanel.tsx +333 -0
- package/src/ui/components/Tabs.tsx +1 -1
- package/src/ui/components/Toolbar.tsx +45 -0
- package/src/ui/globals.css +4 -0
- package/src/ui/hooks/useCopyToClipboard.ts +28 -0
- package/src/ui/state/derived.ts +112 -0
- package/src/ui/state/hooks.ts +52 -0
- package/src/ui/state/model.ts +140 -0
- package/src/ui/state/store.ts +669 -0
- package/src/ui/tabs/CookiesTab.tsx +61 -278
- package/src/ui/tabs/HeadersTab.tsx +85 -103
- package/src/ui/tabs/MessagesTab.tsx +276 -0
- package/src/ui/tabs/RequestTab.tsx +58 -51
- package/src/ui/tabs/ResponseTab.tsx +101 -74
- package/src/ui/tabs/SSEMessagesTab.tsx +224 -0
- package/src/ui/tabs/TimingTab.tsx +30 -43
- package/src/ui/types.ts +4 -1
- package/src/ui/utils/assert.ts +5 -0
- package/src/ui/utils/checkRequestBodyBinary.ts +7 -0
- package/src/ui/utils/copyToClipboard.ts +3 -0
- package/src/ui/utils/escapeShellArg.ts +12 -0
- package/src/ui/utils/generateCurlCommand.ts +83 -0
- package/src/ui/utils/generateFetchCall.ts +64 -0
- package/src/ui/utils/generateMultipartBody.ts +19 -0
- package/src/ui/utils/getId.ts +10 -0
- package/src/ui/utils/getStatusColor.ts +15 -0
- package/src/ui/views/InspectorView.tsx +35 -319
- package/src/utils/applyReactNativeRequestHeadersLogic.ts +30 -0
- package/src/utils/applyReactNativeResponseHeadersLogic.ts +28 -0
- package/src/utils/cookieParser.ts +126 -0
- package/src/utils/getContentTypeMimeType.ts +17 -0
- package/src/utils/getHttpHeader.ts +17 -0
- package/src/utils/getHttpHeaderValueAsString.ts +13 -0
- package/src/utils/getStringSizeInBytes.ts +3 -0
- package/src/utils/inferContentTypeFromPostData.ts +9 -0
- package/src/utils/safeStringify.ts +7 -0
- package/src/utils/typeChecks.ts +27 -0
- package/tailwind.config.ts +3 -0
- package/vite.config.ts +12 -0
- package/dist/src/ui/utils/getHttpHeaderValue.d.ts +0 -2
- package/src/react-native/network-inspector.ts +0 -247
- package/src/ui/utils/getHttpHeaderValue.ts +0 -14
- /package/dist/src/react-native/{network-requests-registry.d.ts → http/network-requests-registry.d.ts} +0 -0
- /package/src/react-native/{network-requests-registry.ts → http/network-requests-registry.ts} +0 -0
|
@@ -1,14 +1,54 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
1
|
+
import { useRef, useEffect } from "react";
|
|
2
2
|
import { useRozeniteDevToolsClient } from "@rozenite/plugin-bridge";
|
|
3
|
-
|
|
3
|
+
import { createNanoEvents } from "nanoevents";
|
|
4
|
+
import { Platform } from "react-native";
|
|
5
|
+
import WebSocketInterceptor from "react-native/Libraries/WebSocket/WebSocketInterceptor";
|
|
6
|
+
import { g as getEventSource } from "./event-source.js";
|
|
7
|
+
function safeStringify(data) {
|
|
8
|
+
try {
|
|
9
|
+
return typeof data === "string" ? data : JSON.stringify(data);
|
|
10
|
+
} catch {
|
|
11
|
+
return String(data);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function getHttpHeader(headers, name) {
|
|
4
15
|
const lowerName = name.toLowerCase();
|
|
5
16
|
for (const key in headers) {
|
|
6
17
|
if (key.toLowerCase() === lowerName) {
|
|
7
|
-
return headers[key];
|
|
18
|
+
return { value: headers[key], originalKey: key };
|
|
8
19
|
}
|
|
9
20
|
}
|
|
10
21
|
return void 0;
|
|
11
22
|
}
|
|
23
|
+
function getContentTypeMime(headers) {
|
|
24
|
+
const contentType = getHttpHeader(headers, "content-type");
|
|
25
|
+
if (!contentType) {
|
|
26
|
+
return void 0;
|
|
27
|
+
}
|
|
28
|
+
const { value } = contentType;
|
|
29
|
+
const actualValue = Array.isArray(value) ? value[0] : value;
|
|
30
|
+
return actualValue.split(";")[0].trim();
|
|
31
|
+
}
|
|
32
|
+
const getContentType = (request) => {
|
|
33
|
+
const responseHeaders = request.responseHeaders;
|
|
34
|
+
const responseType = request.responseType;
|
|
35
|
+
const contentType = getContentTypeMime(responseHeaders || {});
|
|
36
|
+
if (contentType) {
|
|
37
|
+
return contentType;
|
|
38
|
+
}
|
|
39
|
+
switch (responseType) {
|
|
40
|
+
case "arraybuffer":
|
|
41
|
+
case "blob":
|
|
42
|
+
return "application/octet-stream";
|
|
43
|
+
case "text":
|
|
44
|
+
case "":
|
|
45
|
+
return "text/plain";
|
|
46
|
+
case "json":
|
|
47
|
+
return "application/json";
|
|
48
|
+
case "document":
|
|
49
|
+
return "text/html";
|
|
50
|
+
}
|
|
51
|
+
};
|
|
12
52
|
const REQUEST_TTL = 1e3 * 60 * 5;
|
|
13
53
|
const getNetworkRequestsRegistry = () => {
|
|
14
54
|
const registry = /* @__PURE__ */ new Map();
|
|
@@ -42,6 +82,28 @@ const getNetworkRequestsRegistry = () => {
|
|
|
42
82
|
clear
|
|
43
83
|
};
|
|
44
84
|
};
|
|
85
|
+
function getBlobName(blob) {
|
|
86
|
+
if (typeof (blob == null ? void 0 : blob.name) === "string") {
|
|
87
|
+
return blob.name;
|
|
88
|
+
}
|
|
89
|
+
if ((blob == null ? void 0 : blob.data) && typeof blob.data.name === "string") {
|
|
90
|
+
return blob.data.name;
|
|
91
|
+
}
|
|
92
|
+
return void 0;
|
|
93
|
+
}
|
|
94
|
+
function getFormDataEntries(formData) {
|
|
95
|
+
if (!formData || typeof formData !== "object") {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
if (typeof formData.entries === "function") {
|
|
99
|
+
return formData.entries();
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(formData._parts)) {
|
|
102
|
+
return formData._parts;
|
|
103
|
+
}
|
|
104
|
+
return [];
|
|
105
|
+
}
|
|
106
|
+
const XMLHttpRequest = global.XMLHttpRequest || window.XMLHttpRequest;
|
|
45
107
|
const originalXHROpen = XMLHttpRequest.prototype.open;
|
|
46
108
|
const originalXHRSend = XMLHttpRequest.prototype.send;
|
|
47
109
|
const originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
@@ -50,7 +112,8 @@ let sendCallback;
|
|
|
50
112
|
let requestHeaderCallback;
|
|
51
113
|
let headerReceivedCallback;
|
|
52
114
|
let responseCallback;
|
|
53
|
-
let
|
|
115
|
+
let overrideCallback;
|
|
116
|
+
let isInterceptorEnabled$1 = false;
|
|
54
117
|
const XHRInterceptor = {
|
|
55
118
|
/**
|
|
56
119
|
* Invoked before XMLHttpRequest.open(...) is called.
|
|
@@ -82,11 +145,17 @@ const XHRInterceptor = {
|
|
|
82
145
|
setRequestHeaderCallback(callback) {
|
|
83
146
|
requestHeaderCallback = callback;
|
|
84
147
|
},
|
|
148
|
+
/**
|
|
149
|
+
* Invoked before XMLHttpRequest.send(...) is called.
|
|
150
|
+
*/
|
|
151
|
+
setOverrideCallback(callback) {
|
|
152
|
+
overrideCallback = callback;
|
|
153
|
+
},
|
|
85
154
|
isInterceptorEnabled() {
|
|
86
|
-
return isInterceptorEnabled;
|
|
155
|
+
return isInterceptorEnabled$1;
|
|
87
156
|
},
|
|
88
157
|
enableInterception() {
|
|
89
|
-
if (isInterceptorEnabled) {
|
|
158
|
+
if (isInterceptorEnabled$1) {
|
|
90
159
|
return;
|
|
91
160
|
}
|
|
92
161
|
XMLHttpRequest.prototype.open = function(method, url) {
|
|
@@ -105,11 +174,14 @@ const XHRInterceptor = {
|
|
|
105
174
|
if (sendCallback) {
|
|
106
175
|
sendCallback(data, this);
|
|
107
176
|
}
|
|
177
|
+
if (overrideCallback) {
|
|
178
|
+
overrideCallback(this);
|
|
179
|
+
}
|
|
108
180
|
if (this.addEventListener) {
|
|
109
181
|
this.addEventListener(
|
|
110
182
|
"readystatechange",
|
|
111
183
|
() => {
|
|
112
|
-
if (!isInterceptorEnabled) {
|
|
184
|
+
if (!isInterceptorEnabled$1) {
|
|
113
185
|
return;
|
|
114
186
|
}
|
|
115
187
|
if (this.readyState === this.HEADERS_RECEIVED) {
|
|
@@ -149,14 +221,14 @@ const XHRInterceptor = {
|
|
|
149
221
|
}
|
|
150
222
|
originalXHRSend.apply(this, arguments);
|
|
151
223
|
};
|
|
152
|
-
isInterceptorEnabled = true;
|
|
224
|
+
isInterceptorEnabled$1 = true;
|
|
153
225
|
},
|
|
154
226
|
// Unpatch XMLHttpRequest methods and remove the callbacks.
|
|
155
227
|
disableInterception() {
|
|
156
|
-
if (!isInterceptorEnabled) {
|
|
228
|
+
if (!isInterceptorEnabled$1) {
|
|
157
229
|
return;
|
|
158
230
|
}
|
|
159
|
-
isInterceptorEnabled = false;
|
|
231
|
+
isInterceptorEnabled$1 = false;
|
|
160
232
|
XMLHttpRequest.prototype.send = originalXHRSend;
|
|
161
233
|
XMLHttpRequest.prototype.open = originalXHROpen;
|
|
162
234
|
XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
|
|
@@ -165,38 +237,132 @@ const XHRInterceptor = {
|
|
|
165
237
|
sendCallback = null;
|
|
166
238
|
headerReceivedCallback = null;
|
|
167
239
|
requestHeaderCallback = null;
|
|
240
|
+
overrideCallback = null;
|
|
168
241
|
}
|
|
169
242
|
};
|
|
243
|
+
const getStringSizeInBytes = (value) => {
|
|
244
|
+
return new TextEncoder().encode(value).length;
|
|
245
|
+
};
|
|
246
|
+
const splitSetCookieHeaderByComma = (header) => {
|
|
247
|
+
const regex = /(?:^|,\s)([^=;,]+=[^;]+(?:;[^,]*)*)/g;
|
|
248
|
+
const matches = [];
|
|
249
|
+
let match;
|
|
250
|
+
while ((match = regex.exec(header)) !== null) {
|
|
251
|
+
matches.push(match[1].trim());
|
|
252
|
+
}
|
|
253
|
+
return matches;
|
|
254
|
+
};
|
|
255
|
+
const applyReactNativeResponseHeadersLogic = (headers) => {
|
|
256
|
+
const parsedHeaders = { ...headers };
|
|
257
|
+
const setCookieHeader = getHttpHeader(headers, "set-cookie");
|
|
258
|
+
if (setCookieHeader) {
|
|
259
|
+
const { value, originalKey } = setCookieHeader;
|
|
260
|
+
const cookies = splitSetCookieHeaderByComma(value);
|
|
261
|
+
parsedHeaders[originalKey] = cookies.length > 0 ? cookies : value;
|
|
262
|
+
}
|
|
263
|
+
return parsedHeaders;
|
|
264
|
+
};
|
|
265
|
+
const isBlob = (value) => value instanceof Blob;
|
|
266
|
+
const isArrayBuffer = (value) => value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
267
|
+
const isFormData = (value) => value instanceof FormData;
|
|
268
|
+
const isNullOrUndefined = (value) => value === null || value === void 0;
|
|
269
|
+
const createOverridesRegistry = () => {
|
|
270
|
+
let overrides = /* @__PURE__ */ new Map();
|
|
271
|
+
const setOverrides = (newOverrides) => {
|
|
272
|
+
overrides = new Map(newOverrides);
|
|
273
|
+
};
|
|
274
|
+
const getOverrideForUrl = (url) => {
|
|
275
|
+
return overrides.get(url);
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
setOverrides,
|
|
279
|
+
getOverrideForUrl
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
let registryInstance = null;
|
|
283
|
+
const getOverridesRegistry = () => {
|
|
284
|
+
if (!registryInstance) {
|
|
285
|
+
registryInstance = createOverridesRegistry();
|
|
286
|
+
}
|
|
287
|
+
return registryInstance;
|
|
288
|
+
};
|
|
170
289
|
const networkRequestsRegistry = getNetworkRequestsRegistry();
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
290
|
+
const overridesRegistry$1 = getOverridesRegistry();
|
|
291
|
+
const getBinaryPostData = (body) => ({
|
|
292
|
+
type: "binary",
|
|
293
|
+
value: {
|
|
294
|
+
size: body.size,
|
|
295
|
+
type: body.type,
|
|
296
|
+
name: getBlobName(body)
|
|
177
297
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
298
|
+
});
|
|
299
|
+
const getArrayBufferPostData = (body) => ({
|
|
300
|
+
type: "binary",
|
|
301
|
+
value: {
|
|
302
|
+
size: body.byteLength
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
const getTextPostData = (body) => ({
|
|
306
|
+
type: "text",
|
|
307
|
+
value: safeStringify(body)
|
|
308
|
+
});
|
|
309
|
+
const getFormDataPostData = (body) => ({
|
|
310
|
+
type: "form-data",
|
|
311
|
+
value: getFormDataEntries(body).reduce(
|
|
312
|
+
(acc, [key, value]) => {
|
|
313
|
+
if (isBlob(value)) {
|
|
314
|
+
acc[key] = getBinaryPostData(value);
|
|
315
|
+
} else if (isArrayBuffer(value)) {
|
|
316
|
+
acc[key] = getArrayBufferPostData(value);
|
|
317
|
+
} else {
|
|
318
|
+
acc[key] = getTextPostData(value);
|
|
319
|
+
}
|
|
320
|
+
return acc;
|
|
321
|
+
},
|
|
322
|
+
{}
|
|
323
|
+
)
|
|
324
|
+
});
|
|
325
|
+
const getRequestBody = (body) => {
|
|
326
|
+
if (isNullOrUndefined(body)) {
|
|
327
|
+
return body;
|
|
328
|
+
}
|
|
329
|
+
if (isBlob(body)) {
|
|
330
|
+
return getBinaryPostData(body);
|
|
189
331
|
}
|
|
332
|
+
if (isArrayBuffer(body)) {
|
|
333
|
+
return getArrayBufferPostData(body);
|
|
334
|
+
}
|
|
335
|
+
if (isFormData(body)) {
|
|
336
|
+
return getFormDataPostData(body);
|
|
337
|
+
}
|
|
338
|
+
return getTextPostData(body);
|
|
190
339
|
};
|
|
191
340
|
const getResponseSize = (request) => {
|
|
192
|
-
|
|
193
|
-
|
|
341
|
+
try {
|
|
342
|
+
const { responseType, response } = request;
|
|
343
|
+
if (response === null) {
|
|
344
|
+
return 0;
|
|
345
|
+
}
|
|
346
|
+
if (responseType === "" || responseType === "text") {
|
|
347
|
+
return getStringSizeInBytes(request.responseText);
|
|
348
|
+
}
|
|
349
|
+
if (responseType === "json") {
|
|
350
|
+
return getStringSizeInBytes(safeStringify(response));
|
|
351
|
+
}
|
|
352
|
+
if (responseType === "blob") {
|
|
353
|
+
return response.size;
|
|
354
|
+
}
|
|
355
|
+
if (responseType === "arraybuffer") {
|
|
356
|
+
return response.byteLength;
|
|
357
|
+
}
|
|
358
|
+
return 0;
|
|
359
|
+
} catch {
|
|
360
|
+
return null;
|
|
194
361
|
}
|
|
195
|
-
return request.response.length || 0;
|
|
196
362
|
};
|
|
197
363
|
const getResponseBody = async (request) => {
|
|
198
364
|
const responseType = request.responseType;
|
|
199
|
-
if (responseType === "text") {
|
|
365
|
+
if (responseType === "" || responseType === "text") {
|
|
200
366
|
return request.responseText;
|
|
201
367
|
}
|
|
202
368
|
if (responseType === "blob") {
|
|
@@ -211,6 +377,9 @@ const getResponseBody = async (request) => {
|
|
|
211
377
|
});
|
|
212
378
|
}
|
|
213
379
|
}
|
|
380
|
+
if (responseType === "json") {
|
|
381
|
+
return safeStringify(request.response);
|
|
382
|
+
}
|
|
214
383
|
return null;
|
|
215
384
|
};
|
|
216
385
|
const getInitiatorFromStack = () => {
|
|
@@ -241,17 +410,18 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
241
410
|
const handleRequestSend = (data, request) => {
|
|
242
411
|
const sendTime = Date.now();
|
|
243
412
|
const requestId = generateRequestId();
|
|
413
|
+
request._rozeniteRequestId = requestId;
|
|
244
414
|
const initiator = getInitiatorFromStack();
|
|
245
415
|
networkRequestsRegistry.addEntry(requestId, request);
|
|
246
416
|
let ttfb = 0;
|
|
247
417
|
pluginClient.send("request-sent", {
|
|
248
418
|
requestId,
|
|
249
|
-
timestamp: sendTime
|
|
419
|
+
timestamp: sendTime,
|
|
250
420
|
request: {
|
|
251
421
|
url: request._url,
|
|
252
422
|
method: request._method,
|
|
253
423
|
headers: request._headers,
|
|
254
|
-
postData: data
|
|
424
|
+
postData: getRequestBody(data)
|
|
255
425
|
},
|
|
256
426
|
type: "XHR",
|
|
257
427
|
initiator
|
|
@@ -264,23 +434,25 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
264
434
|
request.addEventListener("load", () => {
|
|
265
435
|
pluginClient.send("response-received", {
|
|
266
436
|
requestId,
|
|
267
|
-
timestamp: Date.now()
|
|
437
|
+
timestamp: Date.now(),
|
|
268
438
|
type: "XHR",
|
|
269
439
|
response: {
|
|
270
440
|
url: request._url,
|
|
271
441
|
status: request.status,
|
|
272
442
|
statusText: request.statusText,
|
|
273
|
-
headers:
|
|
443
|
+
headers: applyReactNativeResponseHeadersLogic(
|
|
444
|
+
request.responseHeaders || {}
|
|
445
|
+
),
|
|
274
446
|
contentType: getContentType(request),
|
|
275
447
|
size: getResponseSize(request),
|
|
276
|
-
responseTime: Date.now()
|
|
448
|
+
responseTime: Date.now()
|
|
277
449
|
}
|
|
278
450
|
});
|
|
279
451
|
});
|
|
280
452
|
request.addEventListener("loadend", () => {
|
|
281
453
|
pluginClient.send("request-completed", {
|
|
282
454
|
requestId,
|
|
283
|
-
timestamp: Date.now()
|
|
455
|
+
timestamp: Date.now(),
|
|
284
456
|
duration: Date.now() - sendTime,
|
|
285
457
|
size: getResponseSize(request),
|
|
286
458
|
ttfb
|
|
@@ -289,7 +461,7 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
289
461
|
request.addEventListener("error", () => {
|
|
290
462
|
pluginClient.send("request-failed", {
|
|
291
463
|
requestId,
|
|
292
|
-
timestamp: Date.now()
|
|
464
|
+
timestamp: Date.now(),
|
|
293
465
|
type: "XHR",
|
|
294
466
|
error: "Failed",
|
|
295
467
|
canceled: false
|
|
@@ -298,16 +470,52 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
298
470
|
request.addEventListener("abort", () => {
|
|
299
471
|
pluginClient.send("request-failed", {
|
|
300
472
|
requestId,
|
|
301
|
-
timestamp: Date.now()
|
|
473
|
+
timestamp: Date.now(),
|
|
302
474
|
type: "XHR",
|
|
303
475
|
error: "Aborted",
|
|
304
476
|
canceled: true
|
|
305
477
|
});
|
|
306
478
|
});
|
|
307
479
|
};
|
|
480
|
+
const handleRequestOverride = (request) => {
|
|
481
|
+
const override = overridesRegistry$1.getOverrideForUrl(
|
|
482
|
+
request._url
|
|
483
|
+
);
|
|
484
|
+
if (!override) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
request.addEventListener("readystatechange", () => {
|
|
488
|
+
if (override.body !== void 0) {
|
|
489
|
+
Object.defineProperty(request, "responseType", {
|
|
490
|
+
writable: true
|
|
491
|
+
});
|
|
492
|
+
Object.defineProperty(request, "response", {
|
|
493
|
+
writable: true
|
|
494
|
+
});
|
|
495
|
+
Object.defineProperty(request, "responseText", {
|
|
496
|
+
writable: true
|
|
497
|
+
});
|
|
498
|
+
const contentType = getContentType(request);
|
|
499
|
+
if (contentType === "application/json") {
|
|
500
|
+
request.responseType = "json";
|
|
501
|
+
} else if (contentType === "text/plain") {
|
|
502
|
+
request.responseType = "text";
|
|
503
|
+
}
|
|
504
|
+
request.response = override.body;
|
|
505
|
+
request.responseText = override.body;
|
|
506
|
+
}
|
|
507
|
+
if (override.status !== void 0) {
|
|
508
|
+
Object.defineProperty(request, "status", {
|
|
509
|
+
writable: true
|
|
510
|
+
});
|
|
511
|
+
request.status = override.status;
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
};
|
|
308
515
|
const enable = () => {
|
|
309
516
|
XHRInterceptor.disableInterception();
|
|
310
517
|
XHRInterceptor.setSendCallback(handleRequestSend);
|
|
518
|
+
XHRInterceptor.setOverrideCallback(handleRequestOverride);
|
|
311
519
|
XHRInterceptor.enableInterception();
|
|
312
520
|
};
|
|
313
521
|
const disable = () => {
|
|
@@ -350,19 +558,493 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
350
558
|
dispose
|
|
351
559
|
};
|
|
352
560
|
};
|
|
353
|
-
const
|
|
561
|
+
const getWebSocketInterceptor = () => {
|
|
562
|
+
if (Platform.constants.reactNativeVersion.minor >= 79) {
|
|
563
|
+
return WebSocketInterceptor;
|
|
564
|
+
} else {
|
|
565
|
+
const WebSocketInterceptorPreRN079 = WebSocketInterceptor;
|
|
566
|
+
return {
|
|
567
|
+
...WebSocketInterceptorPreRN079,
|
|
568
|
+
setOnMessageCallback: (callback) => {
|
|
569
|
+
WebSocketInterceptorPreRN079.setOnMessageCallback((socketId, data) => {
|
|
570
|
+
callback(data, socketId);
|
|
571
|
+
});
|
|
572
|
+
},
|
|
573
|
+
setOnCloseCallback: (callback) => {
|
|
574
|
+
WebSocketInterceptorPreRN079.setOnCloseCallback((error, socketId) => {
|
|
575
|
+
callback(socketId, error);
|
|
576
|
+
});
|
|
577
|
+
},
|
|
578
|
+
setOnErrorCallback: (callback) => {
|
|
579
|
+
WebSocketInterceptorPreRN079.setOnErrorCallback((error, socketId) => {
|
|
580
|
+
callback(socketId, error);
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const getWebSocketInspector = () => {
|
|
587
|
+
const eventEmitter = createNanoEvents();
|
|
588
|
+
const socketUrlMap = /* @__PURE__ */ new Map();
|
|
589
|
+
const webSocketInterceptor = getWebSocketInterceptor();
|
|
590
|
+
return {
|
|
591
|
+
enable: () => {
|
|
592
|
+
webSocketInterceptor.setConnectCallback(
|
|
593
|
+
(url, protocols, options, socketId) => {
|
|
594
|
+
socketUrlMap.set(socketId, url);
|
|
595
|
+
const event = {
|
|
596
|
+
type: "websocket-connect",
|
|
597
|
+
url,
|
|
598
|
+
socketId,
|
|
599
|
+
timestamp: Date.now(),
|
|
600
|
+
protocols,
|
|
601
|
+
options
|
|
602
|
+
};
|
|
603
|
+
eventEmitter.emit("websocket-connect", event);
|
|
604
|
+
}
|
|
605
|
+
);
|
|
606
|
+
webSocketInterceptor.setCloseCallback(
|
|
607
|
+
(code, reason, socketId) => {
|
|
608
|
+
const url = socketUrlMap.get(socketId);
|
|
609
|
+
if (!url) {
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
const event = {
|
|
613
|
+
type: "websocket-close",
|
|
614
|
+
url,
|
|
615
|
+
socketId,
|
|
616
|
+
timestamp: Date.now(),
|
|
617
|
+
code: code || 0,
|
|
618
|
+
reason: reason || void 0
|
|
619
|
+
};
|
|
620
|
+
eventEmitter.emit("websocket-close", event);
|
|
621
|
+
socketUrlMap.delete(socketId);
|
|
622
|
+
}
|
|
623
|
+
);
|
|
624
|
+
webSocketInterceptor.setOnMessageCallback(
|
|
625
|
+
(data, socketId) => {
|
|
626
|
+
const url = socketUrlMap.get(socketId);
|
|
627
|
+
if (!url) {
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
const event = {
|
|
631
|
+
type: "websocket-message-received",
|
|
632
|
+
url,
|
|
633
|
+
socketId,
|
|
634
|
+
timestamp: Date.now(),
|
|
635
|
+
data,
|
|
636
|
+
messageType: typeof data === "string" ? "text" : "binary"
|
|
637
|
+
};
|
|
638
|
+
eventEmitter.emit("websocket-message-received", event);
|
|
639
|
+
}
|
|
640
|
+
);
|
|
641
|
+
webSocketInterceptor.setOnErrorCallback(
|
|
642
|
+
(error, socketId) => {
|
|
643
|
+
const url = socketUrlMap.get(socketId);
|
|
644
|
+
if (!url) {
|
|
645
|
+
return;
|
|
646
|
+
}
|
|
647
|
+
const event = {
|
|
648
|
+
type: "websocket-error",
|
|
649
|
+
url,
|
|
650
|
+
socketId,
|
|
651
|
+
timestamp: Date.now(),
|
|
652
|
+
error
|
|
653
|
+
};
|
|
654
|
+
eventEmitter.emit("websocket-error", event);
|
|
655
|
+
}
|
|
656
|
+
);
|
|
657
|
+
webSocketInterceptor.setSendCallback((data, socketId) => {
|
|
658
|
+
const url = socketUrlMap.get(socketId);
|
|
659
|
+
if (!url) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
const event = {
|
|
663
|
+
type: "websocket-message-sent",
|
|
664
|
+
url,
|
|
665
|
+
socketId,
|
|
666
|
+
timestamp: Date.now(),
|
|
667
|
+
data,
|
|
668
|
+
messageType: typeof data === "string" ? "text" : "binary"
|
|
669
|
+
};
|
|
670
|
+
eventEmitter.emit("websocket-message-sent", event);
|
|
671
|
+
});
|
|
672
|
+
webSocketInterceptor.setOnOpenCallback((socketId) => {
|
|
673
|
+
const url = socketUrlMap.get(socketId);
|
|
674
|
+
if (!url) {
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
677
|
+
const event = {
|
|
678
|
+
type: "websocket-open",
|
|
679
|
+
url,
|
|
680
|
+
socketId,
|
|
681
|
+
timestamp: Date.now()
|
|
682
|
+
};
|
|
683
|
+
eventEmitter.emit("websocket-open", event);
|
|
684
|
+
});
|
|
685
|
+
webSocketInterceptor.setOnCloseCallback(
|
|
686
|
+
(error, socketId) => {
|
|
687
|
+
const url = socketUrlMap.get(socketId);
|
|
688
|
+
if (!url) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
const event = {
|
|
692
|
+
type: "websocket-close",
|
|
693
|
+
url,
|
|
694
|
+
socketId,
|
|
695
|
+
timestamp: Date.now(),
|
|
696
|
+
code: error.code,
|
|
697
|
+
reason: error.reason
|
|
698
|
+
};
|
|
699
|
+
eventEmitter.emit("websocket-close", event);
|
|
700
|
+
socketUrlMap.delete(socketId);
|
|
701
|
+
}
|
|
702
|
+
);
|
|
703
|
+
webSocketInterceptor.enableInterception();
|
|
704
|
+
},
|
|
705
|
+
disable: () => {
|
|
706
|
+
webSocketInterceptor.disableInterception();
|
|
707
|
+
},
|
|
708
|
+
isEnabled: () => webSocketInterceptor.isInterceptorEnabled(),
|
|
709
|
+
dispose: () => {
|
|
710
|
+
eventEmitter.events = {};
|
|
711
|
+
socketUrlMap.clear();
|
|
712
|
+
},
|
|
713
|
+
on: (event, callback) => eventEmitter.on(event, callback)
|
|
714
|
+
};
|
|
715
|
+
};
|
|
716
|
+
let connectCallback;
|
|
717
|
+
let messageCallback;
|
|
718
|
+
let errorCallback;
|
|
719
|
+
let openEventCallback;
|
|
720
|
+
let closeCallback;
|
|
721
|
+
let isInterceptorEnabled = false;
|
|
722
|
+
const eventSourceClass = getEventSource();
|
|
723
|
+
const originalOpen = eventSourceClass.prototype.open;
|
|
724
|
+
const originalDispatch = eventSourceClass.prototype.dispatch;
|
|
725
|
+
const BUILT_IN_EVENT_TYPES = /* @__PURE__ */ new Set(["open", "error", "close", "done"]);
|
|
726
|
+
const SSEInterceptor = {
|
|
727
|
+
/**
|
|
728
|
+
* Invoked when EventSource.open() is called (connection attempt starting).
|
|
729
|
+
*/
|
|
730
|
+
setConnectCallback(callback) {
|
|
731
|
+
connectCallback = callback;
|
|
732
|
+
},
|
|
733
|
+
/**
|
|
734
|
+
* Invoked when a message event is received.
|
|
735
|
+
*/
|
|
736
|
+
setMessageCallback(callback) {
|
|
737
|
+
messageCallback = callback;
|
|
738
|
+
},
|
|
739
|
+
/**
|
|
740
|
+
* Invoked when an error event occurs.
|
|
741
|
+
*/
|
|
742
|
+
setErrorCallback(callback) {
|
|
743
|
+
errorCallback = callback;
|
|
744
|
+
},
|
|
745
|
+
/**
|
|
746
|
+
* Invoked when the connection is successfully opened (open event fired).
|
|
747
|
+
*/
|
|
748
|
+
setOpenEventCallback(callback) {
|
|
749
|
+
openEventCallback = callback;
|
|
750
|
+
},
|
|
751
|
+
/**
|
|
752
|
+
* Invoked when the connection is closed.
|
|
753
|
+
*/
|
|
754
|
+
setCloseCallback(callback) {
|
|
755
|
+
closeCallback = callback;
|
|
756
|
+
},
|
|
757
|
+
isInterceptorEnabled() {
|
|
758
|
+
return isInterceptorEnabled;
|
|
759
|
+
},
|
|
760
|
+
enableInterception() {
|
|
761
|
+
if (isInterceptorEnabled) {
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
eventSourceClass.prototype.open = function() {
|
|
765
|
+
if (connectCallback) {
|
|
766
|
+
connectCallback(this.url, this);
|
|
767
|
+
}
|
|
768
|
+
this.addEventListener("open", (event) => {
|
|
769
|
+
if (openEventCallback) {
|
|
770
|
+
openEventCallback(event, this);
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
this.addEventListener(
|
|
774
|
+
"error",
|
|
775
|
+
(event) => {
|
|
776
|
+
if (errorCallback) {
|
|
777
|
+
errorCallback(event, this);
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
);
|
|
781
|
+
this.addEventListener("close", (event) => {
|
|
782
|
+
if (closeCallback) {
|
|
783
|
+
closeCallback(event, this);
|
|
784
|
+
}
|
|
785
|
+
});
|
|
786
|
+
return originalOpen.call(this);
|
|
787
|
+
};
|
|
788
|
+
eventSourceClass.prototype.dispatch = function(eventType, data) {
|
|
789
|
+
if (!BUILT_IN_EVENT_TYPES.has(eventType)) {
|
|
790
|
+
if (messageCallback) {
|
|
791
|
+
messageCallback(data, this);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return originalDispatch.call(this, eventType, data);
|
|
795
|
+
};
|
|
796
|
+
isInterceptorEnabled = true;
|
|
797
|
+
},
|
|
798
|
+
// Unpatch EventSource open method and remove the callbacks.
|
|
799
|
+
disableInterception() {
|
|
800
|
+
if (!isInterceptorEnabled) {
|
|
801
|
+
return;
|
|
802
|
+
}
|
|
803
|
+
isInterceptorEnabled = false;
|
|
804
|
+
eventSourceClass.prototype.open = originalOpen;
|
|
805
|
+
eventSourceClass.prototype.dispatch = originalDispatch;
|
|
806
|
+
connectCallback = null;
|
|
807
|
+
messageCallback = null;
|
|
808
|
+
errorCallback = null;
|
|
809
|
+
openEventCallback = null;
|
|
810
|
+
closeCallback = null;
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
const getSSEInspector = () => {
|
|
814
|
+
const eventEmitter = createNanoEvents();
|
|
815
|
+
const getRequestId = (eventSource) => {
|
|
816
|
+
var _a;
|
|
817
|
+
const requestId = (_a = eventSource._xhr) == null ? void 0 : _a._rozeniteRequestId;
|
|
818
|
+
if (!requestId) {
|
|
819
|
+
return null;
|
|
820
|
+
}
|
|
821
|
+
return requestId;
|
|
822
|
+
};
|
|
823
|
+
return {
|
|
824
|
+
enable: () => {
|
|
825
|
+
SSEInterceptor.setOpenEventCallback((_, eventSource) => {
|
|
826
|
+
const sseEventSource = eventSource;
|
|
827
|
+
const requestId = getRequestId(sseEventSource);
|
|
828
|
+
if (!requestId) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
const sseXhr = sseEventSource._xhr;
|
|
832
|
+
const event = {
|
|
833
|
+
type: "sse-open",
|
|
834
|
+
requestId,
|
|
835
|
+
timestamp: Date.now(),
|
|
836
|
+
response: {
|
|
837
|
+
url: sseXhr._url,
|
|
838
|
+
status: sseXhr.status,
|
|
839
|
+
statusText: sseXhr.statusText,
|
|
840
|
+
headers: sseXhr.responseHeaders || {},
|
|
841
|
+
contentType: getContentType(sseXhr),
|
|
842
|
+
size: 0,
|
|
843
|
+
responseTime: Date.now()
|
|
844
|
+
}
|
|
845
|
+
};
|
|
846
|
+
eventEmitter.emit("sse-open", event);
|
|
847
|
+
});
|
|
848
|
+
SSEInterceptor.setMessageCallback((messageEvent, eventSource) => {
|
|
849
|
+
const sseEventSource = eventSource;
|
|
850
|
+
const requestId = getRequestId(sseEventSource);
|
|
851
|
+
if (!requestId) {
|
|
852
|
+
return;
|
|
853
|
+
}
|
|
854
|
+
const event = {
|
|
855
|
+
type: "sse-message",
|
|
856
|
+
requestId,
|
|
857
|
+
timestamp: Date.now(),
|
|
858
|
+
payload: {
|
|
859
|
+
type: messageEvent.type,
|
|
860
|
+
data: messageEvent.data || ""
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
eventEmitter.emit("sse-message", event);
|
|
864
|
+
});
|
|
865
|
+
SSEInterceptor.setErrorCallback((errorEvent, eventSource) => {
|
|
866
|
+
const sseEventSource = eventSource;
|
|
867
|
+
const requestId = getRequestId(sseEventSource);
|
|
868
|
+
if (!requestId) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const event = {
|
|
872
|
+
type: "sse-error",
|
|
873
|
+
requestId,
|
|
874
|
+
timestamp: Date.now(),
|
|
875
|
+
error: {
|
|
876
|
+
type: errorEvent.type,
|
|
877
|
+
message: errorEvent.type === "timeout" ? "Timeout" : errorEvent.message
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
eventEmitter.emit("sse-error", event);
|
|
881
|
+
});
|
|
882
|
+
SSEInterceptor.setCloseCallback((_, eventSource) => {
|
|
883
|
+
const sseEventSource = eventSource;
|
|
884
|
+
const requestId = getRequestId(sseEventSource);
|
|
885
|
+
if (!requestId) {
|
|
886
|
+
return;
|
|
887
|
+
}
|
|
888
|
+
const event = {
|
|
889
|
+
type: "sse-close",
|
|
890
|
+
requestId,
|
|
891
|
+
timestamp: Date.now()
|
|
892
|
+
};
|
|
893
|
+
eventEmitter.emit("sse-close", event);
|
|
894
|
+
});
|
|
895
|
+
SSEInterceptor.enableInterception();
|
|
896
|
+
},
|
|
897
|
+
disable: () => {
|
|
898
|
+
SSEInterceptor.disableInterception();
|
|
899
|
+
},
|
|
900
|
+
isEnabled: () => SSEInterceptor.isInterceptorEnabled(),
|
|
901
|
+
dispose: () => {
|
|
902
|
+
SSEInterceptor.disableInterception();
|
|
903
|
+
eventEmitter.events = {};
|
|
904
|
+
},
|
|
905
|
+
on: (event, callback) => eventEmitter.on(event, callback)
|
|
906
|
+
};
|
|
907
|
+
};
|
|
908
|
+
const DEFAULT_CONFIG = {
|
|
909
|
+
inspectors: {
|
|
910
|
+
http: true,
|
|
911
|
+
websocket: true,
|
|
912
|
+
sse: true
|
|
913
|
+
},
|
|
914
|
+
clientUISettings: {
|
|
915
|
+
showUrlAsName: false
|
|
916
|
+
}
|
|
917
|
+
};
|
|
918
|
+
const validateConfig = (config) => {
|
|
919
|
+
const inspectors = config.inspectors;
|
|
920
|
+
if (!inspectors) {
|
|
921
|
+
return;
|
|
922
|
+
}
|
|
923
|
+
if (inspectors.sse && !inspectors.http) {
|
|
924
|
+
throw new Error("SSE inspector requires HTTP inspector to be enabled.");
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
const overridesRegistry = getOverridesRegistry();
|
|
928
|
+
const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
|
|
929
|
+
var _a, _b, _c, _d;
|
|
930
|
+
const isRecordingEnabledRef = useRef(false);
|
|
354
931
|
const client = useRozeniteDevToolsClient({
|
|
355
932
|
pluginId: "@rozenite/network-activity-plugin"
|
|
356
933
|
});
|
|
934
|
+
const isHttpInspectorEnabled = ((_a = config.inspectors) == null ? void 0 : _a.http) ?? true;
|
|
935
|
+
const isWebSocketInspectorEnabled = ((_b = config.inspectors) == null ? void 0 : _b.websocket) ?? true;
|
|
936
|
+
const isSSEInspectorEnabled = ((_c = config.inspectors) == null ? void 0 : _c.sse) ?? true;
|
|
937
|
+
const showUrlAsName = (_d = config.clientUISettings) == null ? void 0 : _d.showUrlAsName;
|
|
357
938
|
useEffect(() => {
|
|
358
939
|
if (!client) {
|
|
359
940
|
return;
|
|
360
941
|
}
|
|
942
|
+
validateConfig(config);
|
|
943
|
+
}, [config]);
|
|
944
|
+
useEffect(() => {
|
|
945
|
+
if (!client) {
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const sendClientUISettings = () => {
|
|
949
|
+
var _a2;
|
|
950
|
+
client.send("client-ui-settings", {
|
|
951
|
+
settings: {
|
|
952
|
+
showUrlAsName: showUrlAsName ?? ((_a2 = DEFAULT_CONFIG.clientUISettings) == null ? void 0 : _a2.showUrlAsName)
|
|
953
|
+
}
|
|
954
|
+
});
|
|
955
|
+
};
|
|
956
|
+
const subscriptions = [
|
|
957
|
+
client.onMessage("network-enable", () => {
|
|
958
|
+
isRecordingEnabledRef.current = true;
|
|
959
|
+
}),
|
|
960
|
+
client.onMessage("network-disable", () => {
|
|
961
|
+
isRecordingEnabledRef.current = false;
|
|
962
|
+
}),
|
|
963
|
+
client.onMessage("set-overrides", (data) => {
|
|
964
|
+
overridesRegistry.setOverrides(data.overrides);
|
|
965
|
+
}),
|
|
966
|
+
client.onMessage("get-client-ui-settings", () => {
|
|
967
|
+
sendClientUISettings();
|
|
968
|
+
})
|
|
969
|
+
];
|
|
970
|
+
sendClientUISettings();
|
|
971
|
+
return () => {
|
|
972
|
+
subscriptions.forEach((subscription) => subscription.remove());
|
|
973
|
+
};
|
|
974
|
+
}, [client, showUrlAsName]);
|
|
975
|
+
useEffect(() => {
|
|
976
|
+
if (!client || !isHttpInspectorEnabled) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
361
979
|
const networkInspector = getNetworkInspector(client);
|
|
980
|
+
if (isRecordingEnabledRef.current) {
|
|
981
|
+
networkInspector.enable();
|
|
982
|
+
}
|
|
362
983
|
return () => {
|
|
363
984
|
networkInspector.dispose();
|
|
364
985
|
};
|
|
365
|
-
}, [client]);
|
|
986
|
+
}, [client, isHttpInspectorEnabled]);
|
|
987
|
+
useEffect(() => {
|
|
988
|
+
if (!client || !isWebSocketInspectorEnabled) {
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
const eventsToForward = [
|
|
992
|
+
"websocket-connect",
|
|
993
|
+
"websocket-open",
|
|
994
|
+
"websocket-close",
|
|
995
|
+
"websocket-message-sent",
|
|
996
|
+
"websocket-message-received",
|
|
997
|
+
"websocket-error",
|
|
998
|
+
"websocket-connection-status-changed"
|
|
999
|
+
];
|
|
1000
|
+
const websocketInspector = getWebSocketInspector();
|
|
1001
|
+
eventsToForward.forEach((event) => {
|
|
1002
|
+
websocketInspector.on(event, (event2) => {
|
|
1003
|
+
client.send(event2.type, event2);
|
|
1004
|
+
});
|
|
1005
|
+
});
|
|
1006
|
+
client.onMessage("network-enable", () => {
|
|
1007
|
+
websocketInspector.enable();
|
|
1008
|
+
});
|
|
1009
|
+
client.onMessage("network-disable", () => {
|
|
1010
|
+
websocketInspector.disable();
|
|
1011
|
+
});
|
|
1012
|
+
if (isRecordingEnabledRef.current) {
|
|
1013
|
+
websocketInspector.enable();
|
|
1014
|
+
}
|
|
1015
|
+
return () => {
|
|
1016
|
+
websocketInspector.dispose();
|
|
1017
|
+
};
|
|
1018
|
+
}, [client, isWebSocketInspectorEnabled]);
|
|
1019
|
+
useEffect(() => {
|
|
1020
|
+
if (!client || !isSSEInspectorEnabled) {
|
|
1021
|
+
return;
|
|
1022
|
+
}
|
|
1023
|
+
const eventsToForward = [
|
|
1024
|
+
"sse-open",
|
|
1025
|
+
"sse-message",
|
|
1026
|
+
"sse-error",
|
|
1027
|
+
"sse-close"
|
|
1028
|
+
];
|
|
1029
|
+
const sseInspector = getSSEInspector();
|
|
1030
|
+
eventsToForward.forEach((event) => {
|
|
1031
|
+
sseInspector.on(event, (event2) => {
|
|
1032
|
+
client.send(event2.type, event2);
|
|
1033
|
+
});
|
|
1034
|
+
});
|
|
1035
|
+
client.onMessage("network-enable", () => {
|
|
1036
|
+
sseInspector.enable();
|
|
1037
|
+
});
|
|
1038
|
+
client.onMessage("network-disable", () => {
|
|
1039
|
+
sseInspector.disable();
|
|
1040
|
+
});
|
|
1041
|
+
if (isRecordingEnabledRef.current) {
|
|
1042
|
+
sseInspector.enable();
|
|
1043
|
+
}
|
|
1044
|
+
return () => {
|
|
1045
|
+
sseInspector.dispose();
|
|
1046
|
+
};
|
|
1047
|
+
}, [client, isSSEInspectorEnabled]);
|
|
366
1048
|
return client;
|
|
367
1049
|
};
|
|
368
1050
|
export {
|