/** * fetch monkey-patch — captures URL/method/headers/body for request and * response, including streaming SSE responses, without changing * business-observable fetch behavior. * * Safety contract (do not weaken without updating the spec): * 1. Identity-preserving: replacement is a named `fetch`, with * defineProperty'd name/length/toString so library fingerprint checks * still pass. Response / Request instances are NOT wrapped. * 2. Error-isolated: capture failures are swallowed via `safeEmit`; they * NEVER propagate to business code. * 3. No timing or value change: the original Promise is returned to the * caller unchanged. body capture reads `response.clone()` on a side * branch — the business path retains an untouched stream. * 4. Self-traffic guard: requests carrying `init.__hfeInternal === true` * short-circuit to the original fetch. A URL denylist also skips HMR / * dev-server traffic to prevent capture feedback loops. * 5. Bounded memory: bodies are capped at BODY_CAP per request. SSE * streams stop accumulating and `cancel()` the cloned reader once * the cap is hit. * * The patch is idempotent (re-install is a no-op) and returns a dispose * function that restores the original `window.fetch`. */ import type { NetworkEntry } from '@harnessa-fe/protocol'; export interface FetchPatchOptions { /** Called once for each emitted record (request and response are separate calls). */ onEntry: (entry: NetworkEntry) => void; /** Per-body byte cap. Default 256 KB. */ bodyCap?: number; /** URL patterns to skip capture entirely. */ denylist?: RegExp[]; } /** * Install the fetch patch. Returns a dispose function that restores the * original window.fetch. Safe to call multiple times (subsequent calls * are no-ops while a patch is active). */ export declare function installFetchPatch(opts: FetchPatchOptions): () => void;