@buoy-gg/network 7.0.15 → 7.0.17
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/lib/commonjs/index.web.js +395 -0
- package/lib/commonjs/network/components/DataViewer.web.js +879 -0
- package/lib/commonjs/network/components/NetworkCopyScreen.web.js +48 -0
- package/lib/commonjs/network/components/NetworkCopySettingsView.web.js +1242 -0
- package/lib/commonjs/network/components/NetworkDetailScreen.web.js +101 -0
- package/lib/commonjs/network/components/NetworkDetailStepper.web.js +296 -0
- package/lib/commonjs/network/components/NetworkEventDetailView.web.js +1498 -0
- package/lib/commonjs/network/components/NetworkEventItemCompact.web.js +802 -0
- package/lib/commonjs/network/components/NetworkFilterScreen.web.js +55 -0
- package/lib/commonjs/network/components/NetworkFilterViewV3.web.js +1310 -0
- package/lib/commonjs/network/components/NetworkHeaderLive.web.js +604 -0
- package/lib/commonjs/network/components/NetworkListScreen.js +2 -1
- package/lib/commonjs/network/components/NetworkListScreen.web.js +607 -0
- package/lib/commonjs/network/components/NetworkModal.js +12 -3
- package/lib/commonjs/network/components/NetworkNumberPrompt.web.js +232 -0
- package/lib/commonjs/network/components/NetworkOverrideEditor.web.js +942 -0
- package/lib/commonjs/network/components/NetworkOverrideHeaderButton.web.js +133 -0
- package/lib/commonjs/network/components/NetworkOverridesButton.web.js +143 -0
- package/lib/commonjs/network/components/NetworkOverridesScreen.js +160 -126
- package/lib/commonjs/network/components/NetworkOverridesScreen.web.js +830 -0
- package/lib/commonjs/network/components/NetworkSavedScreen.web.js +459 -0
- package/lib/commonjs/network/components/response-editor/Explorer.web.js +1136 -0
- package/lib/commonjs/network/hooks/useNetworkEventList.js +12 -2
- package/lib/commonjs/network/overrides/applyToXhr.js +276 -15
- package/lib/commonjs/network/utils/generateNetworkCopyText.js +32 -5
- package/lib/commonjs/network/utils/networkEventStore.js +12 -4
- package/lib/commonjs/network/utils/networkListener.js +1 -16
- package/lib/module/index.web.js +81 -0
- package/lib/module/network/components/DataViewer.web.js +875 -0
- package/lib/module/network/components/NetworkCopyScreen.web.js +44 -0
- package/lib/module/network/components/NetworkCopySettingsView.web.js +1237 -0
- package/lib/module/network/components/NetworkDetailScreen.web.js +97 -0
- package/lib/module/network/components/NetworkDetailStepper.web.js +294 -0
- package/lib/module/network/components/NetworkEventDetailView.web.js +1496 -0
- package/lib/module/network/components/NetworkEventItemCompact.web.js +800 -0
- package/lib/module/network/components/NetworkFilterScreen.web.js +51 -0
- package/lib/module/network/components/NetworkFilterViewV3.web.js +1306 -0
- package/lib/module/network/components/NetworkHeaderLive.web.js +598 -0
- package/lib/module/network/components/NetworkListScreen.js +2 -1
- package/lib/module/network/components/NetworkListScreen.web.js +605 -0
- package/lib/module/network/components/NetworkModal.js +12 -3
- package/lib/module/network/components/NetworkNumberPrompt.web.js +230 -0
- package/lib/module/network/components/NetworkOverrideEditor.web.js +939 -0
- package/lib/module/network/components/NetworkOverrideHeaderButton.web.js +131 -0
- package/lib/module/network/components/NetworkOverridesButton.web.js +141 -0
- package/lib/module/network/components/NetworkOverridesScreen.js +161 -127
- package/lib/module/network/components/NetworkOverridesScreen.web.js +826 -0
- package/lib/module/network/components/NetworkSavedScreen.web.js +457 -0
- package/lib/module/network/components/response-editor/Explorer.web.js +1133 -0
- package/lib/module/network/hooks/useNetworkEventList.js +12 -2
- package/lib/module/network/overrides/applyToXhr.js +275 -15
- package/lib/module/network/utils/generateNetworkCopyText.js +28 -1
- package/lib/module/network/utils/networkEventStore.js +12 -4
- package/lib/module/network/utils/networkListener.js +1 -16
- package/lib/typescript/index.web.d.ts +56 -0
- package/lib/typescript/index.web.d.ts.map +1 -0
- package/lib/typescript/network/components/DataViewer.web.d.ts +78 -0
- package/lib/typescript/network/components/DataViewer.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts +27 -0
- package/lib/typescript/network/components/NetworkCopyScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts +68 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts +45 -0
- package/lib/typescript/network/components/NetworkDetailScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts +40 -0
- package/lib/typescript/network/components/NetworkDetailStepper.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts +67 -0
- package/lib/typescript/network/components/NetworkEventDetailView.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts +58 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts +28 -0
- package/lib/typescript/network/components/NetworkFilterScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts +74 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts +112 -0
- package/lib/typescript/network/components/NetworkHeaderLive.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkListScreen.web.d.ts +63 -0
- package/lib/typescript/network/components/NetworkListScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts +38 -0
- package/lib/typescript/network/components/NetworkNumberPrompt.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts +43 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts +32 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts +26 -0
- package/lib/typescript/network/components/NetworkOverridesButton.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +9 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts +69 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts +67 -0
- package/lib/typescript/network/components/NetworkSavedScreen.web.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/Explorer.web.d.ts +56 -0
- package/lib/typescript/network/components/response-editor/Explorer.web.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts +10 -0
- package/lib/typescript/network/hooks/useNetworkEventList.d.ts.map +1 -1
- package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -1
- package/lib/typescript/network/overrides/applyToXhr.d.ts +40 -14
- package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts +34 -1
- package/lib/typescript/network/utils/generateNetworkCopyText.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkListener.d.ts +0 -1
- package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
- 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
|
-
|
|
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
|
|
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
|
|
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:
|
|
16
|
-
* is `require('whatwg-fetch')` —
|
|
17
|
-
* XMLHttpRequest. Overriding here therefore
|
|
18
|
-
* XHR through one code path, and the fake
|
|
19
|
-
* polyfill so the tool records it without
|
|
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
|
-
*
|
|
24
|
-
*
|
|
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
|
|
61
|
+
* Can this XMLHttpRequest be driven through React Native's internals?
|
|
44
62
|
*
|
|
45
|
-
* The
|
|
46
|
-
* than assumed
|
|
47
|
-
*
|
|
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
|
|
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
|
-
|
|
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
|
|
112
|
-
|
|
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"}
|