@rozenite/network-activity-plugin 1.0.0-alpha.1 → 1.0.0-alpha.3
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 +1 -1
- package/dist/assets/panel-CU9Fj1Ml.js +16717 -0
- package/dist/assets/panel-DXGMsavf.css +555 -0
- package/dist/panel.html +2 -2
- package/dist/react-native.cjs +8 -1
- package/dist/react-native.d.ts +86 -1
- package/dist/react-native.js +6 -171
- package/dist/rozenite.json +1 -1
- package/dist/useNetworkActivityDevTools.js +488 -0
- package/package.json +4 -4
- package/react-native.ts +2 -1
- package/rozenite.config.ts +1 -1
- package/src/css-modules.d.ts +1 -1
- package/src/react-native/network-inspector.ts +391 -0
- package/src/react-native/network-requests-registry.ts +122 -0
- package/src/react-native/useNetworkActivityDevTools.ts +6 -217
- package/src/react-native/xhr-interceptor.ts +211 -0
- package/src/react-native/xml-request.d.ts +23 -0
- package/src/types/client.ts +111 -0
- package/src/types/network.ts +26 -147
- package/src/ui/components.tsx +48 -26
- package/src/ui/network-details.module.css +140 -0
- package/src/ui/network-details.tsx +252 -41
- package/src/ui/network-list.module.css +6 -0
- package/src/ui/network-list.tsx +148 -53
- package/src/ui/network-toolbar.tsx +3 -9
- package/src/ui/panel.module.css +6 -0
- package/src/ui/panel.tsx +158 -40
- package/src/ui/tanstack-query.tsx +83 -76
- package/src/ui/utils.ts +22 -13
- package/tsconfig.json +13 -6
- package/vite.config.ts +1 -1
- package/dist/assets/panel-C5YgUUj5.js +0 -54
- package/dist/assets/panel-NCVczPb1.css +0 -1
package/src/ui/panel.module.css
CHANGED
package/src/ui/panel.tsx
CHANGED
|
@@ -1,47 +1,135 @@
|
|
|
1
1
|
import React, { useState, useEffect, useMemo } from 'react';
|
|
2
|
-
import { useRozeniteDevToolsClient } from
|
|
3
|
-
import {
|
|
2
|
+
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
3
|
+
import {
|
|
4
|
+
NetworkActivityEventMap,
|
|
5
|
+
NetworkRequestId,
|
|
6
|
+
NetworkResourceType,
|
|
7
|
+
} from '../types/client';
|
|
8
|
+
import { NetworkEntry } from '../types/network';
|
|
4
9
|
import styles from './panel.module.css';
|
|
5
10
|
import { NetworkToolbar } from './network-toolbar';
|
|
6
11
|
import { PanelHeader } from './components';
|
|
7
12
|
import { NetworkList } from './network-list';
|
|
8
13
|
import { NetworkDetails } from './network-details';
|
|
9
14
|
|
|
15
|
+
// Enhanced network entry with CDP data
|
|
16
|
+
type EnhancedNetworkEntry = NetworkEntry & {
|
|
17
|
+
// CDP specific fields
|
|
18
|
+
loaderId?: string;
|
|
19
|
+
documentURL?: string;
|
|
20
|
+
type?: NetworkResourceType;
|
|
21
|
+
initiator?: {
|
|
22
|
+
type: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
lineNumber?: number;
|
|
25
|
+
columnNumber?: number;
|
|
26
|
+
};
|
|
27
|
+
// Request details
|
|
28
|
+
request?: {
|
|
29
|
+
url: string;
|
|
30
|
+
method: string;
|
|
31
|
+
headers: Record<string, string>;
|
|
32
|
+
postData?: string;
|
|
33
|
+
hasPostData?: boolean;
|
|
34
|
+
};
|
|
35
|
+
// Response details
|
|
36
|
+
response?: {
|
|
37
|
+
url: string;
|
|
38
|
+
status: number;
|
|
39
|
+
statusText: string;
|
|
40
|
+
headers: Record<string, string>;
|
|
41
|
+
mimeType: string;
|
|
42
|
+
encodedDataLength: number;
|
|
43
|
+
responseTime: number;
|
|
44
|
+
};
|
|
45
|
+
// Response body
|
|
46
|
+
responseBody?: {
|
|
47
|
+
body: string;
|
|
48
|
+
base64Encoded: boolean;
|
|
49
|
+
};
|
|
50
|
+
// Timing and data
|
|
51
|
+
dataLength?: number;
|
|
52
|
+
// Error details
|
|
53
|
+
blockedReason?: string;
|
|
54
|
+
corsErrorStatus?: any;
|
|
55
|
+
};
|
|
56
|
+
|
|
10
57
|
export default function NetworkActivityPanel() {
|
|
11
|
-
const client = useRozeniteDevToolsClient<
|
|
58
|
+
const client = useRozeniteDevToolsClient<NetworkActivityEventMap>({
|
|
12
59
|
pluginId: '@rozenite/network-activity-plugin',
|
|
13
60
|
});
|
|
14
61
|
|
|
15
|
-
const [networkEntries, setNetworkEntries] = useState<
|
|
16
|
-
|
|
62
|
+
const [networkEntries, setNetworkEntries] = useState<
|
|
63
|
+
Map<string, EnhancedNetworkEntry>
|
|
64
|
+
>(new Map());
|
|
65
|
+
const [selectedRequestId, setSelectedRequestId] = useState<string | null>(
|
|
66
|
+
null
|
|
67
|
+
);
|
|
17
68
|
const [isRecording, setIsRecording] = useState(true);
|
|
18
69
|
const [containerHeight, setContainerHeight] = useState(0);
|
|
19
70
|
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
20
71
|
|
|
21
72
|
// Convert Map to sorted array for rendering
|
|
22
73
|
const sortedEntries = useMemo(() => {
|
|
23
|
-
return Array.from(networkEntries.values())
|
|
24
|
-
|
|
74
|
+
return Array.from(networkEntries.values()).sort(
|
|
75
|
+
(a, b) => b.startTime - a.startTime
|
|
76
|
+
);
|
|
25
77
|
}, [networkEntries]);
|
|
26
78
|
|
|
27
|
-
const selectedEntry = selectedRequestId
|
|
79
|
+
const selectedEntry = selectedRequestId
|
|
80
|
+
? networkEntries.get(selectedRequestId) || null
|
|
81
|
+
: null;
|
|
82
|
+
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
if (!client) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (isRecording) {
|
|
89
|
+
client.send('network-enable', {});
|
|
90
|
+
console.log('enabling!');
|
|
91
|
+
} else {
|
|
92
|
+
client.send('network-disable', {});
|
|
93
|
+
}
|
|
94
|
+
}, [client, isRecording]);
|
|
28
95
|
|
|
29
96
|
useEffect(() => {
|
|
30
97
|
if (!client) return;
|
|
31
|
-
if (!isRecording) return;
|
|
32
98
|
|
|
33
99
|
const subscriptions: Array<{ remove: () => void }> = [];
|
|
34
100
|
|
|
35
|
-
// Subscribe to Network events
|
|
101
|
+
// Subscribe to CDP Network events
|
|
36
102
|
subscriptions.push(
|
|
37
103
|
client.onMessage('Network.requestWillBeSent', (payload) => {
|
|
38
|
-
setNetworkEntries(prev => {
|
|
104
|
+
setNetworkEntries((prev) => {
|
|
39
105
|
const newMap = new Map(prev);
|
|
106
|
+
const existing = newMap.get(payload.requestId);
|
|
107
|
+
|
|
40
108
|
newMap.set(payload.requestId, {
|
|
41
109
|
requestId: payload.requestId,
|
|
42
|
-
|
|
110
|
+
loaderId: payload.loaderId,
|
|
111
|
+
documentURL: payload.documentURL,
|
|
112
|
+
url: payload.request.url,
|
|
113
|
+
method: payload.request.method,
|
|
114
|
+
headers: payload.request.headers,
|
|
115
|
+
postData: payload.request.postData,
|
|
116
|
+
hasPostData: payload.request.hasPostData,
|
|
43
117
|
status: 'pending',
|
|
44
118
|
startTime: payload.timestamp,
|
|
119
|
+
type: payload.type,
|
|
120
|
+
initiator: payload.initiator,
|
|
121
|
+
request: payload.request,
|
|
122
|
+
// Preserve existing response data if this is a redirect
|
|
123
|
+
...(existing && {
|
|
124
|
+
response: existing.response,
|
|
125
|
+
status: existing.status,
|
|
126
|
+
endTime: existing.endTime,
|
|
127
|
+
duration: existing.duration,
|
|
128
|
+
encodedDataLength: existing.encodedDataLength,
|
|
129
|
+
dataLength: existing.dataLength,
|
|
130
|
+
errorText: existing.errorText,
|
|
131
|
+
canceled: existing.canceled,
|
|
132
|
+
}),
|
|
45
133
|
});
|
|
46
134
|
return newMap;
|
|
47
135
|
});
|
|
@@ -49,14 +137,15 @@ export default function NetworkActivityPanel() {
|
|
|
49
137
|
);
|
|
50
138
|
|
|
51
139
|
subscriptions.push(
|
|
52
|
-
client.onMessage('Network.
|
|
53
|
-
setNetworkEntries(prev => {
|
|
140
|
+
client.onMessage('Network.responseReceived', (payload) => {
|
|
141
|
+
setNetworkEntries((prev) => {
|
|
54
142
|
const newMap = new Map(prev);
|
|
55
143
|
const entry = newMap.get(payload.requestId);
|
|
56
144
|
if (entry) {
|
|
57
145
|
newMap.set(payload.requestId, {
|
|
58
146
|
...entry,
|
|
59
|
-
|
|
147
|
+
response: payload.response,
|
|
148
|
+
status: 'loading',
|
|
60
149
|
});
|
|
61
150
|
}
|
|
62
151
|
return newMap;
|
|
@@ -65,15 +154,15 @@ export default function NetworkActivityPanel() {
|
|
|
65
154
|
);
|
|
66
155
|
|
|
67
156
|
subscriptions.push(
|
|
68
|
-
client.onMessage('Network.
|
|
69
|
-
setNetworkEntries(prev => {
|
|
157
|
+
client.onMessage('Network.dataReceived', (payload) => {
|
|
158
|
+
setNetworkEntries((prev) => {
|
|
70
159
|
const newMap = new Map(prev);
|
|
71
160
|
const entry = newMap.get(payload.requestId);
|
|
72
161
|
if (entry) {
|
|
73
162
|
newMap.set(payload.requestId, {
|
|
74
163
|
...entry,
|
|
75
|
-
|
|
76
|
-
|
|
164
|
+
dataLength: payload.dataLength,
|
|
165
|
+
encodedDataLength: payload.encodedDataLength,
|
|
77
166
|
});
|
|
78
167
|
}
|
|
79
168
|
return newMap;
|
|
@@ -83,18 +172,19 @@ export default function NetworkActivityPanel() {
|
|
|
83
172
|
|
|
84
173
|
subscriptions.push(
|
|
85
174
|
client.onMessage('Network.loadingFinished', (payload) => {
|
|
86
|
-
setNetworkEntries(prev => {
|
|
175
|
+
setNetworkEntries((prev) => {
|
|
87
176
|
const newMap = new Map(prev);
|
|
88
177
|
const entry = newMap.get(payload.requestId);
|
|
89
178
|
if (entry) {
|
|
90
179
|
const endTime = payload.timestamp;
|
|
91
|
-
const duration =
|
|
180
|
+
const duration = endTime - entry.startTime;
|
|
181
|
+
|
|
92
182
|
newMap.set(payload.requestId, {
|
|
93
183
|
...entry,
|
|
94
|
-
loadingFinished: payload,
|
|
95
184
|
status: 'finished',
|
|
96
185
|
endTime,
|
|
97
186
|
duration,
|
|
187
|
+
encodedDataLength: payload.encodedDataLength,
|
|
98
188
|
});
|
|
99
189
|
}
|
|
100
190
|
return newMap;
|
|
@@ -104,18 +194,39 @@ export default function NetworkActivityPanel() {
|
|
|
104
194
|
|
|
105
195
|
subscriptions.push(
|
|
106
196
|
client.onMessage('Network.loadingFailed', (payload) => {
|
|
107
|
-
setNetworkEntries(prev => {
|
|
197
|
+
setNetworkEntries((prev) => {
|
|
108
198
|
const newMap = new Map(prev);
|
|
109
199
|
const entry = newMap.get(payload.requestId);
|
|
110
200
|
if (entry) {
|
|
111
201
|
const endTime = payload.timestamp;
|
|
112
|
-
const duration =
|
|
202
|
+
const duration = endTime - entry.startTime;
|
|
203
|
+
|
|
113
204
|
newMap.set(payload.requestId, {
|
|
114
205
|
...entry,
|
|
115
|
-
loadingFailed: payload,
|
|
116
206
|
status: 'failed',
|
|
117
207
|
endTime,
|
|
118
208
|
duration,
|
|
209
|
+
errorText: payload.errorText,
|
|
210
|
+
canceled: payload.canceled,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return newMap;
|
|
214
|
+
});
|
|
215
|
+
})
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
subscriptions.push(
|
|
219
|
+
client.onMessage('Network.responseBodyReceived', (payload) => {
|
|
220
|
+
setNetworkEntries((prev) => {
|
|
221
|
+
const newMap = new Map(prev);
|
|
222
|
+
const entry = newMap.get(payload.requestId);
|
|
223
|
+
if (entry) {
|
|
224
|
+
newMap.set(payload.requestId, {
|
|
225
|
+
...entry,
|
|
226
|
+
responseBody: {
|
|
227
|
+
body: payload.body,
|
|
228
|
+
base64Encoded: payload.base64Encoded,
|
|
229
|
+
},
|
|
119
230
|
});
|
|
120
231
|
}
|
|
121
232
|
return newMap;
|
|
@@ -124,7 +235,7 @@ export default function NetworkActivityPanel() {
|
|
|
124
235
|
);
|
|
125
236
|
|
|
126
237
|
return () => {
|
|
127
|
-
subscriptions.forEach(sub => sub.remove());
|
|
238
|
+
subscriptions.forEach((sub) => sub.remove());
|
|
128
239
|
};
|
|
129
240
|
}, [client, isRecording]);
|
|
130
241
|
|
|
@@ -141,6 +252,12 @@ export default function NetworkActivityPanel() {
|
|
|
141
252
|
setSelectedRequestId(requestId);
|
|
142
253
|
};
|
|
143
254
|
|
|
255
|
+
const requestResponseBody = (requestId: string) => {
|
|
256
|
+
if (client) {
|
|
257
|
+
client.send('Network.getResponseBody', { requestId });
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
144
261
|
// Update container height on mount and resize
|
|
145
262
|
useEffect(() => {
|
|
146
263
|
const updateHeight = () => {
|
|
@@ -156,10 +273,7 @@ export default function NetworkActivityPanel() {
|
|
|
156
273
|
}, []);
|
|
157
274
|
|
|
158
275
|
return (
|
|
159
|
-
<div
|
|
160
|
-
ref={containerRef}
|
|
161
|
-
className={styles.container}
|
|
162
|
-
>
|
|
276
|
+
<div ref={containerRef} className={styles.container}>
|
|
163
277
|
{/* Toolbar */}
|
|
164
278
|
<NetworkToolbar
|
|
165
279
|
isRecording={isRecording}
|
|
@@ -177,25 +291,29 @@ export default function NetworkActivityPanel() {
|
|
|
177
291
|
<div className={styles.headerStatus}>Status</div>
|
|
178
292
|
<div className={styles.headerMethod}>Method</div>
|
|
179
293
|
<div className={styles.headerName}>Name</div>
|
|
294
|
+
<div className={styles.headerType}>Type</div>
|
|
180
295
|
<div className={styles.headerTime}>Time</div>
|
|
181
296
|
<div className={styles.headerSize}>Size</div>
|
|
182
297
|
</PanelHeader>
|
|
183
298
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
299
|
+
<div className={styles.listContent}>
|
|
300
|
+
<NetworkList
|
|
301
|
+
entries={sortedEntries}
|
|
302
|
+
selectedRequestId={selectedRequestId}
|
|
303
|
+
onSelect={handleSelectRequest}
|
|
304
|
+
height={containerHeight}
|
|
305
|
+
/>
|
|
306
|
+
</div>
|
|
192
307
|
</div>
|
|
193
308
|
|
|
194
309
|
{/* Details Panel */}
|
|
195
310
|
<div className={styles.detailsContainer}>
|
|
196
|
-
<NetworkDetails
|
|
311
|
+
<NetworkDetails
|
|
312
|
+
entry={selectedEntry}
|
|
313
|
+
onRequestResponseBody={requestResponseBody}
|
|
314
|
+
/>
|
|
197
315
|
</div>
|
|
198
316
|
</div>
|
|
199
317
|
</div>
|
|
200
318
|
);
|
|
201
|
-
}
|
|
319
|
+
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
QueryCacheNotifyEvent,
|
|
3
|
+
MutationCacheNotifyEvent,
|
|
4
|
+
QueryClient,
|
|
5
|
+
QueryClientProvider,
|
|
6
|
+
Query,
|
|
7
|
+
Mutation,
|
|
8
|
+
} from '@tanstack/react-query';
|
|
2
9
|
import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools';
|
|
3
10
|
import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
|
|
4
11
|
import { useEffect, useRef } from 'react';
|
|
@@ -15,24 +22,24 @@ const queryClient = new QueryClient({
|
|
|
15
22
|
});
|
|
16
23
|
|
|
17
24
|
type DevToolsEventMap = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
25
|
+
DEVTOOLS_TO_DEVICE: unknown;
|
|
26
|
+
DEVICE_TO_DEVTOOLS: QueryCacheNotifyEvent | MutationCacheNotifyEvent;
|
|
27
|
+
DEVICE_TO_DEVTOOLS_ACK: { requestId: string; success: boolean };
|
|
28
|
+
DEVICE_TO_DEVTOOLS_INITIAL_DATA: { queries: Query[]; mutations: Mutation[] };
|
|
29
|
+
DEVTOOLS_TO_DEVICE_INITIAL_DATA_REQUEST: unknown;
|
|
30
|
+
};
|
|
24
31
|
|
|
25
32
|
const Wrapped = () => {
|
|
26
33
|
const client = useRozeniteDevToolsClient<DevToolsEventMap>({
|
|
27
34
|
pluginId: '@rozenite/tanstack-query-plugin',
|
|
28
|
-
})
|
|
35
|
+
});
|
|
29
36
|
|
|
30
37
|
// Track pending acknowledgments to prevent feedback loops
|
|
31
38
|
const pendingAcknowledgment = useRef<Set<string>>(new Set());
|
|
32
39
|
|
|
33
40
|
useEffect(() => {
|
|
34
41
|
if (!client) return;
|
|
35
|
-
client.send(
|
|
42
|
+
client.send('DEVTOOLS_TO_DEVICE_INITIAL_DATA_REQUEST', null);
|
|
36
43
|
}, [client]);
|
|
37
44
|
|
|
38
45
|
useEffect(() => {
|
|
@@ -40,44 +47,50 @@ const Wrapped = () => {
|
|
|
40
47
|
|
|
41
48
|
const handleEvent = (event: Event) => {
|
|
42
49
|
const detail = (event as CustomEvent).detail;
|
|
43
|
-
|
|
50
|
+
|
|
44
51
|
// Generate a unique request ID for this DevTools action
|
|
45
|
-
const requestId = `devtools-${Date.now()}-${Math.random()
|
|
46
|
-
|
|
52
|
+
const requestId = `devtools-${Date.now()}-${Math.random()
|
|
53
|
+
.toString(36)
|
|
54
|
+
.substr(2, 9)}`;
|
|
55
|
+
|
|
47
56
|
// Mark that we're waiting for acknowledgment
|
|
48
57
|
pendingAcknowledgment.current.add(requestId);
|
|
49
|
-
|
|
58
|
+
|
|
50
59
|
// Add the request ID to the event detail
|
|
51
60
|
const eventWithRequestId = {
|
|
52
61
|
...detail,
|
|
53
62
|
requestId,
|
|
54
63
|
};
|
|
55
|
-
|
|
56
|
-
client.send(
|
|
64
|
+
|
|
65
|
+
client.send('DEVTOOLS_TO_DEVICE', eventWithRequestId);
|
|
57
66
|
};
|
|
58
67
|
|
|
59
68
|
window.addEventListener('@tanstack/query-devtools-event', handleEvent);
|
|
60
|
-
return () =>
|
|
61
|
-
|
|
69
|
+
return () =>
|
|
70
|
+
window.removeEventListener('@tanstack/query-devtools-event', handleEvent);
|
|
71
|
+
}, [client]);
|
|
62
72
|
|
|
63
73
|
useEffect(() => {
|
|
64
74
|
if (!client) return;
|
|
65
75
|
|
|
66
|
-
const ackSubscription = client.onMessage(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
const ackSubscription = client.onMessage(
|
|
77
|
+
'DEVICE_TO_DEVTOOLS_ACK',
|
|
78
|
+
(ack) => {
|
|
79
|
+
// Remove the request from pending acknowledgments
|
|
80
|
+
pendingAcknowledgment.current.delete(ack.requestId);
|
|
81
|
+
}
|
|
82
|
+
);
|
|
70
83
|
|
|
71
|
-
const subscription = client.onMessage(
|
|
84
|
+
const subscription = client.onMessage('DEVICE_TO_DEVTOOLS', (event) => {
|
|
72
85
|
// Don't reflect events if we're waiting for acknowledgments
|
|
73
86
|
if (pendingAcknowledgment.current.size > 0) {
|
|
74
87
|
return;
|
|
75
88
|
}
|
|
76
|
-
|
|
89
|
+
|
|
77
90
|
if ('query' in event) {
|
|
78
91
|
const { query, type } = event as QueryCacheNotifyEvent;
|
|
79
92
|
const queryCache = queryClient.getQueryCache();
|
|
80
|
-
|
|
93
|
+
|
|
81
94
|
if (type === 'updated') {
|
|
82
95
|
const existingQuery = queryCache.get(query.queryHash);
|
|
83
96
|
if (existingQuery) {
|
|
@@ -114,84 +127,78 @@ const Wrapped = () => {
|
|
|
114
127
|
} else if ('mutation' in event) {
|
|
115
128
|
const { mutation, type } = event as MutationCacheNotifyEvent;
|
|
116
129
|
const mutationCache = queryClient.getMutationCache();
|
|
117
|
-
|
|
130
|
+
|
|
118
131
|
if (type === 'added') {
|
|
119
|
-
const existingMutation = mutationCache.find({
|
|
132
|
+
const existingMutation = mutationCache.find({
|
|
133
|
+
mutationKey: mutation.options.mutationKey,
|
|
134
|
+
});
|
|
120
135
|
if (existingMutation) {
|
|
121
136
|
mutationCache.remove(existingMutation);
|
|
122
137
|
}
|
|
123
138
|
|
|
124
|
-
mutationCache.build(
|
|
125
|
-
queryClient,
|
|
126
|
-
mutation.options,
|
|
127
|
-
mutation.state
|
|
128
|
-
);
|
|
139
|
+
mutationCache.build(queryClient, mutation.options, mutation.state);
|
|
129
140
|
} else if (type === 'removed') {
|
|
130
|
-
const existingMutation = mutationCache.find({
|
|
141
|
+
const existingMutation = mutationCache.find({
|
|
142
|
+
mutationKey: mutation.options.mutationKey,
|
|
143
|
+
});
|
|
131
144
|
if (existingMutation) {
|
|
132
145
|
mutationCache.remove(existingMutation);
|
|
133
146
|
}
|
|
134
147
|
} else if (type === 'updated') {
|
|
135
|
-
const existingMutation = mutationCache.find({
|
|
136
|
-
|
|
148
|
+
const existingMutation = mutationCache.find({
|
|
149
|
+
mutationKey: mutation.options.mutationKey,
|
|
150
|
+
});
|
|
151
|
+
|
|
137
152
|
if (existingMutation) {
|
|
138
153
|
mutationCache.remove(existingMutation);
|
|
139
|
-
mutationCache.build(
|
|
140
|
-
queryClient,
|
|
141
|
-
mutation.options,
|
|
142
|
-
mutation.state
|
|
143
|
-
);
|
|
154
|
+
mutationCache.build(queryClient, mutation.options, mutation.state);
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
157
|
}
|
|
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
158
|
});
|
|
177
159
|
|
|
160
|
+
const initialDataSubscription = client.onMessage(
|
|
161
|
+
'DEVICE_TO_DEVTOOLS_INITIAL_DATA',
|
|
162
|
+
(event) => {
|
|
163
|
+
// Clear existing data first
|
|
164
|
+
queryClient.clear();
|
|
165
|
+
queryClient.getMutationCache().clear();
|
|
166
|
+
|
|
167
|
+
// Restore queries
|
|
168
|
+
const queryCache = queryClient.getQueryCache();
|
|
169
|
+
event.queries.forEach((query) => {
|
|
170
|
+
queryCache.build(
|
|
171
|
+
queryClient,
|
|
172
|
+
{
|
|
173
|
+
queryKey: query.queryKey,
|
|
174
|
+
queryHash: query.queryHash,
|
|
175
|
+
},
|
|
176
|
+
query.state
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Restore mutations
|
|
181
|
+
const mutationCache = queryClient.getMutationCache();
|
|
182
|
+
event.mutations.forEach((mutation) => {
|
|
183
|
+
mutationCache.build(queryClient, mutation.options, mutation.state);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
);
|
|
187
|
+
|
|
178
188
|
return () => {
|
|
179
189
|
subscription.remove();
|
|
180
190
|
ackSubscription.remove();
|
|
181
191
|
initialDataSubscription.remove();
|
|
182
192
|
};
|
|
183
|
-
}, [client, queryClient])
|
|
193
|
+
}, [client, queryClient]);
|
|
184
194
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
<ReactQueryDevtoolsPanel />
|
|
188
|
-
)
|
|
189
|
-
}
|
|
195
|
+
return <ReactQueryDevtoolsPanel />;
|
|
196
|
+
};
|
|
190
197
|
|
|
191
198
|
export default function TanStackQueryPanel() {
|
|
192
199
|
return (
|
|
193
200
|
<QueryClientProvider client={queryClient}>
|
|
194
201
|
<Wrapped />
|
|
195
202
|
</QueryClientProvider>
|
|
196
|
-
)
|
|
197
|
-
}
|
|
203
|
+
);
|
|
204
|
+
}
|
package/src/ui/utils.ts
CHANGED
|
@@ -20,12 +20,18 @@ export const getStatusColor = (status: number): string => {
|
|
|
20
20
|
|
|
21
21
|
export const getMethodColor = (method: string): string => {
|
|
22
22
|
switch (method.toUpperCase()) {
|
|
23
|
-
case 'GET':
|
|
24
|
-
|
|
25
|
-
case '
|
|
26
|
-
|
|
27
|
-
case '
|
|
28
|
-
|
|
23
|
+
case 'GET':
|
|
24
|
+
return '#61affe';
|
|
25
|
+
case 'POST':
|
|
26
|
+
return '#49cc90';
|
|
27
|
+
case 'PUT':
|
|
28
|
+
return '#fca130';
|
|
29
|
+
case 'DELETE':
|
|
30
|
+
return '#f93e3e';
|
|
31
|
+
case 'PATCH':
|
|
32
|
+
return '#50e3c2';
|
|
33
|
+
default:
|
|
34
|
+
return '#757575';
|
|
29
35
|
}
|
|
30
36
|
};
|
|
31
37
|
|
|
@@ -61,29 +67,32 @@ export const truncateText = (text: string, maxLength: number): string => {
|
|
|
61
67
|
|
|
62
68
|
export const formatLongUrl = (url: string, maxLength = 80): string => {
|
|
63
69
|
if (url.length <= maxLength) return url;
|
|
64
|
-
|
|
70
|
+
|
|
65
71
|
try {
|
|
66
72
|
const urlObj = new URL(url);
|
|
67
73
|
const protocol = urlObj.protocol;
|
|
68
74
|
const hostname = urlObj.hostname;
|
|
69
75
|
const pathname = urlObj.pathname;
|
|
70
76
|
const search = urlObj.search;
|
|
71
|
-
|
|
77
|
+
|
|
72
78
|
// Keep protocol and hostname, truncate path if needed
|
|
73
79
|
const baseLength = protocol.length + hostname.length + 3; // +3 for "://"
|
|
74
80
|
const remainingLength = maxLength - baseLength - 3; // -3 for "..."
|
|
75
|
-
|
|
81
|
+
|
|
76
82
|
if (remainingLength <= 0) {
|
|
77
83
|
return `${protocol}//${hostname}...`;
|
|
78
84
|
}
|
|
79
|
-
|
|
85
|
+
|
|
80
86
|
const fullPath = pathname + search;
|
|
81
87
|
if (fullPath.length <= remainingLength) {
|
|
82
88
|
return url;
|
|
83
89
|
}
|
|
84
|
-
|
|
85
|
-
return `${protocol}//${hostname}${fullPath.substring(
|
|
90
|
+
|
|
91
|
+
return `${protocol}//${hostname}${fullPath.substring(
|
|
92
|
+
0,
|
|
93
|
+
remainingLength
|
|
94
|
+
)}...`;
|
|
86
95
|
} catch {
|
|
87
96
|
return truncateText(url, maxLength);
|
|
88
97
|
}
|
|
89
|
-
};
|
|
98
|
+
};
|
package/tsconfig.json
CHANGED
|
@@ -16,10 +16,17 @@
|
|
|
16
16
|
"noEmit": true,
|
|
17
17
|
"jsx": "react-jsx"
|
|
18
18
|
},
|
|
19
|
-
"include": [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
"include": ["src/**/*", "react-native.ts", "rozenite.config.ts"],
|
|
20
|
+
"exclude": ["node_modules", "dist", "build"],
|
|
21
|
+
"references": [
|
|
22
|
+
{
|
|
23
|
+
"path": "../plugin-bridge"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"path": "../cli"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"path": "../vite-plugin"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
25
32
|
}
|