@rozenite/network-activity-plugin 1.0.0-alpha.9 → 1.1.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-DoHQsY5s.css → App-BrSkOkws.css} +223 -2
- package/dist/assets/{App-CA1Fbh0I.js → App-Kyi7zHUX.js} +8188 -2671
- 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/http/overrides-registry.d.ts +6 -0
- package/dist/src/react-native/http/xhr-interceptor.d.ts +7 -1
- package/dist/src/react-native/sse/sse-interceptor.d.ts +2 -2
- 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/shared/client.d.ts +55 -4
- package/dist/src/shared/sse-events.d.ts +4 -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 +1 -1
- 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 +9 -4
- 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/Tabs.d.ts +7 -0
- package/dist/src/ui/state/hooks.d.ts +4 -0
- package/dist/src/ui/state/model.d.ts +22 -7
- package/dist/src/ui/state/store.d.ts +27 -3
- package/dist/src/ui/utils/checkRequestBodyBinary.d.ts +2 -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/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 +337 -24
- package/dist/useNetworkActivityDevTools.js +338 -25
- package/package.json +7 -4
- package/react-native.ts +6 -1
- package/src/react-native/config.ts +43 -0
- package/src/react-native/http/network-inspector.ts +190 -8
- package/src/react-native/http/overrides-registry.ts +32 -0
- package/src/react-native/http/xhr-interceptor.ts +19 -2
- package/src/react-native/sse/sse-inspector.ts +27 -5
- package/src/react-native/sse/sse-interceptor.ts +26 -8
- package/src/react-native/useNetworkActivityDevTools.ts +86 -8
- package/src/react-native/utils/getBlobName.ts +45 -0
- package/src/react-native/utils/getFormDataEntries.ts +32 -0
- package/src/react-native/utils.ts +3 -3
- package/src/shared/client.ts +81 -4
- package/src/shared/sse-events.ts +4 -1
- 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 +10 -3
- package/src/ui/components/JsonTreeCopyableItem.tsx +14 -10
- 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 +74 -14
- package/src/ui/components/ScrollArea.tsx +1 -0
- package/src/ui/components/Section.tsx +46 -0
- package/src/ui/components/SidePanel.tsx +15 -5
- package/src/ui/components/Toolbar.tsx +3 -2
- package/src/ui/globals.css +4 -0
- package/src/ui/hooks/useCopyToClipboard.ts +2 -2
- package/src/ui/state/derived.ts +2 -0
- package/src/ui/state/hooks.ts +8 -0
- package/src/ui/state/model.ts +28 -7
- package/src/ui/state/store.ts +640 -500
- package/src/ui/tabs/CookiesTab.tsx +60 -263
- package/src/ui/tabs/HeadersTab.tsx +78 -89
- package/src/ui/tabs/RequestTab.tsx +58 -46
- package/src/ui/tabs/ResponseTab.tsx +98 -67
- package/src/ui/tabs/SSEMessagesTab.tsx +50 -39
- package/src/ui/utils/checkRequestBodyBinary.ts +7 -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/views/InspectorView.tsx +15 -3
- 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/dist/src/ui/utils/getHttpHeaderValue.d.ts +0 -2
- package/src/ui/utils/getHttpHeaderValue.ts +0 -14
package/src/ui/state/store.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { createStore } from 'zustand';
|
|
2
|
+
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
2
3
|
import {
|
|
3
4
|
NetworkActivityDevToolsClient,
|
|
4
5
|
NetworkActivityEventMap,
|
|
6
|
+
RequestOverride,
|
|
5
7
|
RequestId,
|
|
8
|
+
NetworkActivityClientUISettings,
|
|
6
9
|
} from '../../shared/client';
|
|
7
10
|
import {
|
|
8
11
|
NetworkEntry,
|
|
@@ -12,19 +15,24 @@ import {
|
|
|
12
15
|
SSENetworkEntry,
|
|
13
16
|
SSEMessage,
|
|
14
17
|
} from './model';
|
|
15
|
-
import { getHttpHeaderValue } from '../utils/getHttpHeaderValue';
|
|
16
18
|
import { getId } from '../utils/getId';
|
|
17
19
|
import { assert } from '../utils/assert';
|
|
20
|
+
import { getContentTypeMime } from '../../utils/getContentTypeMimeType';
|
|
21
|
+
import { applyReactNativeRequestHeadersLogic } from '../../utils/applyReactNativeRequestHeadersLogic';
|
|
18
22
|
|
|
19
23
|
const MAX_WEBSOCKET_MESSAGES_PER_CONNECTION = 32;
|
|
20
24
|
const MAX_SSE_MESSAGES_PER_CONNECTION = 32;
|
|
21
25
|
|
|
26
|
+
const STORE_VERSION = 1;
|
|
27
|
+
|
|
22
28
|
export interface NetworkActivityState {
|
|
23
29
|
// State
|
|
24
30
|
isRecording: boolean;
|
|
25
31
|
selectedRequestId: RequestId | null;
|
|
26
32
|
networkEntries: Map<RequestId, NetworkEntry>;
|
|
27
33
|
websocketMessages: Map<RequestId, WebSocketMessage[]>;
|
|
34
|
+
overrides: Map<string, RequestOverride>;
|
|
35
|
+
clientUISettings: NetworkActivityClientUISettings | null;
|
|
28
36
|
|
|
29
37
|
// Internal state (not exposed in interface)
|
|
30
38
|
_unsubscribeFunctions?: Array<{ remove: () => void }>;
|
|
@@ -35,6 +43,8 @@ export interface NetworkActivityState {
|
|
|
35
43
|
setRecording: (isRecording: boolean) => void;
|
|
36
44
|
setSelectedRequest: (requestId: RequestId | null) => void;
|
|
37
45
|
clearRequests: () => void;
|
|
46
|
+
addOverride: (requestUrl: string, override: RequestOverride) => void;
|
|
47
|
+
clearOverride: (requestUrl: string) => void;
|
|
38
48
|
};
|
|
39
49
|
|
|
40
50
|
// Event handling
|
|
@@ -51,509 +61,639 @@ export interface NetworkActivityState {
|
|
|
51
61
|
}
|
|
52
62
|
|
|
53
63
|
export const createNetworkActivityStore = () =>
|
|
54
|
-
createStore<NetworkActivityState>(
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
set((state) => {
|
|
144
|
-
const entry = state.networkEntries.get(eventData.requestId);
|
|
145
|
-
if (!entry || entry.type !== 'http') return state;
|
|
146
|
-
|
|
147
|
-
const httpEntry = entry as HttpNetworkEntry;
|
|
148
|
-
const updatedEntry: HttpNetworkEntry = {
|
|
149
|
-
...httpEntry,
|
|
150
|
-
status: 'finished',
|
|
151
|
-
duration: eventData.duration,
|
|
152
|
-
size: eventData.size,
|
|
153
|
-
ttfb: eventData.ttfb,
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
const newEntries = new Map(state.networkEntries);
|
|
157
|
-
newEntries.set(eventData.requestId, updatedEntry);
|
|
158
|
-
return { networkEntries: newEntries };
|
|
159
|
-
});
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
case 'request-failed': {
|
|
164
|
-
const eventData = data as NetworkActivityEventMap['request-failed'];
|
|
165
|
-
set((state) => {
|
|
166
|
-
const entry = state.networkEntries.get(eventData.requestId);
|
|
167
|
-
if (!entry || entry.type !== 'http') return state;
|
|
168
|
-
|
|
169
|
-
const httpEntry = entry as HttpNetworkEntry;
|
|
170
|
-
const updatedEntry: HttpNetworkEntry = {
|
|
171
|
-
...httpEntry,
|
|
172
|
-
status: 'failed',
|
|
173
|
-
error: eventData.error,
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const newEntries = new Map(state.networkEntries);
|
|
177
|
-
newEntries.set(eventData.requestId, updatedEntry);
|
|
178
|
-
return { networkEntries: newEntries };
|
|
179
|
-
});
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
case 'response-body': {
|
|
184
|
-
const eventData = data as NetworkActivityEventMap['response-body'];
|
|
185
|
-
set((state) => {
|
|
186
|
-
const entry = state.networkEntries.get(eventData.requestId);
|
|
187
|
-
if (!entry || entry.type !== 'http') return state;
|
|
188
|
-
|
|
189
|
-
const httpEntry = entry as HttpNetworkEntry;
|
|
190
|
-
const updatedEntry: HttpNetworkEntry = {
|
|
191
|
-
...httpEntry,
|
|
192
|
-
response: httpEntry.response
|
|
193
|
-
? {
|
|
194
|
-
...httpEntry.response,
|
|
195
|
-
body: eventData.body
|
|
64
|
+
createStore<NetworkActivityState>()(
|
|
65
|
+
persist(
|
|
66
|
+
(set, get) => ({
|
|
67
|
+
// Initial state
|
|
68
|
+
isRecording: false,
|
|
69
|
+
selectedRequestId: null,
|
|
70
|
+
networkEntries: new Map(),
|
|
71
|
+
websocketMessages: new Map(),
|
|
72
|
+
overrides: new Map(),
|
|
73
|
+
clientUISettings: null,
|
|
74
|
+
|
|
75
|
+
// Actions
|
|
76
|
+
actions: {
|
|
77
|
+
setRecording: (isRecording: boolean) => {
|
|
78
|
+
const { _client } = get();
|
|
79
|
+
assert(!!_client, 'Client is not set');
|
|
80
|
+
|
|
81
|
+
_client.send(
|
|
82
|
+
isRecording ? 'network-enable' : 'network-disable',
|
|
83
|
+
{}
|
|
84
|
+
);
|
|
85
|
+
set({ isRecording });
|
|
86
|
+
},
|
|
87
|
+
setSelectedRequest: (requestId: RequestId | null) =>
|
|
88
|
+
set({ selectedRequestId: requestId }),
|
|
89
|
+
clearRequests: () =>
|
|
90
|
+
set({
|
|
91
|
+
networkEntries: new Map(),
|
|
92
|
+
websocketMessages: new Map(),
|
|
93
|
+
selectedRequestId: null,
|
|
94
|
+
}),
|
|
95
|
+
addOverride: (requestUrl: string, override: RequestOverride) => {
|
|
96
|
+
const { overrides, _client } = get();
|
|
97
|
+
assert(!!_client, 'Client is not set');
|
|
98
|
+
|
|
99
|
+
const newOverrides = new Map(overrides);
|
|
100
|
+
newOverrides.set(requestUrl, override);
|
|
101
|
+
|
|
102
|
+
_client.send('set-overrides', {
|
|
103
|
+
overrides: Array.from(newOverrides.entries()),
|
|
104
|
+
});
|
|
105
|
+
set({ overrides: newOverrides });
|
|
106
|
+
},
|
|
107
|
+
clearOverride: (requestUrl: string) => {
|
|
108
|
+
const { overrides, _client } = get();
|
|
109
|
+
assert(!!_client, 'Client is not set');
|
|
110
|
+
|
|
111
|
+
const newOverrides = new Map(overrides);
|
|
112
|
+
newOverrides.delete(requestUrl);
|
|
113
|
+
|
|
114
|
+
_client.send('set-overrides', {
|
|
115
|
+
overrides: Array.from(newOverrides.entries()),
|
|
116
|
+
});
|
|
117
|
+
set({ overrides: newOverrides });
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
// Event handling
|
|
121
|
+
handleEvent: <K extends keyof NetworkActivityEventMap>(
|
|
122
|
+
eventType: K,
|
|
123
|
+
data: NetworkActivityEventMap[K]
|
|
124
|
+
) => {
|
|
125
|
+
switch (eventType) {
|
|
126
|
+
case 'client-ui-settings': {
|
|
127
|
+
const eventData = data as NetworkActivityEventMap['client-ui-settings'];
|
|
128
|
+
set({ clientUISettings: eventData.settings || null });
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case 'request-sent': {
|
|
133
|
+
const eventData = data as NetworkActivityEventMap['request-sent'];
|
|
134
|
+
set((state) => {
|
|
135
|
+
const headersWithContentType =
|
|
136
|
+
applyReactNativeRequestHeadersLogic(
|
|
137
|
+
eventData.request.headers,
|
|
138
|
+
eventData.request.postData
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const requestContentType =
|
|
142
|
+
getContentTypeMime(headersWithContentType) || 'text/plain';
|
|
143
|
+
|
|
144
|
+
const entry: HttpNetworkEntry = {
|
|
145
|
+
id: eventData.requestId,
|
|
146
|
+
type: 'http',
|
|
147
|
+
timestamp: eventData.timestamp,
|
|
148
|
+
request: {
|
|
149
|
+
url: eventData.request.url,
|
|
150
|
+
method: eventData.request.method,
|
|
151
|
+
headers: headersWithContentType,
|
|
152
|
+
body: eventData.request.postData
|
|
196
153
|
? {
|
|
197
|
-
type:
|
|
198
|
-
|
|
199
|
-
httpEntry.response?.headers ?? {},
|
|
200
|
-
'content-type'
|
|
201
|
-
)?.split(';')[0] || 'text/plain',
|
|
202
|
-
data: eventData.body,
|
|
154
|
+
type: requestContentType,
|
|
155
|
+
data: eventData.request.postData,
|
|
203
156
|
}
|
|
204
157
|
: undefined,
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
158
|
+
},
|
|
159
|
+
status: 'pending',
|
|
160
|
+
initiator: eventData.initiator,
|
|
161
|
+
resourceType: eventData.type,
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const newEntries = new Map(state.networkEntries);
|
|
165
|
+
newEntries.set(eventData.requestId, entry);
|
|
166
|
+
return { networkEntries: newEntries };
|
|
167
|
+
});
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
case 'request-progress': {
|
|
172
|
+
const eventData =
|
|
173
|
+
data as NetworkActivityEventMap['request-progress'];
|
|
174
|
+
set((state) => {
|
|
175
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
176
|
+
if (!entry || entry.type !== 'http') {
|
|
177
|
+
return state;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
181
|
+
const updatedEntry: HttpNetworkEntry = {
|
|
182
|
+
...httpEntry,
|
|
183
|
+
status: 'loading',
|
|
184
|
+
progress: {
|
|
185
|
+
loaded: eventData.loaded,
|
|
186
|
+
total: eventData.total,
|
|
187
|
+
lengthComputable: eventData.lengthComputable,
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const newEntries = new Map(state.networkEntries);
|
|
192
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
193
|
+
return { networkEntries: newEntries };
|
|
194
|
+
});
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
case 'response-received': {
|
|
199
|
+
const eventData =
|
|
200
|
+
data as NetworkActivityEventMap['response-received'];
|
|
201
|
+
set((state) => {
|
|
202
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
203
|
+
if (!entry || entry.type !== 'http') return state;
|
|
204
|
+
|
|
205
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
206
|
+
const updatedEntry: HttpNetworkEntry = {
|
|
207
|
+
...httpEntry,
|
|
208
|
+
status: 'loading',
|
|
209
|
+
response: {
|
|
210
|
+
...eventData.response,
|
|
211
|
+
size: eventData.response.size ?? 0,
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const newEntries = new Map(state.networkEntries);
|
|
216
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
217
|
+
return { networkEntries: newEntries };
|
|
218
|
+
});
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
case 'request-completed': {
|
|
223
|
+
const eventData =
|
|
224
|
+
data as NetworkActivityEventMap['request-completed'];
|
|
225
|
+
set((state) => {
|
|
226
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
227
|
+
if (!entry || entry.type !== 'http') return state;
|
|
228
|
+
|
|
229
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
230
|
+
const updatedEntry: HttpNetworkEntry = {
|
|
231
|
+
...httpEntry,
|
|
232
|
+
status: 'finished',
|
|
233
|
+
duration: eventData.duration,
|
|
234
|
+
size: eventData.size ?? undefined,
|
|
235
|
+
ttfb: eventData.ttfb,
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const newEntries = new Map(state.networkEntries);
|
|
239
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
240
|
+
return { networkEntries: newEntries };
|
|
241
|
+
});
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
case 'request-failed': {
|
|
246
|
+
const eventData =
|
|
247
|
+
data as NetworkActivityEventMap['request-failed'];
|
|
248
|
+
set((state) => {
|
|
249
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
250
|
+
if (!entry || entry.type !== 'http') return state;
|
|
251
|
+
|
|
252
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
253
|
+
const updatedEntry: HttpNetworkEntry = {
|
|
254
|
+
...httpEntry,
|
|
255
|
+
status: 'failed',
|
|
256
|
+
error: eventData.error,
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const newEntries = new Map(state.networkEntries);
|
|
260
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
261
|
+
return { networkEntries: newEntries };
|
|
262
|
+
});
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
case 'response-body': {
|
|
267
|
+
const eventData =
|
|
268
|
+
data as NetworkActivityEventMap['response-body'];
|
|
269
|
+
set((state) => {
|
|
270
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
271
|
+
if (!entry || entry.type !== 'http') return state;
|
|
272
|
+
|
|
273
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
274
|
+
const updatedEntry: HttpNetworkEntry = {
|
|
275
|
+
...httpEntry,
|
|
276
|
+
response: httpEntry.response
|
|
277
|
+
? {
|
|
278
|
+
...httpEntry.response,
|
|
279
|
+
body: eventData.body
|
|
280
|
+
? {
|
|
281
|
+
type:
|
|
282
|
+
getContentTypeMime(
|
|
283
|
+
httpEntry.response?.headers ?? {}
|
|
284
|
+
) || 'text/plain',
|
|
285
|
+
data: eventData.body,
|
|
286
|
+
}
|
|
287
|
+
: undefined,
|
|
288
|
+
}
|
|
289
|
+
: undefined,
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const newEntries = new Map(state.networkEntries);
|
|
293
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
294
|
+
return { networkEntries: newEntries };
|
|
295
|
+
});
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
case 'websocket-connect': {
|
|
300
|
+
const eventData =
|
|
301
|
+
data as NetworkActivityEventMap['websocket-connect'];
|
|
302
|
+
set((state) => {
|
|
303
|
+
const entry: WebSocketNetworkEntry = {
|
|
304
|
+
id: `ws-${eventData.socketId}`,
|
|
305
|
+
type: 'websocket',
|
|
306
|
+
timestamp: eventData.timestamp,
|
|
307
|
+
connection: {
|
|
308
|
+
url: eventData.url,
|
|
309
|
+
socketId: eventData.socketId,
|
|
310
|
+
protocols: eventData.protocols || undefined,
|
|
311
|
+
options: eventData.options,
|
|
312
|
+
},
|
|
313
|
+
status: 'connecting',
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
const newEntries = new Map(state.networkEntries);
|
|
317
|
+
newEntries.set(entry.id, entry);
|
|
318
|
+
|
|
319
|
+
const newMessages = new Map(state.websocketMessages);
|
|
320
|
+
newMessages.set(entry.id, []);
|
|
321
|
+
|
|
322
|
+
return {
|
|
323
|
+
networkEntries: newEntries,
|
|
324
|
+
websocketMessages: newMessages,
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
case 'websocket-open': {
|
|
331
|
+
const eventData =
|
|
332
|
+
data as NetworkActivityEventMap['websocket-open'];
|
|
333
|
+
set((state) => {
|
|
334
|
+
const entry = state.networkEntries.get(
|
|
335
|
+
`ws-${eventData.socketId}`
|
|
336
|
+
);
|
|
337
|
+
if (!entry || entry.type !== 'websocket') return state;
|
|
338
|
+
|
|
339
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
340
|
+
const updatedEntry: WebSocketNetworkEntry = {
|
|
341
|
+
...wsEntry,
|
|
342
|
+
status: 'open',
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const newEntries = new Map(state.networkEntries);
|
|
346
|
+
newEntries.set(entry.id, updatedEntry);
|
|
347
|
+
return { networkEntries: newEntries };
|
|
348
|
+
});
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
case 'websocket-close': {
|
|
353
|
+
const eventData =
|
|
354
|
+
data as NetworkActivityEventMap['websocket-close'];
|
|
355
|
+
set((state) => {
|
|
356
|
+
const entry = state.networkEntries.get(
|
|
357
|
+
`ws-${eventData.socketId}`
|
|
358
|
+
);
|
|
359
|
+
if (!entry || entry.type !== 'websocket') return state;
|
|
360
|
+
|
|
361
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
362
|
+
const updatedEntry: WebSocketNetworkEntry = {
|
|
363
|
+
...wsEntry,
|
|
364
|
+
status: 'closed',
|
|
365
|
+
closeCode: eventData.code,
|
|
366
|
+
closeReason: eventData.reason,
|
|
367
|
+
duration: eventData.timestamp - wsEntry.timestamp,
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const newEntries = new Map(state.networkEntries);
|
|
371
|
+
newEntries.set(entry.id, updatedEntry);
|
|
372
|
+
return { networkEntries: newEntries };
|
|
373
|
+
});
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
case 'websocket-message-sent': {
|
|
378
|
+
const eventData =
|
|
379
|
+
data as NetworkActivityEventMap['websocket-message-sent'];
|
|
380
|
+
set((state) => {
|
|
381
|
+
const socketId = `ws-${eventData.socketId}`;
|
|
382
|
+
const currentMessages =
|
|
383
|
+
state.websocketMessages.get(socketId) || [];
|
|
384
|
+
|
|
385
|
+
const message: WebSocketMessage = {
|
|
386
|
+
id: getId(`${socketId}-message`),
|
|
387
|
+
direction: 'sent',
|
|
388
|
+
data: eventData.data,
|
|
389
|
+
messageType: eventData.messageType,
|
|
390
|
+
timestamp: eventData.timestamp,
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
const newMessages = new Map(state.websocketMessages);
|
|
394
|
+
newMessages.set(
|
|
395
|
+
socketId,
|
|
396
|
+
[...currentMessages, message].slice(
|
|
397
|
+
-MAX_WEBSOCKET_MESSAGES_PER_CONNECTION
|
|
398
|
+
)
|
|
399
|
+
);
|
|
400
|
+
|
|
401
|
+
return { websocketMessages: newMessages };
|
|
402
|
+
});
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
case 'websocket-message-received': {
|
|
407
|
+
const eventData =
|
|
408
|
+
data as NetworkActivityEventMap['websocket-message-received'];
|
|
409
|
+
set((state) => {
|
|
410
|
+
const socketId = `ws-${eventData.socketId}`;
|
|
411
|
+
const currentMessages =
|
|
412
|
+
state.websocketMessages.get(socketId) || [];
|
|
413
|
+
|
|
414
|
+
const message: WebSocketMessage = {
|
|
415
|
+
id: getId(`${socketId}-message`),
|
|
416
|
+
direction: 'received',
|
|
417
|
+
data: eventData.data,
|
|
418
|
+
messageType: eventData.messageType,
|
|
419
|
+
timestamp: eventData.timestamp,
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
const newMessages = new Map(state.websocketMessages);
|
|
423
|
+
newMessages.set(
|
|
424
|
+
socketId,
|
|
425
|
+
[...currentMessages, message].slice(
|
|
426
|
+
-MAX_WEBSOCKET_MESSAGES_PER_CONNECTION
|
|
427
|
+
)
|
|
428
|
+
);
|
|
429
|
+
|
|
430
|
+
return { websocketMessages: newMessages };
|
|
431
|
+
});
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
case 'websocket-error': {
|
|
436
|
+
const eventData =
|
|
437
|
+
data as NetworkActivityEventMap['websocket-error'];
|
|
438
|
+
set((state) => {
|
|
439
|
+
const entry = state.networkEntries.get(
|
|
440
|
+
`ws-${eventData.socketId}`
|
|
441
|
+
);
|
|
442
|
+
if (!entry || entry.type !== 'websocket') return state;
|
|
443
|
+
|
|
444
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
445
|
+
const updatedEntry: WebSocketNetworkEntry = {
|
|
446
|
+
...wsEntry,
|
|
447
|
+
status: 'error',
|
|
448
|
+
error: eventData.error,
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const newEntries = new Map(state.networkEntries);
|
|
452
|
+
newEntries.set(entry.id, updatedEntry);
|
|
453
|
+
return { networkEntries: newEntries };
|
|
454
|
+
});
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
case 'websocket-connection-status-changed': {
|
|
459
|
+
const eventData =
|
|
460
|
+
data as NetworkActivityEventMap['websocket-connection-status-changed'];
|
|
461
|
+
set((state) => {
|
|
462
|
+
const entry = state.networkEntries.get(
|
|
463
|
+
`ws-${eventData.socketId}`
|
|
464
|
+
);
|
|
465
|
+
if (!entry || entry.type !== 'websocket') return state;
|
|
466
|
+
|
|
467
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
468
|
+
const updatedEntry: WebSocketNetworkEntry = {
|
|
469
|
+
...wsEntry,
|
|
470
|
+
status: eventData.status,
|
|
471
|
+
};
|
|
472
|
+
|
|
473
|
+
const newEntries = new Map(state.networkEntries);
|
|
474
|
+
newEntries.set(entry.id, updatedEntry);
|
|
475
|
+
return { networkEntries: newEntries };
|
|
476
|
+
});
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
case 'sse-open': {
|
|
481
|
+
const eventData = data as NetworkActivityEventMap['sse-open'];
|
|
482
|
+
set((state) => {
|
|
483
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
484
|
+
if (!entry || entry.type !== 'http') return state;
|
|
485
|
+
|
|
486
|
+
// Transform the existing HTTP entry to SSE
|
|
487
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
488
|
+
const sseEntry: SSENetworkEntry = {
|
|
489
|
+
...httpEntry,
|
|
490
|
+
type: 'sse', // Change type from 'http' to 'sse'
|
|
491
|
+
status: 'open', // Update status
|
|
492
|
+
messages: [], // Add SSE-specific field
|
|
493
|
+
response: {
|
|
494
|
+
...eventData.response,
|
|
495
|
+
size: eventData.response.size ?? 0,
|
|
496
|
+
},
|
|
497
|
+
};
|
|
498
|
+
|
|
499
|
+
const newEntries = new Map(state.networkEntries);
|
|
500
|
+
newEntries.set(eventData.requestId, sseEntry);
|
|
501
|
+
return { networkEntries: newEntries };
|
|
502
|
+
});
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
case 'sse-message': {
|
|
507
|
+
const eventData = data as NetworkActivityEventMap['sse-message'];
|
|
508
|
+
set((state) => {
|
|
509
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
510
|
+
if (!entry || entry.type !== 'sse') return state;
|
|
511
|
+
|
|
512
|
+
const sseEntry = entry as SSENetworkEntry;
|
|
513
|
+
const newMessage: SSEMessage = {
|
|
514
|
+
id: getId(`${eventData.requestId}-message`),
|
|
515
|
+
type: eventData.payload.type,
|
|
516
|
+
data: eventData.payload.data,
|
|
517
|
+
timestamp: eventData.timestamp,
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const updatedEntry: SSENetworkEntry = {
|
|
521
|
+
...sseEntry,
|
|
522
|
+
messages: [...sseEntry.messages, newMessage].slice(
|
|
523
|
+
-MAX_SSE_MESSAGES_PER_CONNECTION
|
|
524
|
+
),
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
const newEntries = new Map(state.networkEntries);
|
|
528
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
529
|
+
return { networkEntries: newEntries };
|
|
530
|
+
});
|
|
531
|
+
break;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
case 'sse-error': {
|
|
535
|
+
const eventData = data as NetworkActivityEventMap['sse-error'];
|
|
536
|
+
set((state) => {
|
|
537
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
538
|
+
if (!entry || entry.type !== 'sse') return state;
|
|
539
|
+
|
|
540
|
+
const sseEntry = entry as SSENetworkEntry;
|
|
541
|
+
const updatedEntry: SSENetworkEntry = {
|
|
542
|
+
...sseEntry,
|
|
543
|
+
status: 'error',
|
|
544
|
+
error: eventData.error.message,
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const newEntries = new Map(state.networkEntries);
|
|
548
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
549
|
+
return { networkEntries: newEntries };
|
|
550
|
+
});
|
|
551
|
+
break;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
case 'sse-close': {
|
|
555
|
+
const eventData = data as NetworkActivityEventMap['sse-close'];
|
|
556
|
+
set((state) => {
|
|
557
|
+
const entry = state.networkEntries.get(eventData.requestId);
|
|
558
|
+
if (!entry || entry.type !== 'sse') return state;
|
|
559
|
+
|
|
560
|
+
const sseEntry = entry as SSENetworkEntry;
|
|
561
|
+
const updatedEntry: SSENetworkEntry = {
|
|
562
|
+
...sseEntry,
|
|
563
|
+
status: 'closed',
|
|
564
|
+
duration: eventData.timestamp - sseEntry.timestamp,
|
|
565
|
+
};
|
|
566
|
+
|
|
567
|
+
const newEntries = new Map(state.networkEntries);
|
|
568
|
+
newEntries.set(eventData.requestId, updatedEntry);
|
|
569
|
+
return { networkEntries: newEntries };
|
|
570
|
+
});
|
|
571
|
+
break;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
},
|
|
575
|
+
|
|
576
|
+
// Client management
|
|
577
|
+
client: {
|
|
578
|
+
setupClient: (client: NetworkActivityDevToolsClient) => {
|
|
579
|
+
const { handleEvent } = get();
|
|
580
|
+
|
|
581
|
+
// Subscribe to all events using the unified handler
|
|
582
|
+
const unsubscribeFunctions = [
|
|
583
|
+
client.onMessage('client-ui-settings', (data) =>
|
|
584
|
+
handleEvent('client-ui-settings', data)
|
|
585
|
+
),
|
|
586
|
+
client.onMessage('request-sent', (data) =>
|
|
587
|
+
handleEvent('request-sent', data)
|
|
588
|
+
),
|
|
589
|
+
client.onMessage('request-progress', (data) =>
|
|
590
|
+
handleEvent('request-progress', data)
|
|
591
|
+
),
|
|
592
|
+
client.onMessage('response-received', (data) =>
|
|
593
|
+
handleEvent('response-received', data)
|
|
594
|
+
),
|
|
595
|
+
client.onMessage('request-completed', (data) =>
|
|
596
|
+
handleEvent('request-completed', data)
|
|
597
|
+
),
|
|
598
|
+
client.onMessage('request-failed', (data) =>
|
|
599
|
+
handleEvent('request-failed', data)
|
|
600
|
+
),
|
|
601
|
+
client.onMessage('response-body', (data) =>
|
|
602
|
+
handleEvent('response-body', data)
|
|
424
603
|
),
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
status
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
604
|
+
client.onMessage('websocket-connect', (data) =>
|
|
605
|
+
handleEvent('websocket-connect', data)
|
|
606
|
+
),
|
|
607
|
+
client.onMessage('websocket-open', (data) =>
|
|
608
|
+
handleEvent('websocket-open', data)
|
|
609
|
+
),
|
|
610
|
+
client.onMessage('websocket-close', (data) =>
|
|
611
|
+
handleEvent('websocket-close', data)
|
|
612
|
+
),
|
|
613
|
+
client.onMessage('websocket-message-sent', (data) =>
|
|
614
|
+
handleEvent('websocket-message-sent', data)
|
|
615
|
+
),
|
|
616
|
+
client.onMessage('websocket-message-received', (data) =>
|
|
617
|
+
handleEvent('websocket-message-received', data)
|
|
618
|
+
),
|
|
619
|
+
client.onMessage('websocket-error', (data) =>
|
|
620
|
+
handleEvent('websocket-error', data)
|
|
621
|
+
),
|
|
622
|
+
client.onMessage('websocket-connection-status-changed', (data) =>
|
|
623
|
+
handleEvent('websocket-connection-status-changed', data)
|
|
624
|
+
),
|
|
625
|
+
client.onMessage('sse-open', (data) =>
|
|
626
|
+
handleEvent('sse-open', data)
|
|
627
|
+
),
|
|
628
|
+
client.onMessage('sse-message', (data) =>
|
|
629
|
+
handleEvent('sse-message', data)
|
|
630
|
+
),
|
|
631
|
+
client.onMessage('sse-error', (data) =>
|
|
632
|
+
handleEvent('sse-error', data)
|
|
633
|
+
),
|
|
634
|
+
client.onMessage('sse-close', (data) =>
|
|
635
|
+
handleEvent('sse-close', data)
|
|
636
|
+
),
|
|
637
|
+
];
|
|
638
|
+
|
|
639
|
+
// Store unsubscribe functions in the state for cleanup
|
|
640
|
+
set({
|
|
641
|
+
_unsubscribeFunctions: unsubscribeFunctions,
|
|
642
|
+
_client: client,
|
|
643
|
+
});
|
|
644
|
+
|
|
645
|
+
// Request client UI settings from React Native side
|
|
646
|
+
client.send('get-client-ui-settings', {});
|
|
647
|
+
},
|
|
648
|
+
|
|
649
|
+
cleanupClient: () => {
|
|
650
|
+
const { _unsubscribeFunctions, _client } = get();
|
|
651
|
+
|
|
652
|
+
if (_unsubscribeFunctions) {
|
|
653
|
+
_unsubscribeFunctions.forEach(
|
|
654
|
+
(unsubscribe: { remove: () => void }) => unsubscribe.remove()
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (_client) {
|
|
659
|
+
_client.send('network-disable', {});
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
set({
|
|
663
|
+
_unsubscribeFunctions: undefined,
|
|
664
|
+
_client: undefined,
|
|
665
|
+
});
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
}),
|
|
669
|
+
{
|
|
670
|
+
name: 'rozenite-network-activity-storage',
|
|
671
|
+
version: STORE_VERSION,
|
|
672
|
+
storage: createJSONStorage(() => localStorage, {
|
|
673
|
+
replacer: (key, value) => {
|
|
674
|
+
if (value instanceof Map) {
|
|
675
|
+
return {
|
|
676
|
+
_type: 'map',
|
|
677
|
+
value: Array.from(value.entries()),
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
return value;
|
|
681
|
+
},
|
|
682
|
+
reviver: (key, value) => {
|
|
683
|
+
if (
|
|
684
|
+
typeof value === 'object' &&
|
|
685
|
+
value !== null &&
|
|
686
|
+
'_type' in value &&
|
|
687
|
+
value._type === 'map'
|
|
688
|
+
) {
|
|
689
|
+
return new Map(value.value);
|
|
690
|
+
}
|
|
691
|
+
return value;
|
|
692
|
+
},
|
|
693
|
+
}),
|
|
694
|
+
partialize: (state) => ({ overrides: state.overrides }), // Persist only the overrides
|
|
473
695
|
}
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
// Client management
|
|
477
|
-
client: {
|
|
478
|
-
setupClient: (client: NetworkActivityDevToolsClient) => {
|
|
479
|
-
const { handleEvent } = get();
|
|
480
|
-
|
|
481
|
-
// Subscribe to all events using the unified handler
|
|
482
|
-
const unsubscribeFunctions = [
|
|
483
|
-
client.onMessage('request-sent', (data) =>
|
|
484
|
-
handleEvent('request-sent', data)
|
|
485
|
-
),
|
|
486
|
-
client.onMessage('response-received', (data) =>
|
|
487
|
-
handleEvent('response-received', data)
|
|
488
|
-
),
|
|
489
|
-
client.onMessage('request-completed', (data) =>
|
|
490
|
-
handleEvent('request-completed', data)
|
|
491
|
-
),
|
|
492
|
-
client.onMessage('request-failed', (data) =>
|
|
493
|
-
handleEvent('request-failed', data)
|
|
494
|
-
),
|
|
495
|
-
client.onMessage('response-body', (data) =>
|
|
496
|
-
handleEvent('response-body', data)
|
|
497
|
-
),
|
|
498
|
-
client.onMessage('websocket-connect', (data) =>
|
|
499
|
-
handleEvent('websocket-connect', data)
|
|
500
|
-
),
|
|
501
|
-
client.onMessage('websocket-open', (data) =>
|
|
502
|
-
handleEvent('websocket-open', data)
|
|
503
|
-
),
|
|
504
|
-
client.onMessage('websocket-close', (data) =>
|
|
505
|
-
handleEvent('websocket-close', data)
|
|
506
|
-
),
|
|
507
|
-
client.onMessage('websocket-message-sent', (data) =>
|
|
508
|
-
handleEvent('websocket-message-sent', data)
|
|
509
|
-
),
|
|
510
|
-
client.onMessage('websocket-message-received', (data) =>
|
|
511
|
-
handleEvent('websocket-message-received', data)
|
|
512
|
-
),
|
|
513
|
-
client.onMessage('websocket-error', (data) =>
|
|
514
|
-
handleEvent('websocket-error', data)
|
|
515
|
-
),
|
|
516
|
-
client.onMessage('websocket-connection-status-changed', (data) =>
|
|
517
|
-
handleEvent('websocket-connection-status-changed', data)
|
|
518
|
-
),
|
|
519
|
-
client.onMessage('sse-open', (data) => handleEvent('sse-open', data)),
|
|
520
|
-
client.onMessage('sse-message', (data) =>
|
|
521
|
-
handleEvent('sse-message', data)
|
|
522
|
-
),
|
|
523
|
-
client.onMessage('sse-error', (data) =>
|
|
524
|
-
handleEvent('sse-error', data)
|
|
525
|
-
),
|
|
526
|
-
client.onMessage('sse-close', (data) =>
|
|
527
|
-
handleEvent('sse-close', data)
|
|
528
|
-
),
|
|
529
|
-
];
|
|
530
|
-
|
|
531
|
-
// Store unsubscribe functions in the state for cleanup
|
|
532
|
-
set({
|
|
533
|
-
_unsubscribeFunctions: unsubscribeFunctions,
|
|
534
|
-
_client: client,
|
|
535
|
-
});
|
|
536
|
-
},
|
|
537
|
-
|
|
538
|
-
cleanupClient: () => {
|
|
539
|
-
const { _unsubscribeFunctions, _client } = get();
|
|
540
|
-
|
|
541
|
-
if (_unsubscribeFunctions) {
|
|
542
|
-
_unsubscribeFunctions.forEach((unsubscribe: { remove: () => void }) =>
|
|
543
|
-
unsubscribe.remove()
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
if (_client) {
|
|
548
|
-
_client.send('network-disable', {});
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
set({
|
|
552
|
-
_unsubscribeFunctions: undefined,
|
|
553
|
-
_client: undefined,
|
|
554
|
-
});
|
|
555
|
-
},
|
|
556
|
-
},
|
|
557
|
-
}));
|
|
696
|
+
)
|
|
697
|
+
);
|
|
558
698
|
|
|
559
699
|
export const store = createNetworkActivityStore();
|