@buoy-gg/network 7.0.35 → 7.0.38
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.
- package/README.md +45 -12
- package/lib/commonjs/index.js +26 -1
- package/lib/commonjs/index.web.js +26 -1
- package/lib/commonjs/network/components/NetworkEventDetailView.js +6 -1
- package/lib/commonjs/network/components/NetworkHeaderMenu.js +4 -0
- package/lib/commonjs/network/components/NetworkModal.js +24 -8
- package/lib/commonjs/network/conditions/NetworkConditionsControl.js +235 -0
- package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +136 -0
- package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +33 -0
- package/lib/commonjs/network/conditions/NetworkFloatingTool.js +310 -0
- package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +219 -0
- package/lib/commonjs/network/conditions/store.js +75 -0
- package/lib/commonjs/network/conditions/wait.js +43 -0
- package/lib/commonjs/network/conditions/xhr.js +110 -0
- package/lib/commonjs/network/hooks/useNetworkEvents.js +1 -1
- package/lib/commonjs/network/overrides/applyToXhr.js +10 -8
- package/lib/commonjs/network/overrides/engine.js +2 -1
- package/lib/commonjs/network/sync/networkSyncAdapter.js +224 -3
- package/lib/commonjs/network/utils/generateNetworkCopyText.js +2 -0
- package/lib/commonjs/network/utils/networkEventStore.js +5 -77
- package/lib/commonjs/network/utils/networkListener.js +245 -46
- package/lib/commonjs/network/utils/networkSavedStore.js +2 -2
- package/lib/commonjs/network/utils/selectSavedEvents.js +2 -2
- package/lib/commonjs/preset.js +2 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.web.js +2 -1
- package/lib/module/network/components/NetworkEventDetailView.js +6 -1
- package/lib/module/network/components/NetworkHeaderMenu.js +4 -0
- package/lib/module/network/components/NetworkModal.js +25 -9
- package/lib/module/network/conditions/NetworkConditionsControl.js +231 -0
- package/lib/module/network/conditions/NetworkConditionsControl.test.js +135 -0
- package/lib/module/network/conditions/NetworkConditionsIcon.js +29 -0
- package/lib/module/network/conditions/NetworkFloatingTool.js +304 -0
- package/lib/module/network/conditions/NetworkFloatingTool.test.js +218 -0
- package/lib/module/network/conditions/store.js +65 -0
- package/lib/module/network/conditions/wait.js +38 -0
- package/lib/module/network/conditions/xhr.js +106 -0
- package/lib/module/network/hooks/useNetworkEvents.js +1 -1
- package/lib/module/network/overrides/applyToXhr.js +9 -8
- package/lib/module/network/overrides/engine.js +2 -1
- package/lib/module/network/sync/networkSyncAdapter.js +225 -3
- package/lib/module/network/utils/generateNetworkCopyText.js +2 -0
- package/lib/module/network/utils/networkEventStore.js +6 -77
- package/lib/module/network/utils/networkListener.js +246 -47
- package/lib/module/network/utils/networkSavedStore.js +2 -2
- package/lib/module/network/utils/selectSavedEvents.js +2 -2
- package/lib/module/preset.js +3 -2
- package/lib/typescript/index.d.ts +2 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +2 -0
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkHeaderMenu.d.ts +2 -1
- package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkModal.d.ts +3 -0
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts +12 -0
- package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts.map +1 -0
- package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts +2 -0
- package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts.map +1 -0
- package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts +4 -0
- package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts.map +1 -0
- package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts +15 -0
- package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts.map +1 -0
- package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts +2 -0
- package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts.map +1 -0
- package/lib/typescript/network/conditions/store.d.ts +30 -0
- package/lib/typescript/network/conditions/store.d.ts.map +1 -0
- package/lib/typescript/network/conditions/wait.d.ts +4 -0
- package/lib/typescript/network/conditions/wait.d.ts.map +1 -0
- package/lib/typescript/network/conditions/xhr.d.ts +5 -0
- package/lib/typescript/network/conditions/xhr.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useNetworkEvents.d.ts +1 -1
- package/lib/typescript/network/overrides/applyToXhr.d.ts +2 -0
- package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
- package/lib/typescript/network/overrides/engine.d.ts +0 -10
- package/lib/typescript/network/overrides/engine.d.ts.map +1 -1
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts +29 -0
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/network/types/index.d.ts +1 -0
- package/lib/typescript/network/types/index.d.ts.map +1 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkEventStore.d.ts +0 -15
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkListener.d.ts +13 -28
- package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkSavedStore.d.ts +2 -2
- package/lib/typescript/network/utils/selectSavedEvents.d.ts +2 -2
- package/lib/typescript/preset.d.ts +0 -16
- package/lib/typescript/preset.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { runConditionXhr } from "../conditions/xhr";
|
|
4
|
+
import { snapshotNetworkCondition } from "../conditions/store";
|
|
5
|
+
import { throwIfAborted, waitBeforeDispatch } from "../conditions/wait";
|
|
3
6
|
/**
|
|
4
7
|
* Network listener using Reactotron-style event pattern
|
|
5
8
|
* Simple and reliable network interception for React Native
|
|
@@ -7,7 +10,7 @@
|
|
|
7
10
|
|
|
8
11
|
import { overrideForRequest } from "../overrides/engine";
|
|
9
12
|
import { runOverride } from "../overrides/applyToXhr";
|
|
10
|
-
import { canSynthesizeResponse,
|
|
13
|
+
import { canSynthesizeResponse, synthesizeFetchError, synthesizeResponse } from "../overrides/applyToFetch";
|
|
11
14
|
import { markForOutcome } from "../overrides/types";
|
|
12
15
|
import { httpStatusText, xhrCompletionKind } from "./httpCompletion";
|
|
13
16
|
|
|
@@ -23,7 +26,7 @@ import { httpStatusText, xhrCompletionKind } from "./httpCompletion";
|
|
|
23
26
|
* executor, so a flag raised across the call expression alone is enough to
|
|
24
27
|
* cover the inner `send()` without leaking across the await.
|
|
25
28
|
*/
|
|
26
|
-
let
|
|
29
|
+
let insideFetchHandoff = false;
|
|
27
30
|
|
|
28
31
|
// Extended XMLHttpRequest interface for monkey-patching
|
|
29
32
|
|
|
@@ -68,17 +71,56 @@ export const BUOY_XHR_INTERCEPTOR_FLAG = "__buoyNetworkXhrIntercepted";
|
|
|
68
71
|
* @performance Uses lazy singleton pattern to minimize memory footprint
|
|
69
72
|
* @performance Includes URL filtering to ignore development traffic
|
|
70
73
|
*/
|
|
74
|
+
/**
|
|
75
|
+
* Hosts another Buoy package has claimed as its own traffic.
|
|
76
|
+
*
|
|
77
|
+
* A GLOBAL, not an import: `@buoy-gg/network` cannot depend on `agent-core`
|
|
78
|
+
* (Ask Buoy is optional and this package is older), and `agent-core` ships
|
|
79
|
+
* with no dependencies at all. `registerSelfEndpoint` in agent-core writes the
|
|
80
|
+
* set; this reads it. Absent, undefined or the wrong shape all mean "nothing
|
|
81
|
+
* to exclude", so nothing breaks in an app without Ask Buoy.
|
|
82
|
+
*
|
|
83
|
+
* WHY IT IS NOT ENOUGH TO FILTER LATER. The interceptor reads the response
|
|
84
|
+
* body — `await processResponseBody(response.clone())` — BEFORE handing the
|
|
85
|
+
* response back. On a streamed reply that resolves only at EOF, so an
|
|
86
|
+
* intercepted model endpoint delivers its whole answer at once and Ask Buoy
|
|
87
|
+
* cannot stream a word. Ignoring the URL is what keeps the socket the
|
|
88
|
+
* caller's. It also keeps override rules off model traffic, which a broad
|
|
89
|
+
* user-authored rule would otherwise rewrite.
|
|
90
|
+
*/
|
|
91
|
+
/**
|
|
92
|
+
* Content types whose body arrives over time rather than all at once.
|
|
93
|
+
*
|
|
94
|
+
* These are the ones where reading the clone before returning the response
|
|
95
|
+
* changes the CALLER's behaviour instead of merely observing it.
|
|
96
|
+
*/
|
|
97
|
+
const STREAMED_CONTENT_TYPES = ["text/event-stream", "application/x-ndjson", "application/stream+json"];
|
|
98
|
+
const STREAMING_PLACEHOLDER = "[streaming\u2026]";
|
|
99
|
+
function isStreamedContentType(contentType) {
|
|
100
|
+
if (!contentType) return false;
|
|
101
|
+
const lower = contentType.toLowerCase();
|
|
102
|
+
return STREAMED_CONTENT_TYPES.some(t => lower.includes(t));
|
|
103
|
+
}
|
|
104
|
+
const INTERNAL_HOSTS_KEY = "__BUOY_INTERNAL_HOSTS__";
|
|
105
|
+
function isInternalBuoyHost(url) {
|
|
106
|
+
const hosts = globalThis[INTERNAL_HOSTS_KEY];
|
|
107
|
+
if (!(hosts instanceof Set) || hosts.size === 0) return false;
|
|
108
|
+
let authority;
|
|
109
|
+
try {
|
|
110
|
+
authority = new URL(url).host.toLowerCase();
|
|
111
|
+
} catch {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
for (const host of hosts) {
|
|
115
|
+
if (typeof host === "string" && host && authority === host.toLowerCase()) return true;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
71
119
|
class NetworkListener {
|
|
72
120
|
listeners = [];
|
|
73
121
|
isListening = false;
|
|
74
122
|
requestCounter = 1000;
|
|
75
123
|
|
|
76
|
-
// URLs to ignore (Metro bundler, symbolicate, etc.)
|
|
77
|
-
ignoredUrls = [/\/symbolicate$/, /\/logs$/, /\/debugger-proxy/, /\/reload$/, /\/launch-js-devtools/, /localhost:8081/, /100\.64\.\d+\.\d+:8081/,
|
|
78
|
-
// iOS simulator
|
|
79
|
-
/10\.0\.\d+\.\d+:8081/ // Android emulator
|
|
80
|
-
];
|
|
81
|
-
|
|
82
124
|
// Store original methods
|
|
83
125
|
|
|
84
126
|
/**
|
|
@@ -102,7 +144,7 @@ class NetworkListener {
|
|
|
102
144
|
xhrGeneration = 0;
|
|
103
145
|
constructor() {
|
|
104
146
|
// Store original methods
|
|
105
|
-
this.originalFetch = globalThis.fetch
|
|
147
|
+
this.originalFetch = globalThis.fetch;
|
|
106
148
|
this.originalXHROpen = XMLHttpRequest.prototype.open;
|
|
107
149
|
this.originalXHRSend = XMLHttpRequest.prototype.send;
|
|
108
150
|
this.originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
|
|
@@ -118,7 +160,15 @@ class NetworkListener {
|
|
|
118
160
|
* @returns True if the URL should be ignored
|
|
119
161
|
*/
|
|
120
162
|
shouldIgnoreUrl(url) {
|
|
121
|
-
|
|
163
|
+
try {
|
|
164
|
+
const parsed = new URL(url);
|
|
165
|
+
if (parsed.hostname === "keygen.sh" || parsed.hostname.endsWith(".keygen.sh")) return true;
|
|
166
|
+
const local = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "10.0.2.2";
|
|
167
|
+
if (local && ["8081", "8802"].includes(parsed.port)) return true;
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return isInternalBuoyHost(url);
|
|
122
172
|
}
|
|
123
173
|
|
|
124
174
|
// Emit event to all listeners
|
|
@@ -164,6 +214,70 @@ class NetworkListener {
|
|
|
164
214
|
* @param maxSize - Maximum body size in bytes (default: 1MB)
|
|
165
215
|
* @returns Object containing body, size, and truncation status
|
|
166
216
|
*/
|
|
217
|
+
/**
|
|
218
|
+
* Read a streamed body in the background, with a hard ceiling.
|
|
219
|
+
*
|
|
220
|
+
* Deliberately not `processResponseBody`: that one calls `.text()`, which
|
|
221
|
+
* accumulates the WHOLE body before it checks the size, so a long-lived SSE
|
|
222
|
+
* stream would grow unbounded in memory with nothing to stop it. This stops
|
|
223
|
+
* at the cap and cancels the reader, and a runtime with no `body` (React
|
|
224
|
+
* Native's own fetch) falls back to `.text()` — that response was never
|
|
225
|
+
* streaming there in the first place.
|
|
226
|
+
*/
|
|
227
|
+
async readStreamedBody(response, maxSize = 256 * 1024) {
|
|
228
|
+
const body = response.body;
|
|
229
|
+
if (!body || typeof body.getReader !== "function") {
|
|
230
|
+
const text = await response.text();
|
|
231
|
+
return text.length > maxSize ? {
|
|
232
|
+
body: `${text.slice(0, maxSize)}\n\n... [truncated]`,
|
|
233
|
+
size: text.length
|
|
234
|
+
} : {
|
|
235
|
+
body: text,
|
|
236
|
+
size: text.length
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const reader = body.getReader();
|
|
240
|
+
const decoder = new TextDecoder();
|
|
241
|
+
let out = "";
|
|
242
|
+
let size = 0;
|
|
243
|
+
let capped = false;
|
|
244
|
+
try {
|
|
245
|
+
for (;;) {
|
|
246
|
+
const {
|
|
247
|
+
done,
|
|
248
|
+
value
|
|
249
|
+
} = await reader.read();
|
|
250
|
+
if (done) break;
|
|
251
|
+
size += value?.byteLength ?? 0;
|
|
252
|
+
if (!capped) {
|
|
253
|
+
out += decoder.decode(value, {
|
|
254
|
+
stream: true
|
|
255
|
+
});
|
|
256
|
+
if (size >= maxSize) {
|
|
257
|
+
out = `${out.slice(0, maxSize)}\n\n... [truncated]`;
|
|
258
|
+
capped = true;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!capped) out += decoder.decode();
|
|
264
|
+
} finally {
|
|
265
|
+
try {
|
|
266
|
+
void Promise.resolve(reader.cancel()).catch(() => {});
|
|
267
|
+
} catch {
|
|
268
|
+
/* already gone */
|
|
269
|
+
}
|
|
270
|
+
try {
|
|
271
|
+
reader.releaseLock();
|
|
272
|
+
} catch {
|
|
273
|
+
/* already released */
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
body: out,
|
|
278
|
+
size
|
|
279
|
+
};
|
|
280
|
+
}
|
|
167
281
|
async processResponseBody(response, maxSize = 1024 * 1024 // 1MB default
|
|
168
282
|
) {
|
|
169
283
|
try {
|
|
@@ -236,14 +350,14 @@ class NetworkListener {
|
|
|
236
350
|
* Handle XMLHttpRequest response processing
|
|
237
351
|
* This method processes the response and emits appropriate events
|
|
238
352
|
*/
|
|
239
|
-
handleXHRResponse(xhr, requestId, cleanUrl, method, requestHeaders, requestData, params, startTime, isError = false, clientType = "xhr", override) {
|
|
353
|
+
handleXHRResponse(xhr, requestId, cleanUrl, method, requestHeaders, requestData, params, startTime, isError = false, clientType = "xhr", override, condition) {
|
|
240
354
|
const duration = startTime ? Date.now() - startTime : 0;
|
|
241
355
|
|
|
242
356
|
// XHR's duration was ALREADY total (measured at readyState 4 / load), so
|
|
243
|
-
// only the split is new. `
|
|
357
|
+
// only the split is new. `_buoyTtfb` is stamped at HEADERS_RECEIVED; it is
|
|
244
358
|
// absent for a request that failed before any headers arrived, and the
|
|
245
359
|
// breakdown is then correctly omitted rather than faked as 0.
|
|
246
|
-
const ttfb = xhr.
|
|
360
|
+
const ttfb = xhr._buoyTtfb;
|
|
247
361
|
const timings = ttfb === undefined ? undefined : {
|
|
248
362
|
ttfb,
|
|
249
363
|
download: Math.max(0, duration - ttfb)
|
|
@@ -266,7 +380,8 @@ class NetworkListener {
|
|
|
266
380
|
error: {
|
|
267
381
|
message: isError ? "Request failed" : "Network error or request aborted"
|
|
268
382
|
},
|
|
269
|
-
override
|
|
383
|
+
override,
|
|
384
|
+
condition
|
|
270
385
|
});
|
|
271
386
|
return;
|
|
272
387
|
}
|
|
@@ -408,7 +523,8 @@ class NetworkListener {
|
|
|
408
523
|
body,
|
|
409
524
|
size: responseSize
|
|
410
525
|
},
|
|
411
|
-
override
|
|
526
|
+
override,
|
|
527
|
+
condition
|
|
412
528
|
});
|
|
413
529
|
} else {
|
|
414
530
|
this.emit({
|
|
@@ -434,7 +550,8 @@ class NetworkListener {
|
|
|
434
550
|
error: {
|
|
435
551
|
message: "Network Error"
|
|
436
552
|
},
|
|
437
|
-
override
|
|
553
|
+
override,
|
|
554
|
+
condition
|
|
438
555
|
});
|
|
439
556
|
}
|
|
440
557
|
}
|
|
@@ -500,7 +617,7 @@ class NetworkListener {
|
|
|
500
617
|
// re-installing after a clobber must call through the replacement, and a
|
|
501
618
|
// stale generation must replay the chain exactly as it stood beneath it.
|
|
502
619
|
const passthroughFetch = globalThis.fetch.bind(globalThis);
|
|
503
|
-
this.originalFetch =
|
|
620
|
+
this.originalFetch = globalThis.fetch;
|
|
504
621
|
const generation = ++this.fetchGeneration;
|
|
505
622
|
const wrappedFetch = async (input, init) => {
|
|
506
623
|
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
|
|
@@ -518,7 +635,11 @@ class NetworkListener {
|
|
|
518
635
|
}
|
|
519
636
|
const startTime = Date.now();
|
|
520
637
|
const requestId = `fetch_${++self.requestCounter}`;
|
|
521
|
-
const
|
|
638
|
+
const inputRequest = typeof input === "object" && "method" in input ? input : undefined;
|
|
639
|
+
const method = init?.method ?? inputRequest?.method ?? "GET";
|
|
640
|
+
const signal = init?.signal !== undefined ? init.signal : inputRequest?.signal;
|
|
641
|
+
throwIfAborted(signal);
|
|
642
|
+
const condition = snapshotNetworkCondition(url);
|
|
522
643
|
const {
|
|
523
644
|
url: cleanUrl,
|
|
524
645
|
params
|
|
@@ -526,21 +647,24 @@ class NetworkListener {
|
|
|
526
647
|
|
|
527
648
|
// Parse request headers
|
|
528
649
|
let requestHeaders = {};
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
650
|
+
const headers = init?.headers ?? inputRequest?.headers;
|
|
651
|
+
if (headers) {
|
|
652
|
+
if (headers instanceof Headers) {
|
|
653
|
+
headers.forEach((value, key) => {
|
|
532
654
|
requestHeaders[key] = value;
|
|
533
655
|
});
|
|
534
|
-
} else if (Array.isArray(
|
|
535
|
-
|
|
656
|
+
} else if (Array.isArray(headers)) {
|
|
657
|
+
headers.forEach(([key, value]) => {
|
|
536
658
|
requestHeaders[key] = value;
|
|
537
659
|
});
|
|
538
660
|
} else {
|
|
539
|
-
requestHeaders =
|
|
661
|
+
requestHeaders = headers;
|
|
540
662
|
}
|
|
541
663
|
}
|
|
542
664
|
|
|
543
665
|
// Parse request body
|
|
666
|
+
// Explicitly typed: the late emit for a streamed reply reads this from
|
|
667
|
+
// inside a callback, which defeats the inference it used to rely on.
|
|
544
668
|
let requestData;
|
|
545
669
|
if (init?.body) {
|
|
546
670
|
if (typeof init.body === "string") {
|
|
@@ -566,7 +690,7 @@ class NetworkListener {
|
|
|
566
690
|
* Skipped when `canSynthesizeResponse()` is false so a runtime without a
|
|
567
691
|
* `Response` global degrades to a real request rather than a broken one.
|
|
568
692
|
*/
|
|
569
|
-
const outcome = canSynthesizeResponse() ? overrideForRequest(url, method) : null;
|
|
693
|
+
const outcome = condition?.profile !== "offline" && canSynthesizeResponse() ? overrideForRequest(url, method) : null;
|
|
570
694
|
const override = outcome ? markForOutcome(outcome) : undefined;
|
|
571
695
|
|
|
572
696
|
// Emit request event
|
|
@@ -582,24 +706,28 @@ class NetworkListener {
|
|
|
582
706
|
params: params || undefined,
|
|
583
707
|
client: clientType
|
|
584
708
|
},
|
|
585
|
-
override
|
|
709
|
+
override,
|
|
710
|
+
condition
|
|
586
711
|
});
|
|
587
712
|
try {
|
|
588
|
-
if (outcome) await
|
|
713
|
+
if (condition || outcome) await waitBeforeDispatch((condition?.delayMs ?? 0) + (outcome?.delayMs ?? 0), signal);
|
|
714
|
+
throwIfAborted(signal);
|
|
715
|
+
if (condition?.profile === "offline") throw new TypeError("Network request failed (Buoy Offline)");
|
|
589
716
|
if (outcome?.kind === "fail") throw synthesizeFetchError(outcome);
|
|
590
717
|
let response;
|
|
591
718
|
if (outcome?.kind === "respond") {
|
|
592
719
|
response = synthesizeResponse(url, outcome);
|
|
593
720
|
} else {
|
|
594
|
-
// The flag spans the CALL only — see `
|
|
721
|
+
// The flag spans the CALL only — see `insideFetchHandoff`. It has
|
|
595
722
|
// to be cleared before the await, or it would still be raised for
|
|
596
723
|
// every unrelated request that starts while this one is in flight.
|
|
597
|
-
|
|
724
|
+
const previousFetchHandoff = insideFetchHandoff;
|
|
725
|
+
insideFetchHandoff = true;
|
|
598
726
|
let pending;
|
|
599
727
|
try {
|
|
600
728
|
pending = passthroughFetch(input, init);
|
|
601
729
|
} finally {
|
|
602
|
-
|
|
730
|
+
insideFetchHandoff = previousFetchHandoff;
|
|
603
731
|
}
|
|
604
732
|
response = await pending;
|
|
605
733
|
}
|
|
@@ -609,12 +737,29 @@ class NetworkListener {
|
|
|
609
737
|
// look faster through fetch than through XHR.
|
|
610
738
|
const ttfb = Date.now() - startTime;
|
|
611
739
|
|
|
740
|
+
/**
|
|
741
|
+
* A STREAMED reply is never awaited here.
|
|
742
|
+
*
|
|
743
|
+
* `processResponseBody` reads the clone to the end, and for
|
|
744
|
+
* `text/event-stream` the end is when the server finishes — seconds
|
|
745
|
+
* later, for an LLM. Awaiting it made the interceptor hold the
|
|
746
|
+
* response back until then, so every consumer of a streaming endpoint
|
|
747
|
+
* inside an app with capture on received the whole thing at once and
|
|
748
|
+
* could not stream a word of it. The row is emitted now with what is
|
|
749
|
+
* known, and the body is filled in when the stream closes: the store
|
|
750
|
+
* merges a second `response` event onto the same request id.
|
|
751
|
+
*/
|
|
752
|
+
const streamed = typeof response.body?.getReader === "function" || isStreamedContentType(response.headers?.get?.("content-type"));
|
|
753
|
+
|
|
612
754
|
// Clone response to read body with size limits
|
|
613
755
|
const responseClone = response.clone();
|
|
614
756
|
const {
|
|
615
757
|
body,
|
|
616
758
|
size: responseSize
|
|
617
|
-
} =
|
|
759
|
+
} = streamed ? {
|
|
760
|
+
body: STREAMING_PLACEHOLDER,
|
|
761
|
+
size: 0
|
|
762
|
+
} : await self.processResponseBody(responseClone);
|
|
618
763
|
|
|
619
764
|
// Now the body is in — this is the comparable, total number.
|
|
620
765
|
const duration = Date.now() - startTime;
|
|
@@ -671,8 +816,46 @@ class NetworkListener {
|
|
|
671
816
|
body,
|
|
672
817
|
size: responseSize
|
|
673
818
|
},
|
|
674
|
-
override
|
|
819
|
+
override,
|
|
820
|
+
condition
|
|
675
821
|
});
|
|
822
|
+
if (streamed) {
|
|
823
|
+
// Bounded, cancelled at the cap, and never awaited by the caller.
|
|
824
|
+
void self.readStreamedBody(responseClone).then(late => {
|
|
825
|
+
let capturedBody = late.body;
|
|
826
|
+
if (response.headers?.get?.("content-type")?.includes("json")) {
|
|
827
|
+
try {
|
|
828
|
+
capturedBody = JSON.parse(late.body);
|
|
829
|
+
} catch {/* Partial or malformed JSON stays text. */}
|
|
830
|
+
}
|
|
831
|
+
self.emit({
|
|
832
|
+
type: "response",
|
|
833
|
+
timestamp: new Date(),
|
|
834
|
+
duration: Date.now() - startTime,
|
|
835
|
+
timings,
|
|
836
|
+
request: {
|
|
837
|
+
id: requestId || "unknown",
|
|
838
|
+
url: cleanUrl,
|
|
839
|
+
method,
|
|
840
|
+
headers: requestHeaders,
|
|
841
|
+
data: requestData,
|
|
842
|
+
params: params || undefined,
|
|
843
|
+
client: clientType
|
|
844
|
+
},
|
|
845
|
+
response: {
|
|
846
|
+
status: response.status,
|
|
847
|
+
statusText: response.statusText,
|
|
848
|
+
headers: responseHeaders,
|
|
849
|
+
body: capturedBody,
|
|
850
|
+
size: late.size
|
|
851
|
+
},
|
|
852
|
+
override,
|
|
853
|
+
condition
|
|
854
|
+
});
|
|
855
|
+
}).catch(() => {
|
|
856
|
+
/* the caller's response is unaffected either way */
|
|
857
|
+
});
|
|
858
|
+
}
|
|
676
859
|
return response;
|
|
677
860
|
} catch (error) {
|
|
678
861
|
const duration = Date.now() - startTime;
|
|
@@ -695,7 +878,8 @@ class NetworkListener {
|
|
|
695
878
|
message: error instanceof Error ? error.message : "Network error",
|
|
696
879
|
stack: error instanceof Error ? error.stack : undefined
|
|
697
880
|
},
|
|
698
|
-
override
|
|
881
|
+
override,
|
|
882
|
+
condition
|
|
699
883
|
});
|
|
700
884
|
throw error;
|
|
701
885
|
}
|
|
@@ -716,18 +900,20 @@ class NetworkListener {
|
|
|
716
900
|
this.originalXHRSend = passthroughSend;
|
|
717
901
|
this.originalXHRSetRequestHeader = passthroughSetRequestHeader;
|
|
718
902
|
const generation = ++this.xhrGeneration;
|
|
903
|
+
const pendingCapture = new WeakMap();
|
|
719
904
|
const patchedOpen = function (method, url, async, user, password) {
|
|
720
|
-
//
|
|
721
|
-
|
|
905
|
+
// Native validation runs before replacing metadata or capture listeners.
|
|
906
|
+
const result = passthroughOpen.call(this, method, url, async ?? true, user, password);
|
|
722
907
|
if (generation === self.xhrGeneration) {
|
|
908
|
+
pendingCapture.get(this)?.();
|
|
723
909
|
const xhr = this;
|
|
724
|
-
xhr.
|
|
910
|
+
xhr._buoyRequestId = `xhr_${++self.requestCounter}`;
|
|
725
911
|
xhr._method = method;
|
|
726
912
|
xhr._url = url;
|
|
727
|
-
xhr.
|
|
913
|
+
xhr._buoyStartTime = Date.now();
|
|
728
914
|
xhr._requestHeaders = {};
|
|
729
915
|
}
|
|
730
|
-
return
|
|
916
|
+
return result;
|
|
731
917
|
};
|
|
732
918
|
|
|
733
919
|
// Track request headers
|
|
@@ -742,14 +928,19 @@ class NetworkListener {
|
|
|
742
928
|
// @ts-ignore - this does exist on native
|
|
743
929
|
data) {
|
|
744
930
|
// Superseded generation: silent pass-through (see the fetch wrapper).
|
|
745
|
-
if (generation !== self.xhrGeneration) {
|
|
931
|
+
if (generation !== self.xhrGeneration || insideFetchHandoff) {
|
|
932
|
+
return passthroughSend.call(this, data);
|
|
933
|
+
}
|
|
934
|
+
if (this.readyState !== 1 || this._sent) {
|
|
746
935
|
return passthroughSend.call(this, data);
|
|
747
936
|
}
|
|
748
937
|
const xhr = this;
|
|
749
|
-
const requestId = xhr.
|
|
938
|
+
const requestId = xhr._buoyRequestId;
|
|
750
939
|
const method = xhr._method || "GET";
|
|
751
940
|
const url = xhr._url || "";
|
|
752
|
-
const startTime =
|
|
941
|
+
const startTime = Date.now();
|
|
942
|
+
xhr._buoyStartTime = startTime;
|
|
943
|
+
xhr._buoyTtfb = undefined;
|
|
753
944
|
const requestHeaders = xhr._requestHeaders || {};
|
|
754
945
|
|
|
755
946
|
// Skip ignored URLs
|
|
@@ -789,14 +980,15 @@ class NetworkListener {
|
|
|
789
980
|
* This is the layer that covers `axios` and raw XMLHttpRequest. It also
|
|
790
981
|
* covers `fetch` on BARE React Native, where the whatwg-fetch polyfill
|
|
791
982
|
* runs through XHR — which is why the fetch wrapper raises
|
|
792
|
-
* `
|
|
983
|
+
* `insideFetchHandoff` around its pass-through, so one request can't
|
|
793
984
|
* be overridden twice.
|
|
794
985
|
*
|
|
795
986
|
* Matching uses the raw `url` (query string included), which is what the
|
|
796
987
|
* developer sees in the list and writes into a rule. No-ops in production
|
|
797
988
|
* builds; see `overrideForRequest`.
|
|
798
989
|
*/
|
|
799
|
-
const
|
|
990
|
+
const condition = snapshotNetworkCondition(url);
|
|
991
|
+
const outcome = condition?.profile === "offline" ? null : overrideForRequest(url, method);
|
|
800
992
|
const override = outcome ? markForOutcome(outcome) : undefined;
|
|
801
993
|
|
|
802
994
|
// Emit request event
|
|
@@ -812,7 +1004,8 @@ class NetworkListener {
|
|
|
812
1004
|
params: params || undefined,
|
|
813
1005
|
client: clientType
|
|
814
1006
|
},
|
|
815
|
-
override
|
|
1007
|
+
override,
|
|
1008
|
+
condition
|
|
816
1009
|
});
|
|
817
1010
|
|
|
818
1011
|
// Track if we've already processed this request to avoid duplicate events
|
|
@@ -820,18 +1013,20 @@ class NetworkListener {
|
|
|
820
1013
|
const processResponse = (isError = false) => {
|
|
821
1014
|
if (processed) return;
|
|
822
1015
|
processed = true;
|
|
823
|
-
self.handleXHRResponse(this, requestId || "unknown", cleanUrl, method, requestHeaders, requestData, params, startTime || 0, isError, clientType, override);
|
|
1016
|
+
self.handleXHRResponse(this, requestId || "unknown", cleanUrl, method, requestHeaders, requestData, params, startTime || 0, isError, clientType, override, condition);
|
|
824
1017
|
// Clean up event listeners after processing to prevent memory leaks
|
|
825
1018
|
cleanup();
|
|
826
1019
|
};
|
|
827
1020
|
|
|
828
1021
|
// Cleanup function to remove event listeners
|
|
829
1022
|
const cleanup = () => {
|
|
1023
|
+
pendingCapture.delete(this);
|
|
830
1024
|
this.removeEventListener("load", loadListener);
|
|
831
1025
|
this.removeEventListener("error", errorListener);
|
|
832
1026
|
this.removeEventListener("abort", abortListener);
|
|
833
1027
|
this.removeEventListener("readystatechange", readyStateListener);
|
|
834
1028
|
};
|
|
1029
|
+
pendingCapture.set(this, cleanup);
|
|
835
1030
|
|
|
836
1031
|
// Use addEventListener to listen to events WITHOUT replacing user handlers
|
|
837
1032
|
// This is critical because React Native's XMLHttpRequest uses EventTarget
|
|
@@ -853,8 +1048,8 @@ class NetworkListener {
|
|
|
853
1048
|
// TTFB here costs one comparison and one clock read.
|
|
854
1049
|
if (this.readyState === 2) {
|
|
855
1050
|
const xhr = this;
|
|
856
|
-
if (xhr.
|
|
857
|
-
xhr.
|
|
1051
|
+
if (xhr._buoyTtfb === undefined && xhr._buoyStartTime) {
|
|
1052
|
+
xhr._buoyTtfb = Date.now() - xhr._buoyStartTime;
|
|
858
1053
|
}
|
|
859
1054
|
}
|
|
860
1055
|
if (this.readyState === 4 && !processed) {
|
|
@@ -867,6 +1062,10 @@ class NetworkListener {
|
|
|
867
1062
|
this.addEventListener("error", errorListener);
|
|
868
1063
|
this.addEventListener("abort", abortListener);
|
|
869
1064
|
this.addEventListener("readystatechange", readyStateListener);
|
|
1065
|
+
if (condition) {
|
|
1066
|
+
runConditionXhr(this, url, condition, outcome, () => passthroughSend.call(this, data));
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
870
1069
|
if (outcome) {
|
|
871
1070
|
// Listeners are attached above FIRST: `runOverride` drives the same
|
|
872
1071
|
// readyState transitions a real response would, and the interceptor has
|
|
@@ -39,8 +39,8 @@ export const MAX_PINNED = 25;
|
|
|
39
39
|
export const MAX_SAVED = 50;
|
|
40
40
|
/**
|
|
41
41
|
* @deprecated Read the live limit with `useLimit("network.saved")` — this only
|
|
42
|
-
* reports the FREE tier's value and
|
|
43
|
-
*
|
|
42
|
+
* reports the FREE tier's value and ignores the Weekend Pass. Kept because it
|
|
43
|
+
* is part of the package's public exports.
|
|
44
44
|
*/
|
|
45
45
|
export const FREE_TIER_SAVED_LIMIT = TIER_LIMITS["network.saved"].free;
|
|
46
46
|
/** Per-body cap on a snapshot. */
|
|
@@ -15,8 +15,8 @@ import { MAX_SAVED } from "./networkSavedStore";
|
|
|
15
15
|
export function selectSavedEvents(savedRecords,
|
|
16
16
|
/**
|
|
17
17
|
* How many saves this tier may see — `useLimit("network.saved")`. Takes a
|
|
18
|
-
* number rather than `isPro` because
|
|
19
|
-
* boolean cannot express
|
|
18
|
+
* number rather than `isPro` because Pro's cap is 50, not unlimited, and a
|
|
19
|
+
* boolean cannot express that.
|
|
20
20
|
*/
|
|
21
21
|
limit, search) {
|
|
22
22
|
/**
|
package/lib/module/preset.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { NetworkConditionsIcon } from "./network/conditions/NetworkConditionsIcon";
|
|
3
4
|
/**
|
|
4
5
|
* Pre-configured network monitoring tool for FloatingDevTools
|
|
5
6
|
*
|
|
@@ -17,7 +18,7 @@
|
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
|
-
import {
|
|
21
|
+
import { createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
|
|
21
22
|
import { NetworkModal } from "./network/components/NetworkModal";
|
|
22
23
|
import { overrideRulesStore } from "./network/overrides/overrideRulesStore";
|
|
23
24
|
import { networkEventStore } from "./network/utils/networkEventStore";
|
|
@@ -70,7 +71,7 @@ export const networkToolPreset = defineToolPreset({
|
|
|
70
71
|
slot: "both",
|
|
71
72
|
icon: ({
|
|
72
73
|
size
|
|
73
|
-
}) => /*#__PURE__*/_jsx(
|
|
74
|
+
}) => /*#__PURE__*/_jsx(NetworkConditionsIcon, {
|
|
74
75
|
size: size
|
|
75
76
|
}),
|
|
76
77
|
component: NetworkModal,
|
|
@@ -45,4 +45,6 @@ export { networkSavedStore, flagsForEventId, FREE_TIER_SAVED_LIMIT, MAX_PINNED,
|
|
|
45
45
|
export { generateCurl } from "./network/utils/generateCurl";
|
|
46
46
|
/** @internal */
|
|
47
47
|
export { networkListener, addNetworkListener, removeAllNetworkListeners, } from "./network/utils/networkListener";
|
|
48
|
+
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions } from "./network/conditions/store";
|
|
49
|
+
export type { NetworkConditionProfile, NetworkConditionStamp } from "./network/conditions/store";
|
|
48
50
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAOhE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAClF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAKhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAI9E,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAIhF,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,qBAAqB,GAC3B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAKtF,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAKpC,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB;AACtB;;;GAGG;AACH,KAAK,mBAAmB,GACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,SAAS,IAAI,kBAAkB,EAC/B,oBAAoB,IAAI,wBAAwB,EAChD,UAAU,IAAI,mBAAmB,EACjC,UAAU,IAAI,mBAAmB,EACjC,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC;AAQnC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,oCAAoC,CAAC;AAO5C,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE;;;GAGG;AACH,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAOhE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AAClF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6CAA6C,CAAC;AACrF,OAAO,EAAE,uBAAuB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,wCAAwC,CAAC;AAKhD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAIpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAI9E,OAAO,EACL,eAAe,EACf,KAAK,qBAAqB,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAIhF,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,qBAAqB,GAC3B,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAKtF,OAAO,EACL,WAAW,EACX,cAAc,EACd,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAKpC,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,uBAAuB,GACxB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,EACL,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB;AACtB;;;GAGG;AACH,KAAK,mBAAmB,GACzB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EACL,SAAS,IAAI,kBAAkB,EAC/B,oBAAoB,IAAI,wBAAwB,EAChD,UAAU,IAAI,mBAAmB,EACjC,UAAU,IAAI,mBAAmB,EACjC,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC;AAQnC,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,YAAY,GACb,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EACL,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,oCAAoC,CAAC;AAO5C,gBAAgB;AAChB,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE;;;GAGG;AACH,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,SAAS,EACT,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,gBAAgB;AAChB,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACtI,YAAY,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -53,4 +53,6 @@ export { filterNetworkEvents, applyIgnoredPatterns, } from "./network/utils/filt
|
|
|
53
53
|
export { splitPinned, type PinnedSplit } from "./network/utils/withPinnedFirst";
|
|
54
54
|
export { extractOperationName } from "./network/utils/extractOperationName";
|
|
55
55
|
export { generateCurl } from "./network/utils/generateCurl";
|
|
56
|
+
export { NETWORK_CONDITIONS, getNetworkCondition, setNetworkCondition, subscribeNetworkConditions } from "./network/conditions/store";
|
|
57
|
+
export type { NetworkConditionProfile, NetworkConditionStamp } from "./network/conditions/store";
|
|
56
58
|
//# sourceMappingURL=index.web.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../src/index.web.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../src/index.web.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkEventDetailView.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkEventDetailView.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,UAAU,CAAC;AA0B7D,UAAU,2BAA2B;IACnC,KAAK,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAkRD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"NetworkEventDetailView.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkEventDetailView.tsx"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,UAAU,CAAC;AA0B7D,UAAU,2BAA2B;IACnC,KAAK,EAAE,YAAY,CAAC;IACpB,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAkRD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,sBAAsB,mEAqiBjC,CAAC"}
|
|
@@ -36,11 +36,12 @@ export interface NetworkHeaderMenuProps {
|
|
|
36
36
|
* from the ⋯ should appear.
|
|
37
37
|
*/
|
|
38
38
|
export declare function NetworkHeaderMenu({ onClose, children }: NetworkHeaderMenuProps): import("react").JSX.Element;
|
|
39
|
-
export declare function NetworkHeaderMenuItem({ icon, label, detail, onPress, }: {
|
|
39
|
+
export declare function NetworkHeaderMenuItem({ icon, label, detail, testID, onPress, }: {
|
|
40
40
|
icon: ReactNode;
|
|
41
41
|
label: string;
|
|
42
42
|
/** Right-aligned state, e.g. the active filter count. */
|
|
43
43
|
detail?: string;
|
|
44
|
+
testID?: string;
|
|
44
45
|
onPress: () => void;
|
|
45
46
|
}): import("react").JSX.Element;
|
|
46
47
|
//# sourceMappingURL=NetworkHeaderMenu.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NetworkHeaderMenu.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkHeaderMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,MAAM,EACN,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,+BAoBA;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,sBAAsB,+BAY9E;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,KAAK,EACL,MAAM,EACN,OAAO,GACR,EAAE;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+
|
|
1
|
+
{"version":3,"file":"NetworkHeaderMenu.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkHeaderMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,MAAM,EACN,YAAY,GACb,EAAE;IACD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gEAAgE;IAChE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,+BAoBA;AAED,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,sBAAsB,+BAY9E;AAED,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,KAAK,EACL,MAAM,EACN,MAAM,EACN,OAAO,GACR,EAAE;IACD,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,+BAeA"}
|