@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,5 +1,9 @@
1
1
  import { useEffect } from "react";
2
2
  import { useRozeniteDevToolsClient } from "@rozenite/plugin-bridge";
3
+ import { createNanoEvents } from "nanoevents";
4
+ import { Platform } from "react-native";
5
+ import WebSocketInterceptor from "react-native/Libraries/WebSocket/WebSocketInterceptor";
6
+ import { g as getEventSource } from "./event-source.js";
3
7
  function getHttpHeaderValue(headers, name) {
4
8
  const lowerName = name.toLowerCase();
5
9
  for (const key in headers) {
@@ -9,6 +13,26 @@ function getHttpHeaderValue(headers, name) {
9
13
  }
10
14
  return void 0;
11
15
  }
16
+ const getContentType = (request) => {
17
+ const responseHeaders = request.responseHeaders;
18
+ const responseType = request.responseType;
19
+ const contentType = getHttpHeaderValue(responseHeaders || {}, "content-type");
20
+ if (contentType) {
21
+ return contentType.split(";")[0].trim();
22
+ }
23
+ switch (responseType) {
24
+ case "arraybuffer":
25
+ case "blob":
26
+ return "application/octet-stream";
27
+ case "text":
28
+ case "":
29
+ return "text/plain";
30
+ case "json":
31
+ return "application/json";
32
+ case "document":
33
+ return "text/html";
34
+ }
35
+ };
12
36
  const REQUEST_TTL = 1e3 * 60 * 5;
13
37
  const getNetworkRequestsRegistry = () => {
14
38
  const registry = /* @__PURE__ */ new Map();
@@ -50,7 +74,7 @@ let sendCallback;
50
74
  let requestHeaderCallback;
51
75
  let headerReceivedCallback;
52
76
  let responseCallback;
53
- let isInterceptorEnabled = false;
77
+ let isInterceptorEnabled$1 = false;
54
78
  const XHRInterceptor = {
55
79
  /**
56
80
  * Invoked before XMLHttpRequest.open(...) is called.
@@ -83,10 +107,10 @@ const XHRInterceptor = {
83
107
  requestHeaderCallback = callback;
84
108
  },
85
109
  isInterceptorEnabled() {
86
- return isInterceptorEnabled;
110
+ return isInterceptorEnabled$1;
87
111
  },
88
112
  enableInterception() {
89
- if (isInterceptorEnabled) {
113
+ if (isInterceptorEnabled$1) {
90
114
  return;
91
115
  }
92
116
  XMLHttpRequest.prototype.open = function(method, url) {
@@ -109,7 +133,7 @@ const XHRInterceptor = {
109
133
  this.addEventListener(
110
134
  "readystatechange",
111
135
  () => {
112
- if (!isInterceptorEnabled) {
136
+ if (!isInterceptorEnabled$1) {
113
137
  return;
114
138
  }
115
139
  if (this.readyState === this.HEADERS_RECEIVED) {
@@ -149,14 +173,14 @@ const XHRInterceptor = {
149
173
  }
150
174
  originalXHRSend.apply(this, arguments);
151
175
  };
152
- isInterceptorEnabled = true;
176
+ isInterceptorEnabled$1 = true;
153
177
  },
154
178
  // Unpatch XMLHttpRequest methods and remove the callbacks.
155
179
  disableInterception() {
156
- if (!isInterceptorEnabled) {
180
+ if (!isInterceptorEnabled$1) {
157
181
  return;
158
182
  }
159
- isInterceptorEnabled = false;
183
+ isInterceptorEnabled$1 = false;
160
184
  XMLHttpRequest.prototype.send = originalXHRSend;
161
185
  XMLHttpRequest.prototype.open = originalXHROpen;
162
186
  XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
@@ -168,26 +192,6 @@ const XHRInterceptor = {
168
192
  }
169
193
  };
170
194
  const networkRequestsRegistry = getNetworkRequestsRegistry();
171
- const getContentType = (request) => {
172
- const responseHeaders = request.responseHeaders;
173
- const responseType = request.responseType;
174
- const contentType = getHttpHeaderValue(responseHeaders || {}, "content-type");
175
- if (contentType) {
176
- return contentType.split(";")[0].trim();
177
- }
178
- switch (responseType) {
179
- case "arraybuffer":
180
- case "blob":
181
- return "application/octet-stream";
182
- case "text":
183
- case "":
184
- return "text/plain";
185
- case "json":
186
- return "application/json";
187
- case "document":
188
- return "text/html";
189
- }
190
- };
191
195
  const getResponseSize = (request) => {
192
196
  if (typeof request.response === "object") {
193
197
  return request.response.size;
@@ -196,7 +200,7 @@ const getResponseSize = (request) => {
196
200
  };
197
201
  const getResponseBody = async (request) => {
198
202
  const responseType = request.responseType;
199
- if (responseType === "text") {
203
+ if (responseType === "" || responseType === "text") {
200
204
  return request.responseText;
201
205
  }
202
206
  if (responseType === "blob") {
@@ -241,12 +245,13 @@ const getNetworkInspector = (pluginClient) => {
241
245
  const handleRequestSend = (data, request) => {
242
246
  const sendTime = Date.now();
243
247
  const requestId = generateRequestId();
248
+ request._rozeniteRequestId = requestId;
244
249
  const initiator = getInitiatorFromStack();
245
250
  networkRequestsRegistry.addEntry(requestId, request);
246
251
  let ttfb = 0;
247
252
  pluginClient.send("request-sent", {
248
253
  requestId,
249
- timestamp: sendTime / 1e3,
254
+ timestamp: sendTime,
250
255
  request: {
251
256
  url: request._url,
252
257
  method: request._method,
@@ -264,7 +269,7 @@ const getNetworkInspector = (pluginClient) => {
264
269
  request.addEventListener("load", () => {
265
270
  pluginClient.send("response-received", {
266
271
  requestId,
267
- timestamp: Date.now() / 1e3,
272
+ timestamp: Date.now(),
268
273
  type: "XHR",
269
274
  response: {
270
275
  url: request._url,
@@ -273,14 +278,14 @@ const getNetworkInspector = (pluginClient) => {
273
278
  headers: request.responseHeaders || {},
274
279
  contentType: getContentType(request),
275
280
  size: getResponseSize(request),
276
- responseTime: Date.now() / 1e3
281
+ responseTime: Date.now()
277
282
  }
278
283
  });
279
284
  });
280
285
  request.addEventListener("loadend", () => {
281
286
  pluginClient.send("request-completed", {
282
287
  requestId,
283
- timestamp: Date.now() / 1e3,
288
+ timestamp: Date.now(),
284
289
  duration: Date.now() - sendTime,
285
290
  size: getResponseSize(request),
286
291
  ttfb
@@ -289,7 +294,7 @@ const getNetworkInspector = (pluginClient) => {
289
294
  request.addEventListener("error", () => {
290
295
  pluginClient.send("request-failed", {
291
296
  requestId,
292
- timestamp: Date.now() / 1e3,
297
+ timestamp: Date.now(),
293
298
  type: "XHR",
294
299
  error: "Failed",
295
300
  canceled: false
@@ -298,7 +303,7 @@ const getNetworkInspector = (pluginClient) => {
298
303
  request.addEventListener("abort", () => {
299
304
  pluginClient.send("request-failed", {
300
305
  requestId,
301
- timestamp: Date.now() / 1e3,
306
+ timestamp: Date.now(),
302
307
  type: "XHR",
303
308
  error: "Aborted",
304
309
  canceled: true
@@ -350,6 +355,333 @@ const getNetworkInspector = (pluginClient) => {
350
355
  dispose
351
356
  };
352
357
  };
358
+ const getWebSocketInterceptor = () => {
359
+ if (Platform.constants.reactNativeVersion.minor >= 79) {
360
+ return WebSocketInterceptor;
361
+ } else {
362
+ const WebSocketInterceptorPreRN079 = WebSocketInterceptor;
363
+ return {
364
+ ...WebSocketInterceptorPreRN079,
365
+ setOnMessageCallback: (callback) => {
366
+ WebSocketInterceptorPreRN079.setOnMessageCallback((socketId, data) => {
367
+ callback(data, socketId);
368
+ });
369
+ },
370
+ setOnCloseCallback: (callback) => {
371
+ WebSocketInterceptorPreRN079.setOnCloseCallback((error, socketId) => {
372
+ callback(socketId, error);
373
+ });
374
+ },
375
+ setOnErrorCallback: (callback) => {
376
+ WebSocketInterceptorPreRN079.setOnErrorCallback((error, socketId) => {
377
+ callback(socketId, error);
378
+ });
379
+ }
380
+ };
381
+ }
382
+ };
383
+ const getWebSocketInspector = () => {
384
+ const eventEmitter = createNanoEvents();
385
+ const socketUrlMap = /* @__PURE__ */ new Map();
386
+ const webSocketInterceptor = getWebSocketInterceptor();
387
+ return {
388
+ enable: () => {
389
+ webSocketInterceptor.setConnectCallback(
390
+ (url, protocols, options, socketId) => {
391
+ socketUrlMap.set(socketId, url);
392
+ const event = {
393
+ type: "websocket-connect",
394
+ url,
395
+ socketId,
396
+ timestamp: Date.now(),
397
+ protocols,
398
+ options
399
+ };
400
+ eventEmitter.emit("websocket-connect", event);
401
+ }
402
+ );
403
+ webSocketInterceptor.setCloseCallback(
404
+ (code, reason, socketId) => {
405
+ const url = socketUrlMap.get(socketId);
406
+ if (!url) {
407
+ return;
408
+ }
409
+ const event = {
410
+ type: "websocket-close",
411
+ url,
412
+ socketId,
413
+ timestamp: Date.now(),
414
+ code: code || 0,
415
+ reason: reason || void 0
416
+ };
417
+ eventEmitter.emit("websocket-close", event);
418
+ socketUrlMap.delete(socketId);
419
+ }
420
+ );
421
+ webSocketInterceptor.setOnMessageCallback(
422
+ (data, socketId) => {
423
+ const url = socketUrlMap.get(socketId);
424
+ if (!url) {
425
+ return;
426
+ }
427
+ const event = {
428
+ type: "websocket-message-received",
429
+ url,
430
+ socketId,
431
+ timestamp: Date.now(),
432
+ data,
433
+ messageType: typeof data === "string" ? "text" : "binary"
434
+ };
435
+ eventEmitter.emit("websocket-message-received", event);
436
+ }
437
+ );
438
+ webSocketInterceptor.setOnErrorCallback(
439
+ (error, socketId) => {
440
+ const url = socketUrlMap.get(socketId);
441
+ if (!url) {
442
+ return;
443
+ }
444
+ const event = {
445
+ type: "websocket-error",
446
+ url,
447
+ socketId,
448
+ timestamp: Date.now(),
449
+ error
450
+ };
451
+ eventEmitter.emit("websocket-error", event);
452
+ }
453
+ );
454
+ webSocketInterceptor.setSendCallback((data, socketId) => {
455
+ const url = socketUrlMap.get(socketId);
456
+ if (!url) {
457
+ return;
458
+ }
459
+ const event = {
460
+ type: "websocket-message-sent",
461
+ url,
462
+ socketId,
463
+ timestamp: Date.now(),
464
+ data,
465
+ messageType: typeof data === "string" ? "text" : "binary"
466
+ };
467
+ eventEmitter.emit("websocket-message-sent", event);
468
+ });
469
+ webSocketInterceptor.setOnOpenCallback((socketId) => {
470
+ const url = socketUrlMap.get(socketId);
471
+ if (!url) {
472
+ return;
473
+ }
474
+ const event = {
475
+ type: "websocket-open",
476
+ url,
477
+ socketId,
478
+ timestamp: Date.now()
479
+ };
480
+ eventEmitter.emit("websocket-open", event);
481
+ });
482
+ webSocketInterceptor.setOnCloseCallback(
483
+ (error, socketId) => {
484
+ const url = socketUrlMap.get(socketId);
485
+ if (!url) {
486
+ return;
487
+ }
488
+ const event = {
489
+ type: "websocket-close",
490
+ url,
491
+ socketId,
492
+ timestamp: Date.now(),
493
+ code: error.code,
494
+ reason: error.reason
495
+ };
496
+ eventEmitter.emit("websocket-close", event);
497
+ socketUrlMap.delete(socketId);
498
+ }
499
+ );
500
+ webSocketInterceptor.enableInterception();
501
+ },
502
+ disable: () => {
503
+ webSocketInterceptor.disableInterception();
504
+ },
505
+ isEnabled: () => webSocketInterceptor.isInterceptorEnabled(),
506
+ dispose: () => {
507
+ eventEmitter.events = {};
508
+ socketUrlMap.clear();
509
+ },
510
+ on: (event, callback) => eventEmitter.on(event, callback)
511
+ };
512
+ };
513
+ let connectCallback;
514
+ let messageCallback;
515
+ let errorCallback;
516
+ let openEventCallback;
517
+ let closeCallback;
518
+ let isInterceptorEnabled = false;
519
+ const eventSourceClass = getEventSource();
520
+ const originalOpen = eventSourceClass.prototype.open;
521
+ const SSEInterceptor = {
522
+ /**
523
+ * Invoked when EventSource.open() is called (connection attempt starting).
524
+ */
525
+ setConnectCallback(callback) {
526
+ connectCallback = callback;
527
+ },
528
+ /**
529
+ * Invoked when a message event is received.
530
+ */
531
+ setMessageCallback(callback) {
532
+ messageCallback = callback;
533
+ },
534
+ /**
535
+ * Invoked when an error event occurs.
536
+ */
537
+ setErrorCallback(callback) {
538
+ errorCallback = callback;
539
+ },
540
+ /**
541
+ * Invoked when the connection is successfully opened (open event fired).
542
+ */
543
+ setOpenEventCallback(callback) {
544
+ openEventCallback = callback;
545
+ },
546
+ /**
547
+ * Invoked when the connection is closed.
548
+ */
549
+ setCloseCallback(callback) {
550
+ closeCallback = callback;
551
+ },
552
+ isInterceptorEnabled() {
553
+ return isInterceptorEnabled;
554
+ },
555
+ enableInterception() {
556
+ if (isInterceptorEnabled) {
557
+ return;
558
+ }
559
+ eventSourceClass.prototype.open = function() {
560
+ if (connectCallback) {
561
+ connectCallback(this.url, this);
562
+ }
563
+ this.addEventListener("open", (event) => {
564
+ if (openEventCallback) {
565
+ openEventCallback(event, this);
566
+ }
567
+ });
568
+ this.addEventListener("message", (event) => {
569
+ if (messageCallback) {
570
+ messageCallback(event, this);
571
+ }
572
+ });
573
+ this.addEventListener(
574
+ "error",
575
+ (event) => {
576
+ if (errorCallback) {
577
+ errorCallback(event, this);
578
+ }
579
+ }
580
+ );
581
+ this.addEventListener("close", (event) => {
582
+ if (closeCallback) {
583
+ closeCallback(event, this);
584
+ }
585
+ });
586
+ return originalOpen.call(this);
587
+ };
588
+ isInterceptorEnabled = true;
589
+ },
590
+ // Unpatch EventSource open method and remove the callbacks.
591
+ disableInterception() {
592
+ if (!isInterceptorEnabled) {
593
+ return;
594
+ }
595
+ isInterceptorEnabled = false;
596
+ eventSourceClass.prototype.open = originalOpen;
597
+ connectCallback = null;
598
+ messageCallback = null;
599
+ errorCallback = null;
600
+ openEventCallback = null;
601
+ closeCallback = null;
602
+ }
603
+ };
604
+ const getSSEInspector = () => {
605
+ const eventEmitter = createNanoEvents();
606
+ const getRequestId = (eventSource) => {
607
+ var _a;
608
+ const requestId = (_a = eventSource._xhr) == null ? void 0 : _a._rozeniteRequestId;
609
+ if (!requestId) {
610
+ throw new Error(
611
+ "No request ID found for EventSource. This should never happen!"
612
+ );
613
+ }
614
+ return requestId;
615
+ };
616
+ return {
617
+ enable: () => {
618
+ SSEInterceptor.setOpenEventCallback((_, eventSource) => {
619
+ const sseEventSource = eventSource;
620
+ const requestId = getRequestId(sseEventSource);
621
+ const sseXhr = sseEventSource._xhr;
622
+ const event = {
623
+ type: "sse-open",
624
+ requestId,
625
+ timestamp: Date.now(),
626
+ response: {
627
+ url: sseXhr._url,
628
+ status: sseXhr.status,
629
+ statusText: sseXhr.statusText,
630
+ headers: sseXhr.responseHeaders || {},
631
+ contentType: getContentType(sseXhr),
632
+ size: 0,
633
+ responseTime: Date.now()
634
+ }
635
+ };
636
+ eventEmitter.emit("sse-open", event);
637
+ });
638
+ SSEInterceptor.setMessageCallback((messageEvent, eventSource) => {
639
+ const sseEventSource = eventSource;
640
+ const requestId = getRequestId(sseEventSource);
641
+ const event = {
642
+ type: "sse-message",
643
+ requestId,
644
+ timestamp: Date.now(),
645
+ data: messageEvent.data || ""
646
+ };
647
+ eventEmitter.emit("sse-message", event);
648
+ });
649
+ SSEInterceptor.setErrorCallback((errorEvent, eventSource) => {
650
+ const sseEventSource = eventSource;
651
+ const requestId = getRequestId(sseEventSource);
652
+ const event = {
653
+ type: "sse-error",
654
+ requestId,
655
+ timestamp: Date.now(),
656
+ error: {
657
+ type: errorEvent.type,
658
+ message: errorEvent.type === "timeout" ? "Timeout" : errorEvent.message
659
+ }
660
+ };
661
+ eventEmitter.emit("sse-error", event);
662
+ });
663
+ SSEInterceptor.setCloseCallback((_, eventSource) => {
664
+ const sseEventSource = eventSource;
665
+ const requestId = getRequestId(sseEventSource);
666
+ const event = {
667
+ type: "sse-close",
668
+ requestId,
669
+ timestamp: Date.now()
670
+ };
671
+ eventEmitter.emit("sse-close", event);
672
+ });
673
+ SSEInterceptor.enableInterception();
674
+ },
675
+ disable: () => {
676
+ SSEInterceptor.disableInterception();
677
+ },
678
+ isEnabled: () => SSEInterceptor.isInterceptorEnabled(),
679
+ dispose: () => {
680
+ eventEmitter.events = {};
681
+ },
682
+ on: (event, callback) => eventEmitter.on(event, callback)
683
+ };
684
+ };
353
685
  const useNetworkActivityDevTools = () => {
354
686
  const client = useRozeniteDevToolsClient({
355
687
  pluginId: "@rozenite/network-activity-plugin"
@@ -363,6 +695,61 @@ const useNetworkActivityDevTools = () => {
363
695
  networkInspector.dispose();
364
696
  };
365
697
  }, [client]);
698
+ useEffect(() => {
699
+ if (!client) {
700
+ return;
701
+ }
702
+ const eventsToForward = [
703
+ "websocket-connect",
704
+ "websocket-open",
705
+ "websocket-close",
706
+ "websocket-message-sent",
707
+ "websocket-message-received",
708
+ "websocket-error",
709
+ "websocket-connection-status-changed"
710
+ ];
711
+ const websocketInspector = getWebSocketInspector();
712
+ eventsToForward.forEach((event) => {
713
+ websocketInspector.on(event, (event2) => {
714
+ client.send(event2.type, event2);
715
+ });
716
+ });
717
+ client.onMessage("network-enable", () => {
718
+ websocketInspector.enable();
719
+ });
720
+ client.onMessage("network-disable", () => {
721
+ websocketInspector.disable();
722
+ });
723
+ return () => {
724
+ websocketInspector.dispose();
725
+ };
726
+ }, [client]);
727
+ useEffect(() => {
728
+ if (!client) {
729
+ return;
730
+ }
731
+ const eventsToForward = [
732
+ "sse-open",
733
+ "sse-message",
734
+ "sse-error",
735
+ "sse-close"
736
+ ];
737
+ const sseInspector = getSSEInspector();
738
+ eventsToForward.forEach((event) => {
739
+ sseInspector.on(event, (event2) => {
740
+ client.send(event2.type, event2);
741
+ });
742
+ });
743
+ client.onMessage("network-enable", () => {
744
+ sseInspector.enable();
745
+ });
746
+ client.onMessage("network-disable", () => {
747
+ sseInspector.disable();
748
+ });
749
+ return () => {
750
+ sseInspector.dispose();
751
+ };
752
+ }, [client]);
366
753
  return client;
367
754
  };
368
755
  export {
package/package.json CHANGED
@@ -1,37 +1,48 @@
1
1
  {
2
2
  "name": "@rozenite/network-activity-plugin",
3
- "version": "1.0.0-alpha.8",
3
+ "version": "1.0.0-alpha.9",
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
- "@rozenite/plugin-bridge": "1.0.0-alpha.8"
10
+ "nanoevents": "^9.1.0",
11
+ "@rozenite/plugin-bridge": "1.0.0-alpha.9"
11
12
  },
12
13
  "devDependencies": {
14
+ "@floating-ui/react": "^0.26.0",
13
15
  "@radix-ui/react-scroll-area": "^1.2.9",
14
16
  "@radix-ui/react-separator": "^1.1.7",
15
17
  "@radix-ui/react-slot": "^1.2.3",
16
18
  "@radix-ui/react-tabs": "^1.1.12",
17
19
  "@tanstack/react-table": "^8.21.3",
20
+ "@tanstack/react-virtual": "^3.0.0",
18
21
  "autoprefixer": "^10.4.21",
19
22
  "class-variance-authority": "^0.7.1",
20
23
  "clsx": "^2.1.1",
24
+ "lucide-react": "^0.263.1",
21
25
  "postcss": "^8.5.6",
26
+ "proxy-memoize": "^3.0.1",
22
27
  "react": "*",
23
28
  "react-json-tree": "^0.20.0",
24
- "react-native": "*",
29
+ "react-native-sse": "^1.2.1",
25
30
  "tailwind-merge": "^3.3.1",
26
31
  "tailwindcss": "^3.4.17",
27
32
  "tailwindcss-animate": "^1.0.7",
28
33
  "typescript": "^5.7.3",
29
34
  "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.8",
34
- "rozenite": "1.0.0-alpha.8"
35
+ "zustand": "^5.0.6",
36
+ "@rozenite/vite-plugin": "1.0.0-alpha.9",
37
+ "rozenite": "1.0.0-alpha.9"
38
+ },
39
+ "peerDependencies": {
40
+ "react-native-sse": "*"
41
+ },
42
+ "peerDependenciesMeta": {
43
+ "react-native-sse": {
44
+ "optional": true
45
+ }
35
46
  },
36
47
  "license": "MIT",
37
48
  "scripts": {