@rozenite/network-activity-plugin 1.0.0-alpha.7 → 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 (96) hide show
  1. package/dist/App.html +2 -2
  2. package/dist/assets/{App-CIflVb88.js → App-CA1Fbh0I.js} +12009 -10809
  3. package/dist/assets/{App-Czu6Vt2P.css → App-DoHQsY5s.css} +43 -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 +8 -4
  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 +6 -3
  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/getHttpHeaderValue.d.ts +2 -0
  40. package/dist/src/ui/utils/getId.d.ts +1 -0
  41. package/dist/src/ui/utils/getStatusColor.d.ts +1 -0
  42. package/dist/useNetworkActivityDevTools.cjs +433 -34
  43. package/dist/useNetworkActivityDevTools.js +431 -34
  44. package/package.json +19 -8
  45. package/src/react-native/{network-inspector.ts → http/network-inspector.ts} +14 -32
  46. package/src/react-native/{xml-request.d.ts → http/xml-request.d.ts} +1 -0
  47. package/src/react-native/sse/event-source.ts +25 -0
  48. package/src/react-native/sse/sse-inspector.ts +117 -0
  49. package/src/react-native/sse/sse-interceptor.ts +162 -0
  50. package/src/react-native/sse/types.ts +9 -0
  51. package/src/react-native/useNetworkActivityDevTools.ts +75 -1
  52. package/src/react-native/utils.ts +43 -0
  53. package/src/react-native/websocket/websocket-inspector.ts +180 -0
  54. package/src/react-native/websocket/websocket-interceptor.d.ts +4 -0
  55. package/src/react-native/websocket/websocket-interceptor.ts +166 -0
  56. package/src/shared/client.ts +10 -4
  57. package/src/shared/sse-events.ts +44 -0
  58. package/src/shared/websocket-events.ts +79 -0
  59. package/src/ui/components/Badge.tsx +1 -1
  60. package/src/ui/components/Button.tsx +1 -1
  61. package/src/ui/components/Input.tsx +1 -1
  62. package/src/ui/components/JsonTree.tsx +13 -0
  63. package/src/ui/components/JsonTreeCopyableItem.tsx +33 -0
  64. package/src/ui/components/RequestList.tsx +42 -123
  65. package/src/ui/components/ScrollArea.tsx +1 -1
  66. package/src/ui/components/Separator.tsx +1 -1
  67. package/src/ui/components/SidePanel.tsx +323 -0
  68. package/src/ui/components/Tabs.tsx +2 -2
  69. package/src/ui/components/Toolbar.tsx +45 -0
  70. package/src/ui/hooks/useCopyToClipboard.ts +28 -0
  71. package/src/ui/state/derived.ts +112 -0
  72. package/src/ui/state/hooks.ts +44 -0
  73. package/src/ui/state/model.ts +129 -0
  74. package/src/ui/state/store.ts +559 -0
  75. package/src/ui/tabs/CookiesTab.tsx +168 -179
  76. package/src/ui/tabs/HeadersTab.tsx +24 -31
  77. package/src/ui/tabs/MessagesTab.tsx +276 -0
  78. package/src/ui/tabs/RequestTab.tsx +28 -31
  79. package/src/ui/tabs/ResponseTab.tsx +10 -12
  80. package/src/ui/tabs/SSEMessagesTab.tsx +213 -0
  81. package/src/ui/tabs/TimingTab.tsx +33 -44
  82. package/src/ui/types.ts +6 -2
  83. package/src/ui/utils/assert.ts +5 -0
  84. package/src/ui/utils/copyToClipboard.ts +3 -0
  85. package/src/ui/utils/getHttpHeaderValue.ts +14 -0
  86. package/src/ui/utils/getId.ts +10 -0
  87. package/src/ui/utils/getStatusColor.ts +15 -0
  88. package/src/ui/views/InspectorView.tsx +24 -320
  89. package/tailwind.config.ts +3 -0
  90. package/vite.config.ts +12 -0
  91. /package/dist/src/react-native/{network-requests-registry.d.ts → http/network-requests-registry.d.ts} +0 -0
  92. /package/dist/src/react-native/{xhr-interceptor.d.ts → http/xhr-interceptor.d.ts} +0 -0
  93. /package/dist/src/ui/{utils.d.ts → utils/cn.d.ts} +0 -0
  94. /package/src/react-native/{network-requests-registry.ts → http/network-requests-registry.ts} +0 -0
  95. /package/src/react-native/{xhr-interceptor.ts → http/xhr-interceptor.ts} +0 -0
  96. /package/src/ui/{utils.ts → utils/cn.ts} +0 -0
@@ -2,6 +2,41 @@
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);
11
+ function getHttpHeaderValue(headers, name) {
12
+ const lowerName = name.toLowerCase();
13
+ for (const key in headers) {
14
+ if (key.toLowerCase() === lowerName) {
15
+ return headers[key];
16
+ }
17
+ }
18
+ return void 0;
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
+ };
5
40
  const REQUEST_TTL = 1e3 * 60 * 5;
6
41
  const getNetworkRequestsRegistry = () => {
7
42
  const registry = /* @__PURE__ */ new Map();
@@ -43,7 +78,7 @@ let sendCallback;
43
78
  let requestHeaderCallback;
44
79
  let headerReceivedCallback;
45
80
  let responseCallback;
46
- let isInterceptorEnabled = false;
81
+ let isInterceptorEnabled$1 = false;
47
82
  const XHRInterceptor = {
48
83
  /**
49
84
  * Invoked before XMLHttpRequest.open(...) is called.
@@ -76,10 +111,10 @@ const XHRInterceptor = {
76
111
  requestHeaderCallback = callback;
77
112
  },
78
113
  isInterceptorEnabled() {
79
- return isInterceptorEnabled;
114
+ return isInterceptorEnabled$1;
80
115
  },
81
116
  enableInterception() {
82
- if (isInterceptorEnabled) {
117
+ if (isInterceptorEnabled$1) {
83
118
  return;
84
119
  }
85
120
  XMLHttpRequest.prototype.open = function(method, url) {
@@ -102,7 +137,7 @@ const XHRInterceptor = {
102
137
  this.addEventListener(
103
138
  "readystatechange",
104
139
  () => {
105
- if (!isInterceptorEnabled) {
140
+ if (!isInterceptorEnabled$1) {
106
141
  return;
107
142
  }
108
143
  if (this.readyState === this.HEADERS_RECEIVED) {
@@ -142,14 +177,14 @@ const XHRInterceptor = {
142
177
  }
143
178
  originalXHRSend.apply(this, arguments);
144
179
  };
145
- isInterceptorEnabled = true;
180
+ isInterceptorEnabled$1 = true;
146
181
  },
147
182
  // Unpatch XMLHttpRequest methods and remove the callbacks.
148
183
  disableInterception() {
149
- if (!isInterceptorEnabled) {
184
+ if (!isInterceptorEnabled$1) {
150
185
  return;
151
186
  }
152
- isInterceptorEnabled = false;
187
+ isInterceptorEnabled$1 = false;
153
188
  XMLHttpRequest.prototype.send = originalXHRSend;
154
189
  XMLHttpRequest.prototype.open = originalXHROpen;
155
190
  XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
@@ -161,25 +196,6 @@ const XHRInterceptor = {
161
196
  }
162
197
  };
163
198
  const networkRequestsRegistry = getNetworkRequestsRegistry();
164
- const getContentType = (request) => {
165
- const responseHeaders = request.responseHeaders;
166
- const responseType = request.responseType;
167
- if (responseHeaders == null ? void 0 : responseHeaders["content-type"]) {
168
- return responseHeaders["content-type"].split(";")[0].trim();
169
- }
170
- switch (responseType) {
171
- case "arraybuffer":
172
- case "blob":
173
- return "application/octet-stream";
174
- case "text":
175
- case "":
176
- return "text/plain";
177
- case "json":
178
- return "application/json";
179
- case "document":
180
- return "text/html";
181
- }
182
- };
183
199
  const getResponseSize = (request) => {
184
200
  if (typeof request.response === "object") {
185
201
  return request.response.size;
@@ -188,7 +204,7 @@ const getResponseSize = (request) => {
188
204
  };
189
205
  const getResponseBody = async (request) => {
190
206
  const responseType = request.responseType;
191
- if (responseType === "text") {
207
+ if (responseType === "" || responseType === "text") {
192
208
  return request.responseText;
193
209
  }
194
210
  if (responseType === "blob") {
@@ -233,12 +249,13 @@ const getNetworkInspector = (pluginClient) => {
233
249
  const handleRequestSend = (data, request) => {
234
250
  const sendTime = Date.now();
235
251
  const requestId = generateRequestId();
252
+ request._rozeniteRequestId = requestId;
236
253
  const initiator = getInitiatorFromStack();
237
254
  networkRequestsRegistry.addEntry(requestId, request);
238
255
  let ttfb = 0;
239
256
  pluginClient.send("request-sent", {
240
257
  requestId,
241
- timestamp: sendTime / 1e3,
258
+ timestamp: sendTime,
242
259
  request: {
243
260
  url: request._url,
244
261
  method: request._method,
@@ -256,23 +273,23 @@ const getNetworkInspector = (pluginClient) => {
256
273
  request.addEventListener("load", () => {
257
274
  pluginClient.send("response-received", {
258
275
  requestId,
259
- timestamp: Date.now() / 1e3,
276
+ timestamp: Date.now(),
260
277
  type: "XHR",
261
278
  response: {
262
279
  url: request._url,
263
280
  status: request.status,
264
281
  statusText: request.statusText,
265
- headers: request.responseHeaders,
282
+ headers: request.responseHeaders || {},
266
283
  contentType: getContentType(request),
267
284
  size: getResponseSize(request),
268
- responseTime: Date.now() / 1e3
285
+ responseTime: Date.now()
269
286
  }
270
287
  });
271
288
  });
272
289
  request.addEventListener("loadend", () => {
273
290
  pluginClient.send("request-completed", {
274
291
  requestId,
275
- timestamp: Date.now() / 1e3,
292
+ timestamp: Date.now(),
276
293
  duration: Date.now() - sendTime,
277
294
  size: getResponseSize(request),
278
295
  ttfb
@@ -281,7 +298,7 @@ const getNetworkInspector = (pluginClient) => {
281
298
  request.addEventListener("error", () => {
282
299
  pluginClient.send("request-failed", {
283
300
  requestId,
284
- timestamp: Date.now() / 1e3,
301
+ timestamp: Date.now(),
285
302
  type: "XHR",
286
303
  error: "Failed",
287
304
  canceled: false
@@ -290,7 +307,7 @@ const getNetworkInspector = (pluginClient) => {
290
307
  request.addEventListener("abort", () => {
291
308
  pluginClient.send("request-failed", {
292
309
  requestId,
293
- timestamp: Date.now() / 1e3,
310
+ timestamp: Date.now(),
294
311
  type: "XHR",
295
312
  error: "Aborted",
296
313
  canceled: true
@@ -342,6 +359,333 @@ const getNetworkInspector = (pluginClient) => {
342
359
  dispose
343
360
  };
344
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
+ };
345
689
  const useNetworkActivityDevTools = () => {
346
690
  const client = pluginBridge.useRozeniteDevToolsClient({
347
691
  pluginId: "@rozenite/network-activity-plugin"
@@ -355,6 +699,61 @@ const useNetworkActivityDevTools = () => {
355
699
  networkInspector.dispose();
356
700
  };
357
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]);
358
757
  return client;
359
758
  };
360
759
  exports.useNetworkActivityDevTools = useNetworkActivityDevTools;