@buoy-gg/network 7.0.12 → 7.0.14
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.js +52 -0
- package/lib/commonjs/network/components/NetworkDetailStepper.js +26 -14
- package/lib/commonjs/network/components/NetworkEventDetailView.js +86 -14
- package/lib/commonjs/network/components/NetworkEventItemCompact.js +4 -0
- package/lib/commonjs/network/components/NetworkHeaderLive.js +32 -7
- package/lib/commonjs/network/components/NetworkHeaderMenu.js +183 -0
- package/lib/commonjs/network/components/NetworkListScreen.js +134 -8
- package/lib/commonjs/network/components/NetworkModal.js +198 -51
- package/lib/commonjs/network/components/NetworkNumberPrompt.js +178 -0
- package/lib/commonjs/network/components/NetworkOverrideEditor.js +797 -0
- package/lib/commonjs/network/components/NetworkOverrideHeaderButton.js +102 -0
- package/lib/commonjs/network/components/NetworkOverridesButton.js +88 -0
- package/lib/commonjs/network/components/NetworkOverridesScreen.js +489 -0
- package/lib/commonjs/network/components/response-editor/Explorer.js +973 -0
- package/lib/commonjs/network/components/response-editor/deleteNestedDataByPath.js +56 -0
- package/lib/commonjs/network/components/response-editor/editorContext.js +33 -0
- package/lib/commonjs/network/components/response-editor/updateNestedDataByPath.js +61 -0
- package/lib/commonjs/network/hooks/useNetworkSelection.js +53 -0
- package/lib/commonjs/network/hooks/useOverrideRules.js +36 -0
- package/lib/commonjs/network/overrides/applyToFetch.js +80 -0
- package/lib/commonjs/network/overrides/applyToXhr.js +190 -0
- package/lib/commonjs/network/overrides/engine.js +70 -0
- package/lib/commonjs/network/overrides/matchRule.js +81 -0
- package/lib/commonjs/network/overrides/overrideRulesStore.js +550 -0
- package/lib/commonjs/network/overrides/presets.js +70 -0
- package/lib/commonjs/network/overrides/resolveOverride.js +158 -0
- package/lib/commonjs/network/overrides/types.js +85 -0
- package/lib/commonjs/network/sync/networkSyncAdapter.js +230 -1
- package/lib/commonjs/network/types/index.js +5 -1
- package/lib/commonjs/network/utils/networkEventStore.js +52 -6
- package/lib/commonjs/network/utils/networkListener.js +90 -10
- package/lib/commonjs/network/utils/networkSelectionStore.js +193 -0
- package/lib/commonjs/preset.js +11 -0
- package/lib/module/index.js +19 -0
- package/lib/module/network/components/NetworkDetailStepper.js +27 -15
- package/lib/module/network/components/NetworkEventDetailView.js +87 -15
- package/lib/module/network/components/NetworkEventItemCompact.js +5 -1
- package/lib/module/network/components/NetworkHeaderLive.js +32 -7
- package/lib/module/network/components/NetworkHeaderMenu.js +177 -0
- package/lib/module/network/components/NetworkListScreen.js +135 -9
- package/lib/module/network/components/NetworkModal.js +200 -53
- package/lib/module/network/components/NetworkNumberPrompt.js +174 -0
- package/lib/module/network/components/NetworkOverrideEditor.js +794 -0
- package/lib/module/network/components/NetworkOverrideHeaderButton.js +99 -0
- package/lib/module/network/components/NetworkOverridesButton.js +85 -0
- package/lib/module/network/components/NetworkOverridesScreen.js +485 -0
- package/lib/module/network/components/response-editor/Explorer.js +972 -0
- package/lib/module/network/components/response-editor/deleteNestedDataByPath.js +51 -0
- package/lib/module/network/components/response-editor/editorContext.js +29 -0
- package/lib/module/network/components/response-editor/updateNestedDataByPath.js +56 -0
- package/lib/module/network/hooks/useNetworkSelection.js +46 -0
- package/lib/module/network/hooks/useOverrideRules.js +32 -0
- package/lib/module/network/overrides/applyToFetch.js +72 -0
- package/lib/module/network/overrides/applyToXhr.js +185 -0
- package/lib/module/network/overrides/engine.js +64 -0
- package/lib/module/network/overrides/matchRule.js +75 -0
- package/lib/module/network/overrides/overrideRulesStore.js +547 -0
- package/lib/module/network/overrides/presets.js +65 -0
- package/lib/module/network/overrides/resolveOverride.js +152 -0
- package/lib/module/network/overrides/types.js +80 -0
- package/lib/module/network/sync/networkSyncAdapter.js +230 -1
- package/lib/module/network/types/index.js +3 -1
- package/lib/module/network/utils/networkEventStore.js +52 -6
- package/lib/module/network/utils/networkListener.js +91 -10
- package/lib/module/network/utils/networkSelectionStore.js +188 -0
- package/lib/module/preset.js +13 -1
- package/lib/typescript/index.d.ts +9 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkDetailStepper.d.ts +8 -5
- package/lib/typescript/network/components/NetworkDetailStepper.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts +36 -1
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkEventItemCompact.d.ts +6 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkHeaderLive.d.ts +13 -3
- package/lib/typescript/network/components/NetworkHeaderLive.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkHeaderMenu.d.ts +46 -0
- package/lib/typescript/network/components/NetworkHeaderMenu.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkListScreen.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -1
- package/lib/typescript/network/components/NetworkNumberPrompt.d.ts +33 -0
- package/lib/typescript/network/components/NetworkNumberPrompt.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.d.ts +17 -0
- package/lib/typescript/network/components/NetworkOverrideEditor.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts +27 -0
- package/lib/typescript/network/components/NetworkOverrideHeaderButton.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesButton.d.ts +17 -0
- package/lib/typescript/network/components/NetworkOverridesButton.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts +29 -0
- package/lib/typescript/network/components/NetworkOverridesScreen.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/Explorer.d.ts +17 -0
- package/lib/typescript/network/components/response-editor/Explorer.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts +9 -0
- package/lib/typescript/network/components/response-editor/deleteNestedDataByPath.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/editorContext.d.ts +29 -0
- package/lib/typescript/network/components/response-editor/editorContext.d.ts.map +1 -0
- package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts +10 -0
- package/lib/typescript/network/components/response-editor/updateNestedDataByPath.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useNetworkSelection.d.ts +26 -0
- package/lib/typescript/network/hooks/useNetworkSelection.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useOverrideRules.d.ts +29 -0
- package/lib/typescript/network/hooks/useOverrideRules.d.ts.map +1 -0
- package/lib/typescript/network/overrides/__tests__/applyToFetch.test.d.ts +16 -0
- package/lib/typescript/network/overrides/__tests__/applyToFetch.test.d.ts.map +1 -0
- package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts +19 -0
- package/lib/typescript/network/overrides/__tests__/applyToXhr.test.d.ts.map +1 -0
- package/lib/typescript/network/overrides/__tests__/resolveOverride.test.d.ts +22 -0
- package/lib/typescript/network/overrides/__tests__/resolveOverride.test.d.ts.map +1 -0
- package/lib/typescript/network/overrides/applyToFetch.d.ts +50 -0
- package/lib/typescript/network/overrides/applyToFetch.d.ts.map +1 -0
- package/lib/typescript/network/overrides/applyToXhr.d.ts +43 -0
- package/lib/typescript/network/overrides/applyToXhr.d.ts.map +1 -0
- package/lib/typescript/network/overrides/engine.d.ts +47 -0
- package/lib/typescript/network/overrides/engine.d.ts.map +1 -0
- package/lib/typescript/network/overrides/matchRule.d.ts +22 -0
- package/lib/typescript/network/overrides/matchRule.d.ts.map +1 -0
- package/lib/typescript/network/overrides/overrideRulesStore.d.ts +205 -0
- package/lib/typescript/network/overrides/overrideRulesStore.d.ts.map +1 -0
- package/lib/typescript/network/overrides/presets.d.ts +38 -0
- package/lib/typescript/network/overrides/presets.d.ts.map +1 -0
- package/lib/typescript/network/overrides/resolveOverride.d.ts +46 -0
- package/lib/typescript/network/overrides/resolveOverride.d.ts.map +1 -0
- package/lib/typescript/network/overrides/types.d.ts +169 -0
- package/lib/typescript/network/overrides/types.d.ts.map +1 -0
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts +73 -0
- package/lib/typescript/network/sync/networkSyncAdapter.d.ts.map +1 -1
- package/lib/typescript/network/types/index.d.ts +10 -0
- package/lib/typescript/network/types/index.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkEventStore.d.ts +14 -0
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkListener.d.ts +3 -0
- package/lib/typescript/network/utils/networkListener.d.ts.map +1 -1
- package/lib/typescript/network/utils/networkSelectionStore.d.ts +117 -0
- package/lib/typescript/network/utils/networkSelectionStore.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The override rule list — persisted, and the source of truth for the engine.
|
|
3
|
+
*
|
|
4
|
+
* Shape and persistence follow `networkSavedStore` / `ignoredPatternsStore`:
|
|
5
|
+
* lazy hydrate on first use, a `dirty` flag so a slow read can't clobber a
|
|
6
|
+
* mutation the user just made, and commit = set + emit + persist.
|
|
7
|
+
*
|
|
8
|
+
* Two things here are specific to overrides and worth reading:
|
|
9
|
+
*
|
|
10
|
+
* - `getRules()` is on the HOT PATH. It is called inside the app's own
|
|
11
|
+
* `XMLHttpRequest.send()`, for every request, so it does no work: the master
|
|
12
|
+
* switch collapses to returning a frozen empty array.
|
|
13
|
+
*
|
|
14
|
+
* - `syncKeepAlive()` keeps the interceptor installed while any rule is
|
|
15
|
+
* active. Without it a rule would stop firing the moment the Network tool
|
|
16
|
+
* closed, because the swizzle is reference-counted off capture subscribers.
|
|
17
|
+
*/
|
|
18
|
+
import { type OverrideRule } from "./types";
|
|
19
|
+
export interface OverrideRulesState {
|
|
20
|
+
/** Master switch. Off disables every rule without losing any of them. */
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
rules: OverrideRule[];
|
|
23
|
+
/**
|
|
24
|
+
* Set when the launch-safety guard turned overrides off by itself.
|
|
25
|
+
*
|
|
26
|
+
* Cleared the moment the developer turns them back on or touches a rule. The
|
|
27
|
+
* UI uses it to explain the state rather than leave it looking like a bug.
|
|
28
|
+
*/
|
|
29
|
+
autoPaused: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A rule as authored. `id`/`createdAt` and the runtime counters (`hits`,
|
|
33
|
+
* `seen`) are the store's business, never the caller's.
|
|
34
|
+
*/
|
|
35
|
+
export type OverrideRuleDraft = Omit<OverrideRule, "id" | "hits" | "seen" | "createdAt">;
|
|
36
|
+
/**
|
|
37
|
+
* Handlers the desktop dashboard installs to forward mutations to the device.
|
|
38
|
+
*
|
|
39
|
+
* Rules only DO anything on the device — a rule is applied inside the app's own
|
|
40
|
+
* `fetch`/`XMLHttpRequest`, which the dashboard doesn't have. So in remote mode
|
|
41
|
+
* this store becomes a MIRROR: it renders the device's rules and forwards every
|
|
42
|
+
* edit, writing nothing to this machine's storage. Same seam
|
|
43
|
+
* `networkSavedStore` uses for pins.
|
|
44
|
+
*/
|
|
45
|
+
export interface OverrideRulesRemote {
|
|
46
|
+
setEnabled: (enabled: boolean) => void;
|
|
47
|
+
upsertRule: (draft: OverrideRuleDraft & {
|
|
48
|
+
id?: string;
|
|
49
|
+
}) => void;
|
|
50
|
+
setRuleEnabled: (id: string, enabled: boolean) => void;
|
|
51
|
+
removeRule: (id: string) => void;
|
|
52
|
+
clearRules: () => void;
|
|
53
|
+
/**
|
|
54
|
+
* Fetch the body the snapshot withheld (see `OverrideRule.bodyOmitted`).
|
|
55
|
+
* Optional so an older dashboard still mirrors rules — it just shows an empty
|
|
56
|
+
* body for the large ones.
|
|
57
|
+
*/
|
|
58
|
+
getRuleBody?: (id: string) => Promise<string | null>;
|
|
59
|
+
}
|
|
60
|
+
type Listener = () => void;
|
|
61
|
+
declare class OverrideRulesStore {
|
|
62
|
+
private rules;
|
|
63
|
+
private enabled;
|
|
64
|
+
private readonly listeners;
|
|
65
|
+
private loaded;
|
|
66
|
+
private loadPromise;
|
|
67
|
+
/** Set once a mutation happens so a slow initial load can't clobber it. */
|
|
68
|
+
private dirty;
|
|
69
|
+
private idCounter;
|
|
70
|
+
private state;
|
|
71
|
+
/** Consecutive launches that began with rules armed and nobody touching them. */
|
|
72
|
+
private launchStreak;
|
|
73
|
+
private autoPaused;
|
|
74
|
+
/** Held while any rule is active — see `syncKeepAlive`. */
|
|
75
|
+
private keepAlive;
|
|
76
|
+
private hitEmitTimer;
|
|
77
|
+
/** Set on the desktop dashboard — see `disableEngine`. */
|
|
78
|
+
private engineDisabled;
|
|
79
|
+
/** Set on the desktop dashboard — see `OverrideRulesRemote`. */
|
|
80
|
+
private remote;
|
|
81
|
+
private remoteEchoUntil;
|
|
82
|
+
/**
|
|
83
|
+
* Turn this store into a mirror of a connected device's rules. Edits are
|
|
84
|
+
* applied locally for immediate feedback AND forwarded to the device, which
|
|
85
|
+
* is the source of truth; nothing is persisted to this machine.
|
|
86
|
+
*/
|
|
87
|
+
enableRemoteMode(remote: OverrideRulesRemote): void;
|
|
88
|
+
disableRemoteMode(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Feed the device's rules in (mirror mode only). `force` bypasses the echo
|
|
91
|
+
* guard — used when tearing the mirror down, where there is no later snapshot
|
|
92
|
+
* to converge on.
|
|
93
|
+
*/
|
|
94
|
+
replaceRules(state: OverrideRulesState, force?: boolean): void;
|
|
95
|
+
/** Mark a local optimistic write so the next in-flight mirror is ignored. */
|
|
96
|
+
private markLocalEdit;
|
|
97
|
+
/**
|
|
98
|
+
* Never intercept traffic in this runtime.
|
|
99
|
+
*
|
|
100
|
+
* The desktop dashboard renders the real tool (`NetworkToolView`), so this
|
|
101
|
+
* module is imported there too — but the dashboard is a VIEWER. Its job is to
|
|
102
|
+
* drive rules on the connected device, never to swizzle its own `fetch` and
|
|
103
|
+
* override its own requests. The same seam `networkEventStore.disableCapture()`
|
|
104
|
+
* uses, for the same reason.
|
|
105
|
+
*/
|
|
106
|
+
disableEngine(): void;
|
|
107
|
+
getState(): OverrideRulesState;
|
|
108
|
+
/**
|
|
109
|
+
* The hot path — called inside `send()` for every request the app makes.
|
|
110
|
+
* Returns a frozen empty array when the master switch is off so the caller
|
|
111
|
+
* needs no second check.
|
|
112
|
+
*/
|
|
113
|
+
getRules(): readonly OverrideRule[];
|
|
114
|
+
/**
|
|
115
|
+
* The rule's real body, fetching it from the device when this surface only
|
|
116
|
+
* has the stripped copy (see `OverrideRule.bodyOmitted`).
|
|
117
|
+
*
|
|
118
|
+
* On the device itself every body is already here, so this resolves
|
|
119
|
+
* immediately and the editor never notices the difference.
|
|
120
|
+
*/
|
|
121
|
+
fetchRuleBody(id: string): Promise<string | null>;
|
|
122
|
+
/** Rules that would actually fire — drives the "overrides active" banner. */
|
|
123
|
+
activeCount(): number;
|
|
124
|
+
subscribe(listener: Listener): () => void;
|
|
125
|
+
setEnabled(enabled: boolean): void;
|
|
126
|
+
addRule(draft: OverrideRuleDraft): OverrideRule | null;
|
|
127
|
+
/**
|
|
128
|
+
* Create or replace a rule in one call.
|
|
129
|
+
*
|
|
130
|
+
* THE ONLY WRITE PATH THE UI SHOULD USE. `addRule`/`updateRule` are the
|
|
131
|
+
* primitives underneath and deliberately do NOT forward to the device — if
|
|
132
|
+
* the UI called them directly, an edit made on the dashboard would apply to
|
|
133
|
+
* the mirror and never reach the phone, which looks exactly like it worked.
|
|
134
|
+
*
|
|
135
|
+
* Returns the rule, or null when the list is full.
|
|
136
|
+
*/
|
|
137
|
+
upsertRule(draft: OverrideRuleDraft & {
|
|
138
|
+
id?: string;
|
|
139
|
+
}): OverrideRule | null;
|
|
140
|
+
updateRule(id: string, patch: Partial<OverrideRuleDraft>): void;
|
|
141
|
+
setRuleEnabled(id: string, enabled: boolean): void;
|
|
142
|
+
removeRule(id: string): void;
|
|
143
|
+
clearRules(): void;
|
|
144
|
+
/**
|
|
145
|
+
* One rule matched one request.
|
|
146
|
+
*
|
|
147
|
+
* Replaces the rule object rather than mutating it so memoized rows actually
|
|
148
|
+
* re-render, and coalesces the notification — this runs at request rate.
|
|
149
|
+
*/
|
|
150
|
+
/**
|
|
151
|
+
* One rule matched one request, applied or not.
|
|
152
|
+
*
|
|
153
|
+
* Deliberately silent — this fires on requests an alternating rule lets
|
|
154
|
+
* through, where nothing visible changed. `recordHit` owns the notification.
|
|
155
|
+
*/
|
|
156
|
+
recordMatch(ruleId: string): void;
|
|
157
|
+
recordHit(ruleId: string): void;
|
|
158
|
+
/**
|
|
159
|
+
* Hydrate from storage. Safe to call repeatedly; only the first call reads.
|
|
160
|
+
*
|
|
161
|
+
* Called at package import (see `preset.tsx`) rather than on first subscribe,
|
|
162
|
+
* because a rule has to fire from app boot — with the Network tool closed and
|
|
163
|
+
* nothing capturing.
|
|
164
|
+
*/
|
|
165
|
+
ensureLoaded(): Promise<void>;
|
|
166
|
+
/**
|
|
167
|
+
* Count this launch, and pause overrides if they've been armed and untouched
|
|
168
|
+
* for too many in a row. See MAX_UNTOUCHED_LAUNCHES for why.
|
|
169
|
+
*/
|
|
170
|
+
private applyLaunchGuard;
|
|
171
|
+
/**
|
|
172
|
+
* Keep the interceptor installed for as long as a rule could fire.
|
|
173
|
+
*
|
|
174
|
+
* The swizzle is reference-counted off `networkListener`'s listener count
|
|
175
|
+
* (the event store adds one while capturing). Holding a no-op listener reuses
|
|
176
|
+
* that existing lifecycle instead of inventing a second one.
|
|
177
|
+
*/
|
|
178
|
+
private syncKeepAlive;
|
|
179
|
+
private scheduleHitEmit;
|
|
180
|
+
private commit;
|
|
181
|
+
/** Rebuild the derived view once per mutation so renders get stable refs. */
|
|
182
|
+
private rebuild;
|
|
183
|
+
/**
|
|
184
|
+
* The developer is actively working with the rules, so the launch guard has
|
|
185
|
+
* nothing to protect them from — reset it and clear any auto-pause notice.
|
|
186
|
+
*/
|
|
187
|
+
private markTouched;
|
|
188
|
+
/**
|
|
189
|
+
* The developer reached the override UI, which is proof the app still runs.
|
|
190
|
+
*
|
|
191
|
+
* The launch guard exists to escape a WEDGE — a body the app can't render,
|
|
192
|
+
* where the controls are unreachable because nothing draws. If this call
|
|
193
|
+
* happens, that isn't the situation, so the streak has nothing to protect
|
|
194
|
+
* against. Without it the guard nags anyone who legitimately keeps a rule
|
|
195
|
+
* armed for days, which is a real workflow ("force /checkout to 500 every
|
|
196
|
+
* morning") and not the failure mode it was built for.
|
|
197
|
+
*/
|
|
198
|
+
noteHealthyLaunch(): void;
|
|
199
|
+
private persist;
|
|
200
|
+
private emit;
|
|
201
|
+
}
|
|
202
|
+
/** Singleton — one rule list per JS runtime. */
|
|
203
|
+
export declare const overrideRulesStore: OverrideRulesStore;
|
|
204
|
+
export {};
|
|
205
|
+
//# sourceMappingURL=overrideRulesStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overrideRulesStore.d.ts","sourceRoot":"","sources":["../../../../src/network/overrides/overrideRulesStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning a captured request into a rule draft.
|
|
3
|
+
*
|
|
4
|
+
* Chrome's flow assumes a keyboard, a file tree and a second monitor. On a
|
|
5
|
+
* phone the equivalent has to start from the request you're already looking at,
|
|
6
|
+
* which is what this file is for — the editor never opens on a blank field.
|
|
7
|
+
*
|
|
8
|
+
* There used to be a list of one-tap presets here (Force 500, Empty list,
|
|
9
|
+
* Offline…) rendered as chips. They're gone: the editor's outcome grid says the
|
|
10
|
+
* same things in the same words, so keeping both meant two lists to maintain
|
|
11
|
+
* and two places to look for the same choice.
|
|
12
|
+
*/
|
|
13
|
+
import type { NetworkEvent } from "../types";
|
|
14
|
+
import type { OverrideRuleDraft } from "./overrideRulesStore";
|
|
15
|
+
/**
|
|
16
|
+
* Turn a captured URL into a pattern that will match the request AGAIN.
|
|
17
|
+
*
|
|
18
|
+
* The query string is dropped and replaced with `*`, which is not a
|
|
19
|
+
* simplification — it's the difference between a rule that works and one that
|
|
20
|
+
* silently never fires. Plenty of clients cache-bust
|
|
21
|
+
* (`?timestamp=1785783081234`), carry a request id, or page; pinning the exact
|
|
22
|
+
* URL means the next call to the same endpoint doesn't match. Found exactly
|
|
23
|
+
* that way: an "Offline" preset on a Pokémon request sat at 0 hits because the
|
|
24
|
+
* app appends a timestamp to every call.
|
|
25
|
+
*
|
|
26
|
+
* The path stays exact, so this still means "this endpoint" and not "this
|
|
27
|
+
* host" — and the editor shows the pattern, so narrowing it back down is one
|
|
28
|
+
* edit away.
|
|
29
|
+
*/
|
|
30
|
+
export declare function patternForUrl(url: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Prefill the rule editor from a captured request.
|
|
33
|
+
*
|
|
34
|
+
* Seeds the REAL response as the body so the common edit — change two fields of
|
|
35
|
+
* a payload you just saw — starts from something true rather than from nothing.
|
|
36
|
+
*/
|
|
37
|
+
export declare function draftFromEvent(event: NetworkEvent): OverrideRuleDraft;
|
|
38
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../../../src/network/overrides/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE9D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGjD;AAaD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,YAAY,GAAG,iBAAiB,CAYrE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decide whether a request is overridden — the whole decision, in one pure
|
|
3
|
+
* function.
|
|
4
|
+
*
|
|
5
|
+
* Pure on purpose: this is the piece worth unit-testing, and it runs inside the
|
|
6
|
+
* app's own `XMLHttpRequest.send()`, so it must be cheap, total, and incapable
|
|
7
|
+
* of throwing. Everything that could surprise (defaults, clamping, content-type
|
|
8
|
+
* inference) is resolved HERE, so `applyToXhr` never makes a decision — it just
|
|
9
|
+
* performs the outcome.
|
|
10
|
+
*/
|
|
11
|
+
import { type OverrideOutcome, type OverrideRule } from "./types";
|
|
12
|
+
/** Normalize a matched rule into the exact instructions the interceptor needs. */
|
|
13
|
+
declare function toOutcome(rule: OverrideRule): OverrideOutcome;
|
|
14
|
+
/** A rule that has burned through its `times` budget no longer applies. */
|
|
15
|
+
export declare function isSpent(rule: OverrideRule): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Is this rule in a phase where it should actually fire?
|
|
18
|
+
*
|
|
19
|
+
* Only `alternate` can answer no. It reads the CURRENT `seen` count, before
|
|
20
|
+
* this match is recorded, so an untouched rule (`seen === 0`) lets the first
|
|
21
|
+
* request through and overrides the second.
|
|
22
|
+
*/
|
|
23
|
+
export declare function shouldApply(rule: OverrideRule): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The first enabled rule whose pattern covers this request, phase ignored.
|
|
26
|
+
*
|
|
27
|
+
* Separate from `resolveOverride` because an alternating rule has to advance
|
|
28
|
+
* its phase on the requests it deliberately skips — the caller needs the rule
|
|
29
|
+
* back even when the answer is "not this time".
|
|
30
|
+
*/
|
|
31
|
+
export declare function findMatchingRule(url: string, method: string, rules: readonly OverrideRule[]): OverrideRule | null;
|
|
32
|
+
/**
|
|
33
|
+
* First ENABLED matching rule wins outright — no merging across rules.
|
|
34
|
+
*
|
|
35
|
+
* Chrome cascades header overrides from the most general path segment to the
|
|
36
|
+
* most specific, but that only exists because its rules are directory-nested
|
|
37
|
+
* files. A flat list with a cascade would be a rule whose effect you cannot see
|
|
38
|
+
* by reading it, which is exactly the wrong trade on a phone screen.
|
|
39
|
+
*
|
|
40
|
+
* @param url Full request URL, query string included.
|
|
41
|
+
* @param method HTTP method as the caller sent it (case-insensitive).
|
|
42
|
+
* @param rules Ordered rule list; earlier entries win.
|
|
43
|
+
*/
|
|
44
|
+
export declare function resolveOverride(url: string, method: string, rules: readonly OverrideRule[]): OverrideOutcome | null;
|
|
45
|
+
export { toOutcome };
|
|
46
|
+
//# sourceMappingURL=resolveOverride.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolveOverride.d.ts","sourceRoot":"","sources":["../../../../src/network/overrides/resolveOverride.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AA4CjB,kFAAkF;AAClF,iBAAS,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,eAAe,CA6BtD;AAED,2EAA2E;AAC3E,wBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAEnD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAGvD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,YAAY,EAAE,GAC7B,YAAY,GAAG,IAAI,CAcrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,YAAY,EAAE,GAC7B,eAAe,GAAG,IAAI,CAIxB;AAED,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network response overrides — the rule model.
|
|
3
|
+
*
|
|
4
|
+
* This is Buoy's answer to Chrome DevTools' "Local Overrides", reshaped for
|
|
5
|
+
* mobile. Two deliberate differences from Chrome are worth knowing, because
|
|
6
|
+
* they explain the whole shape of this file:
|
|
7
|
+
*
|
|
8
|
+
* 1. Chrome's rules ARE a directory tree — a body override is a file at
|
|
9
|
+
* `<host>/<path>`, header overrides live in per-directory `.headers` files,
|
|
10
|
+
* and its general→specific header cascade exists only to hang off that
|
|
11
|
+
* nesting. We have no filesystem, so rules are a flat ordered list and the
|
|
12
|
+
* FIRST enabled match wins outright. That's what Charles/Proxyman/MSW do,
|
|
13
|
+
* and it's what a developer can reason about on a phone screen.
|
|
14
|
+
*
|
|
15
|
+
* 2. Chrome CANNOT change a status code. `NetworkManager.ts` computes
|
|
16
|
+
* `responseCode = isBodyOverridden ? 200 : (responseStatusCode || 200)`, so
|
|
17
|
+
* overriding a body forces 200, and there is no latency or failure
|
|
18
|
+
* simulation at all. Chrome's feature is "serve different bytes". Forcing a
|
|
19
|
+
* 500, a timeout or a 3s stall is the entire mobile use case, so `status`,
|
|
20
|
+
* `delayMs` and `kind: "fail"` below are the point of the exercise.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* What a rule does when it matches.
|
|
24
|
+
*
|
|
25
|
+
* - `respond` — synthesize a response. The request never leaves the device.
|
|
26
|
+
* - `fail` — synthesize a transport failure (offline / timeout). Also never
|
|
27
|
+
* leaves the device.
|
|
28
|
+
* - `delay` — let the real request run, just late. Pure latency injection.
|
|
29
|
+
*/
|
|
30
|
+
export type OverrideRuleKind = "respond" | "fail" | "delay";
|
|
31
|
+
/**
|
|
32
|
+
* Which transport failure to fake.
|
|
33
|
+
*
|
|
34
|
+
* `network` surfaces the way a real offline request does — `fetch` rejects with
|
|
35
|
+
* `TypeError: Network request failed`. This is also how you simulate "status 0":
|
|
36
|
+
* you can't, via `respond`, because whatwg-fetch's `Response` constructor throws
|
|
37
|
+
* a RangeError outside 200–599 (see STATUS_MIN/STATUS_MAX).
|
|
38
|
+
*/
|
|
39
|
+
export type OverrideFailKind = "network" | "timeout";
|
|
40
|
+
/**
|
|
41
|
+
* Status codes a synthesized response may use.
|
|
42
|
+
*
|
|
43
|
+
* NOT an arbitrary product decision: React Native's `fetch` is the whatwg-fetch
|
|
44
|
+
* polyfill, whose `Response` constructor throws
|
|
45
|
+
* `RangeError: The status provided is outside the range [200, 599]`. A rule set
|
|
46
|
+
* to 0 would therefore crash the app's own fetch call rather than override it.
|
|
47
|
+
* Use `kind: "fail"` for connection-level failures.
|
|
48
|
+
*/
|
|
49
|
+
export declare const STATUS_MIN = 200;
|
|
50
|
+
export declare const STATUS_MAX = 599;
|
|
51
|
+
/** Bounds the persisted list so a runaway UI can't fill storage. */
|
|
52
|
+
export declare const MAX_RULES = 50;
|
|
53
|
+
/** Free tier gets one active rule; Pro is unlimited (up to MAX_RULES). */
|
|
54
|
+
export declare const FREE_TIER_RULE_LIMIT = 1;
|
|
55
|
+
export interface OverrideRule {
|
|
56
|
+
id: string;
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
/** Display label. Falls back to `urlPattern` when absent. */
|
|
59
|
+
name?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Glob matched against the FULL request URL, query string included.
|
|
62
|
+
*
|
|
63
|
+
* `*` is the only wildcard and the match is anchored, exactly like Chrome's
|
|
64
|
+
* `applyTo` patterns — see `escapeRegex` in `matchRule.ts`, ported from
|
|
65
|
+
* `NetworkPersistenceManager.ts:1051` so a pattern behaves the same way here
|
|
66
|
+
* as it does in the browser.
|
|
67
|
+
*/
|
|
68
|
+
urlPattern: string;
|
|
69
|
+
/** Uppercase methods. Absent or empty means "any method". */
|
|
70
|
+
methods?: string[];
|
|
71
|
+
kind: OverrideRuleKind;
|
|
72
|
+
/** `respond` only. Clamped to [STATUS_MIN, STATUS_MAX]. Defaults to 200. */
|
|
73
|
+
status?: number;
|
|
74
|
+
/**
|
|
75
|
+
* `respond` only. React Native's XMLHttpRequest has no `statusText` field at
|
|
76
|
+
* all (real requests report `undefined`), so this is purely cosmetic — it
|
|
77
|
+
* makes the tool's own list read correctly.
|
|
78
|
+
*/
|
|
79
|
+
statusText?: string;
|
|
80
|
+
/** `respond` only. A `content-type` is inferred from the body when omitted. */
|
|
81
|
+
headers?: Record<string, string>;
|
|
82
|
+
/** `respond` only. Raw text; JSON is just JSON-shaped text. */
|
|
83
|
+
body?: string;
|
|
84
|
+
/** `fail` only. Defaults to `network`. */
|
|
85
|
+
failKind?: OverrideFailKind;
|
|
86
|
+
/** Latency before the outcome, in ms. Applies to all three kinds. */
|
|
87
|
+
delayMs?: number;
|
|
88
|
+
/**
|
|
89
|
+
* Auto-disable after N matches; `null`/absent means "forever".
|
|
90
|
+
*
|
|
91
|
+
* A throwaway rule ("make the next save fail") should retire itself. A rule
|
|
92
|
+
* that silently breaks the app tomorrow is this feature's main footgun.
|
|
93
|
+
*/
|
|
94
|
+
times?: number | null;
|
|
95
|
+
/**
|
|
96
|
+
* Apply to every OTHER matching request instead of every one.
|
|
97
|
+
*
|
|
98
|
+
* For the failure that isn't total: a flaky endpoint, a retry that should
|
|
99
|
+
* succeed on the second attempt, a token refresh that only fires after one
|
|
100
|
+
* 401. Those paths are where retry logic is usually wrong, and a rule that's
|
|
101
|
+
* either always-on or always-off can't reach them.
|
|
102
|
+
*
|
|
103
|
+
* The first matching request passes THROUGH, the second is overridden, and it
|
|
104
|
+
* alternates forever — so the sequence is off, on, off, on.
|
|
105
|
+
*/
|
|
106
|
+
alternate?: boolean;
|
|
107
|
+
/** Times this rule was APPLIED. Runtime-only counter; not persisted. */
|
|
108
|
+
hits: number;
|
|
109
|
+
/**
|
|
110
|
+
* Times this rule MATCHED, whether or not it applied. Runtime-only.
|
|
111
|
+
*
|
|
112
|
+
* Distinct from `hits` because `alternate` needs to advance its phase on the
|
|
113
|
+
* requests it deliberately lets through — counting only applications would
|
|
114
|
+
* leave it stuck in the off phase forever.
|
|
115
|
+
*/
|
|
116
|
+
seen: number;
|
|
117
|
+
createdAt: number;
|
|
118
|
+
/**
|
|
119
|
+
* WIRE-ONLY: this rule's `body` was too big to ride the sync snapshot and was
|
|
120
|
+
* left out of it. Never persisted, never set on the device's own copy.
|
|
121
|
+
*
|
|
122
|
+
* A rule seeded from a real request holds that request's whole response —
|
|
123
|
+
* half a megabyte is normal — and the snapshot goes out several times a second
|
|
124
|
+
* while traffic flows. Streaming those bodies forever is the freeze that
|
|
125
|
+
* `stripLargeBodies` already exists to prevent for events.
|
|
126
|
+
*
|
|
127
|
+
* Remote surfaces fetch the real body with `getOverrideRuleBody` when the user
|
|
128
|
+
* actually opens the rule. The flag also protects the body on save: a
|
|
129
|
+
* dashboard editing a rule it never received the body for sends this back, and
|
|
130
|
+
* the device keeps what it has rather than wiping it.
|
|
131
|
+
*/
|
|
132
|
+
bodyOmitted?: boolean;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Stamped onto the `NetworkEvent` a rule affected, so the list can badge the
|
|
136
|
+
* row and the detail view can offer "edit / disable the rule that did this".
|
|
137
|
+
*/
|
|
138
|
+
export interface NetworkOverrideMark {
|
|
139
|
+
ruleId: string;
|
|
140
|
+
ruleName?: string;
|
|
141
|
+
kind: OverrideRuleKind;
|
|
142
|
+
delayMs?: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* A matched rule, normalized into exactly what the interceptor needs — defaults
|
|
146
|
+
* resolved, status clamped, content-type inferred. Keeping normalization in the
|
|
147
|
+
* resolver means `applyToXhr` never has to make a decision.
|
|
148
|
+
*/
|
|
149
|
+
export type OverrideOutcome = {
|
|
150
|
+
kind: "respond";
|
|
151
|
+
rule: OverrideRule;
|
|
152
|
+
delayMs: number;
|
|
153
|
+
status: number;
|
|
154
|
+
statusText: string;
|
|
155
|
+
headers: Record<string, string>;
|
|
156
|
+
body: string;
|
|
157
|
+
} | {
|
|
158
|
+
kind: "fail";
|
|
159
|
+
rule: OverrideRule;
|
|
160
|
+
delayMs: number;
|
|
161
|
+
failKind: OverrideFailKind;
|
|
162
|
+
} | {
|
|
163
|
+
kind: "delay";
|
|
164
|
+
rule: OverrideRule;
|
|
165
|
+
delayMs: number;
|
|
166
|
+
};
|
|
167
|
+
/** The marker recorded for an outcome. */
|
|
168
|
+
export declare function markForOutcome(outcome: OverrideOutcome): NetworkOverrideMark;
|
|
169
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/network/overrides/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AAE5D;;;;;;;GAOG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,MAAM,CAAC;AAC9B,eAAO,MAAM,UAAU,MAAM,CAAC;AAE9B,oEAAoE;AACpE,eAAO,MAAM,SAAS,KAAK,CAAC;AAE5B,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,gBAAgB,CAAC;IACvB,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;OAaG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,gBAAgB,CAAC;CAC5B,GACD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,0CAA0C;AAC1C,wBAAgB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,mBAAmB,CAO5E"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { OverrideRulesState } from "../overrides/overrideRulesStore";
|
|
2
|
+
import type { OverrideRuleKind } from "../overrides/types";
|
|
1
3
|
import type { NetworkEvent } from "../types";
|
|
2
4
|
/**
|
|
3
5
|
* Request/response bodies larger than this (using the cached size proxy already
|
|
@@ -31,6 +33,12 @@ export declare const networkSyncAdapter: {
|
|
|
31
33
|
version: number;
|
|
32
34
|
getSnapshot: () => {
|
|
33
35
|
events: NetworkEvent[];
|
|
36
|
+
/**
|
|
37
|
+
* Response-override rules live on the DEVICE — that's the only place they
|
|
38
|
+
* can run, since a rule is applied inside the app's own XMLHttpRequest.
|
|
39
|
+
* Remote surfaces mirror this and forward their edits back as actions.
|
|
40
|
+
*/
|
|
41
|
+
overrides: OverrideRulesState;
|
|
34
42
|
saved: {
|
|
35
43
|
event: NetworkEvent;
|
|
36
44
|
key: string;
|
|
@@ -85,6 +93,71 @@ export declare const networkSyncAdapter: {
|
|
|
85
93
|
clearPinnedRequests: () => {
|
|
86
94
|
ok: boolean;
|
|
87
95
|
};
|
|
96
|
+
/** Master switch — turns every rule off without losing any of them. */
|
|
97
|
+
setOverridesEnabled: (params: unknown) => {
|
|
98
|
+
ok: boolean;
|
|
99
|
+
enabled: boolean;
|
|
100
|
+
};
|
|
101
|
+
/** Create a rule, or replace one by id. */
|
|
102
|
+
upsertOverrideRule: (params: unknown) => {
|
|
103
|
+
ok: boolean;
|
|
104
|
+
error: string;
|
|
105
|
+
rule?: undefined;
|
|
106
|
+
} | {
|
|
107
|
+
ok: boolean;
|
|
108
|
+
rule: {
|
|
109
|
+
id: string;
|
|
110
|
+
urlPattern: string;
|
|
111
|
+
enabled: boolean;
|
|
112
|
+
kind: OverrideRuleKind;
|
|
113
|
+
status: number | undefined;
|
|
114
|
+
bodySize: number;
|
|
115
|
+
};
|
|
116
|
+
error?: undefined;
|
|
117
|
+
};
|
|
118
|
+
setOverrideRuleEnabled: (params: unknown) => {
|
|
119
|
+
ok: boolean;
|
|
120
|
+
error: string;
|
|
121
|
+
} | {
|
|
122
|
+
ok: boolean;
|
|
123
|
+
error?: undefined;
|
|
124
|
+
};
|
|
125
|
+
deleteOverrideRule: (params: unknown) => {
|
|
126
|
+
ok: boolean;
|
|
127
|
+
error: string;
|
|
128
|
+
} | {
|
|
129
|
+
ok: boolean;
|
|
130
|
+
error?: undefined;
|
|
131
|
+
};
|
|
132
|
+
clearOverrideRules: () => {
|
|
133
|
+
ok: boolean;
|
|
134
|
+
};
|
|
135
|
+
/** Read the rules back — hit counts included, which the snapshot coalesces. */
|
|
136
|
+
listOverrideRules: () => OverrideRulesState;
|
|
137
|
+
/**
|
|
138
|
+
* The full body of one rule, for the surfaces the snapshot withheld it from
|
|
139
|
+
* (see `stripLargeRuleBodies`). Fetched when the user opens the rule, which
|
|
140
|
+
* is the only moment it's needed.
|
|
141
|
+
*/
|
|
142
|
+
getOverrideRuleBody: (params: unknown) => {
|
|
143
|
+
body: string | null;
|
|
144
|
+
} | null;
|
|
145
|
+
/** Why isn't my rule firing? Reports the engine's own view of the world. */
|
|
146
|
+
debugOverrides: (params: unknown) => {
|
|
147
|
+
interceptorInstalled: boolean;
|
|
148
|
+
listenerCount: number;
|
|
149
|
+
engine: {
|
|
150
|
+
hooksInstalled: boolean;
|
|
151
|
+
devFlag: string | boolean;
|
|
152
|
+
ruleCount: number;
|
|
153
|
+
matches: boolean;
|
|
154
|
+
};
|
|
155
|
+
store: {
|
|
156
|
+
enabled: boolean;
|
|
157
|
+
ruleCount: number;
|
|
158
|
+
rulesVisibleToEngine: number;
|
|
159
|
+
};
|
|
160
|
+
};
|
|
88
161
|
};
|
|
89
162
|
};
|
|
90
163
|
//# sourceMappingURL=networkSyncAdapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkSyncAdapter.d.ts","sourceRoot":"","sources":["../../../../src/network/sync/networkSyncAdapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"networkSyncAdapter.d.ts","sourceRoot":"","sources":["../../../../src/network/sync/networkSyncAdapter.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAEV,kBAAkB,EACnB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;;;;;;GASG;AACH,eAAO,MAAM,0BAA0B,QAAY,CAAC;AA8JpD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,kBAAkB;;;;QAI3B;;;;WAIG;;;;;;;;;;;;;0BAUiB,MAAM,IAAI;;;QAkB9B;;;;;WAKG;+BACoB,OAAO;;;;QAU9B,8CAA8C;4BAC1B,OAAO;;;;;;;;;QAY3B,gDAAgD;2BAC7B,OAAO;;;;;;;;;QAU1B,sDAAsD;oCAC1B,OAAO;;;;;;;;;QAsBnC,uEAAuE;sCACzC,OAAO;;;;QAKrC,2CAA2C;qCACd,OAAO;;;;;;;;;;;;;;;;yCAmCH,OAAO;;;;;;;qCAOX,OAAO;;;;;;;;;;QAYpC,+EAA+E;;QAG/E;;;;WAIG;sCAC2B,OAAO;;;QAYrC,4EAA4E;iCACnD,OAAO;;;;;;;;;;;;;;;;CAiBnC,CAAC"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Network monitoring types for React Native dev tools
|
|
3
3
|
*/
|
|
4
|
+
import type { NetworkOverrideMark } from "../overrides/types";
|
|
5
|
+
export type { NetworkOverrideMark, OverrideRule, OverrideRuleKind, OverrideFailKind, } from "../overrides/types";
|
|
4
6
|
/**
|
|
5
7
|
* The parts of a request's lifetime we can actually observe from JavaScript.
|
|
6
8
|
*
|
|
@@ -93,6 +95,14 @@ export interface NetworkEvent {
|
|
|
93
95
|
* // Display: "GetPokemon › Sandshrew"
|
|
94
96
|
*/
|
|
95
97
|
graphqlVariables?: Record<string, unknown>;
|
|
98
|
+
/**
|
|
99
|
+
* Set when a response-override rule affected this request.
|
|
100
|
+
*
|
|
101
|
+
* OPTIONAL ON PURPOSE, like `timings` — absent on requests captured before
|
|
102
|
+
* overrides existed, and on devices running an older Buoy than the dashboard.
|
|
103
|
+
* Consumers must treat its absence as "not overridden", never as "unknown".
|
|
104
|
+
*/
|
|
105
|
+
override?: NetworkOverrideMark;
|
|
96
106
|
}
|
|
97
107
|
/**
|
|
98
108
|
* Aggregated counts derived from the currently loaded set of network events.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/network/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B;;;;;;;OAOG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EACF,KAAK,GACL,MAAM,GACN,KAAK,GACL,QAAQ,GACR,OAAO,GACP,MAAM,GACN,SAAS,GACT,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,UAAU,CAAC;IACnE;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/network/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,13 @@ export type NetworkEventCallback = (event: NetworkEvent) => void;
|
|
|
31
31
|
export type NetworkEventsArrayCallback = (events: NetworkEvent[]) => void;
|
|
32
32
|
declare class NetworkEventStore extends BaseEventStore<NetworkEvent> {
|
|
33
33
|
private pendingRequests;
|
|
34
|
+
/**
|
|
35
|
+
* Recently seen `METHOD:url` keys → when, and which event id we kept.
|
|
36
|
+
*
|
|
37
|
+
* The timestamp powers the dual-interception dedup below. The id is what lets
|
|
38
|
+
* a DROPPED duplicate still contribute something the kept event doesn't know
|
|
39
|
+
* — see `applyOverrideMark`.
|
|
40
|
+
*/
|
|
34
41
|
private recentRequests;
|
|
35
42
|
private rawListenerUnsubscribe;
|
|
36
43
|
constructor();
|
|
@@ -50,6 +57,13 @@ declare class NetworkEventStore extends BaseEventStore<NetworkEvent> {
|
|
|
50
57
|
* Process a network listener event
|
|
51
58
|
*/
|
|
52
59
|
processNetworkEvent(event: NetworkingEvent): void;
|
|
60
|
+
/**
|
|
61
|
+
* Stamp an override mark onto an already-recorded event.
|
|
62
|
+
*
|
|
63
|
+
* Only ever moves a mark from a dropped duplicate onto the event that was
|
|
64
|
+
* kept, so it never overwrites one that is already there.
|
|
65
|
+
*/
|
|
66
|
+
private applyOverrideMark;
|
|
53
67
|
private extractHost;
|
|
54
68
|
private extractPath;
|
|
55
69
|
private getDataSize;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networkEventStore.d.ts","sourceRoot":"","sources":["../../../../src/network/utils/networkEventStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"networkEventStore.d.ts","sourceRoot":"","sources":["../../../../src/network/utils/networkEventStore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAQzD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,IAAI,CAAC;AAE1E,cAAM,iBAAkB,SAAQ,cAAc,CAAC,YAAY,CAAC;IAC1D,OAAO,CAAC,eAAe,CAAwC;IAC/D;;;;;;OAMG;IACH,OAAO,CAAC,cAAc,CAAsD;IAC5E,OAAO,CAAC,sBAAsB,CAA6B;;IAS3D;;OAEG;IACH,SAAS,CAAC,cAAc,IAAI,IAAI;IAgBhC;;OAEG;IACH,SAAS,CAAC,aAAa,IAAI,IAAI;IAc/B;;OAEG;IACH,WAAW,IAAI,OAAO;IAItB;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAgIjD;;;;;OAKG;IACH,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,WAAW;IAUnB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIlD;;OAEG;IACH,WAAW,IAAI,IAAI;IAMnB;;OAEG;IACH,OAAO,CAAC,QAAQ,EAAE,oBAAoB,EAAE,cAAc,UAAO,GAAG,MAAM,IAAI;IAkB1E,QAAQ;;;;;;;;;IAuCR,YAAY,CAAC,MAAM,EAAE;QACnB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;QACzC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,YAAY,EAAE;CAyCnB;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
|