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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/{panel.html → App.html} +3 -3
  2. package/dist/assets/App-CIflVb88.js +24164 -0
  3. package/dist/assets/App-Czu6Vt2P.css +1233 -0
  4. package/dist/react-native.cjs +1 -1
  5. package/dist/react-native.d.ts +1 -90
  6. package/dist/rozenite.config.d.ts +7 -0
  7. package/dist/rozenite.json +1 -1
  8. package/dist/src/react-native/network-inspector.d.ts +8 -0
  9. package/dist/src/react-native/network-requests-registry.d.ts +6 -0
  10. package/dist/src/react-native/useNetworkActivityDevTools.d.ts +2 -0
  11. package/dist/src/react-native/xhr-interceptor.d.ts +38 -0
  12. package/dist/src/shared/client.d.ts +64 -0
  13. package/dist/src/ui/App.d.ts +1 -0
  14. package/dist/src/ui/components/Badge.d.ts +9 -0
  15. package/dist/src/ui/components/Button.d.ts +11 -0
  16. package/dist/src/ui/components/Input.d.ts +3 -0
  17. package/dist/src/ui/components/JsonTree.d.ts +5 -0
  18. package/dist/src/ui/components/RequestList.d.ts +45 -0
  19. package/dist/src/ui/components/ScrollArea.d.ts +4 -0
  20. package/dist/src/ui/components/Separator.d.ts +3 -0
  21. package/dist/src/ui/tabs/CookiesTab.d.ts +8 -0
  22. package/dist/src/ui/tabs/HeadersTab.d.ts +17 -0
  23. package/dist/src/ui/tabs/RequestTab.d.ts +10 -0
  24. package/dist/src/ui/tabs/ResponseTab.d.ts +12 -0
  25. package/dist/src/ui/tabs/TimingTab.d.ts +7 -0
  26. package/dist/src/ui/types.d.ts +23 -0
  27. package/dist/src/ui/utils.d.ts +2 -0
  28. package/dist/src/ui/views/InspectorView.d.ts +5 -0
  29. package/dist/src/ui/views/LoadingView.d.ts +1 -0
  30. package/dist/useNetworkActivityDevTools.cjs +360 -0
  31. package/dist/useNetworkActivityDevTools.js +108 -236
  32. package/package.json +23 -16
  33. package/postcss.config.js +6 -0
  34. package/rozenite.config.ts +1 -1
  35. package/src/react-native/network-inspector.ts +113 -260
  36. package/src/react-native/network-requests-registry.ts +7 -77
  37. package/src/react-native/useNetworkActivityDevTools.ts +1 -1
  38. package/src/react-native/xhr-interceptor.ts +2 -2
  39. package/src/react-native/xml-request.d.ts +11 -1
  40. package/src/shared/client.ts +80 -0
  41. package/src/ui/App.tsx +19 -0
  42. package/src/ui/components/Badge.tsx +36 -0
  43. package/src/ui/components/Button.tsx +56 -0
  44. package/src/ui/components/Input.tsx +22 -0
  45. package/src/ui/components/JsonTree.tsx +37 -0
  46. package/src/ui/components/RequestList.tsx +376 -0
  47. package/src/ui/components/ScrollArea.tsx +48 -0
  48. package/src/ui/components/Separator.tsx +31 -0
  49. package/src/ui/components/Tabs.tsx +55 -0
  50. package/src/ui/globals.css +90 -0
  51. package/src/ui/tabs/CookiesTab.tsx +290 -0
  52. package/src/ui/tabs/HeadersTab.tsx +117 -0
  53. package/src/ui/tabs/RequestTab.tsx +72 -0
  54. package/src/ui/tabs/ResponseTab.tsx +140 -0
  55. package/src/ui/tabs/TimingTab.tsx +71 -0
  56. package/src/ui/types.ts +30 -0
  57. package/src/ui/utils.ts +5 -97
  58. package/src/ui/views/InspectorView.tsx +349 -0
  59. package/src/ui/views/LoadingView.tsx +19 -0
  60. package/tailwind.config.ts +93 -0
  61. package/dist/assets/panel-BNxB_KsS.js +0 -16663
  62. package/dist/assets/panel-DXGMsavf.css +0 -555
  63. package/src/types/client.ts +0 -111
  64. package/src/types/network.ts +0 -32
  65. package/src/ui/components.module.css +0 -158
  66. package/src/ui/components.tsx +0 -241
  67. package/src/ui/network-details.module.css +0 -197
  68. package/src/ui/network-details.tsx +0 -345
  69. package/src/ui/network-list.module.css +0 -128
  70. package/src/ui/network-list.tsx +0 -240
  71. package/src/ui/network-toolbar.module.css +0 -9
  72. package/src/ui/network-toolbar.tsx +0 -34
  73. package/src/ui/panel.module.css +0 -67
  74. package/src/ui/panel.tsx +0 -318
  75. package/src/ui/tanstack-query.tsx +0 -204
@@ -0,0 +1,360 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const react = require("react");
4
+ const pluginBridge = require("@rozenite/plugin-bridge");
5
+ const REQUEST_TTL = 1e3 * 60 * 5;
6
+ const getNetworkRequestsRegistry = () => {
7
+ const registry = /* @__PURE__ */ new Map();
8
+ const trimRegistry = () => {
9
+ const now = Date.now();
10
+ registry.forEach((entry) => {
11
+ if (now - entry.sentAt < REQUEST_TTL) {
12
+ return;
13
+ }
14
+ registry.delete(entry.id);
15
+ });
16
+ };
17
+ const addEntry = (id, request) => {
18
+ trimRegistry();
19
+ registry.set(id, {
20
+ id,
21
+ request,
22
+ sentAt: Date.now()
23
+ });
24
+ };
25
+ const getEntry = (id) => {
26
+ var _a;
27
+ return ((_a = registry.get(id)) == null ? void 0 : _a.request) ?? null;
28
+ };
29
+ const clear = () => {
30
+ registry.clear();
31
+ };
32
+ return {
33
+ addEntry,
34
+ getEntry,
35
+ clear
36
+ };
37
+ };
38
+ const originalXHROpen = XMLHttpRequest.prototype.open;
39
+ const originalXHRSend = XMLHttpRequest.prototype.send;
40
+ const originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
41
+ let openCallback;
42
+ let sendCallback;
43
+ let requestHeaderCallback;
44
+ let headerReceivedCallback;
45
+ let responseCallback;
46
+ let isInterceptorEnabled = false;
47
+ const XHRInterceptor = {
48
+ /**
49
+ * Invoked before XMLHttpRequest.open(...) is called.
50
+ */
51
+ setOpenCallback(callback) {
52
+ openCallback = callback;
53
+ },
54
+ /**
55
+ * Invoked before XMLHttpRequest.send(...) is called.
56
+ */
57
+ setSendCallback(callback) {
58
+ sendCallback = callback;
59
+ },
60
+ /**
61
+ * Invoked after xhr's readyState becomes xhr.HEADERS_RECEIVED.
62
+ */
63
+ setHeaderReceivedCallback(callback) {
64
+ headerReceivedCallback = callback;
65
+ },
66
+ /**
67
+ * Invoked after xhr's readyState becomes xhr.DONE.
68
+ */
69
+ setResponseCallback(callback) {
70
+ responseCallback = callback;
71
+ },
72
+ /**
73
+ * Invoked before XMLHttpRequest.setRequestHeader(...) is called.
74
+ */
75
+ setRequestHeaderCallback(callback) {
76
+ requestHeaderCallback = callback;
77
+ },
78
+ isInterceptorEnabled() {
79
+ return isInterceptorEnabled;
80
+ },
81
+ enableInterception() {
82
+ if (isInterceptorEnabled) {
83
+ return;
84
+ }
85
+ XMLHttpRequest.prototype.open = function(method, url) {
86
+ if (openCallback) {
87
+ openCallback(method, url, this);
88
+ }
89
+ originalXHROpen.apply(this, arguments);
90
+ };
91
+ XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
92
+ if (requestHeaderCallback) {
93
+ requestHeaderCallback(header, value, this);
94
+ }
95
+ originalXHRSetRequestHeader.apply(this, arguments);
96
+ };
97
+ XMLHttpRequest.prototype.send = function(data) {
98
+ if (sendCallback) {
99
+ sendCallback(data, this);
100
+ }
101
+ if (this.addEventListener) {
102
+ this.addEventListener(
103
+ "readystatechange",
104
+ () => {
105
+ if (!isInterceptorEnabled) {
106
+ return;
107
+ }
108
+ if (this.readyState === this.HEADERS_RECEIVED) {
109
+ const contentTypeString = this.getResponseHeader("Content-Type");
110
+ const contentLengthString = this.getResponseHeader("Content-Length");
111
+ let responseContentType, responseSize;
112
+ if (contentTypeString) {
113
+ responseContentType = contentTypeString.split(";")[0];
114
+ }
115
+ if (contentLengthString) {
116
+ responseSize = parseInt(contentLengthString, 10);
117
+ }
118
+ if (headerReceivedCallback) {
119
+ headerReceivedCallback(
120
+ responseContentType,
121
+ responseSize,
122
+ this.getAllResponseHeaders(),
123
+ this
124
+ );
125
+ }
126
+ }
127
+ if (this.readyState === this.DONE) {
128
+ if (responseCallback) {
129
+ responseCallback(
130
+ this.status,
131
+ this.timeout,
132
+ this.response,
133
+ this.responseURL,
134
+ this.responseType,
135
+ this
136
+ );
137
+ }
138
+ }
139
+ },
140
+ false
141
+ );
142
+ }
143
+ originalXHRSend.apply(this, arguments);
144
+ };
145
+ isInterceptorEnabled = true;
146
+ },
147
+ // Unpatch XMLHttpRequest methods and remove the callbacks.
148
+ disableInterception() {
149
+ if (!isInterceptorEnabled) {
150
+ return;
151
+ }
152
+ isInterceptorEnabled = false;
153
+ XMLHttpRequest.prototype.send = originalXHRSend;
154
+ XMLHttpRequest.prototype.open = originalXHROpen;
155
+ XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
156
+ responseCallback = null;
157
+ openCallback = null;
158
+ sendCallback = null;
159
+ headerReceivedCallback = null;
160
+ requestHeaderCallback = null;
161
+ }
162
+ };
163
+ 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
+ const getResponseSize = (request) => {
184
+ if (typeof request.response === "object") {
185
+ return request.response.size;
186
+ }
187
+ return request.response.length || 0;
188
+ };
189
+ const getResponseBody = async (request) => {
190
+ const responseType = request.responseType;
191
+ if (responseType === "text") {
192
+ return request.responseText;
193
+ }
194
+ if (responseType === "blob") {
195
+ const contentType = request.getResponseHeader("Content-Type") || "";
196
+ if (contentType.startsWith("text/") || contentType.startsWith("application/json")) {
197
+ return new Promise((resolve) => {
198
+ const reader = new FileReader();
199
+ reader.onload = () => {
200
+ resolve(reader.result);
201
+ };
202
+ reader.readAsText(request.response);
203
+ });
204
+ }
205
+ }
206
+ return null;
207
+ };
208
+ const getInitiatorFromStack = () => {
209
+ try {
210
+ const stack = new Error().stack;
211
+ if (!stack) {
212
+ return { type: "other" };
213
+ }
214
+ const line = stack.split("\n")[9];
215
+ const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
216
+ if (match) {
217
+ return {
218
+ type: "script",
219
+ url: match[2],
220
+ lineNumber: parseInt(match[3]),
221
+ columnNumber: parseInt(match[4])
222
+ };
223
+ }
224
+ } catch {
225
+ }
226
+ return { type: "other" };
227
+ };
228
+ const READY_STATE_HEADERS_RECEIVED = 2;
229
+ const getNetworkInspector = (pluginClient) => {
230
+ const generateRequestId = () => {
231
+ return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
232
+ };
233
+ const handleRequestSend = (data, request) => {
234
+ const sendTime = Date.now();
235
+ const requestId = generateRequestId();
236
+ const initiator = getInitiatorFromStack();
237
+ networkRequestsRegistry.addEntry(requestId, request);
238
+ let ttfb = 0;
239
+ pluginClient.send("request-sent", {
240
+ requestId,
241
+ timestamp: sendTime / 1e3,
242
+ request: {
243
+ url: request._url,
244
+ method: request._method,
245
+ headers: request._headers,
246
+ postData: data
247
+ },
248
+ type: "XHR",
249
+ initiator
250
+ });
251
+ request.addEventListener("readystatechange", () => {
252
+ if (request.readyState === READY_STATE_HEADERS_RECEIVED) {
253
+ ttfb = Date.now() - sendTime;
254
+ }
255
+ });
256
+ request.addEventListener("load", () => {
257
+ pluginClient.send("response-received", {
258
+ requestId,
259
+ timestamp: Date.now() / 1e3,
260
+ type: "XHR",
261
+ response: {
262
+ url: request._url,
263
+ status: request.status,
264
+ statusText: request.statusText,
265
+ headers: request.responseHeaders,
266
+ contentType: getContentType(request),
267
+ size: getResponseSize(request),
268
+ responseTime: Date.now() / 1e3
269
+ }
270
+ });
271
+ });
272
+ request.addEventListener("loadend", () => {
273
+ pluginClient.send("request-completed", {
274
+ requestId,
275
+ timestamp: Date.now() / 1e3,
276
+ duration: Date.now() - sendTime,
277
+ size: getResponseSize(request),
278
+ ttfb
279
+ });
280
+ });
281
+ request.addEventListener("error", () => {
282
+ pluginClient.send("request-failed", {
283
+ requestId,
284
+ timestamp: Date.now() / 1e3,
285
+ type: "XHR",
286
+ error: "Failed",
287
+ canceled: false
288
+ });
289
+ });
290
+ request.addEventListener("abort", () => {
291
+ pluginClient.send("request-failed", {
292
+ requestId,
293
+ timestamp: Date.now() / 1e3,
294
+ type: "XHR",
295
+ error: "Aborted",
296
+ canceled: true
297
+ });
298
+ });
299
+ };
300
+ const enable = () => {
301
+ XHRInterceptor.disableInterception();
302
+ XHRInterceptor.setSendCallback(handleRequestSend);
303
+ XHRInterceptor.enableInterception();
304
+ };
305
+ const disable = () => {
306
+ XHRInterceptor.disableInterception();
307
+ networkRequestsRegistry.clear();
308
+ };
309
+ const isEnabled = () => {
310
+ return XHRInterceptor.isInterceptorEnabled();
311
+ };
312
+ const enableSubscription = pluginClient.onMessage("network-enable", () => {
313
+ enable();
314
+ });
315
+ const disableSubscription = pluginClient.onMessage("network-disable", () => {
316
+ disable();
317
+ });
318
+ const handleBodySubscription = pluginClient.onMessage(
319
+ "get-response-body",
320
+ async ({ requestId }) => {
321
+ const request = networkRequestsRegistry.getEntry(requestId);
322
+ if (!request) {
323
+ return;
324
+ }
325
+ const body = await getResponseBody(request);
326
+ pluginClient.send("response-body", {
327
+ requestId,
328
+ body
329
+ });
330
+ }
331
+ );
332
+ const dispose = () => {
333
+ disable();
334
+ enableSubscription.remove();
335
+ disableSubscription.remove();
336
+ handleBodySubscription.remove();
337
+ };
338
+ return {
339
+ enable,
340
+ disable,
341
+ isEnabled,
342
+ dispose
343
+ };
344
+ };
345
+ const useNetworkActivityDevTools = () => {
346
+ const client = pluginBridge.useRozeniteDevToolsClient({
347
+ pluginId: "@rozenite/network-activity-plugin"
348
+ });
349
+ react.useEffect(() => {
350
+ if (!client) {
351
+ return;
352
+ }
353
+ const networkInspector = getNetworkInspector(client);
354
+ return () => {
355
+ networkInspector.dispose();
356
+ };
357
+ }, [client]);
358
+ return client;
359
+ };
360
+ exports.useNetworkActivityDevTools = useNetworkActivityDevTools;