@rozenite/network-activity-plugin 1.0.0-alpha.8 → 1.0.0-alpha.9
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-lNMijPJ4.js → App-CA1Fbh0I.js} +11995 -10804
- package/dist/assets/{App-R2ZMH9wJ.css → App-DoHQsY5s.css} +46 -0
- package/dist/event-source.cjs +22 -0
- package/dist/event-source.js +23 -0
- package/dist/rozenite.json +1 -1
- package/dist/src/react-native/{network-inspector.d.ts → http/network-inspector.d.ts} +1 -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/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 +5 -2
- package/dist/src/shared/sse-events.d.ts +35 -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 +1 -1
- package/dist/src/ui/components/JsonTreeCopyableItem.d.ts +7 -0
- package/dist/src/ui/components/RequestList.d.ts +6 -26
- package/dist/src/ui/components/SidePanel.d.ts +1 -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 +17 -0
- package/dist/src/ui/state/model.d.ts +98 -0
- package/dist/src/ui/state/store.d.ts +24 -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/copyToClipboard.d.ts +1 -0
- package/dist/src/ui/utils/getId.d.ts +1 -0
- package/dist/src/ui/utils/getStatusColor.d.ts +1 -0
- package/dist/useNetworkActivityDevTools.cjs +423 -34
- package/dist/useNetworkActivityDevTools.js +421 -34
- package/package.json +19 -8
- package/src/react-native/{network-inspector.ts → http/network-inspector.ts} +13 -34
- 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 +117 -0
- package/src/react-native/sse/sse-interceptor.ts +162 -0
- package/src/react-native/sse/types.ts +9 -0
- package/src/react-native/useNetworkActivityDevTools.ts +75 -1
- 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 +6 -2
- package/src/shared/sse-events.ts +44 -0
- package/src/shared/websocket-events.ts +79 -0
- package/src/ui/components/JsonTree.tsx +13 -0
- package/src/ui/components/JsonTreeCopyableItem.tsx +33 -0
- package/src/ui/components/RequestList.tsx +42 -124
- package/src/ui/components/SidePanel.tsx +323 -0
- package/src/ui/components/Tabs.tsx +1 -1
- package/src/ui/components/Toolbar.tsx +45 -0
- package/src/ui/hooks/useCopyToClipboard.ts +28 -0
- package/src/ui/state/derived.ts +112 -0
- package/src/ui/state/hooks.ts +44 -0
- package/src/ui/state/model.ts +129 -0
- package/src/ui/state/store.ts +559 -0
- package/src/ui/tabs/CookiesTab.tsx +162 -176
- package/src/ui/tabs/HeadersTab.tsx +23 -30
- package/src/ui/tabs/MessagesTab.tsx +276 -0
- package/src/ui/tabs/RequestTab.tsx +8 -13
- package/src/ui/tabs/ResponseTab.tsx +6 -10
- package/src/ui/tabs/SSEMessagesTab.tsx +213 -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/copyToClipboard.ts +3 -0
- package/src/ui/utils/getId.ts +10 -0
- package/src/ui/utils/getStatusColor.ts +15 -0
- package/src/ui/views/InspectorView.tsx +24 -320
- package/tailwind.config.ts +3 -0
- package/vite.config.ts +12 -0
- /package/dist/src/react-native/{network-requests-registry.d.ts → http/network-requests-registry.d.ts} +0 -0
- /package/dist/src/react-native/{xhr-interceptor.d.ts → http/xhr-interceptor.d.ts} +0 -0
- /package/src/react-native/{network-requests-registry.ts → http/network-requests-registry.ts} +0 -0
- /package/src/react-native/{xhr-interceptor.ts → http/xhr-interceptor.ts} +0 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { memoize } from 'proxy-memoize';
|
|
2
|
+
import { NetworkActivityState } from './store';
|
|
3
|
+
import {
|
|
4
|
+
ProcessedRequest,
|
|
5
|
+
HttpNetworkEntry,
|
|
6
|
+
WebSocketNetworkEntry,
|
|
7
|
+
SSENetworkEntry,
|
|
8
|
+
} from './model';
|
|
9
|
+
|
|
10
|
+
export const getProcessedRequests = memoize((state: NetworkActivityState) => {
|
|
11
|
+
const { networkEntries } = state;
|
|
12
|
+
const requests: ProcessedRequest[] = [];
|
|
13
|
+
|
|
14
|
+
for (const entry of networkEntries.values()) {
|
|
15
|
+
if (entry.type === 'http') {
|
|
16
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
17
|
+
requests.push({
|
|
18
|
+
id: httpEntry.id,
|
|
19
|
+
type: 'http',
|
|
20
|
+
name: httpEntry.request.url,
|
|
21
|
+
status: httpEntry.status,
|
|
22
|
+
timestamp: httpEntry.timestamp,
|
|
23
|
+
duration: httpEntry.duration,
|
|
24
|
+
size: httpEntry.size,
|
|
25
|
+
method: httpEntry.request.method,
|
|
26
|
+
httpStatus: httpEntry.response?.status,
|
|
27
|
+
});
|
|
28
|
+
} else if (entry.type === 'websocket') {
|
|
29
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
30
|
+
requests.push({
|
|
31
|
+
id: wsEntry.id,
|
|
32
|
+
type: 'websocket',
|
|
33
|
+
name: wsEntry.connection.url,
|
|
34
|
+
status: wsEntry.status,
|
|
35
|
+
timestamp: wsEntry.timestamp,
|
|
36
|
+
duration: wsEntry.duration,
|
|
37
|
+
method: 'WS',
|
|
38
|
+
httpStatus: 0,
|
|
39
|
+
});
|
|
40
|
+
} else if (entry.type === 'sse') {
|
|
41
|
+
const sseEntry = entry as SSENetworkEntry;
|
|
42
|
+
requests.push({
|
|
43
|
+
id: sseEntry.id,
|
|
44
|
+
type: 'sse',
|
|
45
|
+
name: sseEntry.request.url,
|
|
46
|
+
status: sseEntry.status,
|
|
47
|
+
timestamp: sseEntry.timestamp,
|
|
48
|
+
duration: sseEntry.duration,
|
|
49
|
+
method: 'SSE',
|
|
50
|
+
httpStatus: 0,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return requests.sort((a, b) => b.timestamp - a.timestamp);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const getSelectedRequest = memoize((state: NetworkActivityState) => {
|
|
59
|
+
const { selectedRequestId, networkEntries } = state;
|
|
60
|
+
if (!selectedRequestId) return null;
|
|
61
|
+
return networkEntries.get(selectedRequestId) || null;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export const getRequestSummary = (
|
|
65
|
+
requestId: string
|
|
66
|
+
): ((state: NetworkActivityState) => ProcessedRequest | null) =>
|
|
67
|
+
memoize((state: NetworkActivityState) => {
|
|
68
|
+
const { networkEntries } = state;
|
|
69
|
+
const entry = networkEntries.get(requestId);
|
|
70
|
+
if (!entry) return null;
|
|
71
|
+
|
|
72
|
+
if (entry.type === 'http') {
|
|
73
|
+
const httpEntry = entry as HttpNetworkEntry;
|
|
74
|
+
return {
|
|
75
|
+
id: httpEntry.id,
|
|
76
|
+
type: 'http',
|
|
77
|
+
name: httpEntry.request.url,
|
|
78
|
+
status: httpEntry.status,
|
|
79
|
+
timestamp: httpEntry.timestamp,
|
|
80
|
+
duration: httpEntry.duration,
|
|
81
|
+
size: httpEntry.size,
|
|
82
|
+
method: httpEntry.request.method,
|
|
83
|
+
httpStatus: httpEntry.response?.status || 0,
|
|
84
|
+
};
|
|
85
|
+
} else if (entry.type === 'websocket') {
|
|
86
|
+
const wsEntry = entry as WebSocketNetworkEntry;
|
|
87
|
+
return {
|
|
88
|
+
id: wsEntry.id,
|
|
89
|
+
type: 'websocket',
|
|
90
|
+
name: wsEntry.connection.url,
|
|
91
|
+
status: wsEntry.status,
|
|
92
|
+
timestamp: wsEntry.timestamp,
|
|
93
|
+
duration: wsEntry.duration,
|
|
94
|
+
method: 'WS',
|
|
95
|
+
httpStatus: 0,
|
|
96
|
+
};
|
|
97
|
+
} else if (entry.type === 'sse') {
|
|
98
|
+
const sseEntry = entry as SSENetworkEntry;
|
|
99
|
+
return {
|
|
100
|
+
id: sseEntry.id,
|
|
101
|
+
type: 'sse',
|
|
102
|
+
name: sseEntry.request.url,
|
|
103
|
+
status: sseEntry.status,
|
|
104
|
+
timestamp: sseEntry.timestamp,
|
|
105
|
+
duration: sseEntry.duration,
|
|
106
|
+
method: 'SSE',
|
|
107
|
+
httpStatus: 0,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useStore } from 'zustand';
|
|
2
|
+
import { store } from './store';
|
|
3
|
+
import type { NetworkActivityState } from './store';
|
|
4
|
+
import { getProcessedRequests, getSelectedRequest } from './derived';
|
|
5
|
+
|
|
6
|
+
export const useNetworkActivityStore = <T>(
|
|
7
|
+
selector: (state: NetworkActivityState) => T
|
|
8
|
+
): T => {
|
|
9
|
+
return useStore(store, selector);
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const useProcessedRequests = () => {
|
|
13
|
+
return useNetworkActivityStore(getProcessedRequests);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const useSelectedRequest = () => {
|
|
17
|
+
return useNetworkActivityStore(getSelectedRequest);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export const useHasSelectedRequest = () => {
|
|
21
|
+
return useNetworkActivityStore((state) => !!getSelectedRequest(state));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const useSelectedRequestId = () => {
|
|
25
|
+
return useNetworkActivityStore((state) => state.selectedRequestId);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const useIsRecording = () => {
|
|
29
|
+
return useNetworkActivityStore((state) => state.isRecording);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const useNetworkActivityActions = () => {
|
|
33
|
+
return useNetworkActivityStore((state) => state.actions);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const useNetworkActivityClientManagement = () => {
|
|
37
|
+
return useNetworkActivityStore((state) => state.client);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const useWebSocketMessages = (requestId: string) => {
|
|
41
|
+
return useNetworkActivityStore(
|
|
42
|
+
(state) => state.websocketMessages.get(requestId) || []
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Initiator, ResourceType } from '../../shared/client';
|
|
2
|
+
|
|
3
|
+
export type RequestId = string;
|
|
4
|
+
export type Timestamp = number;
|
|
5
|
+
export type SocketId = number;
|
|
6
|
+
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
|
|
7
|
+
|
|
8
|
+
export type NetworkEntryType = 'http' | 'websocket' | 'sse';
|
|
9
|
+
|
|
10
|
+
/* HTTP */
|
|
11
|
+
export type HttpData = {
|
|
12
|
+
type: string;
|
|
13
|
+
data: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type HttpRequest = {
|
|
17
|
+
url: string;
|
|
18
|
+
method: HttpMethod;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
body?: HttpData;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type HttpResponse = {
|
|
24
|
+
url: string;
|
|
25
|
+
status: number;
|
|
26
|
+
statusText: string;
|
|
27
|
+
headers: Record<string, string>;
|
|
28
|
+
contentType: string;
|
|
29
|
+
size: number;
|
|
30
|
+
responseTime: Timestamp;
|
|
31
|
+
body?: HttpData;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type HttpStatus = 'pending' | 'loading' | 'finished' | 'failed';
|
|
35
|
+
|
|
36
|
+
export type HttpNetworkEntry = {
|
|
37
|
+
id: RequestId;
|
|
38
|
+
type: 'http';
|
|
39
|
+
timestamp: Timestamp;
|
|
40
|
+
duration?: number;
|
|
41
|
+
|
|
42
|
+
request: HttpRequest;
|
|
43
|
+
response?: HttpResponse;
|
|
44
|
+
status: HttpStatus;
|
|
45
|
+
error?: string;
|
|
46
|
+
canceled?: boolean;
|
|
47
|
+
ttfb?: number;
|
|
48
|
+
size?: number;
|
|
49
|
+
initiator?: Initiator;
|
|
50
|
+
resourceType?: ResourceType;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/* SSE */
|
|
54
|
+
export type SSEMessage = {
|
|
55
|
+
id: string;
|
|
56
|
+
data: string;
|
|
57
|
+
timestamp: Timestamp;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type SSEStatus = 'connecting' | 'open' | 'closed' | 'error';
|
|
61
|
+
|
|
62
|
+
export type SSENetworkEntry = {
|
|
63
|
+
id: RequestId;
|
|
64
|
+
type: 'sse';
|
|
65
|
+
timestamp: Timestamp;
|
|
66
|
+
duration?: number;
|
|
67
|
+
|
|
68
|
+
request: HttpRequest;
|
|
69
|
+
response?: HttpResponse;
|
|
70
|
+
status: SSEStatus;
|
|
71
|
+
messages: SSEMessage[];
|
|
72
|
+
error?: string;
|
|
73
|
+
initiator?: Initiator;
|
|
74
|
+
resourceType?: ResourceType;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/* WebSocket */
|
|
78
|
+
export type WebSocketConnection = {
|
|
79
|
+
url: string;
|
|
80
|
+
socketId: SocketId;
|
|
81
|
+
protocols?: string[];
|
|
82
|
+
options?: string[];
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export type WebSocketMessage = {
|
|
86
|
+
id: string;
|
|
87
|
+
direction: 'sent' | 'received';
|
|
88
|
+
data: string;
|
|
89
|
+
messageType: 'text' | 'binary';
|
|
90
|
+
timestamp: Timestamp;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export type WebSocketStatus =
|
|
94
|
+
| 'connecting'
|
|
95
|
+
| 'open'
|
|
96
|
+
| 'closing'
|
|
97
|
+
| 'closed'
|
|
98
|
+
| 'error';
|
|
99
|
+
|
|
100
|
+
export type WebSocketNetworkEntry = {
|
|
101
|
+
id: RequestId;
|
|
102
|
+
type: 'websocket';
|
|
103
|
+
timestamp: Timestamp;
|
|
104
|
+
duration?: number;
|
|
105
|
+
|
|
106
|
+
connection: WebSocketConnection;
|
|
107
|
+
status: WebSocketStatus;
|
|
108
|
+
error?: string;
|
|
109
|
+
closeCode?: number;
|
|
110
|
+
closeReason?: string;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/* Shared */
|
|
114
|
+
export type NetworkEntry =
|
|
115
|
+
| HttpNetworkEntry
|
|
116
|
+
| WebSocketNetworkEntry
|
|
117
|
+
| SSENetworkEntry;
|
|
118
|
+
|
|
119
|
+
export type ProcessedRequest = {
|
|
120
|
+
id: RequestId;
|
|
121
|
+
type: NetworkEntryType;
|
|
122
|
+
name: string;
|
|
123
|
+
status: HttpStatus | WebSocketStatus | SSEStatus;
|
|
124
|
+
timestamp: Timestamp;
|
|
125
|
+
duration?: number;
|
|
126
|
+
size?: number;
|
|
127
|
+
method: HttpMethod | 'WS' | 'SSE';
|
|
128
|
+
httpStatus?: number;
|
|
129
|
+
};
|