@rozenite/network-activity-plugin 1.0.0-alpha.9 → 1.0.0

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 (111) hide show
  1. package/README.md +2 -0
  2. package/dist/App.html +2 -2
  3. package/dist/assets/{App-DoHQsY5s.css → App-BrSkOkws.css} +223 -2
  4. package/dist/assets/{App-CA1Fbh0I.js → App-C6wCDVkW.js} +8157 -2677
  5. package/dist/react-native.cjs +4 -1
  6. package/dist/react-native.js +4 -1
  7. package/dist/rozenite.json +1 -1
  8. package/dist/src/react-native/config.d.ts +20 -0
  9. package/dist/src/react-native/http/overrides-registry.d.ts +6 -0
  10. package/dist/src/react-native/http/xhr-interceptor.d.ts +7 -1
  11. package/dist/src/react-native/sse/sse-interceptor.d.ts +2 -2
  12. package/dist/src/react-native/useNetworkActivityDevTools.d.ts +2 -1
  13. package/dist/src/react-native/utils/getBlobName.d.ts +35 -0
  14. package/dist/src/react-native/utils/getFormDataEntries.d.ts +18 -0
  15. package/dist/src/shared/client.d.ts +48 -4
  16. package/dist/src/shared/sse-events.d.ts +4 -1
  17. package/dist/src/ui/components/Button.d.ts +2 -2
  18. package/dist/src/ui/components/CodeBlock.d.ts +3 -0
  19. package/dist/src/ui/components/CodeEditor.d.ts +5 -0
  20. package/dist/src/ui/components/CookieCard.d.ts +7 -0
  21. package/dist/src/ui/components/CopyRequestDropdown.d.ts +7 -0
  22. package/dist/src/ui/components/DropdownMenu.d.ts +27 -0
  23. package/dist/src/ui/components/FilterBar.d.ts +10 -0
  24. package/dist/src/ui/components/JsonTreeCopyableItem.d.ts +1 -1
  25. package/dist/src/ui/components/KeyValueGrid.d.ts +13 -0
  26. package/dist/src/ui/components/OverrideResponse.d.ts +8 -0
  27. package/dist/src/ui/components/RequestBody.d.ts +6 -0
  28. package/dist/src/ui/components/RequestList.d.ts +9 -4
  29. package/dist/src/ui/components/ScrollArea.d.ts +3 -2
  30. package/dist/src/ui/components/Section.d.ts +8 -0
  31. package/dist/src/ui/components/Separator.d.ts +2 -1
  32. package/dist/src/ui/components/Tabs.d.ts +7 -0
  33. package/dist/src/ui/state/hooks.d.ts +4 -0
  34. package/dist/src/ui/state/model.d.ts +12 -7
  35. package/dist/src/ui/state/store.d.ts +27 -3
  36. package/dist/src/ui/utils/checkRequestBodyBinary.d.ts +2 -0
  37. package/dist/src/ui/utils/escapeShellArg.d.ts +1 -0
  38. package/dist/src/ui/utils/generateCurlCommand.d.ts +2 -0
  39. package/dist/src/ui/utils/generateFetchCall.d.ts +2 -0
  40. package/dist/src/ui/utils/generateMultipartBody.d.ts +4 -0
  41. package/dist/src/utils/applyReactNativeRequestHeadersLogic.d.ts +7 -0
  42. package/dist/src/utils/applyReactNativeResponseHeadersLogic.d.ts +9 -0
  43. package/dist/src/utils/cookieParser.d.ts +6 -0
  44. package/dist/src/utils/getContentTypeMimeType.d.ts +2 -0
  45. package/dist/src/utils/getHttpHeader.d.ts +5 -0
  46. package/dist/src/utils/getHttpHeaderValueAsString.d.ts +11 -0
  47. package/dist/src/utils/getStringSizeInBytes.d.ts +1 -0
  48. package/dist/src/utils/inferContentTypeFromPostData.d.ts +2 -0
  49. package/dist/src/utils/safeStringify.d.ts +1 -0
  50. package/dist/src/utils/typeChecks.d.ts +9 -0
  51. package/dist/useNetworkActivityDevTools.cjs +319 -24
  52. package/dist/useNetworkActivityDevTools.js +320 -25
  53. package/package.json +7 -4
  54. package/react-native.ts +6 -1
  55. package/src/react-native/config.ts +43 -0
  56. package/src/react-native/http/network-inspector.ts +170 -8
  57. package/src/react-native/http/overrides-registry.ts +32 -0
  58. package/src/react-native/http/xhr-interceptor.ts +19 -2
  59. package/src/react-native/sse/sse-inspector.ts +27 -5
  60. package/src/react-native/sse/sse-interceptor.ts +26 -8
  61. package/src/react-native/useNetworkActivityDevTools.ts +86 -8
  62. package/src/react-native/utils/getBlobName.ts +45 -0
  63. package/src/react-native/utils/getFormDataEntries.ts +32 -0
  64. package/src/react-native/utils.ts +3 -3
  65. package/src/shared/client.ts +73 -4
  66. package/src/shared/sse-events.ts +4 -1
  67. package/src/ui/components/Button.tsx +1 -0
  68. package/src/ui/components/CodeBlock.tsx +19 -0
  69. package/src/ui/components/CodeEditor.tsx +26 -0
  70. package/src/ui/components/CookieCard.tsx +64 -0
  71. package/src/ui/components/CopyRequestDropdown.tsx +95 -0
  72. package/src/ui/components/DropdownMenu.tsx +206 -0
  73. package/src/ui/components/FilterBar.tsx +117 -0
  74. package/src/ui/components/Input.tsx +1 -1
  75. package/src/ui/components/JsonTree.tsx +10 -3
  76. package/src/ui/components/JsonTreeCopyableItem.tsx +14 -10
  77. package/src/ui/components/KeyValueGrid.tsx +51 -0
  78. package/src/ui/components/OverrideResponse.tsx +132 -0
  79. package/src/ui/components/RequestBody.tsx +86 -0
  80. package/src/ui/components/RequestList.tsx +65 -13
  81. package/src/ui/components/ScrollArea.tsx +1 -0
  82. package/src/ui/components/Section.tsx +46 -0
  83. package/src/ui/components/SidePanel.tsx +15 -5
  84. package/src/ui/globals.css +4 -0
  85. package/src/ui/hooks/useCopyToClipboard.ts +2 -2
  86. package/src/ui/state/hooks.ts +8 -0
  87. package/src/ui/state/model.ts +18 -7
  88. package/src/ui/state/store.ts +610 -500
  89. package/src/ui/tabs/CookiesTab.tsx +60 -263
  90. package/src/ui/tabs/HeadersTab.tsx +78 -89
  91. package/src/ui/tabs/RequestTab.tsx +58 -46
  92. package/src/ui/tabs/ResponseTab.tsx +98 -67
  93. package/src/ui/tabs/SSEMessagesTab.tsx +50 -39
  94. package/src/ui/utils/checkRequestBodyBinary.ts +7 -0
  95. package/src/ui/utils/escapeShellArg.ts +12 -0
  96. package/src/ui/utils/generateCurlCommand.ts +83 -0
  97. package/src/ui/utils/generateFetchCall.ts +64 -0
  98. package/src/ui/utils/generateMultipartBody.ts +19 -0
  99. package/src/ui/views/InspectorView.tsx +15 -3
  100. package/src/utils/applyReactNativeRequestHeadersLogic.ts +30 -0
  101. package/src/utils/applyReactNativeResponseHeadersLogic.ts +28 -0
  102. package/src/utils/cookieParser.ts +126 -0
  103. package/src/utils/getContentTypeMimeType.ts +17 -0
  104. package/src/utils/getHttpHeader.ts +17 -0
  105. package/src/utils/getHttpHeaderValueAsString.ts +13 -0
  106. package/src/utils/getStringSizeInBytes.ts +3 -0
  107. package/src/utils/inferContentTypeFromPostData.ts +9 -0
  108. package/src/utils/safeStringify.ts +7 -0
  109. package/src/utils/typeChecks.ts +27 -0
  110. package/dist/src/ui/utils/getHttpHeaderValue.d.ts +0 -2
  111. package/src/ui/utils/getHttpHeaderValue.ts +0 -14
@@ -0,0 +1,5 @@
1
+ import { HttpHeaders, XHRHeaders } from '../shared/client';
2
+ export declare function getHttpHeader<T extends HttpHeaders | XHRHeaders>(headers: T, name: string): {
3
+ value: T[Extract<keyof T, string>];
4
+ originalKey: Extract<keyof T, string>;
5
+ } | undefined;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Combines multiple HTTP header values according to RFC 7230 Section 3.2.2
3
+ *
4
+ * Per RFC 7230 Section 3.2.2: "A recipient MAY combine multiple header fields
5
+ * with the same field name into one 'field-name: field-value' pair, without
6
+ * changing the semantics of the message, by appending each subsequent field
7
+ * value to the combined field value in order, separated by a comma."
8
+ *
9
+ * @see https://tools.ietf.org/html/rfc7230#section-3.2.2
10
+ */
11
+ export declare function getHttpHeaderValueAsString(value: string | string[]): string;
@@ -0,0 +1 @@
1
+ export declare const getStringSizeInBytes: (value: string) => number;
@@ -0,0 +1,2 @@
1
+ import { RequestPostData } from '../shared/client';
2
+ export declare function inferContentTypeFromPostData(postData: RequestPostData): "multipart/form-data" | undefined;
@@ -0,0 +1 @@
1
+ export declare function safeStringify(data: unknown): string;
@@ -0,0 +1,9 @@
1
+ export declare const isBlob: (value: unknown) => value is Blob;
2
+ export declare const isArrayBuffer: (value: unknown) => value is ArrayBuffer | ArrayBufferView;
3
+ export declare const isFormData: (value: unknown) => value is FormData;
4
+ export declare const isNullOrUndefined: (value: unknown) => value is null | undefined;
5
+ export declare const isString: (value: unknown) => value is string;
6
+ export declare const isNumber: (value: unknown) => value is number;
7
+ export declare const isBoolean: (value: unknown) => value is boolean;
8
+ export declare const isObject: (value: unknown) => value is object;
9
+ export declare const isArray: (value: unknown) => value is unknown[];
@@ -8,21 +8,37 @@ const WebSocketInterceptor = require("react-native/Libraries/WebSocket/WebSocket
8
8
  const eventSource = require("./event-source.cjs");
9
9
  const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
10
10
  const WebSocketInterceptor__default = /* @__PURE__ */ _interopDefault(WebSocketInterceptor);
11
- function getHttpHeaderValue(headers, name) {
11
+ function safeStringify(data) {
12
+ try {
13
+ return typeof data === "string" ? data : JSON.stringify(data);
14
+ } catch {
15
+ return String(data);
16
+ }
17
+ }
18
+ function getHttpHeader(headers, name) {
12
19
  const lowerName = name.toLowerCase();
13
20
  for (const key in headers) {
14
21
  if (key.toLowerCase() === lowerName) {
15
- return headers[key];
22
+ return { value: headers[key], originalKey: key };
16
23
  }
17
24
  }
18
25
  return void 0;
19
26
  }
27
+ function getContentTypeMime(headers) {
28
+ const contentType = getHttpHeader(headers, "content-type");
29
+ if (!contentType) {
30
+ return void 0;
31
+ }
32
+ const { value } = contentType;
33
+ const actualValue = Array.isArray(value) ? value[0] : value;
34
+ return actualValue.split(";")[0].trim();
35
+ }
20
36
  const getContentType = (request) => {
21
37
  const responseHeaders = request.responseHeaders;
22
38
  const responseType = request.responseType;
23
- const contentType = getHttpHeaderValue(responseHeaders || {}, "content-type");
39
+ const contentType = getContentTypeMime(responseHeaders || {});
24
40
  if (contentType) {
25
- return contentType.split(";")[0].trim();
41
+ return contentType;
26
42
  }
27
43
  switch (responseType) {
28
44
  case "arraybuffer":
@@ -70,6 +86,28 @@ const getNetworkRequestsRegistry = () => {
70
86
  clear
71
87
  };
72
88
  };
89
+ function getBlobName(blob) {
90
+ if (typeof (blob == null ? void 0 : blob.name) === "string") {
91
+ return blob.name;
92
+ }
93
+ if ((blob == null ? void 0 : blob.data) && typeof blob.data.name === "string") {
94
+ return blob.data.name;
95
+ }
96
+ return void 0;
97
+ }
98
+ function getFormDataEntries(formData) {
99
+ if (!formData || typeof formData !== "object") {
100
+ return [];
101
+ }
102
+ if (typeof formData.entries === "function") {
103
+ return formData.entries();
104
+ }
105
+ if (Array.isArray(formData._parts)) {
106
+ return formData._parts;
107
+ }
108
+ return [];
109
+ }
110
+ const XMLHttpRequest = global.XMLHttpRequest || window.XMLHttpRequest;
73
111
  const originalXHROpen = XMLHttpRequest.prototype.open;
74
112
  const originalXHRSend = XMLHttpRequest.prototype.send;
75
113
  const originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
@@ -78,6 +116,7 @@ let sendCallback;
78
116
  let requestHeaderCallback;
79
117
  let headerReceivedCallback;
80
118
  let responseCallback;
119
+ let overrideCallback;
81
120
  let isInterceptorEnabled$1 = false;
82
121
  const XHRInterceptor = {
83
122
  /**
@@ -110,6 +149,12 @@ const XHRInterceptor = {
110
149
  setRequestHeaderCallback(callback) {
111
150
  requestHeaderCallback = callback;
112
151
  },
152
+ /**
153
+ * Invoked before XMLHttpRequest.send(...) is called.
154
+ */
155
+ setOverrideCallback(callback) {
156
+ overrideCallback = callback;
157
+ },
113
158
  isInterceptorEnabled() {
114
159
  return isInterceptorEnabled$1;
115
160
  },
@@ -133,6 +178,9 @@ const XHRInterceptor = {
133
178
  if (sendCallback) {
134
179
  sendCallback(data, this);
135
180
  }
181
+ if (overrideCallback) {
182
+ overrideCallback(this);
183
+ }
136
184
  if (this.addEventListener) {
137
185
  this.addEventListener(
138
186
  "readystatechange",
@@ -193,14 +241,128 @@ const XHRInterceptor = {
193
241
  sendCallback = null;
194
242
  headerReceivedCallback = null;
195
243
  requestHeaderCallback = null;
244
+ overrideCallback = null;
245
+ }
246
+ };
247
+ const getStringSizeInBytes = (value) => {
248
+ return new TextEncoder().encode(value).length;
249
+ };
250
+ const splitSetCookieHeaderByComma = (header) => {
251
+ const regex = /(?:^|,\s)([^=;,]+=[^;]+(?:;[^,]*)*)/g;
252
+ const matches = [];
253
+ let match;
254
+ while ((match = regex.exec(header)) !== null) {
255
+ matches.push(match[1].trim());
256
+ }
257
+ return matches;
258
+ };
259
+ const applyReactNativeResponseHeadersLogic = (headers) => {
260
+ const parsedHeaders = { ...headers };
261
+ const setCookieHeader = getHttpHeader(headers, "set-cookie");
262
+ if (setCookieHeader) {
263
+ const { value, originalKey } = setCookieHeader;
264
+ const cookies = splitSetCookieHeaderByComma(value);
265
+ parsedHeaders[originalKey] = cookies.length > 0 ? cookies : value;
266
+ }
267
+ return parsedHeaders;
268
+ };
269
+ const isBlob = (value) => value instanceof Blob;
270
+ const isArrayBuffer = (value) => value instanceof ArrayBuffer || ArrayBuffer.isView(value);
271
+ const isFormData = (value) => value instanceof FormData;
272
+ const isNullOrUndefined = (value) => value === null || value === void 0;
273
+ const createOverridesRegistry = () => {
274
+ let overrides = /* @__PURE__ */ new Map();
275
+ const setOverrides = (newOverrides) => {
276
+ overrides = new Map(newOverrides);
277
+ };
278
+ const getOverrideForUrl = (url) => {
279
+ return overrides.get(url);
280
+ };
281
+ return {
282
+ setOverrides,
283
+ getOverrideForUrl
284
+ };
285
+ };
286
+ let registryInstance = null;
287
+ const getOverridesRegistry = () => {
288
+ if (!registryInstance) {
289
+ registryInstance = createOverridesRegistry();
196
290
  }
291
+ return registryInstance;
197
292
  };
198
293
  const networkRequestsRegistry = getNetworkRequestsRegistry();
294
+ const overridesRegistry$1 = getOverridesRegistry();
295
+ const getBinaryPostData = (body) => ({
296
+ type: "binary",
297
+ value: {
298
+ size: body.size,
299
+ type: body.type,
300
+ name: getBlobName(body)
301
+ }
302
+ });
303
+ const getArrayBufferPostData = (body) => ({
304
+ type: "binary",
305
+ value: {
306
+ size: body.byteLength
307
+ }
308
+ });
309
+ const getTextPostData = (body) => ({
310
+ type: "text",
311
+ value: safeStringify(body)
312
+ });
313
+ const getFormDataPostData = (body) => ({
314
+ type: "form-data",
315
+ value: getFormDataEntries(body).reduce(
316
+ (acc, [key, value]) => {
317
+ if (isBlob(value)) {
318
+ acc[key] = getBinaryPostData(value);
319
+ } else if (isArrayBuffer(value)) {
320
+ acc[key] = getArrayBufferPostData(value);
321
+ } else {
322
+ acc[key] = getTextPostData(value);
323
+ }
324
+ return acc;
325
+ },
326
+ {}
327
+ )
328
+ });
329
+ const getRequestBody = (body) => {
330
+ if (isNullOrUndefined(body)) {
331
+ return body;
332
+ }
333
+ if (isBlob(body)) {
334
+ return getBinaryPostData(body);
335
+ }
336
+ if (isArrayBuffer(body)) {
337
+ return getArrayBufferPostData(body);
338
+ }
339
+ if (isFormData(body)) {
340
+ return getFormDataPostData(body);
341
+ }
342
+ return getTextPostData(body);
343
+ };
199
344
  const getResponseSize = (request) => {
200
- if (typeof request.response === "object") {
201
- return request.response.size;
345
+ try {
346
+ const { responseType, response } = request;
347
+ if (response === null) {
348
+ return 0;
349
+ }
350
+ if (responseType === "" || responseType === "text") {
351
+ return getStringSizeInBytes(request.responseText);
352
+ }
353
+ if (responseType === "json") {
354
+ return getStringSizeInBytes(safeStringify(response));
355
+ }
356
+ if (responseType === "blob") {
357
+ return response.size;
358
+ }
359
+ if (responseType === "arraybuffer") {
360
+ return response.byteLength;
361
+ }
362
+ return 0;
363
+ } catch {
364
+ return null;
202
365
  }
203
- return request.response.length || 0;
204
366
  };
205
367
  const getResponseBody = async (request) => {
206
368
  const responseType = request.responseType;
@@ -219,6 +381,9 @@ const getResponseBody = async (request) => {
219
381
  });
220
382
  }
221
383
  }
384
+ if (responseType === "json") {
385
+ return safeStringify(request.response);
386
+ }
222
387
  return null;
223
388
  };
224
389
  const getInitiatorFromStack = () => {
@@ -260,7 +425,7 @@ const getNetworkInspector = (pluginClient) => {
260
425
  url: request._url,
261
426
  method: request._method,
262
427
  headers: request._headers,
263
- postData: data
428
+ postData: getRequestBody(data)
264
429
  },
265
430
  type: "XHR",
266
431
  initiator
@@ -279,7 +444,9 @@ const getNetworkInspector = (pluginClient) => {
279
444
  url: request._url,
280
445
  status: request.status,
281
446
  statusText: request.statusText,
282
- headers: request.responseHeaders || {},
447
+ headers: applyReactNativeResponseHeadersLogic(
448
+ request.responseHeaders || {}
449
+ ),
283
450
  contentType: getContentType(request),
284
451
  size: getResponseSize(request),
285
452
  responseTime: Date.now()
@@ -314,9 +481,45 @@ const getNetworkInspector = (pluginClient) => {
314
481
  });
315
482
  });
316
483
  };
484
+ const handleRequestOverride = (request) => {
485
+ const override = overridesRegistry$1.getOverrideForUrl(
486
+ request._url
487
+ );
488
+ if (!override) {
489
+ return;
490
+ }
491
+ request.addEventListener("readystatechange", () => {
492
+ if (override.body !== void 0) {
493
+ Object.defineProperty(request, "responseType", {
494
+ writable: true
495
+ });
496
+ Object.defineProperty(request, "response", {
497
+ writable: true
498
+ });
499
+ Object.defineProperty(request, "responseText", {
500
+ writable: true
501
+ });
502
+ const contentType = getContentType(request);
503
+ if (contentType === "application/json") {
504
+ request.responseType = "json";
505
+ } else if (contentType === "text/plain") {
506
+ request.responseType = "text";
507
+ }
508
+ request.response = override.body;
509
+ request.responseText = override.body;
510
+ }
511
+ if (override.status !== void 0) {
512
+ Object.defineProperty(request, "status", {
513
+ writable: true
514
+ });
515
+ request.status = override.status;
516
+ }
517
+ });
518
+ };
317
519
  const enable = () => {
318
520
  XHRInterceptor.disableInterception();
319
521
  XHRInterceptor.setSendCallback(handleRequestSend);
522
+ XHRInterceptor.setOverrideCallback(handleRequestOverride);
320
523
  XHRInterceptor.enableInterception();
321
524
  };
322
525
  const disable = () => {
@@ -522,6 +725,8 @@ let closeCallback;
522
725
  let isInterceptorEnabled = false;
523
726
  const eventSourceClass = eventSource.getEventSource();
524
727
  const originalOpen = eventSourceClass.prototype.open;
728
+ const originalDispatch = eventSourceClass.prototype.dispatch;
729
+ const BUILT_IN_EVENT_TYPES = /* @__PURE__ */ new Set(["open", "error", "close", "done"]);
525
730
  const SSEInterceptor = {
526
731
  /**
527
732
  * Invoked when EventSource.open() is called (connection attempt starting).
@@ -569,11 +774,6 @@ const SSEInterceptor = {
569
774
  openEventCallback(event, this);
570
775
  }
571
776
  });
572
- this.addEventListener("message", (event) => {
573
- if (messageCallback) {
574
- messageCallback(event, this);
575
- }
576
- });
577
777
  this.addEventListener(
578
778
  "error",
579
779
  (event) => {
@@ -589,6 +789,14 @@ const SSEInterceptor = {
589
789
  });
590
790
  return originalOpen.call(this);
591
791
  };
792
+ eventSourceClass.prototype.dispatch = function(eventType, data) {
793
+ if (!BUILT_IN_EVENT_TYPES.has(eventType)) {
794
+ if (messageCallback) {
795
+ messageCallback(data, this);
796
+ }
797
+ }
798
+ return originalDispatch.call(this, eventType, data);
799
+ };
592
800
  isInterceptorEnabled = true;
593
801
  },
594
802
  // Unpatch EventSource open method and remove the callbacks.
@@ -598,6 +806,7 @@ const SSEInterceptor = {
598
806
  }
599
807
  isInterceptorEnabled = false;
600
808
  eventSourceClass.prototype.open = originalOpen;
809
+ eventSourceClass.prototype.dispatch = originalDispatch;
601
810
  connectCallback = null;
602
811
  messageCallback = null;
603
812
  errorCallback = null;
@@ -611,9 +820,7 @@ const getSSEInspector = () => {
611
820
  var _a;
612
821
  const requestId = (_a = eventSource2._xhr) == null ? void 0 : _a._rozeniteRequestId;
613
822
  if (!requestId) {
614
- throw new Error(
615
- "No request ID found for EventSource. This should never happen!"
616
- );
823
+ return null;
617
824
  }
618
825
  return requestId;
619
826
  };
@@ -622,6 +829,9 @@ const getSSEInspector = () => {
622
829
  SSEInterceptor.setOpenEventCallback((_, eventSource2) => {
623
830
  const sseEventSource = eventSource2;
624
831
  const requestId = getRequestId(sseEventSource);
832
+ if (!requestId) {
833
+ return;
834
+ }
625
835
  const sseXhr = sseEventSource._xhr;
626
836
  const event = {
627
837
  type: "sse-open",
@@ -642,17 +852,26 @@ const getSSEInspector = () => {
642
852
  SSEInterceptor.setMessageCallback((messageEvent, eventSource2) => {
643
853
  const sseEventSource = eventSource2;
644
854
  const requestId = getRequestId(sseEventSource);
855
+ if (!requestId) {
856
+ return;
857
+ }
645
858
  const event = {
646
859
  type: "sse-message",
647
860
  requestId,
648
861
  timestamp: Date.now(),
649
- data: messageEvent.data || ""
862
+ payload: {
863
+ type: messageEvent.type,
864
+ data: messageEvent.data || ""
865
+ }
650
866
  };
651
867
  eventEmitter.emit("sse-message", event);
652
868
  });
653
869
  SSEInterceptor.setErrorCallback((errorEvent, eventSource2) => {
654
870
  const sseEventSource = eventSource2;
655
871
  const requestId = getRequestId(sseEventSource);
872
+ if (!requestId) {
873
+ return;
874
+ }
656
875
  const event = {
657
876
  type: "sse-error",
658
877
  requestId,
@@ -667,6 +886,9 @@ const getSSEInspector = () => {
667
886
  SSEInterceptor.setCloseCallback((_, eventSource2) => {
668
887
  const sseEventSource = eventSource2;
669
888
  const requestId = getRequestId(sseEventSource);
889
+ if (!requestId) {
890
+ return;
891
+ }
670
892
  const event = {
671
893
  type: "sse-close",
672
894
  requestId,
@@ -681,26 +903,93 @@ const getSSEInspector = () => {
681
903
  },
682
904
  isEnabled: () => SSEInterceptor.isInterceptorEnabled(),
683
905
  dispose: () => {
906
+ SSEInterceptor.disableInterception();
684
907
  eventEmitter.events = {};
685
908
  },
686
909
  on: (event, callback) => eventEmitter.on(event, callback)
687
910
  };
688
911
  };
689
- const useNetworkActivityDevTools = () => {
912
+ const DEFAULT_CONFIG = {
913
+ inspectors: {
914
+ http: true,
915
+ websocket: true,
916
+ sse: true
917
+ },
918
+ clientUISettings: {
919
+ showUrlAsName: false
920
+ }
921
+ };
922
+ const validateConfig = (config) => {
923
+ const inspectors = config.inspectors;
924
+ if (!inspectors) {
925
+ return;
926
+ }
927
+ if (inspectors.sse && !inspectors.http) {
928
+ throw new Error("SSE inspector requires HTTP inspector to be enabled.");
929
+ }
930
+ };
931
+ const overridesRegistry = getOverridesRegistry();
932
+ const useNetworkActivityDevTools = (config = DEFAULT_CONFIG) => {
933
+ var _a, _b, _c, _d;
934
+ const isRecordingEnabledRef = react.useRef(false);
690
935
  const client = pluginBridge.useRozeniteDevToolsClient({
691
936
  pluginId: "@rozenite/network-activity-plugin"
692
937
  });
938
+ const isHttpInspectorEnabled = ((_a = config.inspectors) == null ? void 0 : _a.http) ?? true;
939
+ const isWebSocketInspectorEnabled = ((_b = config.inspectors) == null ? void 0 : _b.websocket) ?? true;
940
+ const isSSEInspectorEnabled = ((_c = config.inspectors) == null ? void 0 : _c.sse) ?? true;
941
+ const showUrlAsName = (_d = config.clientUISettings) == null ? void 0 : _d.showUrlAsName;
693
942
  react.useEffect(() => {
694
943
  if (!client) {
695
944
  return;
696
945
  }
946
+ validateConfig(config);
947
+ }, [config]);
948
+ react.useEffect(() => {
949
+ if (!client) {
950
+ return;
951
+ }
952
+ const sendClientUISettings = () => {
953
+ var _a2;
954
+ client.send("client-ui-settings", {
955
+ settings: {
956
+ showUrlAsName: showUrlAsName ?? ((_a2 = DEFAULT_CONFIG.clientUISettings) == null ? void 0 : _a2.showUrlAsName)
957
+ }
958
+ });
959
+ };
960
+ const subscriptions = [
961
+ client.onMessage("network-enable", () => {
962
+ isRecordingEnabledRef.current = true;
963
+ }),
964
+ client.onMessage("network-disable", () => {
965
+ isRecordingEnabledRef.current = false;
966
+ }),
967
+ client.onMessage("set-overrides", (data) => {
968
+ overridesRegistry.setOverrides(data.overrides);
969
+ }),
970
+ client.onMessage("get-client-ui-settings", () => {
971
+ sendClientUISettings();
972
+ })
973
+ ];
974
+ sendClientUISettings();
975
+ return () => {
976
+ subscriptions.forEach((subscription) => subscription.remove());
977
+ };
978
+ }, [client, showUrlAsName]);
979
+ react.useEffect(() => {
980
+ if (!client || !isHttpInspectorEnabled) {
981
+ return;
982
+ }
697
983
  const networkInspector = getNetworkInspector(client);
984
+ if (isRecordingEnabledRef.current) {
985
+ networkInspector.enable();
986
+ }
698
987
  return () => {
699
988
  networkInspector.dispose();
700
989
  };
701
- }, [client]);
990
+ }, [client, isHttpInspectorEnabled]);
702
991
  react.useEffect(() => {
703
- if (!client) {
992
+ if (!client || !isWebSocketInspectorEnabled) {
704
993
  return;
705
994
  }
706
995
  const eventsToForward = [
@@ -724,12 +1013,15 @@ const useNetworkActivityDevTools = () => {
724
1013
  client.onMessage("network-disable", () => {
725
1014
  websocketInspector.disable();
726
1015
  });
1016
+ if (isRecordingEnabledRef.current) {
1017
+ websocketInspector.enable();
1018
+ }
727
1019
  return () => {
728
1020
  websocketInspector.dispose();
729
1021
  };
730
- }, [client]);
1022
+ }, [client, isWebSocketInspectorEnabled]);
731
1023
  react.useEffect(() => {
732
- if (!client) {
1024
+ if (!client || !isSSEInspectorEnabled) {
733
1025
  return;
734
1026
  }
735
1027
  const eventsToForward = [
@@ -750,10 +1042,13 @@ const useNetworkActivityDevTools = () => {
750
1042
  client.onMessage("network-disable", () => {
751
1043
  sseInspector.disable();
752
1044
  });
1045
+ if (isRecordingEnabledRef.current) {
1046
+ sseInspector.enable();
1047
+ }
753
1048
  return () => {
754
1049
  sseInspector.dispose();
755
1050
  };
756
- }, [client]);
1051
+ }, [client, isSSEInspectorEnabled]);
757
1052
  return client;
758
1053
  };
759
1054
  exports.useNetworkActivityDevTools = useNetworkActivityDevTools;