@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.
Files changed (91) hide show
  1. package/README.md +45 -12
  2. package/lib/commonjs/index.js +26 -1
  3. package/lib/commonjs/index.web.js +26 -1
  4. package/lib/commonjs/network/components/NetworkEventDetailView.js +6 -1
  5. package/lib/commonjs/network/components/NetworkHeaderMenu.js +4 -0
  6. package/lib/commonjs/network/components/NetworkModal.js +24 -8
  7. package/lib/commonjs/network/conditions/NetworkConditionsControl.js +235 -0
  8. package/lib/commonjs/network/conditions/NetworkConditionsControl.test.js +136 -0
  9. package/lib/commonjs/network/conditions/NetworkConditionsIcon.js +33 -0
  10. package/lib/commonjs/network/conditions/NetworkFloatingTool.js +310 -0
  11. package/lib/commonjs/network/conditions/NetworkFloatingTool.test.js +219 -0
  12. package/lib/commonjs/network/conditions/store.js +75 -0
  13. package/lib/commonjs/network/conditions/wait.js +43 -0
  14. package/lib/commonjs/network/conditions/xhr.js +110 -0
  15. package/lib/commonjs/network/hooks/useNetworkEvents.js +1 -1
  16. package/lib/commonjs/network/overrides/applyToXhr.js +10 -8
  17. package/lib/commonjs/network/overrides/engine.js +2 -1
  18. package/lib/commonjs/network/sync/networkSyncAdapter.js +224 -3
  19. package/lib/commonjs/network/utils/generateNetworkCopyText.js +2 -0
  20. package/lib/commonjs/network/utils/networkEventStore.js +5 -77
  21. package/lib/commonjs/network/utils/networkListener.js +245 -46
  22. package/lib/commonjs/network/utils/networkSavedStore.js +2 -2
  23. package/lib/commonjs/network/utils/selectSavedEvents.js +2 -2
  24. package/lib/commonjs/preset.js +2 -1
  25. package/lib/module/index.js +2 -1
  26. package/lib/module/index.web.js +2 -1
  27. package/lib/module/network/components/NetworkEventDetailView.js +6 -1
  28. package/lib/module/network/components/NetworkHeaderMenu.js +4 -0
  29. package/lib/module/network/components/NetworkModal.js +25 -9
  30. package/lib/module/network/conditions/NetworkConditionsControl.js +231 -0
  31. package/lib/module/network/conditions/NetworkConditionsControl.test.js +135 -0
  32. package/lib/module/network/conditions/NetworkConditionsIcon.js +29 -0
  33. package/lib/module/network/conditions/NetworkFloatingTool.js +304 -0
  34. package/lib/module/network/conditions/NetworkFloatingTool.test.js +218 -0
  35. package/lib/module/network/conditions/store.js +65 -0
  36. package/lib/module/network/conditions/wait.js +38 -0
  37. package/lib/module/network/conditions/xhr.js +106 -0
  38. package/lib/module/network/hooks/useNetworkEvents.js +1 -1
  39. package/lib/module/network/overrides/applyToXhr.js +9 -8
  40. package/lib/module/network/overrides/engine.js +2 -1
  41. package/lib/module/network/sync/networkSyncAdapter.js +225 -3
  42. package/lib/module/network/utils/generateNetworkCopyText.js +2 -0
  43. package/lib/module/network/utils/networkEventStore.js +6 -77
  44. package/lib/module/network/utils/networkListener.js +246 -47
  45. package/lib/module/network/utils/networkSavedStore.js +2 -2
  46. package/lib/module/network/utils/selectSavedEvents.js +2 -2
  47. package/lib/module/preset.js +3 -2
  48. package/lib/typescript/index.d.ts +2 -0
  49. package/lib/typescript/index.d.ts.map +1 -1
  50. package/lib/typescript/index.web.d.ts +2 -0
  51. package/lib/typescript/index.web.d.ts.map +1 -1
  52. package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +1 -1
  53. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts +2 -1
  54. package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +1 -1
  55. package/lib/typescript/network/components/NetworkModal.d.ts +3 -0
  56. package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
  57. package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts +12 -0
  58. package/lib/typescript/network/conditions/NetworkConditionsControl.d.ts.map +1 -0
  59. package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts +2 -0
  60. package/lib/typescript/network/conditions/NetworkConditionsControl.test.d.ts.map +1 -0
  61. package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts +4 -0
  62. package/lib/typescript/network/conditions/NetworkConditionsIcon.d.ts.map +1 -0
  63. package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts +15 -0
  64. package/lib/typescript/network/conditions/NetworkFloatingTool.d.ts.map +1 -0
  65. package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts +2 -0
  66. package/lib/typescript/network/conditions/NetworkFloatingTool.test.d.ts.map +1 -0
  67. package/lib/typescript/network/conditions/store.d.ts +30 -0
  68. package/lib/typescript/network/conditions/store.d.ts.map +1 -0
  69. package/lib/typescript/network/conditions/wait.d.ts +4 -0
  70. package/lib/typescript/network/conditions/wait.d.ts.map +1 -0
  71. package/lib/typescript/network/conditions/xhr.d.ts +5 -0
  72. package/lib/typescript/network/conditions/xhr.d.ts.map +1 -0
  73. package/lib/typescript/network/hooks/useNetworkEvents.d.ts +1 -1
  74. package/lib/typescript/network/overrides/applyToXhr.d.ts +2 -0
  75. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
  76. package/lib/typescript/network/overrides/engine.d.ts +0 -10
  77. package/lib/typescript/network/overrides/engine.d.ts.map +1 -1
  78. package/lib/typescript/network/sync/networkSyncAdapter.d.ts +29 -0
  79. package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +1 -1
  80. package/lib/typescript/network/types/index.d.ts +1 -0
  81. package/lib/typescript/network/types/index.d.ts.map +1 -1
  82. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
  83. package/lib/typescript/network/utils/networkEventStore.d.ts +0 -15
  84. package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
  85. package/lib/typescript/network/utils/networkListener.d.ts +13 -28
  86. package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
  87. package/lib/typescript/network/utils/networkSavedStore.d.ts +2 -2
  88. package/lib/typescript/network/utils/selectSavedEvents.d.ts +2 -2
  89. package/lib/typescript/preset.d.ts +0 -16
  90. package/lib/typescript/preset.d.ts.map +1 -1
  91. 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, sleep, synthesizeFetchError, synthesizeResponse } from "../overrides/applyToFetch";
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 insideOverriddenFetch = false;
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.bind(globalThis);
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
- return this.ignoredUrls.some(pattern => pattern.test(url));
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. `_ttfb` is stamped at HEADERS_RECEIVED; it is
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._ttfb;
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 = passthroughFetch;
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 method = init?.method || "GET";
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
- if (init?.headers) {
530
- if (init.headers instanceof Headers) {
531
- init.headers.forEach((value, key) => {
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(init.headers)) {
535
- init.headers.forEach(([key, value]) => {
656
+ } else if (Array.isArray(headers)) {
657
+ headers.forEach(([key, value]) => {
536
658
  requestHeaders[key] = value;
537
659
  });
538
660
  } else {
539
- requestHeaders = init.headers;
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 sleep(outcome.delayMs);
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 `insideOverriddenFetch`. It has
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
- insideOverriddenFetch = outcome != null;
724
+ const previousFetchHandoff = insideFetchHandoff;
725
+ insideFetchHandoff = true;
598
726
  let pending;
599
727
  try {
600
728
  pending = passthroughFetch(input, init);
601
729
  } finally {
602
- insideOverriddenFetch = false;
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
- } = await self.processResponseBody(responseClone);
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
- // Superseded generations must not re-stamp (a double stamp burns two
721
- // request ids per request) — just pass through.
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._requestId = `xhr_${++self.requestCounter}`;
910
+ xhr._buoyRequestId = `xhr_${++self.requestCounter}`;
725
911
  xhr._method = method;
726
912
  xhr._url = url;
727
- xhr._startTime = Date.now();
913
+ xhr._buoyStartTime = Date.now();
728
914
  xhr._requestHeaders = {};
729
915
  }
730
- return passthroughOpen.call(this, method, url, async ?? true, user, password);
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._requestId;
938
+ const requestId = xhr._buoyRequestId;
750
939
  const method = xhr._method || "GET";
751
940
  const url = xhr._url || "";
752
- const startTime = xhr._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
- * `insideOverriddenFetch` around its pass-through, so one request can't
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 outcome = insideOverriddenFetch ? null : overrideForRequest(url, method);
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._ttfb === undefined && xhr._startTime) {
857
- xhr._ttfb = Date.now() - xhr._startTime;
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 is blind to the anonymous tier. Kept
43
- * because it is part of the package's public exports.
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 there are now three tiers, and a
19
- * boolean cannot express the anonymous one.
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
  /**
@@ -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 { NetworkIcon, createToolFactory, defineToolPreset } from "@buoy-gg/shared-ui";
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(NetworkIcon, {
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":"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"}
@@ -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,mEAoiBjC,CAAC"}
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,+BAYA"}
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"}