@rozenite/network-activity-plugin 1.5.1 → 1.6.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.
@@ -1,1086 +1,5 @@
1
- import { createNanoEvents } from "nanoevents";
2
- import { g as getEventSource } from "./event-source.js";
3
- import { Platform } from "react-native";
4
- import WebSocketInterceptor from "react-native/Libraries/WebSocket/WebSocketInterceptor";
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
- return registry.get(id)?.request ?? null;
27
- };
28
- const clear = () => {
29
- registry.clear();
30
- };
31
- return {
32
- addEntry,
33
- getEntry,
34
- clear
35
- };
36
- };
37
- const XMLHttpRequest = global.XMLHttpRequest || window.XMLHttpRequest;
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 overrideCallback;
47
- let isInterceptorEnabled$1 = false;
48
- const XHRInterceptor = {
49
- /**
50
- * Invoked before XMLHttpRequest.open(...) is called.
51
- */
52
- setOpenCallback(callback) {
53
- openCallback = callback;
54
- },
55
- /**
56
- * Invoked before XMLHttpRequest.send(...) is called.
57
- */
58
- setSendCallback(callback) {
59
- sendCallback = callback;
60
- },
61
- /**
62
- * Invoked after xhr's readyState becomes xhr.HEADERS_RECEIVED.
63
- */
64
- setHeaderReceivedCallback(callback) {
65
- headerReceivedCallback = callback;
66
- },
67
- /**
68
- * Invoked after xhr's readyState becomes xhr.DONE.
69
- */
70
- setResponseCallback(callback) {
71
- responseCallback = callback;
72
- },
73
- /**
74
- * Invoked before XMLHttpRequest.setRequestHeader(...) is called.
75
- */
76
- setRequestHeaderCallback(callback) {
77
- requestHeaderCallback = callback;
78
- },
79
- /**
80
- * Invoked before XMLHttpRequest.send(...) is called.
81
- */
82
- setOverrideCallback(callback) {
83
- overrideCallback = callback;
84
- },
85
- isInterceptorEnabled() {
86
- return isInterceptorEnabled$1;
87
- },
88
- enableInterception() {
89
- if (isInterceptorEnabled$1) {
90
- return;
91
- }
92
- XMLHttpRequest.prototype.open = function(method, url) {
93
- if (openCallback) {
94
- openCallback(method, url, this);
95
- }
96
- originalXHROpen.apply(this, arguments);
97
- };
98
- XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
99
- if (requestHeaderCallback) {
100
- requestHeaderCallback(header, value, this);
101
- }
102
- originalXHRSetRequestHeader.apply(this, arguments);
103
- };
104
- XMLHttpRequest.prototype.send = function(data) {
105
- if (sendCallback) {
106
- sendCallback(data, this);
107
- }
108
- if (overrideCallback) {
109
- overrideCallback(this);
110
- }
111
- if (this.addEventListener) {
112
- this.addEventListener(
113
- "readystatechange",
114
- () => {
115
- if (!isInterceptorEnabled$1) {
116
- return;
117
- }
118
- if (this.readyState === this.HEADERS_RECEIVED) {
119
- const contentTypeString = this.getResponseHeader("Content-Type");
120
- const contentLengthString = this.getResponseHeader("Content-Length");
121
- let responseContentType, responseSize;
122
- if (contentTypeString) {
123
- responseContentType = contentTypeString.split(";")[0];
124
- }
125
- if (contentLengthString) {
126
- responseSize = parseInt(contentLengthString, 10);
127
- }
128
- if (headerReceivedCallback) {
129
- headerReceivedCallback(
130
- responseContentType,
131
- responseSize,
132
- this.getAllResponseHeaders(),
133
- this
134
- );
135
- }
136
- }
137
- if (this.readyState === this.DONE) {
138
- if (responseCallback) {
139
- responseCallback(
140
- this.status,
141
- this.timeout,
142
- this.response,
143
- this.responseURL,
144
- this.responseType,
145
- this
146
- );
147
- }
148
- }
149
- },
150
- false
151
- );
152
- }
153
- originalXHRSend.apply(this, arguments);
154
- };
155
- isInterceptorEnabled$1 = true;
156
- },
157
- // Unpatch XMLHttpRequest methods and remove the callbacks.
158
- disableInterception() {
159
- if (!isInterceptorEnabled$1) {
160
- return;
161
- }
162
- isInterceptorEnabled$1 = false;
163
- XMLHttpRequest.prototype.send = originalXHRSend;
164
- XMLHttpRequest.prototype.open = originalXHROpen;
165
- XMLHttpRequest.prototype.setRequestHeader = originalXHRSetRequestHeader;
166
- responseCallback = null;
167
- openCallback = null;
168
- sendCallback = null;
169
- headerReceivedCallback = null;
170
- requestHeaderCallback = null;
171
- overrideCallback = null;
172
- }
173
- };
174
- function safeStringify(data) {
175
- try {
176
- return typeof data === "string" ? data : JSON.stringify(data);
177
- } catch {
178
- return String(data);
179
- }
180
- }
181
- const getStringSizeInBytes = (value) => {
182
- return new TextEncoder().encode(value).length;
183
- };
184
- const isBlob = (value) => value instanceof Blob;
185
- const isArrayBuffer = (value) => value instanceof ArrayBuffer || ArrayBuffer.isView(value);
186
- const isFormData = (value) => value instanceof FormData;
187
- const isNullOrUndefined = (value) => value === null || value === void 0;
188
- function getHttpHeader(headers, name) {
189
- const lowerName = name.toLowerCase();
190
- for (const key in headers) {
191
- if (key.toLowerCase() === lowerName) {
192
- return { value: headers[key], originalKey: key };
193
- }
194
- }
195
- return void 0;
196
- }
197
- function getContentTypeMime(headers) {
198
- const contentType = getHttpHeader(headers, "content-type");
199
- if (!contentType) {
200
- return void 0;
201
- }
202
- const { value } = contentType;
203
- const actualValue = Array.isArray(value) ? value[0] : value;
204
- return actualValue.split(";")[0].trim();
205
- }
206
- const getContentType = (request) => {
207
- const responseHeaders = request.responseHeaders;
208
- const responseType = request.responseType;
209
- const contentType = getContentTypeMime(responseHeaders || {});
210
- if (contentType) {
211
- return contentType;
212
- }
213
- switch (responseType) {
214
- case "arraybuffer":
215
- case "blob":
216
- return "application/octet-stream";
217
- case "text":
218
- case "":
219
- return "text/plain";
220
- case "json":
221
- return "application/json";
222
- case "document":
223
- return "text/html";
224
- }
225
- };
226
- function getBlobName(blob) {
227
- if (typeof blob?.name === "string") {
228
- return blob.name;
229
- }
230
- if (blob?.data && typeof blob.data.name === "string") {
231
- return blob.data.name;
232
- }
233
- return void 0;
234
- }
235
- function getFormDataEntries(formData) {
236
- if (!formData || typeof formData !== "object") {
237
- return [];
238
- }
239
- if (typeof formData.entries === "function") {
240
- return formData.entries();
241
- }
242
- if (Array.isArray(formData._parts)) {
243
- return formData._parts;
244
- }
245
- return [];
246
- }
247
- const getBinaryPostData = (body) => ({
248
- type: "binary",
249
- value: {
250
- size: body.size,
251
- type: body.type,
252
- name: getBlobName(body)
253
- }
254
- });
255
- const getArrayBufferPostData = (body) => ({
256
- type: "binary",
257
- value: {
258
- size: body.byteLength
259
- }
260
- });
261
- const getTextPostData = (body) => ({
262
- type: "text",
263
- value: safeStringify(body)
264
- });
265
- const getFormDataPostData = (body) => ({
266
- type: "form-data",
267
- value: Array.from(getFormDataEntries(body)).reduce((acc, [key, value]) => {
268
- if (isBlob(value)) {
269
- acc[key] = getBinaryPostData(value);
270
- } else if (isArrayBuffer(value)) {
271
- acc[key] = getArrayBufferPostData(value);
272
- } else {
273
- acc[key] = getTextPostData(value);
274
- }
275
- return acc;
276
- }, {})
277
- });
278
- const getRequestBody = (body) => {
279
- if (isNullOrUndefined(body)) {
280
- return body;
281
- }
282
- if (isBlob(body)) {
283
- return getBinaryPostData(body);
284
- }
285
- if (isArrayBuffer(body)) {
286
- return getArrayBufferPostData(body);
287
- }
288
- if (isFormData(body)) {
289
- return getFormDataPostData(body);
290
- }
291
- return getTextPostData(body);
292
- };
293
- const getResponseSize = (request) => {
294
- try {
295
- const { responseType, response } = request;
296
- if (response === null) {
297
- return 0;
298
- }
299
- if (responseType === "" || responseType === "text") {
300
- return getStringSizeInBytes(request.responseText);
301
- }
302
- if (responseType === "json") {
303
- return getStringSizeInBytes(safeStringify(response));
304
- }
305
- if (responseType === "blob") {
306
- return response.size;
307
- }
308
- if (responseType === "arraybuffer") {
309
- return response.byteLength;
310
- }
311
- return 0;
312
- } catch {
313
- return null;
314
- }
315
- };
316
- const getResponseBody = async (request) => {
317
- const responseType = request.responseType;
318
- if (responseType === "" || responseType === "text") {
319
- return request.responseText;
320
- }
321
- if (responseType === "blob") {
322
- const contentType = request.getResponseHeader("Content-Type") || "";
323
- if (contentType.startsWith("text/") || contentType.startsWith("application/json")) {
324
- return new Promise((resolve) => {
325
- const reader = new FileReader();
326
- reader.onload = () => {
327
- resolve(reader.result);
328
- };
329
- reader.readAsText(request.response);
330
- });
331
- }
332
- }
333
- if (responseType === "json") {
334
- return safeStringify(request.response);
335
- }
336
- return null;
337
- };
338
- const getInitiatorFromStack = () => {
339
- try {
340
- const stack = new Error().stack;
341
- if (!stack) {
342
- return { type: "other" };
343
- }
344
- const line = stack.split("\n")[9];
345
- const match = line.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/);
346
- if (match) {
347
- return {
348
- type: "script",
349
- url: match[2],
350
- lineNumber: parseInt(match[3]),
351
- columnNumber: parseInt(match[4])
352
- };
353
- }
354
- } catch {
355
- }
356
- return { type: "other" };
357
- };
358
- const setupRequestOverride = (overridesRegistry, request) => {
359
- const override = overridesRegistry.getOverrideForUrl(request._url);
360
- if (!override) return;
361
- request.addEventListener("readystatechange", () => {
362
- if (override.body !== void 0) {
363
- Object.defineProperty(request, "responseType", { writable: true });
364
- Object.defineProperty(request, "response", { writable: true });
365
- Object.defineProperty(request, "responseText", { writable: true });
366
- const contentType = getContentType(request);
367
- if (contentType === "application/json") {
368
- request.responseType = "json";
369
- } else if (contentType === "text/plain") {
370
- request.responseType = "text";
371
- }
372
- request.response = override.body;
373
- request.responseText = override.body;
374
- }
375
- if (override.status !== void 0) {
376
- Object.defineProperty(request, "status", { writable: true });
377
- request.status = override.status;
378
- }
379
- });
380
- };
381
- const splitSetCookieHeaderByComma = (header) => {
382
- const regex = /(?:^|,\s)([^=;,]+=[^;]+(?:;[^,]*)*)/g;
383
- const matches = [];
384
- let match;
385
- while ((match = regex.exec(header)) !== null) {
386
- matches.push(match[1].trim());
387
- }
388
- return matches;
389
- };
390
- const applyReactNativeResponseHeadersLogic = (headers) => {
391
- const parsedHeaders = { ...headers };
392
- const setCookieHeader = getHttpHeader(headers, "set-cookie");
393
- if (setCookieHeader) {
394
- const { value, originalKey } = setCookieHeader;
395
- const cookies = splitSetCookieHeaderByComma(value);
396
- parsedHeaders[originalKey] = cookies.length > 0 ? cookies : value;
397
- }
398
- return parsedHeaders;
399
- };
400
- const createOverridesRegistry = () => {
401
- let overrides = /* @__PURE__ */ new Map();
402
- const setOverrides = (newOverrides) => {
403
- overrides = new Map(newOverrides);
404
- };
405
- const getOverrideForUrl = (url) => {
406
- return overrides.get(url);
407
- };
408
- return {
409
- setOverrides,
410
- getOverrideForUrl
411
- };
412
- };
413
- let registryInstance = null;
414
- const getOverridesRegistry = () => {
415
- if (!registryInstance) {
416
- registryInstance = createOverridesRegistry();
417
- }
418
- return registryInstance;
419
- };
420
- const HTTP_EVENTS = [
421
- "request-sent",
422
- "response-received",
423
- "request-completed",
424
- "request-failed",
425
- "request-progress"
426
- ];
427
- const isHttpEvent = (type) => {
428
- return HTTP_EVENTS.includes(type);
429
- };
430
- const READY_STATE_HEADERS_RECEIVED = 2;
431
- const getHTTPInspector = () => {
432
- const eventEmitter = createNanoEvents();
433
- const networkRequestsRegistry = getNetworkRequestsRegistry();
434
- const overridesRegistry = getOverridesRegistry();
435
- XHRInterceptor.setOverrideCallback(
436
- (request) => setupRequestOverride(overridesRegistry, request)
437
- );
438
- return {
439
- enable: () => {
440
- if (XHRInterceptor.isInterceptorEnabled()) return;
441
- XHRInterceptor.disableInterception();
442
- XHRInterceptor.setSendCallback((data, request) => {
443
- const initiator = getInitiatorFromStack();
444
- const sendTime = Date.now();
445
- const requestId = `req_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
446
- request._rozeniteRequestId = requestId;
447
- networkRequestsRegistry.addEntry(requestId, request);
448
- let ttfb = 0;
449
- eventEmitter.emit("request-sent", {
450
- requestId,
451
- timestamp: sendTime,
452
- request: {
453
- url: request._url,
454
- method: request._method,
455
- headers: request._headers,
456
- postData: getRequestBody(data)
457
- },
458
- type: "XHR",
459
- initiator
460
- });
461
- request.addEventListener("readystatechange", () => {
462
- if (request.readyState === READY_STATE_HEADERS_RECEIVED) {
463
- ttfb = Date.now() - sendTime;
464
- }
465
- });
466
- request.addEventListener("progress", (event) => {
467
- eventEmitter.emit("request-progress", {
468
- requestId,
469
- timestamp: Date.now(),
470
- loaded: event.loaded,
471
- total: event.total,
472
- lengthComputable: event.lengthComputable
473
- });
474
- });
475
- request.addEventListener("load", () => {
476
- eventEmitter.emit("response-received", {
477
- requestId,
478
- timestamp: Date.now(),
479
- type: "XHR",
480
- response: {
481
- url: request._url,
482
- status: request.status,
483
- statusText: request.statusText,
484
- headers: applyReactNativeResponseHeadersLogic(
485
- request.responseHeaders || {}
486
- ),
487
- contentType: getContentType(request),
488
- size: getResponseSize(request),
489
- responseTime: Date.now()
490
- }
491
- });
492
- });
493
- request.addEventListener("loadend", () => {
494
- eventEmitter.emit("request-completed", {
495
- requestId,
496
- timestamp: Date.now(),
497
- duration: Date.now() - sendTime,
498
- size: getResponseSize(request),
499
- ttfb
500
- });
501
- });
502
- request.addEventListener("error", () => {
503
- eventEmitter.emit("request-failed", {
504
- requestId,
505
- timestamp: Date.now(),
506
- type: "XHR",
507
- error: "Failed",
508
- canceled: false
509
- });
510
- });
511
- request.addEventListener("abort", () => {
512
- eventEmitter.emit("request-failed", {
513
- requestId,
514
- timestamp: Date.now(),
515
- type: "XHR",
516
- error: "Aborted",
517
- canceled: true
518
- });
519
- });
520
- request.addEventListener("timeout", () => {
521
- eventEmitter.emit("request-failed", {
522
- requestId,
523
- timestamp: Date.now(),
524
- type: "XHR",
525
- error: "Timeout",
526
- canceled: false
527
- });
528
- });
529
- });
530
- XHRInterceptor.enableInterception();
531
- },
532
- disable: () => {
533
- XHRInterceptor.disableInterception();
534
- networkRequestsRegistry.clear();
535
- },
536
- isEnabled: () => {
537
- return XHRInterceptor.isInterceptorEnabled();
538
- },
539
- dispose: () => {
540
- XHRInterceptor.disableInterception();
541
- networkRequestsRegistry.clear();
542
- },
543
- getNetworkRequestsRegistry: () => networkRequestsRegistry,
544
- on: (event, callback) => eventEmitter.on(event, callback)
545
- };
546
- };
547
- const getWebSocketInterceptor = () => {
548
- if (Platform.constants.reactNativeVersion.minor >= 79) {
549
- return WebSocketInterceptor;
550
- } else {
551
- const WebSocketInterceptorPreRN079 = WebSocketInterceptor;
552
- return {
553
- ...WebSocketInterceptorPreRN079,
554
- setOnMessageCallback: (callback) => {
555
- WebSocketInterceptorPreRN079.setOnMessageCallback((socketId, data) => {
556
- callback(data, socketId);
557
- });
558
- },
559
- setOnCloseCallback: (callback) => {
560
- WebSocketInterceptorPreRN079.setOnCloseCallback((error, socketId) => {
561
- callback(socketId, error);
562
- });
563
- },
564
- setOnErrorCallback: (callback) => {
565
- WebSocketInterceptorPreRN079.setOnErrorCallback((error, socketId) => {
566
- callback(socketId, error);
567
- });
568
- }
569
- };
570
- }
571
- };
572
- const WEBSOCKET_EVENTS = [
573
- "websocket-connect",
574
- "websocket-open",
575
- "websocket-close",
576
- "websocket-message-sent",
577
- "websocket-message-received",
578
- "websocket-error",
579
- "websocket-connection-status-changed"
580
- ];
581
- const isWebSocketEvent = (type) => {
582
- return WEBSOCKET_EVENTS.includes(type);
583
- };
584
- const getWebSocketInspector = () => {
585
- const eventEmitter = createNanoEvents();
586
- const socketUrlMap = /* @__PURE__ */ new Map();
587
- const webSocketInterceptor = getWebSocketInterceptor();
588
- return {
589
- enable: () => {
590
- webSocketInterceptor.setConnectCallback(
591
- (url, protocols, options, socketId) => {
592
- socketUrlMap.set(socketId, url);
593
- const event = {
594
- type: "websocket-connect",
595
- url,
596
- socketId,
597
- timestamp: Date.now(),
598
- protocols,
599
- options
600
- };
601
- eventEmitter.emit("websocket-connect", event);
602
- }
603
- );
604
- webSocketInterceptor.setCloseCallback(
605
- (code, reason, socketId) => {
606
- const url = socketUrlMap.get(socketId);
607
- if (!url) {
608
- return;
609
- }
610
- const event = {
611
- type: "websocket-close",
612
- url,
613
- socketId,
614
- timestamp: Date.now(),
615
- code: code || 0,
616
- reason: reason || void 0
617
- };
618
- eventEmitter.emit("websocket-close", event);
619
- socketUrlMap.delete(socketId);
620
- }
621
- );
622
- webSocketInterceptor.setOnMessageCallback(
623
- (data, socketId) => {
624
- const url = socketUrlMap.get(socketId);
625
- if (!url) {
626
- return;
627
- }
628
- const event = {
629
- type: "websocket-message-received",
630
- url,
631
- socketId,
632
- timestamp: Date.now(),
633
- data,
634
- messageType: typeof data === "string" ? "text" : "binary"
635
- };
636
- eventEmitter.emit("websocket-message-received", event);
637
- }
638
- );
639
- webSocketInterceptor.setOnErrorCallback(
640
- (error, socketId) => {
641
- const url = socketUrlMap.get(socketId);
642
- if (!url) {
643
- return;
644
- }
645
- const event = {
646
- type: "websocket-error",
647
- url,
648
- socketId,
649
- timestamp: Date.now(),
650
- error
651
- };
652
- eventEmitter.emit("websocket-error", event);
653
- }
654
- );
655
- webSocketInterceptor.setSendCallback((data, socketId) => {
656
- const url = socketUrlMap.get(socketId);
657
- if (!url) {
658
- return;
659
- }
660
- const event = {
661
- type: "websocket-message-sent",
662
- url,
663
- socketId,
664
- timestamp: Date.now(),
665
- data,
666
- messageType: typeof data === "string" ? "text" : "binary"
667
- };
668
- eventEmitter.emit("websocket-message-sent", event);
669
- });
670
- webSocketInterceptor.setOnOpenCallback((socketId) => {
671
- const url = socketUrlMap.get(socketId);
672
- if (!url) {
673
- return;
674
- }
675
- const event = {
676
- type: "websocket-open",
677
- url,
678
- socketId,
679
- timestamp: Date.now()
680
- };
681
- eventEmitter.emit("websocket-open", event);
682
- });
683
- webSocketInterceptor.setOnCloseCallback(
684
- (error, socketId) => {
685
- const url = socketUrlMap.get(socketId);
686
- if (!url) {
687
- return;
688
- }
689
- const event = {
690
- type: "websocket-close",
691
- url,
692
- socketId,
693
- timestamp: Date.now(),
694
- code: error.code,
695
- reason: error.reason
696
- };
697
- eventEmitter.emit("websocket-close", event);
698
- socketUrlMap.delete(socketId);
699
- }
700
- );
701
- webSocketInterceptor.enableInterception();
702
- },
703
- disable: () => {
704
- webSocketInterceptor.disableInterception();
705
- },
706
- isEnabled: () => webSocketInterceptor.isInterceptorEnabled(),
707
- dispose: () => {
708
- webSocketInterceptor.disableInterception();
709
- socketUrlMap.clear();
710
- },
711
- on: (event, callback) => eventEmitter.on(event, callback)
712
- };
713
- };
714
- let connectCallback;
715
- let messageCallback;
716
- let errorCallback;
717
- let openEventCallback;
718
- let closeCallback;
719
- let isInterceptorEnabled = false;
720
- const eventSourceClass = getEventSource();
721
- const originalOpen = eventSourceClass.prototype.open;
722
- const originalDispatch = eventSourceClass.prototype.dispatch;
723
- const BUILT_IN_EVENT_TYPES = /* @__PURE__ */ new Set(["open", "error", "close", "done"]);
724
- const SSEInterceptor = {
725
- /**
726
- * Invoked when EventSource.open() is called (connection attempt starting).
727
- */
728
- setConnectCallback(callback) {
729
- connectCallback = callback;
730
- },
731
- /**
732
- * Invoked when a message event is received.
733
- */
734
- setMessageCallback(callback) {
735
- messageCallback = callback;
736
- },
737
- /**
738
- * Invoked when an error event occurs.
739
- */
740
- setErrorCallback(callback) {
741
- errorCallback = callback;
742
- },
743
- /**
744
- * Invoked when the connection is successfully opened (open event fired).
745
- */
746
- setOpenEventCallback(callback) {
747
- openEventCallback = callback;
748
- },
749
- /**
750
- * Invoked when the connection is closed.
751
- */
752
- setCloseCallback(callback) {
753
- closeCallback = callback;
754
- },
755
- isInterceptorEnabled() {
756
- return isInterceptorEnabled;
757
- },
758
- enableInterception() {
759
- if (isInterceptorEnabled) {
760
- return;
761
- }
762
- eventSourceClass.prototype.open = function() {
763
- if (connectCallback) {
764
- connectCallback(this.url, this);
765
- }
766
- this.addEventListener("open", (event) => {
767
- if (openEventCallback) {
768
- openEventCallback(event, this);
769
- }
770
- });
771
- this.addEventListener(
772
- "error",
773
- (event) => {
774
- if (errorCallback) {
775
- errorCallback(event, this);
776
- }
777
- }
778
- );
779
- this.addEventListener("close", (event) => {
780
- if (closeCallback) {
781
- closeCallback(event, this);
782
- }
783
- });
784
- return originalOpen.call(this);
785
- };
786
- eventSourceClass.prototype.dispatch = function(eventType, data) {
787
- if (!BUILT_IN_EVENT_TYPES.has(eventType)) {
788
- if (messageCallback) {
789
- messageCallback(data, this);
790
- }
791
- }
792
- return originalDispatch.call(this, eventType, data);
793
- };
794
- isInterceptorEnabled = true;
795
- },
796
- // Unpatch EventSource open method and remove the callbacks.
797
- disableInterception() {
798
- if (!isInterceptorEnabled) {
799
- return;
800
- }
801
- isInterceptorEnabled = false;
802
- eventSourceClass.prototype.open = originalOpen;
803
- eventSourceClass.prototype.dispatch = originalDispatch;
804
- connectCallback = null;
805
- messageCallback = null;
806
- errorCallback = null;
807
- openEventCallback = null;
808
- closeCallback = null;
809
- }
810
- };
811
- const SSE_EVENTS = [
812
- "sse-open",
813
- "sse-message",
814
- "sse-error",
815
- "sse-close"
816
- ];
817
- const isSSEEvent = (type) => {
818
- return SSE_EVENTS.includes(type);
819
- };
820
- const getSSEInspector = () => {
821
- const eventEmitter = createNanoEvents();
822
- const getRequestId = (eventSource) => {
823
- const requestId = eventSource._xhr?._rozeniteRequestId;
824
- if (!requestId) {
825
- return null;
826
- }
827
- return requestId;
828
- };
829
- return {
830
- enable: () => {
831
- SSEInterceptor.setOpenEventCallback((_, eventSource) => {
832
- const sseEventSource = eventSource;
833
- const requestId = getRequestId(sseEventSource);
834
- if (!requestId) {
835
- return;
836
- }
837
- const sseXhr = sseEventSource._xhr;
838
- const event = {
839
- type: "sse-open",
840
- requestId,
841
- timestamp: Date.now(),
842
- response: {
843
- url: sseXhr._url,
844
- status: sseXhr.status,
845
- statusText: sseXhr.statusText,
846
- headers: sseXhr.responseHeaders || {},
847
- contentType: getContentType(sseXhr),
848
- size: 0,
849
- responseTime: Date.now()
850
- }
851
- };
852
- eventEmitter.emit("sse-open", event);
853
- });
854
- SSEInterceptor.setMessageCallback((messageEvent, eventSource) => {
855
- const sseEventSource = eventSource;
856
- const requestId = getRequestId(sseEventSource);
857
- if (!requestId) {
858
- return;
859
- }
860
- const event = {
861
- type: "sse-message",
862
- requestId,
863
- timestamp: Date.now(),
864
- payload: {
865
- type: messageEvent.type,
866
- data: messageEvent.data || ""
867
- }
868
- };
869
- eventEmitter.emit("sse-message", event);
870
- });
871
- SSEInterceptor.setErrorCallback((errorEvent, eventSource) => {
872
- const sseEventSource = eventSource;
873
- const requestId = getRequestId(sseEventSource);
874
- if (!requestId) {
875
- return;
876
- }
877
- const event = {
878
- type: "sse-error",
879
- requestId,
880
- timestamp: Date.now(),
881
- error: {
882
- type: errorEvent.type,
883
- message: errorEvent.type === "timeout" ? "Timeout" : errorEvent.message
884
- }
885
- };
886
- eventEmitter.emit("sse-error", event);
887
- });
888
- SSEInterceptor.setCloseCallback((_, eventSource) => {
889
- const sseEventSource = eventSource;
890
- const requestId = getRequestId(sseEventSource);
891
- if (!requestId) {
892
- return;
893
- }
894
- const event = {
895
- type: "sse-close",
896
- requestId,
897
- timestamp: Date.now()
898
- };
899
- eventEmitter.emit("sse-close", event);
900
- });
901
- SSEInterceptor.enableInterception();
902
- },
903
- disable: () => {
904
- SSEInterceptor.disableInterception();
905
- },
906
- isEnabled: () => SSEInterceptor.isInterceptorEnabled(),
907
- dispose: () => {
908
- SSEInterceptor.disableInterception();
909
- },
910
- on: (event, callback) => eventEmitter.on(event, callback)
911
- };
912
- };
913
- const DEFAULT_CONFIG = {
914
- inspectors: {
915
- http: true,
916
- websocket: true,
917
- sse: true
918
- },
919
- clientUISettings: {
920
- showUrlAsName: false
921
- }
922
- };
923
- const validateConfig = (config) => {
924
- const inspectors = config.inspectors;
925
- if (!inspectors) {
926
- return;
927
- }
928
- if (inspectors.sse && !inspectors.http) {
929
- throw new Error("SSE inspector requires HTTP inspector to be enabled.");
930
- }
931
- };
932
- class EventsListener {
933
- constructor() {
934
- this.messageQueue = [];
935
- this.sendFunction = null;
936
- this.maxQueueSize = 200;
937
- this.isQueuing = false;
938
- }
939
- setMaxQueueSize(size) {
940
- this.maxQueueSize = size;
941
- }
942
- /**
943
- * Enable queuing mode to capture events before client is connected
944
- */
945
- enableQueuing() {
946
- this.isQueuing = true;
947
- }
948
- /**
949
- * Connect the actual send function and automatically flush queued messages
950
- */
951
- connect(sendFn, filterFn) {
952
- this.sendFunction = sendFn;
953
- this.isQueuing = false;
954
- this.flushQueue(filterFn);
955
- }
956
- isInQueueMode() {
957
- return this.isQueuing;
958
- }
959
- /**
960
- * Send a message (queued if not connected, sent directly if connected)
961
- */
962
- send(type, data) {
963
- if (this.isQueuing) {
964
- this.enqueueMessage({ type, data });
965
- } else if (this.sendFunction) {
966
- this.sendFunction(type, data);
967
- }
968
- }
969
- enqueueMessage(message) {
970
- if (this.messageQueue.length >= this.maxQueueSize) {
971
- this.messageQueue.shift();
972
- }
973
- this.messageQueue.push(message);
974
- }
975
- flushQueue(filterFn) {
976
- if (!this.sendFunction) {
977
- return;
978
- }
979
- while (this.messageQueue.length > 0) {
980
- const message = this.messageQueue.shift();
981
- if (message) {
982
- if (filterFn && !filterFn(message)) {
983
- continue;
984
- }
985
- this.sendFunction(message.type, message.data);
986
- }
987
- }
988
- }
989
- }
990
- const createEventsListener = () => {
991
- return new EventsListener();
992
- };
993
- const createNetworkInspectorInstance = () => {
994
- const http = getHTTPInspector();
995
- const sse = getSSEInspector();
996
- const websocket = getWebSocketInspector();
997
- return {
998
- http,
999
- sse,
1000
- websocket,
1001
- setup(eventsListener) {
1002
- HTTP_EVENTS.forEach((event) => {
1003
- http.on(event, (data) => {
1004
- eventsListener.send(event, data);
1005
- });
1006
- });
1007
- SSE_EVENTS.forEach((event) => {
1008
- sse.on(event, (data) => {
1009
- eventsListener.send(data.type, data);
1010
- });
1011
- });
1012
- WEBSOCKET_EVENTS.forEach((event) => {
1013
- websocket.on(event, (data) => {
1014
- eventsListener.send(data.type, data);
1015
- });
1016
- });
1017
- },
1018
- enable(config = { http: true, sse: true, websocket: true }) {
1019
- if (config.http) http.enable();
1020
- if (config.sse) sse.enable();
1021
- if (config.websocket) websocket.enable();
1022
- },
1023
- disable() {
1024
- http.disable();
1025
- sse.disable();
1026
- websocket.disable();
1027
- },
1028
- dispose() {
1029
- http.dispose();
1030
- sse.dispose();
1031
- websocket.dispose();
1032
- }
1033
- };
1034
- };
1035
- const getNetworkInspector = /* @__PURE__ */ (() => {
1036
- let instance = null;
1037
- return () => {
1038
- if (!instance) {
1039
- instance = createNetworkInspectorInstance();
1040
- }
1041
- return instance;
1042
- };
1043
- })();
1044
- let inspectorsConfig;
1045
- let bootRecordingEnabled = false;
1046
- const createNetworkInspectorsConfiguration = (options) => {
1047
- if (inspectorsConfig) {
1048
- return inspectorsConfig;
1049
- }
1050
- bootRecordingEnabled = options?.enableBootRecording ?? true;
1051
- const maxQueueSize = options?.maxQueueSize ?? 200;
1052
- const inspectors = {
1053
- http: true,
1054
- websocket: true,
1055
- sse: true,
1056
- ...options?.inspectors
1057
- };
1058
- validateConfig({ inspectors });
1059
- const eventsListener = createEventsListener();
1060
- eventsListener.setMaxQueueSize(maxQueueSize);
1061
- const networkInspector = getNetworkInspector();
1062
- networkInspector.setup(eventsListener);
1063
- if (bootRecordingEnabled) {
1064
- eventsListener.enableQueuing();
1065
- networkInspector.enable(inspectors);
1066
- }
1067
- inspectorsConfig = {
1068
- eventsListener,
1069
- networkInspector
1070
- };
1071
- return inspectorsConfig;
1072
- };
1073
- const withOnBootNetworkActivityRecording = (options) => {
1074
- createNetworkInspectorsConfiguration(options);
1075
- };
1
+ import { c, w } from "./boot-recording.js";
1076
2
  export {
1077
- DEFAULT_CONFIG as D,
1078
- getResponseBody as a,
1079
- isWebSocketEvent as b,
1080
- createNetworkInspectorsConfiguration as c,
1081
- isSSEEvent as d,
1082
- getOverridesRegistry as g,
1083
- isHttpEvent as i,
1084
- validateConfig as v,
1085
- withOnBootNetworkActivityRecording as w
3
+ c as createNetworkInspectorsConfiguration,
4
+ w as withOnBootNetworkActivityRecording
1086
5
  };