@rozenite/network-activity-plugin 1.0.0-alpha.5 → 1.0.0-alpha.6

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 (75) hide show
  1. package/dist/{panel.html → App.html} +3 -3
  2. package/dist/assets/App-CIflVb88.js +24164 -0
  3. package/dist/assets/App-Czu6Vt2P.css +1233 -0
  4. package/dist/react-native.cjs +1 -1
  5. package/dist/react-native.d.ts +1 -90
  6. package/dist/rozenite.config.d.ts +7 -0
  7. package/dist/rozenite.json +1 -1
  8. package/dist/src/react-native/network-inspector.d.ts +8 -0
  9. package/dist/src/react-native/network-requests-registry.d.ts +6 -0
  10. package/dist/src/react-native/useNetworkActivityDevTools.d.ts +2 -0
  11. package/dist/src/react-native/xhr-interceptor.d.ts +38 -0
  12. package/dist/src/shared/client.d.ts +64 -0
  13. package/dist/src/ui/App.d.ts +1 -0
  14. package/dist/src/ui/components/Badge.d.ts +9 -0
  15. package/dist/src/ui/components/Button.d.ts +11 -0
  16. package/dist/src/ui/components/Input.d.ts +3 -0
  17. package/dist/src/ui/components/JsonTree.d.ts +5 -0
  18. package/dist/src/ui/components/RequestList.d.ts +45 -0
  19. package/dist/src/ui/components/ScrollArea.d.ts +4 -0
  20. package/dist/src/ui/components/Separator.d.ts +3 -0
  21. package/dist/src/ui/tabs/CookiesTab.d.ts +8 -0
  22. package/dist/src/ui/tabs/HeadersTab.d.ts +17 -0
  23. package/dist/src/ui/tabs/RequestTab.d.ts +10 -0
  24. package/dist/src/ui/tabs/ResponseTab.d.ts +12 -0
  25. package/dist/src/ui/tabs/TimingTab.d.ts +7 -0
  26. package/dist/src/ui/types.d.ts +23 -0
  27. package/dist/src/ui/utils.d.ts +2 -0
  28. package/dist/src/ui/views/InspectorView.d.ts +5 -0
  29. package/dist/src/ui/views/LoadingView.d.ts +1 -0
  30. package/dist/useNetworkActivityDevTools.cjs +360 -0
  31. package/dist/useNetworkActivityDevTools.js +108 -236
  32. package/package.json +23 -16
  33. package/postcss.config.js +6 -0
  34. package/rozenite.config.ts +1 -1
  35. package/src/react-native/network-inspector.ts +113 -260
  36. package/src/react-native/network-requests-registry.ts +7 -77
  37. package/src/react-native/useNetworkActivityDevTools.ts +1 -1
  38. package/src/react-native/xhr-interceptor.ts +2 -2
  39. package/src/react-native/xml-request.d.ts +11 -1
  40. package/src/shared/client.ts +80 -0
  41. package/src/ui/App.tsx +19 -0
  42. package/src/ui/components/Badge.tsx +36 -0
  43. package/src/ui/components/Button.tsx +56 -0
  44. package/src/ui/components/Input.tsx +22 -0
  45. package/src/ui/components/JsonTree.tsx +37 -0
  46. package/src/ui/components/RequestList.tsx +376 -0
  47. package/src/ui/components/ScrollArea.tsx +48 -0
  48. package/src/ui/components/Separator.tsx +31 -0
  49. package/src/ui/components/Tabs.tsx +55 -0
  50. package/src/ui/globals.css +90 -0
  51. package/src/ui/tabs/CookiesTab.tsx +290 -0
  52. package/src/ui/tabs/HeadersTab.tsx +117 -0
  53. package/src/ui/tabs/RequestTab.tsx +72 -0
  54. package/src/ui/tabs/ResponseTab.tsx +140 -0
  55. package/src/ui/tabs/TimingTab.tsx +71 -0
  56. package/src/ui/types.ts +30 -0
  57. package/src/ui/utils.ts +5 -97
  58. package/src/ui/views/InspectorView.tsx +349 -0
  59. package/src/ui/views/LoadingView.tsx +19 -0
  60. package/tailwind.config.ts +93 -0
  61. package/dist/assets/panel-BNxB_KsS.js +0 -16663
  62. package/dist/assets/panel-DXGMsavf.css +0 -555
  63. package/src/types/client.ts +0 -111
  64. package/src/types/network.ts +0 -32
  65. package/src/ui/components.module.css +0 -158
  66. package/src/ui/components.tsx +0 -241
  67. package/src/ui/network-details.module.css +0 -197
  68. package/src/ui/network-details.tsx +0 -345
  69. package/src/ui/network-list.module.css +0 -128
  70. package/src/ui/network-list.tsx +0 -240
  71. package/src/ui/network-toolbar.module.css +0 -9
  72. package/src/ui/network-toolbar.tsx +0 -34
  73. package/src/ui/panel.module.css +0 -67
  74. package/src/ui/panel.tsx +0 -318
  75. package/src/ui/tanstack-query.tsx +0 -204
@@ -1,7 +1,5 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const react = require("react");
4
- const pluginBridge = require("@rozenite/plugin-bridge");
1
+ import { useEffect } from "react";
2
+ import { useRozeniteDevToolsClient } from "@rozenite/plugin-bridge";
5
3
  const REQUEST_TTL = 1e3 * 60 * 5;
6
4
  const getNetworkRequestsRegistry = () => {
7
5
  const registry = /* @__PURE__ */ new Map();
@@ -14,35 +12,17 @@ const getNetworkRequestsRegistry = () => {
14
12
  registry.delete(entry.id);
15
13
  });
16
14
  };
17
- const addEntry = (id, request, metadata) => {
15
+ const addEntry = (id, request) => {
18
16
  trimRegistry();
19
- const fullMetadata = {
20
- id,
21
- method: metadata.method || "GET",
22
- url: metadata.url || "",
23
- headers: metadata.headers || {},
24
- startTime: metadata.startTime || Date.now(),
25
- status: metadata.status || "pending",
26
- ...metadata
27
- };
28
17
  registry.set(id, {
29
18
  id,
30
19
  request,
31
- metadata: fullMetadata,
32
20
  sentAt: Date.now()
33
21
  });
34
22
  };
35
23
  const getEntry = (id) => {
36
- return registry.get(id) ?? null;
37
- };
38
- const updateEntry = (id, updates) => {
39
- const entry = registry.get(id);
40
- if (entry) {
41
- entry.metadata = { ...entry.metadata, ...updates };
42
- }
43
- };
44
- const getAllEntries = () => {
45
- return Array.from(registry.values());
24
+ var _a;
25
+ return ((_a = registry.get(id)) == null ? void 0 : _a.request) ?? null;
46
26
  };
47
27
  const clear = () => {
48
28
  registry.clear();
@@ -50,8 +30,6 @@ const getNetworkRequestsRegistry = () => {
50
30
  return {
51
31
  addEntry,
52
32
  getEntry,
53
- updateEntry,
54
- getAllEntries,
55
33
  clear
56
34
  };
57
35
  };
@@ -181,11 +159,15 @@ const XHRInterceptor = {
181
159
  }
182
160
  };
183
161
  const networkRequestsRegistry = getNetworkRequestsRegistry();
184
- const mimeTypeFromResponseType = (responseType) => {
162
+ const getContentType = (request) => {
163
+ const responseHeaders = request.responseHeaders;
164
+ const responseType = request.responseType;
165
+ if (responseHeaders == null ? void 0 : responseHeaders["content-type"]) {
166
+ return responseHeaders["content-type"].split(";")[0].trim();
167
+ }
185
168
  switch (responseType) {
186
169
  case "arraybuffer":
187
170
  case "blob":
188
- case "base64":
189
171
  return "application/octet-stream";
190
172
  case "text":
191
173
  case "":
@@ -195,67 +177,31 @@ const mimeTypeFromResponseType = (responseType) => {
195
177
  case "document":
196
178
  return "text/html";
197
179
  }
198
- return void 0;
199
180
  };
200
- const parseHeaders = (headersString) => {
201
- const headers = {};
202
- if (!headersString) return headers;
203
- const lines = headersString.split("\r\n");
204
- for (const line of lines) {
205
- const colonIndex = line.indexOf(":");
206
- if (colonIndex > 0) {
207
- const key = line.substring(0, colonIndex).trim();
208
- const value = line.substring(colonIndex + 1).trim();
209
- headers[key] = value;
210
- }
181
+ const getResponseSize = (request) => {
182
+ if (typeof request.response === "object") {
183
+ return request.response.size;
211
184
  }
212
- return headers;
185
+ return request.response.length || 0;
213
186
  };
214
187
  const getResponseBody = async (request) => {
215
- try {
216
- if (request.responseType === "arraybuffer") {
217
- const arrayBuffer = request.response;
218
- return {
219
- body: btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))),
220
- base64Encoded: true
221
- };
222
- }
223
- if (request.responseType === "blob") {
224
- const contentType = request.getResponseHeader("Content-Type") || "";
225
- if (contentType.startsWith("text/") || contentType.startsWith("application/json")) {
226
- return new Promise((resolve) => {
227
- const reader = new FileReader();
228
- reader.onload = () => {
229
- resolve({
230
- body: reader.result,
231
- base64Encoded: false
232
- });
233
- };
234
- reader.readAsText(request.response);
235
- });
236
- }
237
- }
238
- if (request.responseType === "text") {
239
- return {
240
- body: request.responseText || request.response || "",
241
- base64Encoded: false
242
- };
188
+ const responseType = request.responseType;
189
+ if (responseType === "text") {
190
+ return request.responseText;
191
+ }
192
+ if (responseType === "blob") {
193
+ const contentType = request.getResponseHeader("Content-Type") || "";
194
+ if (contentType.startsWith("text/") || contentType.startsWith("application/json")) {
195
+ return new Promise((resolve) => {
196
+ const reader = new FileReader();
197
+ reader.onload = () => {
198
+ resolve(reader.result);
199
+ };
200
+ reader.readAsText(request.response);
201
+ });
243
202
  }
244
- return {
245
- body: request.responseText || request.response || "",
246
- base64Encoded: false
247
- };
248
- } catch (error) {
249
- return {
250
- body: `[Error reading response: ${error}]`,
251
- base64Encoded: false
252
- };
253
203
  }
254
- };
255
- const findRequestId = (request) => {
256
- const allRequests = networkRequestsRegistry.getAllEntries();
257
- const entry = allRequests.find(({ request: req }) => req === request);
258
- return (entry == null ? void 0 : entry.id) ?? null;
204
+ return null;
259
205
  };
260
206
  const getInitiatorFromStack = () => {
261
207
  try {
@@ -277,154 +223,81 @@ const getInitiatorFromStack = () => {
277
223
  }
278
224
  return { type: "other" };
279
225
  };
226
+ const READY_STATE_HEADERS_RECEIVED = 2;
280
227
  const getNetworkInspector = (pluginClient) => {
281
228
  const generateRequestId = () => {
282
229
  return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
283
230
  };
284
- const generateLoaderId = () => {
285
- return `loader_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
286
- };
287
- const enable = () => {
288
- XHRInterceptor.disableInterception();
289
- XHRInterceptor.setOpenCallback(
290
- (method, url, request) => {
291
- const requestId = generateRequestId();
292
- const loaderId = generateLoaderId();
293
- const startTime = Date.now();
294
- const initiator = getInitiatorFromStack();
295
- networkRequestsRegistry.addEntry(requestId, request, {
296
- id: requestId,
297
- loaderId,
298
- documentURL: typeof document !== "undefined" ? document.URL : void 0,
299
- method,
300
- url,
301
- headers: (request == null ? void 0 : request._headers) || {},
302
- startTime,
303
- status: "pending",
304
- type: "XHR",
305
- initiator
306
- });
231
+ const handleRequestSend = (data, request) => {
232
+ const sendTime = Date.now();
233
+ const requestId = generateRequestId();
234
+ const initiator = getInitiatorFromStack();
235
+ networkRequestsRegistry.addEntry(requestId, request);
236
+ let ttfb = 0;
237
+ pluginClient.send("request-sent", {
238
+ requestId,
239
+ timestamp: sendTime / 1e3,
240
+ request: {
241
+ url: request._url,
242
+ method: request._method,
243
+ headers: request._headers,
244
+ postData: data
245
+ },
246
+ type: "XHR",
247
+ initiator
248
+ });
249
+ request.addEventListener("readystatechange", () => {
250
+ if (request.readyState === READY_STATE_HEADERS_RECEIVED) {
251
+ ttfb = Date.now() - sendTime;
307
252
  }
308
- );
309
- XHRInterceptor.setSendCallback((data, request) => {
310
- const requestId = findRequestId(request);
311
- if (!requestId) return;
312
- const entry = networkRequestsRegistry.getEntry(requestId);
313
- if (!entry) return;
314
- const metadata = entry.metadata;
315
- networkRequestsRegistry.updateEntry(requestId, {
316
- postData: data,
317
- hasPostData: !!data,
318
- headers: (request == null ? void 0 : request._headers) || {}
253
+ });
254
+ request.addEventListener("load", () => {
255
+ pluginClient.send("response-received", {
256
+ requestId,
257
+ timestamp: Date.now() / 1e3,
258
+ type: "XHR",
259
+ response: {
260
+ url: request._url,
261
+ status: request.status,
262
+ statusText: request.statusText,
263
+ headers: request.responseHeaders,
264
+ contentType: getContentType(request),
265
+ size: getResponseSize(request),
266
+ responseTime: Date.now() / 1e3
267
+ }
319
268
  });
320
- pluginClient.send("Network.requestWillBeSent", {
269
+ });
270
+ request.addEventListener("loadend", () => {
271
+ pluginClient.send("request-completed", {
321
272
  requestId,
322
- loaderId: metadata.loaderId || "",
323
- documentURL: metadata.documentURL || "",
324
- request: {
325
- url: metadata.url,
326
- method: metadata.method,
327
- headers: metadata.headers,
328
- postData: data,
329
- hasPostData: !!data
330
- },
331
- timestamp: metadata.startTime,
332
- wallTime: metadata.startTime,
333
- initiator: metadata.initiator || { type: "other" },
334
- type: metadata.type
273
+ timestamp: Date.now() / 1e3,
274
+ duration: Date.now() - sendTime,
275
+ size: getResponseSize(request),
276
+ ttfb
335
277
  });
336
278
  });
337
- XHRInterceptor.setHeaderReceivedCallback(
338
- (responseContentType, responseSize, allHeaders, request) => {
339
- const requestId = findRequestId(request);
340
- if (!requestId) return;
341
- const entry = networkRequestsRegistry.getEntry(requestId);
342
- if (!entry) return;
343
- const metadata = entry.metadata;
344
- const headers = parseHeaders(allHeaders);
345
- const mimeType = responseContentType || mimeTypeFromResponseType(request.responseType) || "text/plain";
346
- networkRequestsRegistry.updateEntry(requestId, {
347
- status: "loading",
348
- response: {
349
- url: metadata.url,
350
- status: request.status,
351
- statusText: request.statusText,
352
- headers,
353
- mimeType,
354
- encodedDataLength: responseSize || 0,
355
- responseTime: Date.now()
356
- }
357
- });
358
- pluginClient.send("Network.responseReceived", {
359
- requestId,
360
- loaderId: metadata.loaderId || "",
361
- timestamp: Date.now(),
362
- type: metadata.type || "Other",
363
- response: {
364
- url: metadata.url,
365
- status: request.status,
366
- statusText: request.statusText,
367
- headers,
368
- mimeType,
369
- encodedDataLength: responseSize || 0,
370
- responseTime: Date.now()
371
- }
372
- });
373
- }
374
- );
375
- XHRInterceptor.setResponseCallback(
376
- (status, timeout, response, responseURL, responseType, request) => {
377
- const requestId = findRequestId(request);
378
- if (!requestId) return;
379
- const entry = networkRequestsRegistry.getEntry(requestId);
380
- if (!entry) return;
381
- const metadata = entry.metadata;
382
- if (!metadata) return;
383
- const endTime = Date.now();
384
- const duration = endTime - metadata.startTime;
385
- const dataLength = response ? response.length : 0;
386
- networkRequestsRegistry.updateEntry(requestId, {
387
- endTime,
388
- duration,
389
- dataLength,
390
- encodedDataLength: dataLength
391
- });
392
- if (status >= 400 || request.readyState === 0) {
393
- const errorText = request.statusText || "Request failed";
394
- const canceled = request.readyState === 0;
395
- networkRequestsRegistry.updateEntry(requestId, {
396
- status: "failed",
397
- errorText,
398
- canceled
399
- });
400
- pluginClient.send("Network.loadingFailed", {
401
- requestId,
402
- timestamp: endTime,
403
- type: metadata.type || "Other",
404
- errorText,
405
- canceled
406
- });
407
- } else {
408
- networkRequestsRegistry.updateEntry(requestId, {
409
- status: "finished",
410
- encodedDataLength: dataLength
411
- });
412
- if (dataLength > 0) {
413
- pluginClient.send("Network.dataReceived", {
414
- requestId,
415
- timestamp: endTime,
416
- dataLength,
417
- encodedDataLength: dataLength
418
- });
419
- }
420
- pluginClient.send("Network.loadingFinished", {
421
- requestId,
422
- timestamp: endTime,
423
- encodedDataLength: dataLength
424
- });
425
- }
426
- }
427
- );
279
+ request.addEventListener("error", () => {
280
+ pluginClient.send("request-failed", {
281
+ requestId,
282
+ timestamp: Date.now() / 1e3,
283
+ type: "XHR",
284
+ error: "Failed",
285
+ canceled: false
286
+ });
287
+ });
288
+ request.addEventListener("abort", () => {
289
+ pluginClient.send("request-failed", {
290
+ requestId,
291
+ timestamp: Date.now() / 1e3,
292
+ type: "XHR",
293
+ error: "Aborted",
294
+ canceled: true
295
+ });
296
+ });
297
+ };
298
+ const enable = () => {
299
+ XHRInterceptor.disableInterception();
300
+ XHRInterceptor.setSendCallback(handleRequestSend);
428
301
  XHRInterceptor.enableInterception();
429
302
  };
430
303
  const disable = () => {
@@ -441,19 +314,16 @@ const getNetworkInspector = (pluginClient) => {
441
314
  disable();
442
315
  });
443
316
  const handleBodySubscription = pluginClient.onMessage(
444
- "Network.getResponseBody",
445
- async (payload) => {
446
- const requestId = payload.requestId;
447
- const entry = networkRequestsRegistry.getEntry(requestId);
448
- if (!entry) {
317
+ "get-response-body",
318
+ async ({ requestId }) => {
319
+ const request = networkRequestsRegistry.getEntry(requestId);
320
+ if (!request) {
449
321
  return;
450
322
  }
451
- const { request } = entry;
452
- const { body, base64Encoded } = await getResponseBody(request);
453
- pluginClient.send("Network.responseBodyReceived", {
323
+ const body = await getResponseBody(request);
324
+ pluginClient.send("response-body", {
454
325
  requestId,
455
- body,
456
- base64Encoded
326
+ body
457
327
  });
458
328
  }
459
329
  );
@@ -471,10 +341,10 @@ const getNetworkInspector = (pluginClient) => {
471
341
  };
472
342
  };
473
343
  const useNetworkActivityDevTools = () => {
474
- const client = pluginBridge.useRozeniteDevToolsClient({
344
+ const client = useRozeniteDevToolsClient({
475
345
  pluginId: "@rozenite/network-activity-plugin"
476
346
  });
477
- react.useEffect(() => {
347
+ useEffect(() => {
478
348
  if (!client) {
479
349
  return;
480
350
  }
@@ -485,4 +355,6 @@ const useNetworkActivityDevTools = () => {
485
355
  }, [client]);
486
356
  return client;
487
357
  };
488
- exports.useNetworkActivityDevTools = useNetworkActivityDevTools;
358
+ export {
359
+ useNetworkActivityDevTools
360
+ };
package/package.json CHANGED
@@ -1,30 +1,37 @@
1
1
  {
2
2
  "name": "@rozenite/network-activity-plugin",
3
- "version": "1.0.0-alpha.5",
3
+ "version": "1.0.0-alpha.6",
4
4
  "description": "Network Activity for Rozenite.",
5
5
  "type": "module",
6
6
  "main": "./dist/react-native.cjs",
7
7
  "module": "./dist/react-native.js",
8
8
  "types": "./dist/react-native.d.ts",
9
9
  "dependencies": {
10
- "@tanstack/react-virtual": "^3.0.0",
11
- "@floating-ui/react": "^0.26.0",
12
- "@rozenite/plugin-bridge": "1.0.0-alpha.5"
10
+ "@rozenite/plugin-bridge": "1.0.0-alpha.6"
13
11
  },
14
12
  "devDependencies": {
15
- "vite": "^6.0.0",
16
- "typescript": "^5.7.3",
17
- "react-native-web": "0.21.0",
18
- "react": "18.3.1",
19
- "react-dom": "18.3.0",
20
- "react-native": "0.76.0",
21
- "@types/react": "~18.3.12",
22
- "@rozenite/vite-plugin": "1.0.0-alpha.5",
23
- "rozenite": "1.0.0-alpha.5"
24
- },
25
- "peerDependencies": {
13
+ "@radix-ui/react-scroll-area": "^1.2.9",
14
+ "@radix-ui/react-separator": "^1.1.7",
15
+ "@radix-ui/react-slot": "^1.2.3",
16
+ "@radix-ui/react-tabs": "^1.1.12",
17
+ "@tanstack/react-table": "^8.21.3",
18
+ "autoprefixer": "^10.4.21",
19
+ "class-variance-authority": "^0.7.1",
20
+ "clsx": "^2.1.1",
21
+ "postcss": "^8.5.6",
26
22
  "react": "*",
27
- "react-native": "*"
23
+ "react-json-tree": "^0.20.0",
24
+ "react-native": "*",
25
+ "tailwind-merge": "^3.3.1",
26
+ "tailwindcss": "^3.4.17",
27
+ "tailwindcss-animate": "^1.0.7",
28
+ "typescript": "^5.7.3",
29
+ "vite": "^6.0.0",
30
+ "@floating-ui/react": "^0.26.0",
31
+ "@tanstack/react-virtual": "^3.0.0",
32
+ "lucide-react": "^0.263.1",
33
+ "@rozenite/vite-plugin": "1.0.0-alpha.6",
34
+ "rozenite": "1.0.0-alpha.6"
28
35
  },
29
36
  "license": "MIT",
30
37
  "scripts": {
@@ -0,0 +1,6 @@
1
+ export default {
2
+ plugins: {
3
+ tailwindcss: {},
4
+ autoprefixer: {},
5
+ },
6
+ };
@@ -2,7 +2,7 @@ export default {
2
2
  panels: [
3
3
  {
4
4
  name: 'Network Activity',
5
- source: './src/ui/panel.tsx',
5
+ source: './src/ui/App.tsx',
6
6
  },
7
7
  ],
8
8
  };