@rozenite/network-activity-plugin 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +3 -5
- package/dist/{panel.html → App.html} +3 -3
- package/dist/assets/App-CA1Fbh0I.js +25364 -0
- package/dist/assets/App-DoHQsY5s.css +1276 -0
- package/dist/event-source.cjs +22 -0
- package/dist/event-source.js +23 -0
- package/dist/react-native.cjs +8 -1
- package/dist/react-native.d.ts +1 -5
- package/dist/react-native.js +6 -171
- package/dist/rozenite.config.d.ts +7 -0
- package/dist/rozenite.json +1 -1
- package/dist/src/react-native/http/network-inspector.d.ts +8 -0
- package/dist/src/react-native/http/network-requests-registry.d.ts +6 -0
- package/dist/src/react-native/http/xhr-interceptor.d.ts +38 -0
- 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 -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 +68 -0
- package/dist/src/shared/sse-events.d.ts +35 -0
- package/dist/src/shared/websocket-events.d.ts +60 -0
- package/dist/src/ui/App.d.ts +1 -0
- package/dist/src/ui/components/Badge.d.ts +9 -0
- package/dist/src/ui/components/Button.d.ts +11 -0
- package/dist/src/ui/components/Input.d.ts +3 -0
- package/dist/src/ui/components/JsonTree.d.ts +5 -0
- package/dist/src/ui/components/JsonTreeCopyableItem.d.ts +7 -0
- package/dist/src/ui/components/RequestList.d.ts +25 -0
- package/dist/src/ui/components/ScrollArea.d.ts +4 -0
- package/dist/src/ui/components/Separator.d.ts +3 -0
- 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 +5 -0
- package/dist/src/ui/tabs/HeadersTab.d.ts +5 -0
- package/dist/src/ui/tabs/MessagesTab.d.ts +5 -0
- package/dist/src/ui/tabs/RequestTab.d.ts +5 -0
- package/dist/src/ui/tabs/ResponseTab.d.ts +6 -0
- package/dist/src/ui/tabs/SSEMessagesTab.d.ts +5 -0
- package/dist/src/ui/tabs/TimingTab.d.ts +5 -0
- package/dist/src/ui/types.d.ts +26 -0
- package/dist/src/ui/utils/assert.d.ts +1 -0
- package/dist/src/ui/utils/cn.d.ts +2 -0
- package/dist/src/ui/utils/copyToClipboard.d.ts +1 -0
- package/dist/src/ui/utils/getHttpHeaderValue.d.ts +2 -0
- package/dist/src/ui/utils/getId.d.ts +1 -0
- package/dist/src/ui/utils/getStatusColor.d.ts +1 -0
- package/dist/src/ui/views/InspectorView.d.ts +5 -0
- package/dist/src/ui/views/LoadingView.d.ts +1 -0
- package/dist/useNetworkActivityDevTools.cjs +759 -0
- package/dist/useNetworkActivityDevTools.js +757 -0
- package/package.json +31 -10
- package/postcss.config.js +6 -0
- package/project.json +12 -0
- package/react-native.ts +2 -1
- package/rozenite.config.ts +2 -2
- package/src/css-modules.d.ts +1 -1
- package/src/react-native/http/network-inspector.ts +226 -0
- package/src/react-native/http/network-requests-registry.ts +52 -0
- package/src/react-native/http/xhr-interceptor.ts +211 -0
- package/src/react-native/http/xml-request.d.ts +34 -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 +73 -210
- 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 +86 -0
- package/src/shared/sse-events.ts +44 -0
- package/src/shared/websocket-events.ts +79 -0
- package/src/ui/App.tsx +19 -0
- package/src/ui/components/Badge.tsx +36 -0
- package/src/ui/components/Button.tsx +56 -0
- package/src/ui/components/Input.tsx +22 -0
- package/src/ui/components/JsonTree.tsx +50 -0
- package/src/ui/components/JsonTreeCopyableItem.tsx +33 -0
- package/src/ui/components/RequestList.tsx +295 -0
- package/src/ui/components/ScrollArea.tsx +48 -0
- package/src/ui/components/Separator.tsx +31 -0
- package/src/ui/components/SidePanel.tsx +323 -0
- package/src/ui/components/Tabs.tsx +55 -0
- package/src/ui/components/Toolbar.tsx +45 -0
- package/src/ui/globals.css +90 -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 +279 -0
- package/src/ui/tabs/HeadersTab.tsx +110 -0
- package/src/ui/tabs/MessagesTab.tsx +276 -0
- package/src/ui/tabs/RequestTab.tsx +69 -0
- package/src/ui/tabs/ResponseTab.tsx +138 -0
- package/src/ui/tabs/SSEMessagesTab.tsx +213 -0
- package/src/ui/tabs/TimingTab.tsx +60 -0
- package/src/ui/types.ts +34 -0
- package/src/ui/utils/assert.ts +5 -0
- package/src/ui/utils/cn.ts +6 -0
- package/src/ui/utils/copyToClipboard.ts +3 -0
- package/src/ui/utils/getHttpHeaderValue.ts +14 -0
- package/src/ui/utils/getId.ts +10 -0
- package/src/ui/utils/getStatusColor.ts +15 -0
- package/src/ui/views/InspectorView.tsx +53 -0
- package/src/ui/views/LoadingView.tsx +19 -0
- package/tailwind.config.ts +96 -0
- package/tsconfig.json +13 -6
- package/tsconfig.tsbuildinfo +1 -0
- package/vite.config.ts +13 -1
- package/dist/assets/panel-C5YgUUj5.js +0 -54
- package/dist/assets/panel-NCVczPb1.css +0 -1
- package/src/types/network.ts +0 -153
- package/src/ui/components.module.css +0 -158
- package/src/ui/components.tsx +0 -219
- package/src/ui/network-details.module.css +0 -57
- package/src/ui/network-details.tsx +0 -134
- package/src/ui/network-list.module.css +0 -122
- package/src/ui/network-list.tsx +0 -145
- package/src/ui/network-toolbar.module.css +0 -9
- package/src/ui/network-toolbar.tsx +0 -40
- package/src/ui/panel.module.css +0 -61
- package/src/ui/panel.tsx +0 -201
- package/src/ui/tanstack-query.tsx +0 -197
- package/src/ui/utils.ts +0 -89
package/src/ui/panel.tsx
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
-
import { useRozeniteDevToolsClient } from "@rozenite/plugin-bridge";
|
|
3
|
-
import { NetworkEventMap, NetworkEntry } from '../types/network';
|
|
4
|
-
import styles from './panel.module.css';
|
|
5
|
-
import { NetworkToolbar } from './network-toolbar';
|
|
6
|
-
import { PanelHeader } from './components';
|
|
7
|
-
import { NetworkList } from './network-list';
|
|
8
|
-
import { NetworkDetails } from './network-details';
|
|
9
|
-
|
|
10
|
-
export default function NetworkActivityPanel() {
|
|
11
|
-
const client = useRozeniteDevToolsClient<NetworkEventMap>({
|
|
12
|
-
pluginId: '@rozenite/network-activity-plugin',
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const [networkEntries, setNetworkEntries] = useState<Map<string, NetworkEntry>>(new Map());
|
|
16
|
-
const [selectedRequestId, setSelectedRequestId] = useState<string | null>(null);
|
|
17
|
-
const [isRecording, setIsRecording] = useState(true);
|
|
18
|
-
const [containerHeight, setContainerHeight] = useState(0);
|
|
19
|
-
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
20
|
-
|
|
21
|
-
// Convert Map to sorted array for rendering
|
|
22
|
-
const sortedEntries = useMemo(() => {
|
|
23
|
-
return Array.from(networkEntries.values())
|
|
24
|
-
.sort((a, b) => b.startTime - a.startTime);
|
|
25
|
-
}, [networkEntries]);
|
|
26
|
-
|
|
27
|
-
const selectedEntry = selectedRequestId ? networkEntries.get(selectedRequestId) || null : null;
|
|
28
|
-
|
|
29
|
-
useEffect(() => {
|
|
30
|
-
if (!client) return;
|
|
31
|
-
if (!isRecording) return;
|
|
32
|
-
|
|
33
|
-
const subscriptions: Array<{ remove: () => void }> = [];
|
|
34
|
-
|
|
35
|
-
// Subscribe to Network events
|
|
36
|
-
subscriptions.push(
|
|
37
|
-
client.onMessage('Network.requestWillBeSent', (payload) => {
|
|
38
|
-
setNetworkEntries(prev => {
|
|
39
|
-
const newMap = new Map(prev);
|
|
40
|
-
newMap.set(payload.requestId, {
|
|
41
|
-
requestId: payload.requestId,
|
|
42
|
-
request: payload,
|
|
43
|
-
status: 'pending',
|
|
44
|
-
startTime: payload.timestamp,
|
|
45
|
-
});
|
|
46
|
-
return newMap;
|
|
47
|
-
});
|
|
48
|
-
})
|
|
49
|
-
);
|
|
50
|
-
|
|
51
|
-
subscriptions.push(
|
|
52
|
-
client.onMessage('Network.requestWillBeSentExtraInfo', (payload) => {
|
|
53
|
-
setNetworkEntries(prev => {
|
|
54
|
-
const newMap = new Map(prev);
|
|
55
|
-
const entry = newMap.get(payload.requestId);
|
|
56
|
-
if (entry) {
|
|
57
|
-
newMap.set(payload.requestId, {
|
|
58
|
-
...entry,
|
|
59
|
-
extraInfo: payload,
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
return newMap;
|
|
63
|
-
});
|
|
64
|
-
})
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
subscriptions.push(
|
|
68
|
-
client.onMessage('Network.responseReceived', (payload) => {
|
|
69
|
-
setNetworkEntries(prev => {
|
|
70
|
-
const newMap = new Map(prev);
|
|
71
|
-
const entry = newMap.get(payload.requestId);
|
|
72
|
-
if (entry) {
|
|
73
|
-
newMap.set(payload.requestId, {
|
|
74
|
-
...entry,
|
|
75
|
-
response: payload,
|
|
76
|
-
status: 'loading',
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
return newMap;
|
|
80
|
-
});
|
|
81
|
-
})
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
subscriptions.push(
|
|
85
|
-
client.onMessage('Network.loadingFinished', (payload) => {
|
|
86
|
-
setNetworkEntries(prev => {
|
|
87
|
-
const newMap = new Map(prev);
|
|
88
|
-
const entry = newMap.get(payload.requestId);
|
|
89
|
-
if (entry) {
|
|
90
|
-
const endTime = payload.timestamp;
|
|
91
|
-
const duration = (endTime - entry.startTime) * 1000; // Convert to milliseconds
|
|
92
|
-
newMap.set(payload.requestId, {
|
|
93
|
-
...entry,
|
|
94
|
-
loadingFinished: payload,
|
|
95
|
-
status: 'finished',
|
|
96
|
-
endTime,
|
|
97
|
-
duration,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
return newMap;
|
|
101
|
-
});
|
|
102
|
-
})
|
|
103
|
-
);
|
|
104
|
-
|
|
105
|
-
subscriptions.push(
|
|
106
|
-
client.onMessage('Network.loadingFailed', (payload) => {
|
|
107
|
-
setNetworkEntries(prev => {
|
|
108
|
-
const newMap = new Map(prev);
|
|
109
|
-
const entry = newMap.get(payload.requestId);
|
|
110
|
-
if (entry) {
|
|
111
|
-
const endTime = payload.timestamp;
|
|
112
|
-
const duration = (endTime - entry.startTime) * 1000; // Convert to milliseconds
|
|
113
|
-
newMap.set(payload.requestId, {
|
|
114
|
-
...entry,
|
|
115
|
-
loadingFailed: payload,
|
|
116
|
-
status: 'failed',
|
|
117
|
-
endTime,
|
|
118
|
-
duration,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
return newMap;
|
|
122
|
-
});
|
|
123
|
-
})
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
return () => {
|
|
127
|
-
subscriptions.forEach(sub => sub.remove());
|
|
128
|
-
};
|
|
129
|
-
}, [client, isRecording]);
|
|
130
|
-
|
|
131
|
-
const clearNetworkLog = () => {
|
|
132
|
-
setNetworkEntries(new Map());
|
|
133
|
-
setSelectedRequestId(null);
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
const toggleRecording = () => {
|
|
137
|
-
setIsRecording(!isRecording);
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const handleSelectRequest = (requestId: string) => {
|
|
141
|
-
setSelectedRequestId(requestId);
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
// Update container height on mount and resize
|
|
145
|
-
useEffect(() => {
|
|
146
|
-
const updateHeight = () => {
|
|
147
|
-
if (containerRef.current) {
|
|
148
|
-
const rect = containerRef.current.getBoundingClientRect();
|
|
149
|
-
setContainerHeight(rect.height - 120); // Subtract toolbar and header height
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
updateHeight();
|
|
154
|
-
window.addEventListener('resize', updateHeight);
|
|
155
|
-
return () => window.removeEventListener('resize', updateHeight);
|
|
156
|
-
}, []);
|
|
157
|
-
|
|
158
|
-
return (
|
|
159
|
-
<div
|
|
160
|
-
ref={containerRef}
|
|
161
|
-
className={styles.container}
|
|
162
|
-
>
|
|
163
|
-
{/* Toolbar */}
|
|
164
|
-
<NetworkToolbar
|
|
165
|
-
isRecording={isRecording}
|
|
166
|
-
onToggleRecording={toggleRecording}
|
|
167
|
-
onClear={clearNetworkLog}
|
|
168
|
-
requestCount={sortedEntries.length}
|
|
169
|
-
/>
|
|
170
|
-
|
|
171
|
-
{/* Main Content */}
|
|
172
|
-
<div className={styles.mainContent}>
|
|
173
|
-
{/* Network List */}
|
|
174
|
-
<div className={styles.networkListContainer}>
|
|
175
|
-
{/* List Header */}
|
|
176
|
-
<PanelHeader>
|
|
177
|
-
<div className={styles.headerStatus}>Status</div>
|
|
178
|
-
<div className={styles.headerMethod}>Method</div>
|
|
179
|
-
<div className={styles.headerName}>Name</div>
|
|
180
|
-
<div className={styles.headerTime}>Time</div>
|
|
181
|
-
<div className={styles.headerSize}>Size</div>
|
|
182
|
-
</PanelHeader>
|
|
183
|
-
|
|
184
|
-
<div className={styles.listContent}>
|
|
185
|
-
<NetworkList
|
|
186
|
-
entries={sortedEntries}
|
|
187
|
-
selectedRequestId={selectedRequestId}
|
|
188
|
-
onSelect={handleSelectRequest}
|
|
189
|
-
height={containerHeight}
|
|
190
|
-
/>
|
|
191
|
-
</div>
|
|
192
|
-
</div>
|
|
193
|
-
|
|
194
|
-
{/* Details Panel */}
|
|
195
|
-
<div className={styles.detailsContainer}>
|
|
196
|
-
<NetworkDetails entry={selectedEntry} />
|
|
197
|
-
</div>
|
|
198
|
-
</div>
|
|
199
|
-
</div>
|
|
200
|
-
);
|
|
201
|
-
}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
import { QueryCacheNotifyEvent, MutationCacheNotifyEvent, QueryClient, QueryClientProvider, Query, Mutation } from '@tanstack/react-query';
|
|
2
|
-
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools';
|
|
3
|
-
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
4
|
-
import { useEffect, useRef } from 'react';
|
|
5
|
-
|
|
6
|
-
const queryClient = new QueryClient({
|
|
7
|
-
defaultOptions: {
|
|
8
|
-
queries: {
|
|
9
|
-
queryFn: async () => {
|
|
10
|
-
// Prevent refetch from throwing an error
|
|
11
|
-
return Promise.resolve(null);
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
},
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
type DevToolsEventMap = {
|
|
18
|
-
"DEVTOOLS_TO_DEVICE": unknown;
|
|
19
|
-
"DEVICE_TO_DEVTOOLS": QueryCacheNotifyEvent | MutationCacheNotifyEvent;
|
|
20
|
-
"DEVICE_TO_DEVTOOLS_ACK": { requestId: string; success: boolean };
|
|
21
|
-
"DEVICE_TO_DEVTOOLS_INITIAL_DATA": { queries: Query[]; mutations: Mutation[] };
|
|
22
|
-
"DEVTOOLS_TO_DEVICE_INITIAL_DATA_REQUEST": unknown;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const Wrapped = () => {
|
|
26
|
-
const client = useRozeniteDevToolsClient<DevToolsEventMap>({
|
|
27
|
-
pluginId: '@rozenite/tanstack-query-plugin',
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
// Track pending acknowledgments to prevent feedback loops
|
|
31
|
-
const pendingAcknowledgment = useRef<Set<string>>(new Set());
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
if (!client) return;
|
|
35
|
-
client.send("DEVTOOLS_TO_DEVICE_INITIAL_DATA_REQUEST", null);
|
|
36
|
-
}, [client]);
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (!client) return;
|
|
40
|
-
|
|
41
|
-
const handleEvent = (event: Event) => {
|
|
42
|
-
const detail = (event as CustomEvent).detail;
|
|
43
|
-
|
|
44
|
-
// Generate a unique request ID for this DevTools action
|
|
45
|
-
const requestId = `devtools-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
46
|
-
|
|
47
|
-
// Mark that we're waiting for acknowledgment
|
|
48
|
-
pendingAcknowledgment.current.add(requestId);
|
|
49
|
-
|
|
50
|
-
// Add the request ID to the event detail
|
|
51
|
-
const eventWithRequestId = {
|
|
52
|
-
...detail,
|
|
53
|
-
requestId,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
client.send("DEVTOOLS_TO_DEVICE", eventWithRequestId);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
window.addEventListener('@tanstack/query-devtools-event', handleEvent);
|
|
60
|
-
return () => window.removeEventListener('@tanstack/query-devtools-event', handleEvent);
|
|
61
|
-
}, [client])
|
|
62
|
-
|
|
63
|
-
useEffect(() => {
|
|
64
|
-
if (!client) return;
|
|
65
|
-
|
|
66
|
-
const ackSubscription = client.onMessage("DEVICE_TO_DEVTOOLS_ACK", (ack) => {
|
|
67
|
-
// Remove the request from pending acknowledgments
|
|
68
|
-
pendingAcknowledgment.current.delete(ack.requestId);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
const subscription = client.onMessage("DEVICE_TO_DEVTOOLS", (event) => {
|
|
72
|
-
// Don't reflect events if we're waiting for acknowledgments
|
|
73
|
-
if (pendingAcknowledgment.current.size > 0) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
if ('query' in event) {
|
|
78
|
-
const { query, type } = event as QueryCacheNotifyEvent;
|
|
79
|
-
const queryCache = queryClient.getQueryCache();
|
|
80
|
-
|
|
81
|
-
if (type === 'updated') {
|
|
82
|
-
const existingQuery = queryCache.get(query.queryHash);
|
|
83
|
-
if (existingQuery) {
|
|
84
|
-
existingQuery.setState(query.state);
|
|
85
|
-
} else {
|
|
86
|
-
queryCache.build(
|
|
87
|
-
queryClient,
|
|
88
|
-
{
|
|
89
|
-
queryKey: query.queryKey,
|
|
90
|
-
queryHash: query.queryHash,
|
|
91
|
-
},
|
|
92
|
-
query.state
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
} else if (type === 'added') {
|
|
96
|
-
const existingQuery = queryCache.get(query.queryHash);
|
|
97
|
-
if (!existingQuery) {
|
|
98
|
-
// Only add if it doesn't already exist
|
|
99
|
-
queryCache.build(
|
|
100
|
-
queryClient,
|
|
101
|
-
{
|
|
102
|
-
queryKey: query.queryKey,
|
|
103
|
-
queryHash: query.queryHash,
|
|
104
|
-
},
|
|
105
|
-
query.state
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
} else if (type === 'removed') {
|
|
109
|
-
const existingQuery = queryCache.get(query.queryHash);
|
|
110
|
-
if (existingQuery) {
|
|
111
|
-
queryCache.remove(existingQuery);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} else if ('mutation' in event) {
|
|
115
|
-
const { mutation, type } = event as MutationCacheNotifyEvent;
|
|
116
|
-
const mutationCache = queryClient.getMutationCache();
|
|
117
|
-
|
|
118
|
-
if (type === 'added') {
|
|
119
|
-
const existingMutation = mutationCache.find({ mutationKey: mutation.options.mutationKey });
|
|
120
|
-
if (existingMutation) {
|
|
121
|
-
mutationCache.remove(existingMutation);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
mutationCache.build(
|
|
125
|
-
queryClient,
|
|
126
|
-
mutation.options,
|
|
127
|
-
mutation.state
|
|
128
|
-
);
|
|
129
|
-
} else if (type === 'removed') {
|
|
130
|
-
const existingMutation = mutationCache.find({ mutationKey: mutation.options.mutationKey });
|
|
131
|
-
if (existingMutation) {
|
|
132
|
-
mutationCache.remove(existingMutation);
|
|
133
|
-
}
|
|
134
|
-
} else if (type === 'updated') {
|
|
135
|
-
const existingMutation = mutationCache.find({ mutationKey: mutation.options.mutationKey });
|
|
136
|
-
|
|
137
|
-
if (existingMutation) {
|
|
138
|
-
mutationCache.remove(existingMutation);
|
|
139
|
-
mutationCache.build(
|
|
140
|
-
queryClient,
|
|
141
|
-
mutation.options,
|
|
142
|
-
mutation.state
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
const initialDataSubscription = client.onMessage("DEVICE_TO_DEVTOOLS_INITIAL_DATA", (event) => {
|
|
150
|
-
// Clear existing data first
|
|
151
|
-
queryClient.clear();
|
|
152
|
-
queryClient.getMutationCache().clear();
|
|
153
|
-
|
|
154
|
-
// Restore queries
|
|
155
|
-
const queryCache = queryClient.getQueryCache();
|
|
156
|
-
event.queries.forEach(query => {
|
|
157
|
-
queryCache.build(
|
|
158
|
-
queryClient,
|
|
159
|
-
{
|
|
160
|
-
queryKey: query.queryKey,
|
|
161
|
-
queryHash: query.queryHash,
|
|
162
|
-
},
|
|
163
|
-
query.state
|
|
164
|
-
);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// Restore mutations
|
|
168
|
-
const mutationCache = queryClient.getMutationCache();
|
|
169
|
-
event.mutations.forEach(mutation => {
|
|
170
|
-
mutationCache.build(
|
|
171
|
-
queryClient,
|
|
172
|
-
mutation.options,
|
|
173
|
-
mutation.state
|
|
174
|
-
);
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
return () => {
|
|
179
|
-
subscription.remove();
|
|
180
|
-
ackSubscription.remove();
|
|
181
|
-
initialDataSubscription.remove();
|
|
182
|
-
};
|
|
183
|
-
}, [client, queryClient])
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return (
|
|
187
|
-
<ReactQueryDevtoolsPanel />
|
|
188
|
-
)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export default function TanStackQueryPanel() {
|
|
192
|
-
return (
|
|
193
|
-
<QueryClientProvider client={queryClient}>
|
|
194
|
-
<Wrapped />
|
|
195
|
-
</QueryClientProvider>
|
|
196
|
-
)
|
|
197
|
-
}
|
package/src/ui/utils.ts
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
// Utility functions for formatting and styling
|
|
2
|
-
|
|
3
|
-
export const formatTime = (timestamp: number): string => {
|
|
4
|
-
const date = new Date(timestamp * 1000);
|
|
5
|
-
return date.toLocaleTimeString();
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export const formatDuration = (duration: number): string => {
|
|
9
|
-
if (duration < 1000) return `${Math.round(duration)}ms`;
|
|
10
|
-
return `${(duration / 1000).toFixed(2)}s`;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const getStatusColor = (status: number): string => {
|
|
14
|
-
if (status >= 200 && status < 300) return '#4caf50';
|
|
15
|
-
if (status >= 300 && status < 400) return '#ff9800';
|
|
16
|
-
if (status >= 400 && status < 500) return '#f44336';
|
|
17
|
-
if (status >= 500) return '#9c27b0';
|
|
18
|
-
return '#757575';
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export const getMethodColor = (method: string): string => {
|
|
22
|
-
switch (method.toUpperCase()) {
|
|
23
|
-
case 'GET': return '#61affe';
|
|
24
|
-
case 'POST': return '#49cc90';
|
|
25
|
-
case 'PUT': return '#fca130';
|
|
26
|
-
case 'DELETE': return '#f93e3e';
|
|
27
|
-
case 'PATCH': return '#50e3c2';
|
|
28
|
-
default: return '#757575';
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export const formatFileSize = (bytes: number): string => {
|
|
33
|
-
if (bytes === 0) return '0 B';
|
|
34
|
-
const k = 1024;
|
|
35
|
-
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
36
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
37
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const parseUrl = (url: string) => {
|
|
41
|
-
try {
|
|
42
|
-
const urlObj = new URL(url);
|
|
43
|
-
return {
|
|
44
|
-
domain: urlObj.hostname,
|
|
45
|
-
path: urlObj.pathname + urlObj.search,
|
|
46
|
-
protocol: urlObj.protocol,
|
|
47
|
-
};
|
|
48
|
-
} catch {
|
|
49
|
-
return {
|
|
50
|
-
domain: 'Invalid URL',
|
|
51
|
-
path: url,
|
|
52
|
-
protocol: 'unknown',
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
export const truncateText = (text: string, maxLength: number): string => {
|
|
58
|
-
if (text.length <= maxLength) return text;
|
|
59
|
-
return text.substring(0, maxLength) + '...';
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export const formatLongUrl = (url: string, maxLength = 80): string => {
|
|
63
|
-
if (url.length <= maxLength) return url;
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const urlObj = new URL(url);
|
|
67
|
-
const protocol = urlObj.protocol;
|
|
68
|
-
const hostname = urlObj.hostname;
|
|
69
|
-
const pathname = urlObj.pathname;
|
|
70
|
-
const search = urlObj.search;
|
|
71
|
-
|
|
72
|
-
// Keep protocol and hostname, truncate path if needed
|
|
73
|
-
const baseLength = protocol.length + hostname.length + 3; // +3 for "://"
|
|
74
|
-
const remainingLength = maxLength - baseLength - 3; // -3 for "..."
|
|
75
|
-
|
|
76
|
-
if (remainingLength <= 0) {
|
|
77
|
-
return `${protocol}//${hostname}...`;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const fullPath = pathname + search;
|
|
81
|
-
if (fullPath.length <= remainingLength) {
|
|
82
|
-
return url;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return `${protocol}//${hostname}${fullPath.substring(0, remainingLength)}...`;
|
|
86
|
-
} catch {
|
|
87
|
-
return truncateText(url, maxLength);
|
|
88
|
-
}
|
|
89
|
-
};
|