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