@buoy-gg/network 7.0.14 → 7.0.16

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 (107) hide show
  1. package/lib/commonjs/index.web.js +395 -0
  2. package/lib/commonjs/network/components/DataViewer.web.js +879 -0
  3. package/lib/commonjs/network/components/NetworkCopyScreen.web.js +48 -0
  4. package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +1242 -0
  5. package/lib/commonjs/network/components/NetworkDetailScreen.web.js +101 -0
  6. package/lib/commonjs/network/components/NetworkDetailStepper.web.js +296 -0
  7. package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1498 -0
  8. package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +802 -0
  9. package/lib/commonjs/network/components/NetworkFilterScreen.web.js +55 -0
  10. package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1310 -0
  11. package/lib/commonjs/network/components/NetworkHeaderLive.web.js +604 -0
  12. package/lib/commonjs/network/components/NetworkListScreen.js +2 -1
  13. package/lib/commonjs/network/components/NetworkListScreen.web.js +607 -0
  14. package/lib/commonjs/network/components/NetworkModal.js +12 -3
  15. package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +232 -0
  16. package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +942 -0
  17. package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +133 -0
  18. package/lib/commonjs/network/components/NetworkOverridesButton.web.js +143 -0
  19. package/lib/commonjs/network/components/NetworkOverridesScreen.js +160 -126
  20. package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +830 -0
  21. package/lib/commonjs/network/components/NetworkSavedScreen.web.js +459 -0
  22. package/lib/commonjs/network/components/response-editor/Explorer.web.js +1136 -0
  23. package/lib/commonjs/network/hooks/useNetworkEventList.js +12 -2
  24. package/lib/commonjs/network/overrides/applyToXhr.js +276 -15
  25. package/lib/commonjs/network/utils/generateNetworkCopyText.js +32 -5
  26. package/lib/commonjs/network/utils/networkEventStore.js +12 -4
  27. package/lib/commonjs/network/utils/networkListener.js +1 -16
  28. package/lib/module/index.web.js +81 -0
  29. package/lib/module/network/components/DataViewer.web.js +875 -0
  30. package/lib/module/network/components/NetworkCopyScreen.web.js +44 -0
  31. package/lib/module/network/components/NetworkCopySettingsView.web.js +1237 -0
  32. package/lib/module/network/components/NetworkDetailScreen.web.js +97 -0
  33. package/lib/module/network/components/NetworkDetailStepper.web.js +294 -0
  34. package/lib/module/network/components/NetworkEventDetailView.web.js +1496 -0
  35. package/lib/module/network/components/NetworkEventItemCompact.web.js +800 -0
  36. package/lib/module/network/components/NetworkFilterScreen.web.js +51 -0
  37. package/lib/module/network/components/NetworkFilterViewV3.web.js +1306 -0
  38. package/lib/module/network/components/NetworkHeaderLive.web.js +598 -0
  39. package/lib/module/network/components/NetworkListScreen.js +2 -1
  40. package/lib/module/network/components/NetworkListScreen.web.js +605 -0
  41. package/lib/module/network/components/NetworkModal.js +12 -3
  42. package/lib/module/network/components/NetworkNumberPrompt.web.js +230 -0
  43. package/lib/module/network/components/NetworkOverrideEditor.web.js +939 -0
  44. package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +131 -0
  45. package/lib/module/network/components/NetworkOverridesButton.web.js +141 -0
  46. package/lib/module/network/components/NetworkOverridesScreen.js +161 -127
  47. package/lib/module/network/components/NetworkOverridesScreen.web.js +826 -0
  48. package/lib/module/network/components/NetworkSavedScreen.web.js +457 -0
  49. package/lib/module/network/components/response-editor/Explorer.web.js +1133 -0
  50. package/lib/module/network/hooks/useNetworkEventList.js +12 -2
  51. package/lib/module/network/overrides/applyToXhr.js +275 -15
  52. package/lib/module/network/utils/generateNetworkCopyText.js +28 -1
  53. package/lib/module/network/utils/networkEventStore.js +12 -4
  54. package/lib/module/network/utils/networkListener.js +1 -16
  55. package/lib/typescript/index.web.d.ts +56 -0
  56. package/lib/typescript/index.web.d.ts.map +1 -0
  57. package/lib/typescript/network/components/DataViewer.web.d.ts +78 -0
  58. package/lib/typescript/network/components/DataViewer.web.d.ts.map +1 -0
  59. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts +27 -0
  60. package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +1 -0
  61. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts +68 -0
  62. package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +1 -0
  63. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts +45 -0
  64. package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +1 -0
  65. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts +40 -0
  66. package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +1 -0
  67. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts +67 -0
  68. package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +1 -0
  69. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts +58 -0
  70. package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +1 -0
  71. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts +28 -0
  72. package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +1 -0
  73. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts +74 -0
  74. package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +1 -0
  75. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts +112 -0
  76. package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +1 -0
  77. package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
  78. package/lib/typescript/network/components/NetworkListScreen.web.d.ts +63 -0
  79. package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +1 -0
  80. package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
  81. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts +38 -0
  82. package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +1 -0
  83. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts +43 -0
  84. package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +1 -0
  85. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts +32 -0
  86. package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +1 -0
  87. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts +26 -0
  88. package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +1 -0
  89. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +9 -0
  90. package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
  91. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts +69 -0
  92. package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +1 -0
  93. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts +67 -0
  94. package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +1 -0
  95. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts +56 -0
  96. package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +1 -0
  97. package/lib/typescript/network/hooks/useNetworkEventList.d.ts +10 -0
  98. package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
  99. package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -1
  100. package/lib/typescript/network/overrides/applyToXhr.d.ts +40 -14
  101. package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
  102. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts +34 -1
  103. package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
  104. package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
  105. package/lib/typescript/network/utils/networkListener.d.ts +0 -1
  106. package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
  107. package/package.json +2 -2
@@ -27,11 +27,21 @@ export function useNetworkEventList(options) {
27
27
  filter,
28
28
  ignoredPatterns,
29
29
  paused,
30
+ visible = true,
30
31
  isPro
31
32
  } = options;
32
33
  const [events, setEvents] = useState(() => networkEventStore.getEvents());
33
34
  useEffect(() => {
34
- if (paused) return undefined;
35
+ // Hidden: neither subscribe nor sync — a hidden screen re-rendering for
36
+ // stream traffic is pure waste (the stable-router contract).
37
+ if (!visible) return undefined;
38
+ if (paused) {
39
+ // Pause freezes the STREAM, not the data. The store still holds the
40
+ // frozen events, and a screen entering visibility during a pause must
41
+ // show them rather than whatever it had at mount.
42
+ setEvents(networkEventStore.getEvents());
43
+ return undefined;
44
+ }
35
45
  // Coalesce store emissions to one commit per frame: a burst of N
36
46
  // concurrent requests emits 2N times (add + response each), and
37
47
  // uncoalesced each emission is its own commit re-rendering the
@@ -54,7 +64,7 @@ export function useNetworkEventList(options) {
54
64
  unsubscribe();
55
65
  if (rafId != null) cancelAnimationFrame(rafId);
56
66
  };
57
- }, [paused]);
67
+ }, [paused, visible]);
58
68
  useEffect(() => networkEventStore.onClear(() => {
59
69
  setEvents([]);
60
70
  }), []);
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
 
3
3
  /**
4
- * Perform an override outcome against a React Native XMLHttpRequest.
4
+ * Perform an override outcome against an XMLHttpRequest — React Native's OR a
5
+ * standards (browser/webview) one.
5
6
  *
6
- * WHY THIS IS POSSIBLE AT ALL: React Native's XMLHttpRequest
7
+ * WHY THIS IS POSSIBLE ON RN: React Native's XMLHttpRequest
7
8
  * (`react-native/Libraries/Network/XMLHttpRequest.js`) is pure JavaScript.
8
9
  * `readyState`, `status`, `responseHeaders` and `responseURL` are plain
9
10
  * writable fields, and `setResponseHeaders()` / `setReadyState()` are real
@@ -12,16 +13,33 @@
12
13
  * `_hasError` → error, otherwise load; always loadend). So a response can be
13
14
  * synthesized end to end without touching native code.
14
15
  *
15
- * WHY XHR IS THE ONLY PLACE WE HOOK: `react-native/Libraries/Network/fetch.js`
16
- * is `require('whatwg-fetch')` — RN's `fetch` IS the polyfill over
17
- * XMLHttpRequest. Overriding here therefore covers `fetch`, `axios` and raw
18
- * XHR through one code path, and the fake response flows back up through the
19
- * polyfill so the tool records it without any extra plumbing.
16
+ * WHY XHR IS THE ONLY PLACE WE HOOK ON RN:
17
+ * `react-native/Libraries/Network/fetch.js` is `require('whatwg-fetch')` —
18
+ * RN's `fetch` IS the polyfill over XMLHttpRequest. Overriding here therefore
19
+ * covers `fetch`, `axios` and raw XHR through one code path, and the fake
20
+ * response flows back up through the polyfill so the tool records it without
21
+ * any extra plumbing.
20
22
  *
21
23
  * Verified field-for-field on React Native 0.81.4 and 0.85.3.
22
24
  *
23
- * Four non-obvious behaviours are handled below; each one is a real bug if you
24
- * skip it, and each is commented at the line that fixes it.
25
+ * WHY THERE IS A SECOND PATH: on a STANDARDS XMLHttpRequest (a webview port —
26
+ * Tauri/Capacitor — or react-native-web) none of the RN internals exist, and
27
+ * `status` / `readyState` / `response` are readonly ACCESSORS on
28
+ * `XMLHttpRequest.prototype`, so plain assignment silently no-ops (or throws
29
+ * in strict mode). This file used to feature-detect that and give up —
30
+ * "degraded, but never broken" — which was right for react-native-web as a
31
+ * by-product of an RN app, and wrong the moment the web ports made the
32
+ * browser XHR a first-class target: the row got FLAGGED as overridden (the
33
+ * rule matched) while the real request went out. The fix is
34
+ * `runStandardOverride` below: `Object.defineProperty` INSTANCE own-properties
35
+ * shadow the prototype accessors (legal on any object), and the lifecycle
36
+ * events are dispatched by hand through the XHR's own EventTarget — which
37
+ * fires `addEventListener` listeners AND the `onload`/`onloadend`/
38
+ * `onreadystatechange` handler attributes, exactly what axios's XHR adapter
39
+ * listens on.
40
+ *
41
+ * Several non-obvious behaviours are handled below; each one is a real bug if
42
+ * you skip it, and each is commented at the line that fixes it.
25
43
  */
26
44
 
27
45
  const HEADERS_RECEIVED = 2;
@@ -40,22 +58,33 @@ const internalsOf = xhr => xhr;
40
58
  let warnedUnsupported = false;
41
59
 
42
60
  /**
43
- * Can this XMLHttpRequest be driven by hand?
61
+ * Can this XMLHttpRequest be driven through React Native's internals?
44
62
  *
45
- * The whole technique rests on RN internals, so it is feature-detected rather
46
- * than assumed: on a browser XMLHttpRequest (react-native-web) these methods
47
- * don't exist and `status` is a read-only getter. There, overrides no-op and
48
- * the request goes out for real — degraded, but never broken.
63
+ * The RN technique rests on those internals, so it is feature-detected rather
64
+ * than assumed. A request that fails this check is NOT automatically a lost
65
+ * cause — `canSynthesizeStandard` covers the standards XHR next.
49
66
  */
50
67
  export function canSynthesize(xhr) {
51
68
  const internals = internalsOf(xhr);
52
69
  return typeof internals.setReadyState === "function" && typeof internals.setResponseHeaders === "function";
53
70
  }
71
+
72
+ /**
73
+ * Can this XMLHttpRequest be driven as a STANDARDS one?
74
+ *
75
+ * `dispatchEvent` is the load-bearing requirement: the whole standard path
76
+ * works by defining instance own-properties and then dispatching the
77
+ * lifecycle events through the XHR's own EventTarget. `removeEventListener`
78
+ * rules out half-mocks that could take the branch and then leak listeners.
79
+ */
80
+ export function canSynthesizeStandard(xhr) {
81
+ return typeof xhr.addEventListener === "function" && typeof xhr.removeEventListener === "function" && typeof xhr.dispatchEvent === "function";
82
+ }
54
83
  function warnUnsupported() {
55
84
  if (warnedUnsupported) return;
56
85
  warnedUnsupported = true;
57
86
  if (typeof __DEV__ !== "undefined" && __DEV__) {
58
- console.warn("[Buoy] Network overrides need React Native's XMLHttpRequest and this " + "environment provides a different one — requests will run normally.");
87
+ console.warn("[Buoy] Network overrides need an XMLHttpRequest they can drive (React " + "Native's, or a standards EventTarget one) and this environment " + "provides neither — requests will run normally.");
59
88
  }
60
89
  }
61
90
 
@@ -115,6 +144,230 @@ function fail(xhr, outcome) {
115
144
  internals.setReadyState?.(DONE);
116
145
  }
117
146
 
147
+ // ============================================================================
148
+ // STANDARDS XMLHttpRequest path (webview ports / react-native-web)
149
+ // ============================================================================
150
+
151
+ /**
152
+ * Shadow a prototype accessor with an instance own-property.
153
+ *
154
+ * This is the entire trick: `xhr.status = 500` silently no-ops (or throws in
155
+ * strict mode) against the readonly getter on `XMLHttpRequest.prototype`, but
156
+ * an own DATA property on the instance is legal and takes precedence in every
157
+ * lookup. `configurable: true` so `readyState` can be redefined per
158
+ * transition. Works identically against RN's plain class fields, so nothing
159
+ * here is browser-only — the RN path just has a richer mechanism available.
160
+ */
161
+ function defineOwn(xhr, name, value) {
162
+ Object.defineProperty(xhr, name, {
163
+ value,
164
+ configurable: true,
165
+ enumerable: true,
166
+ writable: false
167
+ });
168
+ }
169
+
170
+ /**
171
+ * Build a lifecycle event to dispatch by hand.
172
+ *
173
+ * `ProgressEvent` where the spec uses one (load/loadend/error/timeout/abort)
174
+ * and the constructor exists; plain `Event` otherwise (Node test runs have no
175
+ * ProgressEvent); a `{ type }` literal as the last resort for event-target
176
+ * shims. Dispatching through the XHR's own EventTarget is what makes the
177
+ * `onload`/`onloadend`/`onreadystatechange` handler ATTRIBUTES fire too —
178
+ * they're listeners in the same list, which is exactly what axios's adapter
179
+ * registers.
180
+ */
181
+ function makeEvent(type) {
182
+ if (type !== "readystatechange" && typeof ProgressEvent === "function") {
183
+ try {
184
+ return new ProgressEvent(type);
185
+ } catch {
186
+ // fall through
187
+ }
188
+ }
189
+ if (typeof Event === "function") {
190
+ try {
191
+ return new Event(type);
192
+ } catch {
193
+ // fall through
194
+ }
195
+ }
196
+ return {
197
+ type
198
+ };
199
+ }
200
+ function fireEvent(xhr, type) {
201
+ xhr.dispatchEvent(makeEvent(type));
202
+ }
203
+
204
+ /** Move the shadowed `readyState` and announce it — the interceptor's own
205
+ * listener stamps TTFB off the HEADERS_RECEIVED notification, same as a real
206
+ * response. */
207
+ function setStandardReadyState(xhr, state) {
208
+ defineOwn(xhr, "readyState", state);
209
+ fireEvent(xhr, "readystatechange");
210
+ }
211
+
212
+ /**
213
+ * `xhr.response` in the caller's requested shape.
214
+ *
215
+ * A standards XHR types `response` off `responseType`; axios sets it when the
216
+ * caller asked for one (default '' → text). JSON is parsed (spec: null on
217
+ * parse failure), arraybuffer/blob are best-effort encodings of the rule's
218
+ * text body, everything else falls back to the string.
219
+ */
220
+ function standardResponseFor(xhr, outcome) {
221
+ let responseType = "";
222
+ try {
223
+ responseType = xhr.responseType;
224
+ } catch {
225
+ // Some shims throw on access before send — treat as default text.
226
+ }
227
+ switch (responseType) {
228
+ case "":
229
+ case "text":
230
+ return outcome.body;
231
+ case "json":
232
+ try {
233
+ return JSON.parse(outcome.body);
234
+ } catch {
235
+ return null;
236
+ }
237
+ case "arraybuffer":
238
+ if (typeof TextEncoder === "function") {
239
+ return new TextEncoder().encode(outcome.body).buffer;
240
+ }
241
+ return outcome.body;
242
+ case "blob":
243
+ if (typeof Blob === "function") {
244
+ const contentType = Object.entries(outcome.headers).find(([name]) => name.toLowerCase() === "content-type")?.[1] ?? "";
245
+ return new Blob([outcome.body], {
246
+ type: contentType
247
+ });
248
+ }
249
+ return outcome.body;
250
+ default:
251
+ return outcome.body;
252
+ }
253
+ }
254
+
255
+ /** Synthesize a successful response on a standards XHR. */
256
+ function respondStandard(xhr, url, outcome, isAborted) {
257
+ const headers = outcome.headers;
258
+ // Spec shape: lowercase names, `name: value\r\n` per pair — axios splits on
259
+ // newlines and trims, raw XHR users get what a real response reads like.
260
+ const allHeaders = Object.entries(headers).map(([name, value]) => `${name.toLowerCase()}: ${value}\r\n`).join("");
261
+ defineOwn(xhr, "getAllResponseHeaders", () => allHeaders);
262
+ defineOwn(xhr, "getResponseHeader", name => {
263
+ const wanted = String(name).toLowerCase();
264
+ for (const [key, value] of Object.entries(headers)) {
265
+ if (key.toLowerCase() === wanted) return value;
266
+ }
267
+ return null;
268
+ });
269
+ defineOwn(xhr, "responseURL", url);
270
+ defineOwn(xhr, "status", outcome.status);
271
+ defineOwn(xhr, "statusText", outcome.statusText);
272
+ defineOwn(xhr, "response", standardResponseFor(xhr, outcome));
273
+ // Own property, so it answers with the body even under a non-text
274
+ // `responseType` (where the real accessor would throw). axios reads it
275
+ // whenever `responseType` is '' or 'text'.
276
+ defineOwn(xhr, "responseText", outcome.body);
277
+ setStandardReadyState(xhr, HEADERS_RECEIVED);
278
+ if (isAborted()) return;
279
+ setStandardReadyState(xhr, LOADING);
280
+ if (isAborted()) return;
281
+ setStandardReadyState(xhr, DONE);
282
+ fireEvent(xhr, "load");
283
+ fireEvent(xhr, "loadend");
284
+ }
285
+
286
+ /** Synthesize a transport failure on a standards XHR — offline or timeout. */
287
+ function failStandard(xhr, outcome) {
288
+ // `status` stays 0 (the prototype getter's answer for a request whose real
289
+ // send never ran) — exactly what a genuine network error reports. The
290
+ // 'error'/'timeout' event is the entire signal; axios turns them into
291
+ // ERR_NETWORK / ECONNABORTED the same way whatwg-fetch turns RN's flags
292
+ // into TypeErrors.
293
+ setStandardReadyState(xhr, DONE);
294
+ fireEvent(xhr, outcome.failKind === "timeout" ? "timeout" : "error");
295
+ fireEvent(xhr, "loadend");
296
+ }
297
+
298
+ /**
299
+ * Apply an outcome to a standards XMLHttpRequest that has NOT been sent.
300
+ *
301
+ * The real `send()` is never invoked for respond/fail — the request must not
302
+ * touch the network. That leaves `abort()` with nothing to do natively (per
303
+ * spec, abort on a request whose send flag is unset dispatches NOTHING), so
304
+ * an instance shadow gives it the in-flight behaviour the app expects:
305
+ * cancel the pending outcome and dispatch abort + loadend. The shadow deletes
306
+ * itself the moment it can't matter anymore — after settling, and before a
307
+ * `delay` pass-through hands the request to the real network, where the
308
+ * prototype `abort()` must be reachable again.
309
+ */
310
+ function runStandardOverride(xhr, url, outcome, passThrough) {
311
+ let timer = null;
312
+ let aborted = false;
313
+ let settled = false;
314
+ const restoreAbort = () => {
315
+ try {
316
+ delete xhr.abort;
317
+ } catch {
318
+ // Non-configurable shadow can't happen (we define it configurable), but
319
+ // never let cleanup throw into app code.
320
+ }
321
+ };
322
+ Object.defineProperty(xhr, "abort", {
323
+ configurable: true,
324
+ writable: true,
325
+ value: () => {
326
+ if (settled || aborted) return;
327
+ aborted = true;
328
+ settled = true;
329
+ if (timer !== null) {
330
+ clearTimeout(timer);
331
+ timer = null;
332
+ }
333
+ restoreAbort();
334
+ // The in-flight abort sequence: DONE, then 'abort', then 'loadend' —
335
+ // whatwg's request-error steps, which is also what RN's setReadyState
336
+ // dispatches off `_aborted`.
337
+ setStandardReadyState(xhr, DONE);
338
+ fireEvent(xhr, "abort");
339
+ fireEvent(xhr, "loadend");
340
+ }
341
+ });
342
+ const fire = () => {
343
+ timer = null;
344
+ if (aborted) return;
345
+ if (outcome.kind === "delay") {
346
+ // The real request is about to be genuinely in flight — put the
347
+ // prototype `abort()` back FIRST so cancelling reaches the network.
348
+ restoreAbort();
349
+ passThrough();
350
+ return;
351
+ }
352
+ if (outcome.kind === "fail") {
353
+ failStandard(xhr, outcome);
354
+ } else {
355
+ respondStandard(xhr, url, outcome, () => aborted);
356
+ }
357
+ settled = true;
358
+ restoreAbort();
359
+ };
360
+
361
+ // ALWAYS asynchronous, even at 0ms — same contract as the RN path: callers
362
+ // legitimately attach handlers after `send()` returns (axios does).
363
+ timer = setTimeout(fire, outcome.delayMs);
364
+ return true;
365
+ }
366
+
367
+ // ============================================================================
368
+ // Entry point
369
+ // ============================================================================
370
+
118
371
  /**
119
372
  * Apply an outcome to a request that has NOT been sent yet.
120
373
  *
@@ -125,6 +378,13 @@ function fail(xhr, outcome) {
125
378
  */
126
379
  export function runOverride(xhr, url, outcome, passThrough) {
127
380
  if (!canSynthesize(xhr)) {
381
+ // Not React Native's XMLHttpRequest — a standards one (webview port,
382
+ // react-native-web) is driven through instance property shadowing
383
+ // instead. Order matters: RN's XHR also extends an EventTarget shim, so
384
+ // the RN check must win first.
385
+ if (canSynthesizeStandard(xhr)) {
386
+ return runStandardOverride(xhr, url, outcome, passThrough);
387
+ }
128
388
  warnUnsupported();
129
389
  return false;
130
390
  }
@@ -6,9 +6,36 @@
6
6
  * callback previously inlined in NetworkModal — kept pure so the header
7
7
  * CopyButton can resolve it LAZILY at copy time (CopyButton accepts a
8
8
  * function value) instead of rebuilding the string on every event.
9
+ *
10
+ * PLATFORM-FREE ON PURPOSE: this module is reused verbatim by the web ports
11
+ * (webview shims resolve `@buoy-gg/shared-ui` to a minimal storage-only shim),
12
+ * so it must not reach the RN component graph or the shared-ui barrel. That is
13
+ * why:
14
+ * - `CopySettings` is defined HERE rather than imported from
15
+ * NetworkCopySettingsView.tsx (which pulls in react-native + shared-ui RN
16
+ * chrome). The RN view keeps its own structurally-identical definition —
17
+ * keep the two shapes in sync.
18
+ * - `formatBytes` is a verbatim copy of
19
+ * shared/src/utils/formatting/dataFormatting.ts rather than the
20
+ * `./formatting` re-export of `@buoy-gg/shared-ui` (not in the web shim).
9
21
  */
10
22
 
11
- import { formatBytes } from "./formatting";
23
+ /**
24
+ * What the copy exporter includes and how it formats it. Structurally
25
+ * identical to (and must stay in sync with) the `CopySettings` exported by
26
+ * NetworkCopySettingsView.tsx — see the platform-free note above for why the
27
+ * definition lives here.
28
+ */
29
+
30
+ /** shared/src/utils/formatting/dataFormatting.ts `formatBytes` — verbatim. */
31
+ function formatBytes(bytes) {
32
+ if (bytes === undefined || bytes === null) return "N/A";
33
+ if (bytes === 0) return "0 B";
34
+ const k = 1024;
35
+ const sizes = ["B", "KB", "MB", "GB", "TB"];
36
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
37
+ return `${(bytes / Math.pow(k, i)).toFixed(1)} ${sizes[i]}`;
38
+ }
12
39
  function shouldIncludePayload(data, bodySizeThresholdKb) {
13
40
  if (bodySizeThresholdKb === -1) return true;
14
41
  if (!data) return true;
@@ -108,8 +108,14 @@ class NetworkEventStore extends BaseEventStore {
108
108
  const now = Date.now();
109
109
  const recent = this.recentRequests.get(requestKey);
110
110
 
111
- // If same request within 50ms, likely a duplicate from XHR/fetch dual interception
112
- if (recent && now - recent.at < 50) {
111
+ // If same request within 50ms, likely a duplicate from XHR/fetch dual
112
+ // interception. The age must be non-negative: Date.now() is not
113
+ // monotonic, and after a backwards clock adjustment (iOS time sync) a
114
+ // future-dated entry would satisfy `< 50` for EVERY request to this
115
+ // endpoint until the clock caught up — capture going silent for minutes
116
+ // to hours, "fixed" only by Clear wiping this map (field-reported). A
117
+ // negative age falls through and re-stamps the entry with the new clock.
118
+ if (recent && now - recent.at >= 0 && now - recent.at < 50) {
113
119
  // …but the duplicate is not always redundant. On React Native a
114
120
  // `fetch()` is seen twice: once by the fetch wrapper, which is what
115
121
  // creates this event, and again by the XHR wrapper underneath it —
@@ -126,11 +132,13 @@ class NetworkEventStore extends BaseEventStore {
126
132
  id: request.id
127
133
  });
128
134
 
129
- // Clean up old entries to prevent memory leak
135
+ // Clean up old entries to prevent memory leak. Future-dated entries are
136
+ // stale by definition (clock moved backwards) — drop those too, or they
137
+ // survive every sweep until the clock overtakes them.
130
138
  if (this.recentRequests.size > 100) {
131
139
  const cutoff = now - 5000;
132
140
  for (const [key, entry] of this.recentRequests.entries()) {
133
- if (entry.at < cutoff) {
141
+ if (entry.at < cutoff || entry.at > now) {
134
142
  this.recentRequests.delete(key);
135
143
  }
136
144
  }
@@ -200,20 +200,6 @@ class NetworkListener {
200
200
  return `${Math.round(bytes / Math.pow(k, i) * 100) / 100} ${sizes[i]}`;
201
201
  }
202
202
 
203
- // Get response body size
204
- getResponseSize(body) {
205
- if (!body) return 0;
206
- if (typeof body === "string") return body.length;
207
- if (typeof body === "object") {
208
- try {
209
- return JSON.stringify(body).length;
210
- } catch {
211
- return 0;
212
- }
213
- }
214
- return 0;
215
- }
216
-
217
203
  /**
218
204
  * Handle XMLHttpRequest response processing
219
205
  * This method processes the response and emits appropriate events
@@ -541,8 +527,7 @@ class NetworkListener {
541
527
  const responseClone = response.clone();
542
528
  const {
543
529
  body,
544
- size: responseSize,
545
- truncated
530
+ size: responseSize
546
531
  } = await self.processResponseBody(responseClone);
547
532
 
548
533
  // Now the body is in — this is the comparable, total number.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @buoy-gg/network — Web Entry Point (webview ports: Tauri / Capacitor / web).
3
+ *
4
+ * Exposes the platform-free capture + data layer only. The capture core
5
+ * (networkListener) patches `globalThis.fetch` and `XMLHttpRequest.prototype`
6
+ * — standard web APIs — so it runs in a webview unchanged; the RN UI
7
+ * components (NetworkModal etc.) are NOT exported here. Their DOM twins are
8
+ * added feature-by-feature as the web tools port progresses.
9
+ *
10
+ * Consumers resolve `@buoy-gg/shared-ui` to a web shim (see
11
+ * example-tauri/src/shims/shared-ui.web.ts) providing localStorage-backed
12
+ * persistentStorage, devToolsStorageKeys, BaseEventStore, and the pure
13
+ * ignored-patterns helpers.
14
+ *
15
+ * @platform React DOM Web
16
+ */
17
+ export { networkListener, startNetworkListener, stopNetworkListener, addNetworkListener, removeAllNetworkListeners, isNetworkListening, } from "./network/utils/networkListener";
18
+ export type { NetworkingEvent, NetworkingEventListener, } from "./network/utils/networkListener";
19
+ export { networkEventStore } from "./network/utils/networkEventStore";
20
+ export { networkSavedStore, flagsForEventId, } from "./network/utils/networkSavedStore";
21
+ export type { NetworkEvent, NetworkStats, NetworkFilter, NetworkTimings, } from "./network/types";
22
+ export { useNetworkEvents, FREE_TIER_REQUEST_LIMIT } from "./network/hooks/useNetworkEvents";
23
+ export { useNetworkEventList } from "./network/hooks/useNetworkEventList";
24
+ export { useLiveNetworkEvent } from "./network/hooks/useLiveNetworkEvent";
25
+ export { useNetworkBadgeCounts } from "./network/hooks/useNetworkBadgeCounts";
26
+ export { useHasNetworkSelection, useSelectedNetworkEventId, useNetworkBodyEventId, useNetworkCursor, } from "./network/hooks/useNetworkSelection";
27
+ export { networkSelectionStore, toSelectionIds, } from "./network/utils/networkSelectionStore";
28
+ export { NetworkListScreen } from "./network/components/NetworkListScreen.web";
29
+ export { NetworkEventItemCompact } from "./network/components/NetworkEventItemCompact.web";
30
+ export { NetworkHeaderBadges, NetworkClearButton, NetworkSavedButton, NetworkDetailPinActions, NetworkHeaderCopyButton, } from "./network/components/NetworkHeaderLive.web";
31
+ export { NetworkEventDetailView } from "./network/components/NetworkEventDetailView.web";
32
+ export { NetworkDetailStepper } from "./network/components/NetworkDetailStepper.web";
33
+ export { NetworkDetailScreen } from "./network/components/NetworkDetailScreen.web";
34
+ export { NetworkFilterViewV3 } from "./network/components/NetworkFilterViewV3.web";
35
+ export { NetworkFilterScreen } from "./network/components/NetworkFilterScreen.web";
36
+ export { NetworkSavedScreen } from "./network/components/NetworkSavedScreen.web";
37
+ export { NetworkCopySettingsView, DEFAULT_COPY_SETTINGS, } from "./network/components/NetworkCopySettingsView.web";
38
+ export { NetworkCopyScreen } from "./network/components/NetworkCopyScreen.web";
39
+ export { generateNetworkCopyText, type CopySettings, } from "./network/utils/generateNetworkCopyText";
40
+ export { selectSavedEvents } from "./network/utils/selectSavedEvents";
41
+ export { FREE_TIER_SAVED_LIMIT, MAX_SAVED } from "./network/utils/networkSavedStore";
42
+ export { NetworkOverridesScreen } from "./network/components/NetworkOverridesScreen.web";
43
+ export { NetworkOverrideEditor } from "./network/components/NetworkOverrideEditor.web";
44
+ export { NetworkNumberPrompt } from "./network/components/NetworkNumberPrompt.web";
45
+ export { NetworkOverridesButton } from "./network/components/NetworkOverridesButton.web";
46
+ export { NetworkOverrideHeaderButton } from "./network/components/NetworkOverrideHeaderButton.web";
47
+ export { useOverrideRules } from "./network/hooks/useOverrideRules";
48
+ export { overrideRulesStore, type OverrideRuleDraft, } from "./network/overrides/overrideRulesStore";
49
+ export { draftFromEvent, patternForUrl } from "./network/overrides/presets";
50
+ export { FREE_TIER_RULE_LIMIT, MAX_RULES, STATUS_MAX, STATUS_MIN, type OverrideRule, type NetworkOverrideMark, } from "./network/overrides/types";
51
+ export { ruleMatches } from "./network/overrides/matchRule";
52
+ export { filterNetworkEvents, applyIgnoredPatterns, } from "./network/utils/filterNetworkEvents";
53
+ export { splitPinned, type PinnedSplit } from "./network/utils/withPinnedFirst";
54
+ export { extractOperationName } from "./network/utils/extractOperationName";
55
+ export { generateCurl } from "./network/utils/generateCurl";
56
+ //# sourceMappingURL=index.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.web.d.ts","sourceRoot":"","sources":["../../src/index.web.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * DataViewer.web — DOM twin of the shared-ui data-viewer stack, exactly as the
3
+ * network DETAIL view consumes it (`rawMode` + type-filter legend +
4
+ * `initialExpanded`). The web shim exposes none of this chrome, so it is
5
+ * replicated here as DOM with provenance:
6
+ *
7
+ * - `DataViewer` — shared/src/dataViewer/DataViewer.tsx (type-filter chips +
8
+ * the `flattenByType` filtered projection, algorithms copied verbatim).
9
+ * - Tree rows — shared/src/dataViewer/VirtualizedDataExplorer.tsx, rawMode
10
+ * path: synthetic "root" row, 24px rows, 16px indent per depth, chevron
11
+ * expander, `key:` in monospace, values colored by type
12
+ * (macOSColors.dataTypes via the gameUIColors macOS theme), expandable rows
13
+ * reading "object (3 items)", per-row copy button, MAX_ITEMS_PER_LEVEL 500 /
14
+ * MAX_DEPTH_LIMIT 15 caps and the circular-reference guard.
15
+ * - Indent guides — shared/src/dataViewer/IndentGuidesOverlay.tsx (same
16
+ * segment computation, 1px lines at (depth-0.5)*16, primary @ ~30% alpha).
17
+ * - Type chips — shared/src/dataViewer/TypeLegend.tsx (`getTypeColor` copied
18
+ * verbatim).
19
+ * - `CopyButton` / `InlineCopyButton` — shared/src/ui/components/
20
+ * CopyButton.tsx: idle/success/error states, 1500ms feedback, lazy function
21
+ * values resolved at press time, object values pretty-printed (2-space,
22
+ * circular-safe — clipboard/copyToClipboard.ts's safeStringify semantics).
23
+ *
24
+ * Intentional deviations (all logged):
25
+ * - FlatList virtualization + the chunked/debounced async flatten
26
+ * ("Processing data…") → a synchronous flatten over plain DOM rows. The
27
+ * same 500-per-level/15-deep caps bound the work, and web rows are cheap;
28
+ * the settle-window in `networkSelectionStore` (see `showBodies` on the
29
+ * detail view) is what keeps stepping fast, exactly as on native.
30
+ * - Row selection / double-tap inline editing / `DataTreeActionBar` are NOT
31
+ * ported — that is the response-EDITOR surface (overrides), a later port
32
+ * feature. Read-only rows toggle expansion on press, as native does when no
33
+ * `onSelectionChange` is wired.
34
+ * - `CopyButton`'s Pro upgrade modal + first-copy hint banner are not ported
35
+ * (license gating isn't part of the web port); `disableCopy` is accepted
36
+ * for API compatibility and ignored, same as the native explorer.
37
+ * - `displayValue`'s minimal-SuperJSON serialization → JSON.stringify; for
38
+ * the JSON payloads this tool renders the output is identical.
39
+ *
40
+ * @platform React DOM Web
41
+ */
42
+ import { type CSSProperties } from "react";
43
+ interface CopyButtonProps {
44
+ /** The value to copy — any type; a FUNCTION value is resolved at press time
45
+ * (CopyButton's latest-ref pattern), so no string is built per render. */
46
+ value: unknown;
47
+ /** Icon size (default 16, matching native). */
48
+ size?: number;
49
+ buttonStyle?: CSSProperties;
50
+ /** Custom colors per state — same contract as native. */
51
+ colors?: {
52
+ idle?: string;
53
+ success?: string;
54
+ error?: string;
55
+ };
56
+ "aria-label"?: string;
57
+ }
58
+ /**
59
+ * Copy button with idle/success/error feedback (1500ms), same icon set and
60
+ * state colors as native. No Pro modal / hint banner — see the deviations log.
61
+ */
62
+ export declare const CopyButton: import("react").NamedExoticComponent<CopyButtonProps>;
63
+ /** Preset copy button for inline use (smaller size) — native `InlineCopyButton`. */
64
+ export declare const InlineCopyButton: import("react").NamedExoticComponent<Omit<CopyButtonProps, "size">>;
65
+ type JsonValue = unknown;
66
+ export interface DataViewerProps {
67
+ title: string;
68
+ data: JsonValue;
69
+ maxDepth?: number;
70
+ rawMode?: boolean;
71
+ showTypeFilter?: boolean;
72
+ initialExpanded?: boolean;
73
+ /** Accepted for API compatibility with native; ignored (see deviations). */
74
+ disableCopy?: boolean;
75
+ }
76
+ export declare function DataViewer({ title: _title, data, maxDepth, rawMode: _rawMode, showTypeFilter, initialExpanded, disableCopy: _disableCopy, }: DataViewerProps): import("react").JSX.Element;
77
+ export {};
78
+ //# sourceMappingURL=DataViewer.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataViewer.web.d.ts","sourceRoot":"","sources":["../../../../src/network/components/DataViewer.web.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AAEH,OAAO,EAML,KAAK,aAAa,EAEnB,MAAM,OAAO,CAAC;AAuJf,UAAU,eAAe;IACvB;8EAC0E;IAC1E,KAAK,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,aAAa,CAAC;IAC5B,yDAAyD;IACzD,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,uDAwErB,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,gBAAgB,qEAI3B,CAAC;AAqBH,KAAK,SAAS,GAAG,OAAO,CAAC;AAsdzB,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,UAAU,CAAC,EACzB,KAAK,EAAE,MAAM,EACb,IAAI,EACJ,QAAa,EACb,OAAO,EAAE,QAAe,EACxB,cAAqB,EACrB,eAAuB,EACvB,WAAW,EAAE,YAAoB,GAClC,EAAE,eAAe,+BAmGjB"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * NetworkCopyScreen.web — DOM twin of the `NetworkCopyScreen` screen
3
+ * component inside NetworkModal.tsx (the native screen is private to the
4
+ * modal; web hosts compose their own shell, so the screen is exported here as
5
+ * the reusable piece — same precedent as NetworkFilterScreen.web).
6
+ *
7
+ * Same rule4 contract as native: hooks run unconditionally and the component
8
+ * returns null when not visible; the subscription passes `paused || !visible`
9
+ * so a hidden screen doesn't subscribe. The preview reads the SAME filtered
10
+ * list the user is looking at (`useNetworkEventList` — the platform-free hook
11
+ * native uses, reused, not forked).
12
+ *
13
+ * @platform React DOM Web
14
+ */
15
+ import type { IgnoredPattern, NetworkFilter } from "../types";
16
+ import type { CopySettings } from "../utils/generateNetworkCopyText";
17
+ export interface NetworkCopyScreenProps {
18
+ visible: boolean;
19
+ paused: boolean;
20
+ isPro: boolean;
21
+ filter: NetworkFilter;
22
+ ignoredPatterns: IgnoredPattern[];
23
+ settings: CopySettings;
24
+ onSettingsChange: (settings: CopySettings) => void;
25
+ }
26
+ export declare function NetworkCopyScreen({ visible, paused, isPro, filter, ignoredPatterns, settings, onSettingsChange, }: NetworkCopyScreenProps): import("react").JSX.Element | null;
27
+ //# sourceMappingURL=NetworkCopyScreen.web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NetworkCopyScreen.web.d.ts","sourceRoot":"","sources":["../../../../src/network/components/NetworkCopyScreen.web.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAIrE,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,aAAa,CAAC;IACtB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,QAAQ,EAAE,YAAY,CAAC;IACvB,gBAAgB,EAAE,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;CACpD;AAED,wBAAgB,iBAAiB,CAAC,EAChC,OAAO,EACP,MAAM,EACN,KAAK,EACL,MAAM,EACN,eAAe,EACf,QAAQ,EACR,gBAAgB,GACjB,EAAE,sBAAsB,sCAexB"}