@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.
Files changed (87) hide show
  1. package/dist/App.html +2 -2
  2. package/dist/assets/{App-lNMijPJ4.js → App-CA1Fbh0I.js} +11995 -10804
  3. package/dist/assets/{App-R2ZMH9wJ.css → App-DoHQsY5s.css} +46 -0
  4. package/dist/event-source.cjs +22 -0
  5. package/dist/event-source.js +23 -0
  6. package/dist/rozenite.json +1 -1
  7. package/dist/src/react-native/{network-inspector.d.ts → http/network-inspector.d.ts} +1 -1
  8. package/dist/src/react-native/sse/event-source.d.ts +2 -0
  9. package/dist/src/react-native/sse/sse-inspector.d.ts +9 -0
  10. package/dist/src/react-native/sse/sse-interceptor.d.ts +36 -0
  11. package/dist/src/react-native/sse/types.d.ts +6 -0
  12. package/dist/src/react-native/utils.d.ts +6 -0
  13. package/dist/src/react-native/websocket/websocket-inspector.d.ts +9 -0
  14. package/dist/src/react-native/websocket/websocket-interceptor.d.ts +74 -0
  15. package/dist/src/shared/client.d.ts +5 -2
  16. package/dist/src/shared/sse-events.d.ts +35 -0
  17. package/dist/src/shared/websocket-events.d.ts +60 -0
  18. package/dist/src/ui/components/Badge.d.ts +1 -1
  19. package/dist/src/ui/components/Button.d.ts +1 -1
  20. package/dist/src/ui/components/JsonTreeCopyableItem.d.ts +7 -0
  21. package/dist/src/ui/components/RequestList.d.ts +6 -26
  22. package/dist/src/ui/components/SidePanel.d.ts +1 -0
  23. package/dist/src/ui/components/Toolbar.d.ts +1 -0
  24. package/dist/src/ui/hooks/useCopyToClipboard.d.ts +4 -0
  25. package/dist/src/ui/state/derived.d.ts +5 -0
  26. package/dist/src/ui/state/hooks.d.ts +17 -0
  27. package/dist/src/ui/state/model.d.ts +98 -0
  28. package/dist/src/ui/state/store.d.ts +24 -0
  29. package/dist/src/ui/tabs/CookiesTab.d.ts +3 -6
  30. package/dist/src/ui/tabs/HeadersTab.d.ts +3 -15
  31. package/dist/src/ui/tabs/MessagesTab.d.ts +5 -0
  32. package/dist/src/ui/tabs/RequestTab.d.ts +2 -7
  33. package/dist/src/ui/tabs/ResponseTab.d.ts +2 -8
  34. package/dist/src/ui/tabs/SSEMessagesTab.d.ts +5 -0
  35. package/dist/src/ui/tabs/TimingTab.d.ts +3 -5
  36. package/dist/src/ui/types.d.ts +4 -1
  37. package/dist/src/ui/utils/assert.d.ts +1 -0
  38. package/dist/src/ui/utils/copyToClipboard.d.ts +1 -0
  39. package/dist/src/ui/utils/getId.d.ts +1 -0
  40. package/dist/src/ui/utils/getStatusColor.d.ts +1 -0
  41. package/dist/useNetworkActivityDevTools.cjs +423 -34
  42. package/dist/useNetworkActivityDevTools.js +421 -34
  43. package/package.json +19 -8
  44. package/src/react-native/{network-inspector.ts → http/network-inspector.ts} +13 -34
  45. package/src/react-native/{xml-request.d.ts → http/xml-request.d.ts} +1 -0
  46. package/src/react-native/sse/event-source.ts +25 -0
  47. package/src/react-native/sse/sse-inspector.ts +117 -0
  48. package/src/react-native/sse/sse-interceptor.ts +162 -0
  49. package/src/react-native/sse/types.ts +9 -0
  50. package/src/react-native/useNetworkActivityDevTools.ts +75 -1
  51. package/src/react-native/utils.ts +43 -0
  52. package/src/react-native/websocket/websocket-inspector.ts +180 -0
  53. package/src/react-native/websocket/websocket-interceptor.d.ts +4 -0
  54. package/src/react-native/websocket/websocket-interceptor.ts +166 -0
  55. package/src/shared/client.ts +6 -2
  56. package/src/shared/sse-events.ts +44 -0
  57. package/src/shared/websocket-events.ts +79 -0
  58. package/src/ui/components/JsonTree.tsx +13 -0
  59. package/src/ui/components/JsonTreeCopyableItem.tsx +33 -0
  60. package/src/ui/components/RequestList.tsx +42 -124
  61. package/src/ui/components/SidePanel.tsx +323 -0
  62. package/src/ui/components/Tabs.tsx +1 -1
  63. package/src/ui/components/Toolbar.tsx +45 -0
  64. package/src/ui/hooks/useCopyToClipboard.ts +28 -0
  65. package/src/ui/state/derived.ts +112 -0
  66. package/src/ui/state/hooks.ts +44 -0
  67. package/src/ui/state/model.ts +129 -0
  68. package/src/ui/state/store.ts +559 -0
  69. package/src/ui/tabs/CookiesTab.tsx +162 -176
  70. package/src/ui/tabs/HeadersTab.tsx +23 -30
  71. package/src/ui/tabs/MessagesTab.tsx +276 -0
  72. package/src/ui/tabs/RequestTab.tsx +8 -13
  73. package/src/ui/tabs/ResponseTab.tsx +6 -10
  74. package/src/ui/tabs/SSEMessagesTab.tsx +213 -0
  75. package/src/ui/tabs/TimingTab.tsx +30 -43
  76. package/src/ui/types.ts +4 -1
  77. package/src/ui/utils/assert.ts +5 -0
  78. package/src/ui/utils/copyToClipboard.ts +3 -0
  79. package/src/ui/utils/getId.ts +10 -0
  80. package/src/ui/utils/getStatusColor.ts +15 -0
  81. package/src/ui/views/InspectorView.tsx +24 -320
  82. package/tailwind.config.ts +3 -0
  83. package/vite.config.ts +12 -0
  84. /package/dist/src/react-native/{network-requests-registry.d.ts → http/network-requests-registry.d.ts} +0 -0
  85. /package/dist/src/react-native/{xhr-interceptor.d.ts → http/xhr-interceptor.d.ts} +0 -0
  86. /package/src/react-native/{network-requests-registry.ts → http/network-requests-registry.ts} +0 -0
  87. /package/src/react-native/{xhr-interceptor.ts → http/xhr-interceptor.ts} +0 -0
@@ -1,7 +1,7 @@
1
1
  import { ScrollArea } from '../components/ScrollArea';
2
2
  import { Badge } from '../components/Badge';
3
- import { NetworkEntry } from '../types';
4
3
  import { HttpHeaders } from '../../shared/client';
4
+ import { HttpNetworkEntry, SSENetworkEntry } from '../state/model';
5
5
 
6
6
  type Cookie = {
7
7
  name: string;
@@ -16,10 +16,7 @@ type Cookie = {
16
16
  };
17
17
 
18
18
  export type CookiesTabProps = {
19
- selectedRequest: {
20
- id: string;
21
- };
22
- networkEntries: Map<string, NetworkEntry>;
19
+ selectedRequest: HttpNetworkEntry | SSENetworkEntry;
23
20
  };
24
21
 
25
22
  const parseCookieString = (cookieString: string): Cookie[] => {
@@ -96,197 +93,186 @@ const extractCookiesFromHeaders = (
96
93
  return { requestCookies, responseCookies };
97
94
  };
98
95
 
99
- export const CookiesTab = ({
100
- selectedRequest,
101
- networkEntries,
102
- }: CookiesTabProps) => {
96
+ export const CookiesTab = ({ selectedRequest }: CookiesTabProps) => {
103
97
  return (
104
98
  <ScrollArea className="h-full w-full">
105
99
  <div className="p-4">
106
100
  {(() => {
107
- const entry = networkEntries.get(selectedRequest.id);
108
- if (!entry) {
109
- return (
110
- <div className="text-sm text-gray-400">
111
- No request data available
112
- </div>
113
- );
114
- }
101
+ // Extract cookies from request and response headers separately
102
+ const requestHeaders = selectedRequest.request?.headers || {};
103
+ const responseHeaders = selectedRequest.response?.headers || {};
115
104
 
116
- // Extract cookies from request and response headers separately
117
- const requestHeaders = entry.request?.headers || {};
118
- const responseHeaders = entry.response?.headers || {};
105
+ const { requestCookies } = extractCookiesFromHeaders(requestHeaders);
106
+ const { responseCookies } =
107
+ extractCookiesFromHeaders(responseHeaders);
119
108
 
120
- const { requestCookies } = extractCookiesFromHeaders(requestHeaders);
121
- const { responseCookies } = extractCookiesFromHeaders(responseHeaders);
109
+ const hasRequestCookies = requestCookies.length > 0;
110
+ const hasResponseCookies = responseCookies.length > 0;
122
111
 
123
- const hasRequestCookies = requestCookies.length > 0;
124
- const hasResponseCookies = responseCookies.length > 0;
112
+ if (!hasRequestCookies && !hasResponseCookies) {
113
+ return (
114
+ <div className="text-sm text-gray-400">
115
+ No cookies for this request
116
+ </div>
117
+ );
118
+ }
125
119
 
126
- if (!hasRequestCookies && !hasResponseCookies) {
127
120
  return (
128
- <div className="text-sm text-gray-400">
129
- No cookies for this request
130
- </div>
131
- );
132
- }
133
-
134
- return (
135
- <div className="space-y-6">
136
- {/* Request Cookies */}
137
- {hasRequestCookies && (
138
- <div>
139
- <h4 className="text-sm font-medium text-gray-300 mb-3">
140
- Request Cookies ({requestCookies.length})
141
- </h4>
142
- <div className="space-y-2">
143
- {requestCookies.map((cookie, index) => (
144
- <div
145
- key={`request-${index}`}
146
- className="bg-gray-800 border border-gray-700 rounded p-3"
147
- >
148
- <div className="flex items-center justify-between mb-2">
149
- <span className="text-sm font-medium text-blue-400">
150
- {cookie.name}
151
- </span>
152
- <div className="flex items-center gap-2">
153
- {cookie.secure && (
154
- <Badge
155
- variant="outline"
156
- className="text-xs text-yellow-400 border-yellow-400"
157
- >
158
- Secure
159
- </Badge>
121
+ <div className="space-y-6">
122
+ {/* Request Cookies */}
123
+ {hasRequestCookies && (
124
+ <div>
125
+ <h4 className="text-sm font-medium text-gray-300 mb-3">
126
+ Request Cookies ({requestCookies.length})
127
+ </h4>
128
+ <div className="space-y-2">
129
+ {requestCookies.map((cookie, index) => (
130
+ <div
131
+ key={`request-${index}`}
132
+ className="bg-gray-800 border border-gray-700 rounded p-3"
133
+ >
134
+ <div className="flex items-center justify-between mb-2">
135
+ <span className="text-sm font-medium text-blue-400">
136
+ {cookie.name}
137
+ </span>
138
+ <div className="flex items-center gap-2">
139
+ {cookie.secure && (
140
+ <Badge
141
+ variant="outline"
142
+ className="text-xs text-yellow-400 border-yellow-400"
143
+ >
144
+ Secure
145
+ </Badge>
146
+ )}
147
+ {cookie.httpOnly && (
148
+ <Badge
149
+ variant="outline"
150
+ className="text-xs text-purple-400 border-purple-400"
151
+ >
152
+ HttpOnly
153
+ </Badge>
154
+ )}
155
+ </div>
156
+ </div>
157
+ <div className="text-sm text-gray-300 mb-2">
158
+ {cookie.value}
159
+ </div>
160
+ <div className="grid grid-cols-2 gap-4 text-xs text-gray-400">
161
+ {cookie.domain && (
162
+ <div>
163
+ <span className="font-medium">Domain:</span>{' '}
164
+ {cookie.domain}
165
+ </div>
166
+ )}
167
+ {cookie.path && (
168
+ <div>
169
+ <span className="font-medium">Path:</span>{' '}
170
+ {cookie.path}
171
+ </div>
172
+ )}
173
+ {cookie.expires && (
174
+ <div>
175
+ <span className="font-medium">Expires:</span>{' '}
176
+ {cookie.expires}
177
+ </div>
178
+ )}
179
+ {cookie.maxAge && (
180
+ <div>
181
+ <span className="font-medium">Max-Age:</span>{' '}
182
+ {cookie.maxAge}
183
+ </div>
160
184
  )}
161
- {cookie.httpOnly && (
162
- <Badge
163
- variant="outline"
164
- className="text-xs text-purple-400 border-purple-400"
165
- >
166
- HttpOnly
167
- </Badge>
185
+ {cookie.sameSite && (
186
+ <div>
187
+ <span className="font-medium">SameSite:</span>{' '}
188
+ {cookie.sameSite}
189
+ </div>
168
190
  )}
169
191
  </div>
170
192
  </div>
171
- <div className="text-sm text-gray-300 mb-2">
172
- {cookie.value}
173
- </div>
174
- <div className="grid grid-cols-2 gap-4 text-xs text-gray-400">
175
- {cookie.domain && (
176
- <div>
177
- <span className="font-medium">Domain:</span>{' '}
178
- {cookie.domain}
179
- </div>
180
- )}
181
- {cookie.path && (
182
- <div>
183
- <span className="font-medium">Path:</span>{' '}
184
- {cookie.path}
185
- </div>
186
- )}
187
- {cookie.expires && (
188
- <div>
189
- <span className="font-medium">Expires:</span>{' '}
190
- {cookie.expires}
191
- </div>
192
- )}
193
- {cookie.maxAge && (
194
- <div>
195
- <span className="font-medium">Max-Age:</span>{' '}
196
- {cookie.maxAge}
197
- </div>
198
- )}
199
- {cookie.sameSite && (
200
- <div>
201
- <span className="font-medium">SameSite:</span>{' '}
202
- {cookie.sameSite}
203
- </div>
204
- )}
205
- </div>
206
- </div>
207
- ))}
193
+ ))}
194
+ </div>
208
195
  </div>
209
- </div>
210
- )}
196
+ )}
211
197
 
212
- {/* Response Cookies */}
213
- {hasResponseCookies && (
214
- <div>
215
- <h4 className="text-sm font-medium text-gray-300 mb-3">
216
- Response Cookies ({responseCookies.length})
217
- </h4>
218
- <div className="space-y-2">
219
- {responseCookies.map((cookie, index) => (
220
- <div
221
- key={`response-${index}`}
222
- className="bg-gray-800 border border-gray-700 rounded p-3"
223
- >
224
- <div className="flex items-center justify-between mb-2">
225
- <span className="text-sm font-medium text-green-400">
226
- {cookie.name}
227
- </span>
228
- <div className="flex items-center gap-2">
229
- {cookie.secure && (
230
- <Badge
231
- variant="outline"
232
- className="text-xs text-yellow-400 border-yellow-400"
233
- >
234
- Secure
235
- </Badge>
198
+ {/* Response Cookies */}
199
+ {hasResponseCookies && (
200
+ <div>
201
+ <h4 className="text-sm font-medium text-gray-300 mb-3">
202
+ Response Cookies ({responseCookies.length})
203
+ </h4>
204
+ <div className="space-y-2">
205
+ {responseCookies.map((cookie, index) => (
206
+ <div
207
+ key={`response-${index}`}
208
+ className="bg-gray-800 border border-gray-700 rounded p-3"
209
+ >
210
+ <div className="flex items-center justify-between mb-2">
211
+ <span className="text-sm font-medium text-green-400">
212
+ {cookie.name}
213
+ </span>
214
+ <div className="flex items-center gap-2">
215
+ {cookie.secure && (
216
+ <Badge
217
+ variant="outline"
218
+ className="text-xs text-yellow-400 border-yellow-400"
219
+ >
220
+ Secure
221
+ </Badge>
222
+ )}
223
+ {cookie.httpOnly && (
224
+ <Badge
225
+ variant="outline"
226
+ className="text-xs text-purple-400 border-purple-400"
227
+ >
228
+ HttpOnly
229
+ </Badge>
230
+ )}
231
+ </div>
232
+ </div>
233
+ <div className="text-sm text-gray-300 mb-2">
234
+ {cookie.value}
235
+ </div>
236
+ <div className="grid grid-cols-2 gap-4 text-xs text-gray-400">
237
+ {cookie.domain && (
238
+ <div>
239
+ <span className="font-medium">Domain:</span>{' '}
240
+ {cookie.domain}
241
+ </div>
242
+ )}
243
+ {cookie.path && (
244
+ <div>
245
+ <span className="font-medium">Path:</span>{' '}
246
+ {cookie.path}
247
+ </div>
248
+ )}
249
+ {cookie.expires && (
250
+ <div>
251
+ <span className="font-medium">Expires:</span>{' '}
252
+ {cookie.expires}
253
+ </div>
236
254
  )}
237
- {cookie.httpOnly && (
238
- <Badge
239
- variant="outline"
240
- className="text-xs text-purple-400 border-purple-400"
241
- >
242
- HttpOnly
243
- </Badge>
255
+ {cookie.maxAge && (
256
+ <div>
257
+ <span className="font-medium">Max-Age:</span>{' '}
258
+ {cookie.maxAge}
259
+ </div>
260
+ )}
261
+ {cookie.sameSite && (
262
+ <div>
263
+ <span className="font-medium">SameSite:</span>{' '}
264
+ {cookie.sameSite}
265
+ </div>
244
266
  )}
245
267
  </div>
246
268
  </div>
247
- <div className="text-sm text-gray-300 mb-2">
248
- {cookie.value}
249
- </div>
250
- <div className="grid grid-cols-2 gap-4 text-xs text-gray-400">
251
- {cookie.domain && (
252
- <div>
253
- <span className="font-medium">Domain:</span>{' '}
254
- {cookie.domain}
255
- </div>
256
- )}
257
- {cookie.path && (
258
- <div>
259
- <span className="font-medium">Path:</span>{' '}
260
- {cookie.path}
261
- </div>
262
- )}
263
- {cookie.expires && (
264
- <div>
265
- <span className="font-medium">Expires:</span>{' '}
266
- {cookie.expires}
267
- </div>
268
- )}
269
- {cookie.maxAge && (
270
- <div>
271
- <span className="font-medium">Max-Age:</span>{' '}
272
- {cookie.maxAge}
273
- </div>
274
- )}
275
- {cookie.sameSite && (
276
- <div>
277
- <span className="font-medium">SameSite:</span>{' '}
278
- {cookie.sameSite}
279
- </div>
280
- )}
281
- </div>
282
- </div>
283
- ))}
269
+ ))}
270
+ </div>
284
271
  </div>
285
- </div>
286
- )}
287
- </div>
288
- );
289
- })()}
272
+ )}
273
+ </div>
274
+ );
275
+ })()}
290
276
  </div>
291
277
  </ScrollArea>
292
278
  );
@@ -1,27 +1,19 @@
1
+ import { useMemo } from 'react';
1
2
  import { ScrollArea } from '../components/ScrollArea';
2
- import { NetworkEntry } from '../types';
3
+ import { HttpNetworkEntry, SSENetworkEntry } from '../state/model';
4
+ import { getStatusColor } from '../utils/getStatusColor';
3
5
 
4
6
  export type HeadersTabProps = {
5
- selectedRequest: {
6
- id: string;
7
- domain: string;
8
- path: string;
9
- method: string;
10
- status: number;
11
- requestBody?: {
12
- type: string;
13
- data: string;
14
- };
15
- };
16
- networkEntries: Map<string, NetworkEntry>;
17
- getStatusColor: (status: number) => string;
7
+ selectedRequest: HttpNetworkEntry | SSENetworkEntry;
18
8
  };
19
9
 
20
- export const HeadersTab = ({
21
- selectedRequest,
22
- networkEntries,
23
- getStatusColor,
24
- }: HeadersTabProps) => {
10
+ export const HeadersTab = ({ selectedRequest }: HeadersTabProps) => {
11
+ const url = useMemo(() => {
12
+ const { hostname, port, pathname } = new URL(selectedRequest.request.url);
13
+
14
+ return `${hostname}${port ? `:${port}` : ''}${pathname}`;
15
+ }, [selectedRequest.request.url]);
16
+
25
17
  return (
26
18
  <ScrollArea className="h-full w-full">
27
19
  <div className="p-4 space-y-4">
@@ -31,25 +23,28 @@ export const HeadersTab = ({
31
23
  <div className="flex">
32
24
  <span className="w-32 text-gray-400">Request URL:</span>
33
25
  <span className="text-blue-400">
34
- {selectedRequest.domain}
35
- {selectedRequest.path}
26
+ {url}
36
27
  </span>
37
28
  </div>
38
29
  <div className="flex">
39
30
  <span className="w-32 text-gray-400">Request Method:</span>
40
- <span>{selectedRequest.method}</span>
31
+ <span>{selectedRequest.request.method}</span>
41
32
  </div>
42
33
  <div className="flex">
43
34
  <span className="w-32 text-gray-400">Status Code:</span>
44
- <span className={getStatusColor(selectedRequest.status)}>
45
- {selectedRequest.status}
35
+ <span
36
+ className={getStatusColor(
37
+ selectedRequest.response?.status ?? 0
38
+ )}
39
+ >
40
+ {selectedRequest.response?.status ?? 'Pending'}
46
41
  </span>
47
42
  </div>
48
- {selectedRequest.requestBody && (
43
+ {selectedRequest.request.body && (
49
44
  <div className="flex">
50
45
  <span className="w-32 text-gray-400">Content-Type:</span>
51
46
  <span className="text-blue-400">
52
- {selectedRequest.requestBody.type}
47
+ {selectedRequest.request.body.type}
53
48
  </span>
54
49
  </div>
55
50
  )}
@@ -62,8 +57,7 @@ export const HeadersTab = ({
62
57
  </h4>
63
58
  <div className="space-y-1 text-sm font-mono">
64
59
  {(() => {
65
- const entry = networkEntries.get(selectedRequest.id);
66
- const responseHeaders = entry?.response?.headers;
60
+ const responseHeaders = selectedRequest.response?.headers;
67
61
  if (responseHeaders && Object.keys(responseHeaders).length > 0) {
68
62
  return Object.entries(responseHeaders).map(([key, value]) => (
69
63
  <div key={key} className="flex">
@@ -90,8 +84,7 @@ export const HeadersTab = ({
90
84
  </h4>
91
85
  <div className="space-y-1 text-sm font-mono">
92
86
  {(() => {
93
- const entry = networkEntries.get(selectedRequest.id);
94
- const requestHeaders = entry?.request?.headers;
87
+ const requestHeaders = selectedRequest.request.headers;
95
88
  if (requestHeaders && Object.keys(requestHeaders).length > 0) {
96
89
  return Object.entries(requestHeaders).map(([key, value]) => (
97
90
  <div key={key} className="flex">