@rozenite/network-activity-plugin 1.0.0-alpha.15 → 1.0.0-alpha.16
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/dist/App.html +2 -2
- package/dist/assets/{App-CfJuBHc_.css → App-BrSkOkws.css} +21 -0
- package/dist/assets/{App-CZPlDq_M.js → App-CM3Ub2ZA.js} +911 -479
- package/dist/rozenite.json +1 -1
- package/dist/src/react-native/http/overrides-registry.d.ts +6 -0
- package/dist/src/react-native/http/xhr-interceptor.d.ts +5 -0
- package/dist/src/shared/client.d.ts +7 -0
- package/dist/src/ui/components/CodeEditor.d.ts +5 -0
- package/dist/src/ui/components/OverrideResponse.d.ts +8 -0
- package/dist/src/ui/components/RequestList.d.ts +3 -2
- package/dist/src/ui/components/Section.d.ts +2 -1
- package/dist/src/ui/state/hooks.d.ts +3 -0
- package/dist/src/ui/state/store.d.ts +26 -3
- package/dist/useNetworkActivityDevTools.cjs +72 -0
- package/dist/useNetworkActivityDevTools.js +72 -0
- package/package.json +4 -4
- package/src/react-native/http/network-inspector.ts +50 -0
- package/src/react-native/http/overrides-registry.ts +32 -0
- package/src/react-native/http/xhr-interceptor.ts +14 -0
- package/src/react-native/useNetworkActivityDevTools.ts +6 -0
- package/src/shared/client.ts +9 -0
- package/src/ui/components/CodeEditor.tsx +26 -0
- package/src/ui/components/OverrideResponse.tsx +132 -0
- package/src/ui/components/RequestList.tsx +15 -8
- package/src/ui/components/Section.tsx +5 -1
- package/src/ui/components/SidePanel.tsx +8 -0
- package/src/ui/state/hooks.ts +4 -0
- package/src/ui/state/store.ts +585 -502
- package/src/ui/tabs/ResponseTab.tsx +60 -12
- package/src/ui/views/InspectorView.tsx +7 -1
package/dist/rozenite.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@rozenite/network-activity-plugin","version":"1.0.0-alpha.
|
|
1
|
+
{"name":"@rozenite/network-activity-plugin","version":"1.0.0-alpha.15","description":"Network Activity for Rozenite.","panels":[{"name":"Network Activity","source":"/App.html"}]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { RequestOverride } from '../../shared/client';
|
|
2
|
+
export type OverridesRegistry = {
|
|
3
|
+
setOverrides: (newOverrides: [string, RequestOverride][]) => void;
|
|
4
|
+
getOverrideForUrl: (url: string) => RequestOverride | undefined;
|
|
5
|
+
};
|
|
6
|
+
export declare const getOverridesRegistry: () => OverridesRegistry;
|
|
@@ -4,6 +4,7 @@ type XHRInterceptorSendCallback = (data: XHRPostData, request: XMLHttpRequest) =
|
|
|
4
4
|
type XHRInterceptorRequestHeaderCallback = (header: string, value: string, request: XMLHttpRequest) => void;
|
|
5
5
|
type XHRInterceptorHeaderReceivedCallback = (responseContentType: string | undefined, responseSize: number | undefined, allHeaders: string, request: XMLHttpRequest) => void;
|
|
6
6
|
type XHRInterceptorResponseCallback = (status: number, timeout: number, response: string, responseURL: string, responseType: string, request: XMLHttpRequest) => void;
|
|
7
|
+
type XHRInterceptorOverrideCallback = (request: XMLHttpRequest) => void;
|
|
7
8
|
/**
|
|
8
9
|
* A network interceptor which monkey-patches XMLHttpRequest methods
|
|
9
10
|
* to gather all network requests/responses, in order to show their
|
|
@@ -32,6 +33,10 @@ export declare const XHRInterceptor: {
|
|
|
32
33
|
* Invoked before XMLHttpRequest.setRequestHeader(...) is called.
|
|
33
34
|
*/
|
|
34
35
|
setRequestHeaderCallback(callback: XHRInterceptorRequestHeaderCallback): void;
|
|
36
|
+
/**
|
|
37
|
+
* Invoked before XMLHttpRequest.send(...) is called.
|
|
38
|
+
*/
|
|
39
|
+
setOverrideCallback(callback: XHRInterceptorOverrideCallback): void;
|
|
35
40
|
isInterceptorEnabled(): boolean;
|
|
36
41
|
enableInterception(): void;
|
|
37
42
|
disableInterception(): void;
|
|
@@ -57,6 +57,10 @@ export type Initiator = {
|
|
|
57
57
|
columnNumber?: number;
|
|
58
58
|
};
|
|
59
59
|
export type ResourceType = 'XHR' | 'Fetch' | 'Other';
|
|
60
|
+
export type RequestOverride = {
|
|
61
|
+
status?: number;
|
|
62
|
+
body?: string;
|
|
63
|
+
};
|
|
60
64
|
export type NetworkActivityEventMap = {
|
|
61
65
|
'network-enable': unknown;
|
|
62
66
|
'network-disable': unknown;
|
|
@@ -94,5 +98,8 @@ export type NetworkActivityEventMap = {
|
|
|
94
98
|
requestId: RequestId;
|
|
95
99
|
body: string | null;
|
|
96
100
|
};
|
|
101
|
+
'set-overrides': {
|
|
102
|
+
overrides: [string, RequestOverride][];
|
|
103
|
+
};
|
|
97
104
|
} & WebSocketEventMap & SSEEventMap;
|
|
98
105
|
export type NetworkActivityDevToolsClient = RozeniteDevToolsClient<NetworkActivityEventMap>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { HttpNetworkEntry } from '../state/model';
|
|
2
|
+
import { RequestOverride } from '../../shared/client';
|
|
3
|
+
export type OverrideResponseProps = {
|
|
4
|
+
selectedRequest: HttpNetworkEntry;
|
|
5
|
+
initialOverride: RequestOverride | undefined;
|
|
6
|
+
onClear: () => void;
|
|
7
|
+
};
|
|
8
|
+
export declare const OverrideResponse: ({ selectedRequest, initialOverride, onClear, }: OverrideResponseProps) => import("react/jsx-runtime").JSX.Element | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ProcessedRequest } from '../state/model';
|
|
2
|
-
import { RequestId } from '../../shared/client';
|
|
2
|
+
import { RequestId, RequestOverride } from '../../shared/client';
|
|
3
3
|
import { FilterState } from './FilterBar';
|
|
4
4
|
type NetworkRequest = {
|
|
5
5
|
id: RequestId;
|
|
@@ -12,6 +12,7 @@ type NetworkRequest = {
|
|
|
12
12
|
time: string;
|
|
13
13
|
type: string;
|
|
14
14
|
startTime: string;
|
|
15
|
+
hasOverride: boolean;
|
|
15
16
|
};
|
|
16
17
|
declare const formatSize: (bytes: number) => string;
|
|
17
18
|
declare const formatDuration: (duration: number) => string;
|
|
@@ -21,7 +22,7 @@ declare const extractDomainAndPath: (url: string) => {
|
|
|
21
22
|
path: string;
|
|
22
23
|
};
|
|
23
24
|
declare const generateName: (url: string) => string;
|
|
24
|
-
declare const processNetworkRequests: (processedRequests: ProcessedRequest[]) => NetworkRequest[];
|
|
25
|
+
declare const processNetworkRequests: (processedRequests: ProcessedRequest[], overrides: Map<string, RequestOverride>) => NetworkRequest[];
|
|
25
26
|
export type RequestListProps = {
|
|
26
27
|
filter: FilterState;
|
|
27
28
|
};
|
|
@@ -3,5 +3,6 @@ export type SectionProps = {
|
|
|
3
3
|
title: string;
|
|
4
4
|
children: React.ReactNode;
|
|
5
5
|
collapsible?: boolean;
|
|
6
|
+
action?: React.ReactNode;
|
|
6
7
|
};
|
|
7
|
-
export declare const Section: ({ title, children, collapsible, }: SectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare const Section: ({ title, children, collapsible, action, }: SectionProps) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -9,9 +9,12 @@ export declare const useNetworkActivityActions: () => {
|
|
|
9
9
|
setRecording: (isRecording: boolean) => void;
|
|
10
10
|
setSelectedRequest: (requestId: import('../../shared/client').RequestId | null) => void;
|
|
11
11
|
clearRequests: () => void;
|
|
12
|
+
addOverride: (requestUrl: string, override: import('../../shared/client').RequestOverride) => void;
|
|
13
|
+
clearOverride: (requestUrl: string) => void;
|
|
12
14
|
};
|
|
13
15
|
export declare const useNetworkActivityClientManagement: () => {
|
|
14
16
|
setupClient: (client: import('../../shared/client').NetworkActivityDevToolsClient) => void;
|
|
15
17
|
cleanupClient: () => void;
|
|
16
18
|
};
|
|
17
19
|
export declare const useWebSocketMessages: (requestId: string) => import('./model').WebSocketMessage[];
|
|
20
|
+
export declare const useOverrides: () => Map<string, import('../../shared/client').RequestOverride>;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { NetworkActivityDevToolsClient, NetworkActivityEventMap, RequestId } from '../../shared/client';
|
|
1
|
+
import { NetworkActivityDevToolsClient, NetworkActivityEventMap, RequestOverride, RequestId } from '../../shared/client';
|
|
2
2
|
import { NetworkEntry, WebSocketMessage } from './model';
|
|
3
3
|
export interface NetworkActivityState {
|
|
4
4
|
isRecording: boolean;
|
|
5
5
|
selectedRequestId: RequestId | null;
|
|
6
6
|
networkEntries: Map<RequestId, NetworkEntry>;
|
|
7
7
|
websocketMessages: Map<RequestId, WebSocketMessage[]>;
|
|
8
|
+
overrides: Map<string, RequestOverride>;
|
|
8
9
|
_unsubscribeFunctions?: Array<{
|
|
9
10
|
remove: () => void;
|
|
10
11
|
}>;
|
|
@@ -13,6 +14,8 @@ export interface NetworkActivityState {
|
|
|
13
14
|
setRecording: (isRecording: boolean) => void;
|
|
14
15
|
setSelectedRequest: (requestId: RequestId | null) => void;
|
|
15
16
|
clearRequests: () => void;
|
|
17
|
+
addOverride: (requestUrl: string, override: RequestOverride) => void;
|
|
18
|
+
clearOverride: (requestUrl: string) => void;
|
|
16
19
|
};
|
|
17
20
|
handleEvent: <K extends keyof NetworkActivityEventMap>(eventType: K, data: NetworkActivityEventMap[K]) => void;
|
|
18
21
|
client: {
|
|
@@ -20,5 +23,25 @@ export interface NetworkActivityState {
|
|
|
20
23
|
cleanupClient: () => void;
|
|
21
24
|
};
|
|
22
25
|
}
|
|
23
|
-
export declare const createNetworkActivityStore: () => import('zustand').StoreApi<NetworkActivityState
|
|
24
|
-
|
|
26
|
+
export declare const createNetworkActivityStore: () => Omit<import('zustand').StoreApi<NetworkActivityState>, "persist"> & {
|
|
27
|
+
persist: {
|
|
28
|
+
setOptions: (options: Partial<import('zustand/middleware').PersistOptions<NetworkActivityState, unknown>>) => void;
|
|
29
|
+
clearStorage: () => void;
|
|
30
|
+
rehydrate: () => Promise<void> | void;
|
|
31
|
+
hasHydrated: () => boolean;
|
|
32
|
+
onHydrate: (fn: (state: NetworkActivityState) => void) => () => void;
|
|
33
|
+
onFinishHydration: (fn: (state: NetworkActivityState) => void) => () => void;
|
|
34
|
+
getOptions: () => Partial<import('zustand/middleware').PersistOptions<NetworkActivityState, unknown>>;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export declare const store: Omit<import('zustand').StoreApi<NetworkActivityState>, "persist"> & {
|
|
38
|
+
persist: {
|
|
39
|
+
setOptions: (options: Partial<import('zustand/middleware').PersistOptions<NetworkActivityState, unknown>>) => void;
|
|
40
|
+
clearStorage: () => void;
|
|
41
|
+
rehydrate: () => Promise<void> | void;
|
|
42
|
+
hasHydrated: () => boolean;
|
|
43
|
+
onHydrate: (fn: (state: NetworkActivityState) => void) => () => void;
|
|
44
|
+
onFinishHydration: (fn: (state: NetworkActivityState) => void) => () => void;
|
|
45
|
+
getOptions: () => Partial<import('zustand/middleware').PersistOptions<NetworkActivityState, unknown>>;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -116,6 +116,7 @@ let sendCallback;
|
|
|
116
116
|
let requestHeaderCallback;
|
|
117
117
|
let headerReceivedCallback;
|
|
118
118
|
let responseCallback;
|
|
119
|
+
let overrideCallback;
|
|
119
120
|
let isInterceptorEnabled$1 = false;
|
|
120
121
|
const XHRInterceptor = {
|
|
121
122
|
/**
|
|
@@ -148,6 +149,12 @@ const XHRInterceptor = {
|
|
|
148
149
|
setRequestHeaderCallback(callback) {
|
|
149
150
|
requestHeaderCallback = callback;
|
|
150
151
|
},
|
|
152
|
+
/**
|
|
153
|
+
* Invoked before XMLHttpRequest.send(...) is called.
|
|
154
|
+
*/
|
|
155
|
+
setOverrideCallback(callback) {
|
|
156
|
+
overrideCallback = callback;
|
|
157
|
+
},
|
|
151
158
|
isInterceptorEnabled() {
|
|
152
159
|
return isInterceptorEnabled$1;
|
|
153
160
|
},
|
|
@@ -171,6 +178,9 @@ const XHRInterceptor = {
|
|
|
171
178
|
if (sendCallback) {
|
|
172
179
|
sendCallback(data, this);
|
|
173
180
|
}
|
|
181
|
+
if (overrideCallback) {
|
|
182
|
+
overrideCallback(this);
|
|
183
|
+
}
|
|
174
184
|
if (this.addEventListener) {
|
|
175
185
|
this.addEventListener(
|
|
176
186
|
"readystatechange",
|
|
@@ -231,6 +241,7 @@ const XHRInterceptor = {
|
|
|
231
241
|
sendCallback = null;
|
|
232
242
|
headerReceivedCallback = null;
|
|
233
243
|
requestHeaderCallback = null;
|
|
244
|
+
overrideCallback = null;
|
|
234
245
|
}
|
|
235
246
|
};
|
|
236
247
|
const getStringSizeInBytes = (value) => {
|
|
@@ -259,7 +270,28 @@ const isBlob = (value) => value instanceof Blob;
|
|
|
259
270
|
const isArrayBuffer = (value) => value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
260
271
|
const isFormData = (value) => value instanceof FormData;
|
|
261
272
|
const isNullOrUndefined = (value) => value === null || value === void 0;
|
|
273
|
+
const createOverridesRegistry = () => {
|
|
274
|
+
let overrides = /* @__PURE__ */ new Map();
|
|
275
|
+
const setOverrides = (newOverrides) => {
|
|
276
|
+
overrides = new Map(newOverrides);
|
|
277
|
+
};
|
|
278
|
+
const getOverrideForUrl = (url) => {
|
|
279
|
+
return overrides.get(url);
|
|
280
|
+
};
|
|
281
|
+
return {
|
|
282
|
+
setOverrides,
|
|
283
|
+
getOverrideForUrl
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
let registryInstance = null;
|
|
287
|
+
const getOverridesRegistry = () => {
|
|
288
|
+
if (!registryInstance) {
|
|
289
|
+
registryInstance = createOverridesRegistry();
|
|
290
|
+
}
|
|
291
|
+
return registryInstance;
|
|
292
|
+
};
|
|
262
293
|
const networkRequestsRegistry = getNetworkRequestsRegistry();
|
|
294
|
+
const overridesRegistry$1 = getOverridesRegistry();
|
|
263
295
|
const getBinaryPostData = (body) => ({
|
|
264
296
|
type: "binary",
|
|
265
297
|
value: {
|
|
@@ -449,9 +481,45 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
449
481
|
});
|
|
450
482
|
});
|
|
451
483
|
};
|
|
484
|
+
const handleRequestOverride = (request) => {
|
|
485
|
+
const override = overridesRegistry$1.getOverrideForUrl(
|
|
486
|
+
request._url
|
|
487
|
+
);
|
|
488
|
+
if (!override) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
request.addEventListener("readystatechange", () => {
|
|
492
|
+
if (override.body !== void 0) {
|
|
493
|
+
Object.defineProperty(request, "responseType", {
|
|
494
|
+
writable: true
|
|
495
|
+
});
|
|
496
|
+
Object.defineProperty(request, "response", {
|
|
497
|
+
writable: true
|
|
498
|
+
});
|
|
499
|
+
Object.defineProperty(request, "responseText", {
|
|
500
|
+
writable: true
|
|
501
|
+
});
|
|
502
|
+
const contentType = getContentType(request);
|
|
503
|
+
if (contentType === "application/json") {
|
|
504
|
+
request.responseType = "json";
|
|
505
|
+
} else if (contentType === "text/plain") {
|
|
506
|
+
request.responseType = "text";
|
|
507
|
+
}
|
|
508
|
+
request.response = override.body;
|
|
509
|
+
request.responseText = override.body;
|
|
510
|
+
}
|
|
511
|
+
if (override.status !== void 0) {
|
|
512
|
+
Object.defineProperty(request, "status", {
|
|
513
|
+
writable: true
|
|
514
|
+
});
|
|
515
|
+
request.status = override.status;
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
};
|
|
452
519
|
const enable = () => {
|
|
453
520
|
XHRInterceptor.disableInterception();
|
|
454
521
|
XHRInterceptor.setSendCallback(handleRequestSend);
|
|
522
|
+
XHRInterceptor.setOverrideCallback(handleRequestOverride);
|
|
455
523
|
XHRInterceptor.enableInterception();
|
|
456
524
|
};
|
|
457
525
|
const disable = () => {
|
|
@@ -857,6 +925,7 @@ const validateConfig = (config) => {
|
|
|
857
925
|
throw new Error("SSE inspector requires HTTP inspector to be enabled.");
|
|
858
926
|
}
|
|
859
927
|
};
|
|
928
|
+
const overridesRegistry = getOverridesRegistry();
|
|
860
929
|
const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
|
|
861
930
|
var _a, _b, _c;
|
|
862
931
|
const isRecordingEnabledRef = react.useRef(false);
|
|
@@ -882,6 +951,9 @@ const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
|
|
|
882
951
|
}),
|
|
883
952
|
client.onMessage("network-disable", () => {
|
|
884
953
|
isRecordingEnabledRef.current = false;
|
|
954
|
+
}),
|
|
955
|
+
client.onMessage("set-overrides", (data) => {
|
|
956
|
+
overridesRegistry.setOverrides(data.overrides);
|
|
885
957
|
})
|
|
886
958
|
];
|
|
887
959
|
return () => {
|
|
@@ -112,6 +112,7 @@ let sendCallback;
|
|
|
112
112
|
let requestHeaderCallback;
|
|
113
113
|
let headerReceivedCallback;
|
|
114
114
|
let responseCallback;
|
|
115
|
+
let overrideCallback;
|
|
115
116
|
let isInterceptorEnabled$1 = false;
|
|
116
117
|
const XHRInterceptor = {
|
|
117
118
|
/**
|
|
@@ -144,6 +145,12 @@ const XHRInterceptor = {
|
|
|
144
145
|
setRequestHeaderCallback(callback) {
|
|
145
146
|
requestHeaderCallback = callback;
|
|
146
147
|
},
|
|
148
|
+
/**
|
|
149
|
+
* Invoked before XMLHttpRequest.send(...) is called.
|
|
150
|
+
*/
|
|
151
|
+
setOverrideCallback(callback) {
|
|
152
|
+
overrideCallback = callback;
|
|
153
|
+
},
|
|
147
154
|
isInterceptorEnabled() {
|
|
148
155
|
return isInterceptorEnabled$1;
|
|
149
156
|
},
|
|
@@ -167,6 +174,9 @@ const XHRInterceptor = {
|
|
|
167
174
|
if (sendCallback) {
|
|
168
175
|
sendCallback(data, this);
|
|
169
176
|
}
|
|
177
|
+
if (overrideCallback) {
|
|
178
|
+
overrideCallback(this);
|
|
179
|
+
}
|
|
170
180
|
if (this.addEventListener) {
|
|
171
181
|
this.addEventListener(
|
|
172
182
|
"readystatechange",
|
|
@@ -227,6 +237,7 @@ const XHRInterceptor = {
|
|
|
227
237
|
sendCallback = null;
|
|
228
238
|
headerReceivedCallback = null;
|
|
229
239
|
requestHeaderCallback = null;
|
|
240
|
+
overrideCallback = null;
|
|
230
241
|
}
|
|
231
242
|
};
|
|
232
243
|
const getStringSizeInBytes = (value) => {
|
|
@@ -255,7 +266,28 @@ const isBlob = (value) => value instanceof Blob;
|
|
|
255
266
|
const isArrayBuffer = (value) => value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
256
267
|
const isFormData = (value) => value instanceof FormData;
|
|
257
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
|
+
};
|
|
258
289
|
const networkRequestsRegistry = getNetworkRequestsRegistry();
|
|
290
|
+
const overridesRegistry$1 = getOverridesRegistry();
|
|
259
291
|
const getBinaryPostData = (body) => ({
|
|
260
292
|
type: "binary",
|
|
261
293
|
value: {
|
|
@@ -445,9 +477,45 @@ const getNetworkInspector = (pluginClient) => {
|
|
|
445
477
|
});
|
|
446
478
|
});
|
|
447
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
|
+
};
|
|
448
515
|
const enable = () => {
|
|
449
516
|
XHRInterceptor.disableInterception();
|
|
450
517
|
XHRInterceptor.setSendCallback(handleRequestSend);
|
|
518
|
+
XHRInterceptor.setOverrideCallback(handleRequestOverride);
|
|
451
519
|
XHRInterceptor.enableInterception();
|
|
452
520
|
};
|
|
453
521
|
const disable = () => {
|
|
@@ -853,6 +921,7 @@ const validateConfig = (config) => {
|
|
|
853
921
|
throw new Error("SSE inspector requires HTTP inspector to be enabled.");
|
|
854
922
|
}
|
|
855
923
|
};
|
|
924
|
+
const overridesRegistry = getOverridesRegistry();
|
|
856
925
|
const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
|
|
857
926
|
var _a, _b, _c;
|
|
858
927
|
const isRecordingEnabledRef = useRef(false);
|
|
@@ -878,6 +947,9 @@ const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
|
|
|
878
947
|
}),
|
|
879
948
|
client.onMessage("network-disable", () => {
|
|
880
949
|
isRecordingEnabledRef.current = false;
|
|
950
|
+
}),
|
|
951
|
+
client.onMessage("set-overrides", (data) => {
|
|
952
|
+
overridesRegistry.setOverrides(data.overrides);
|
|
881
953
|
})
|
|
882
954
|
];
|
|
883
955
|
return () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rozenite/network-activity-plugin",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.16",
|
|
4
4
|
"description": "Network Activity for Rozenite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/react-native.cjs",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"types": "./dist/react-native.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"nanoevents": "^9.1.0",
|
|
11
|
-
"@rozenite/plugin-bridge": "1.0.0-alpha.
|
|
11
|
+
"@rozenite/plugin-bridge": "1.0.0-alpha.16"
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@floating-ui/react": "^0.26.0",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"zustand": "^5.0.6",
|
|
37
37
|
"@types/react": "~18.3.23",
|
|
38
38
|
"@types/react-dom": "~18.3.1",
|
|
39
|
-
"@rozenite/vite-plugin": "1.0.0-alpha.
|
|
40
|
-
"rozenite": "1.0.0-alpha.
|
|
39
|
+
"@rozenite/vite-plugin": "1.0.0-alpha.16",
|
|
40
|
+
"rozenite": "1.0.0-alpha.16"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"react-native-sse": "*"
|
|
@@ -21,8 +21,10 @@ import {
|
|
|
21
21
|
isFormData,
|
|
22
22
|
isNullOrUndefined,
|
|
23
23
|
} from '../../utils/typeChecks';
|
|
24
|
+
import { getOverridesRegistry } from './overrides-registry';
|
|
24
25
|
|
|
25
26
|
const networkRequestsRegistry = getNetworkRequestsRegistry();
|
|
27
|
+
const overridesRegistry = getOverridesRegistry();
|
|
26
28
|
|
|
27
29
|
const getBinaryPostData = (body: Blob): RequestBinaryPostData => ({
|
|
28
30
|
type: 'binary',
|
|
@@ -281,9 +283,57 @@ export const getNetworkInspector = (
|
|
|
281
283
|
});
|
|
282
284
|
};
|
|
283
285
|
|
|
286
|
+
const handleRequestOverride = (request: XMLHttpRequest): void => {
|
|
287
|
+
const override = overridesRegistry.getOverrideForUrl(
|
|
288
|
+
request._url as string
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
if (!override) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
request.addEventListener('readystatechange', () => {
|
|
296
|
+
if (override.body !== undefined) {
|
|
297
|
+
Object.defineProperty(request, 'responseType', {
|
|
298
|
+
writable: true,
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
Object.defineProperty(request, 'response', {
|
|
302
|
+
writable: true,
|
|
303
|
+
});
|
|
304
|
+
Object.defineProperty(request, 'responseText', {
|
|
305
|
+
writable: true,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
const contentType = getContentType(request);
|
|
309
|
+
|
|
310
|
+
if (contentType === 'application/json') {
|
|
311
|
+
request.responseType = 'json';
|
|
312
|
+
} else if (contentType === 'text/plain') {
|
|
313
|
+
request.responseType = 'text';
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// @ts-expect-error - Mocking response
|
|
317
|
+
request.response = override.body;
|
|
318
|
+
// @ts-expect-error - Mocking responseText
|
|
319
|
+
request.responseText = override.body;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (override.status !== undefined) {
|
|
323
|
+
Object.defineProperty(request, 'status', {
|
|
324
|
+
writable: true,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
// @ts-expect-error - Mocking status
|
|
328
|
+
request.status = override.status;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
};
|
|
332
|
+
|
|
284
333
|
const enable = () => {
|
|
285
334
|
XHRInterceptor.disableInterception();
|
|
286
335
|
XHRInterceptor.setSendCallback(handleRequestSend);
|
|
336
|
+
XHRInterceptor.setOverrideCallback(handleRequestOverride);
|
|
287
337
|
XHRInterceptor.enableInterception();
|
|
288
338
|
};
|
|
289
339
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RequestOverride } from '../../shared/client';
|
|
2
|
+
|
|
3
|
+
export type OverridesRegistry = {
|
|
4
|
+
setOverrides: (newOverrides: [string, RequestOverride][]) => void;
|
|
5
|
+
getOverrideForUrl: (url: string) => RequestOverride | undefined;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
const createOverridesRegistry = (): OverridesRegistry => {
|
|
9
|
+
let overrides = new Map<string, RequestOverride>();
|
|
10
|
+
|
|
11
|
+
const setOverrides = (newOverrides: [string, RequestOverride][]) => {
|
|
12
|
+
overrides = new Map(newOverrides);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const getOverrideForUrl = (url: string) => {
|
|
16
|
+
return overrides.get(url);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
setOverrides,
|
|
21
|
+
getOverrideForUrl,
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
let registryInstance: OverridesRegistry | null = null;
|
|
26
|
+
|
|
27
|
+
export const getOverridesRegistry = (): OverridesRegistry => {
|
|
28
|
+
if (!registryInstance) {
|
|
29
|
+
registryInstance = createOverridesRegistry();
|
|
30
|
+
}
|
|
31
|
+
return registryInstance;
|
|
32
|
+
};
|
|
@@ -49,11 +49,14 @@ type XHRInterceptorResponseCallback = (
|
|
|
49
49
|
request: XMLHttpRequest
|
|
50
50
|
) => void;
|
|
51
51
|
|
|
52
|
+
type XHRInterceptorOverrideCallback = (request: XMLHttpRequest) => void;
|
|
53
|
+
|
|
52
54
|
let openCallback: XHRInterceptorOpenCallback | null;
|
|
53
55
|
let sendCallback: XHRInterceptorSendCallback | null;
|
|
54
56
|
let requestHeaderCallback: XHRInterceptorRequestHeaderCallback | null;
|
|
55
57
|
let headerReceivedCallback: XHRInterceptorHeaderReceivedCallback | null;
|
|
56
58
|
let responseCallback: XHRInterceptorResponseCallback | null;
|
|
59
|
+
let overrideCallback: XHRInterceptorOverrideCallback | null;
|
|
57
60
|
|
|
58
61
|
let isInterceptorEnabled = false;
|
|
59
62
|
|
|
@@ -100,6 +103,13 @@ export const XHRInterceptor = {
|
|
|
100
103
|
requestHeaderCallback = callback;
|
|
101
104
|
},
|
|
102
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Invoked before XMLHttpRequest.send(...) is called.
|
|
108
|
+
*/
|
|
109
|
+
setOverrideCallback(callback: XHRInterceptorOverrideCallback) {
|
|
110
|
+
overrideCallback = callback;
|
|
111
|
+
},
|
|
112
|
+
|
|
103
113
|
isInterceptorEnabled(): boolean {
|
|
104
114
|
return isInterceptorEnabled;
|
|
105
115
|
},
|
|
@@ -143,6 +153,9 @@ export const XHRInterceptor = {
|
|
|
143
153
|
if (sendCallback) {
|
|
144
154
|
sendCallback(data, this);
|
|
145
155
|
}
|
|
156
|
+
if (overrideCallback) {
|
|
157
|
+
overrideCallback(this);
|
|
158
|
+
}
|
|
146
159
|
if (this.addEventListener) {
|
|
147
160
|
this.addEventListener(
|
|
148
161
|
'readystatechange',
|
|
@@ -210,5 +223,6 @@ export const XHRInterceptor = {
|
|
|
210
223
|
sendCallback = null;
|
|
211
224
|
headerReceivedCallback = null;
|
|
212
225
|
requestHeaderCallback = null;
|
|
226
|
+
overrideCallback = null;
|
|
213
227
|
},
|
|
214
228
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect, useRef } from 'react';
|
|
2
2
|
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
3
3
|
import { getNetworkInspector } from './http/network-inspector';
|
|
4
|
+
import { getOverridesRegistry } from './http/overrides-registry';
|
|
4
5
|
import { NetworkActivityEventMap } from '../shared/client';
|
|
5
6
|
import { getWebSocketInspector } from './websocket/websocket-inspector';
|
|
6
7
|
import { WebSocketEventMap } from '../shared/websocket-events';
|
|
@@ -13,6 +14,8 @@ import {
|
|
|
13
14
|
validateConfig,
|
|
14
15
|
} from './config';
|
|
15
16
|
|
|
17
|
+
const overridesRegistry = getOverridesRegistry();
|
|
18
|
+
|
|
16
19
|
export const useNetworkActivityDevTools = (
|
|
17
20
|
config: NetworkActivityDevToolsConfig = DEFAULT_CONFIG
|
|
18
21
|
) => {
|
|
@@ -46,6 +49,9 @@ export const useNetworkActivityDevTools = (
|
|
|
46
49
|
client.onMessage('network-disable', () => {
|
|
47
50
|
isRecordingEnabledRef.current = false;
|
|
48
51
|
}),
|
|
52
|
+
client.onMessage('set-overrides', (data) => {
|
|
53
|
+
overridesRegistry.setOverrides(data.overrides);
|
|
54
|
+
}),
|
|
49
55
|
];
|
|
50
56
|
|
|
51
57
|
return () => {
|
package/src/shared/client.ts
CHANGED
|
@@ -84,6 +84,11 @@ export type Initiator = {
|
|
|
84
84
|
|
|
85
85
|
export type ResourceType = 'XHR' | 'Fetch' | 'Other';
|
|
86
86
|
|
|
87
|
+
export type RequestOverride = {
|
|
88
|
+
status?: number;
|
|
89
|
+
body?: string;
|
|
90
|
+
};
|
|
91
|
+
|
|
87
92
|
export type NetworkActivityEventMap = {
|
|
88
93
|
// Control events
|
|
89
94
|
'network-enable': unknown;
|
|
@@ -129,6 +134,10 @@ export type NetworkActivityEventMap = {
|
|
|
129
134
|
requestId: RequestId;
|
|
130
135
|
body: string | null;
|
|
131
136
|
};
|
|
137
|
+
|
|
138
|
+
'set-overrides': {
|
|
139
|
+
overrides: [string, RequestOverride][];
|
|
140
|
+
};
|
|
132
141
|
} & WebSocketEventMap &
|
|
133
142
|
SSEEventMap;
|
|
134
143
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { forwardRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export type CodeEditorProps = {
|
|
4
|
+
data: string | undefined;
|
|
5
|
+
onInput?: (event: React.FormEvent<HTMLPreElement>) => void;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const CodeEditor = forwardRef<HTMLPreElement, CodeEditorProps>(
|
|
9
|
+
({ data, onInput }, ref) => {
|
|
10
|
+
return (
|
|
11
|
+
<pre
|
|
12
|
+
ref={ref}
|
|
13
|
+
contentEditable
|
|
14
|
+
suppressContentEditableWarning
|
|
15
|
+
className={
|
|
16
|
+
'w-full text-sm font-mono text-gray-300 whitespace-pre-wrap bg-gray-800 p-3 rounded-md border border-gray-700 overflow-x-auto wrap-anywhere ring-offset-blue-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2'
|
|
17
|
+
}
|
|
18
|
+
onInput={onInput}
|
|
19
|
+
>
|
|
20
|
+
{data}
|
|
21
|
+
</pre>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
CodeEditor.displayName = 'CodeEditor';
|