import type { Command } from '../args.js'; import type { Profile } from '../profiles.js'; import { type DerivedServerOpts } from '../server-opts.js'; import { type Io } from '../output.js'; /** The surface every fpx verb touches on FetchproxyServer (mock-friendly). */ export interface VerbServer { listen(): Promise; close(): Promise; request(method: string, path: string, opts?: { headers?: Record; body?: string; domain?: string; viaTab?: string; inPage?: boolean; credentials?: 'include' | 'omit'; }): Promise<{ status: number; body: string; url: string; }>; readCookies(o: { keys: string[]; domain?: string; subdomain?: string; }): Promise; readLocalStorage(o: { keys: string[]; domain?: string; subdomain?: string; }): Promise>; readSessionStorage(o: { keys: string[]; domain?: string; subdomain?: string; }): Promise>; readIndexedDb(o: { database: string; store: string; keys: string[]; domain?: string; subdomain?: string; }): Promise>; captureRequestHeader(o: { headerName: string; host: string; path?: string; timeoutMs?: number; }): Promise; captureRedirect(o: { host: string; path?: string; timeoutMs?: number; }): Promise; graphqlQuery(o: { name: string; variables: Record; tabUrl?: string; }): Promise; writeCookies(o: { cookies: Record; domain?: string; subdomain?: string; path?: string; }): Promise; readDom(o: { names: string[]; domain?: string; subdomain?: string; }): Promise>; readDomList(o: { name: string; domain?: string; subdomain?: string; }): Promise[]>; download(o: { url: string; filename?: string; }): Promise<{ path: string; bytes: number; mime?: string; finalUrl?: string; }>; bridgeHealth(): unknown; } export type VerbServerFactory = (opts: DerivedServerOpts & { onPairCode: (code: string) => void; /** * The transport deadline every verb's reply wait is raced against. * * Nothing in the CLI sets it since #237: the capture verbs used to, to buy * a longer wait on one verb by lengthening all of them, and the server now * derives that per verb from the window the call asked for. Kept on the * factory's opts rather than on `DerivedServerOpts` because it is a * transport-level deadline and not something derived from the profile — * and kept at all so a caller with a genuinely slow bridge still has it. */ fetchTimeoutMs?: number; }) => VerbServer; export declare const defaultServerFactory: VerbServerFactory; export declare function pairCodePrinter(io: Io): (code: string) => void; /** * Assert a HOST is on one of the profile's declared domains and return the * matching declared apex. * * Shared with `capture-redirect`, whose target is a bare host rather than a * URL: that verb re-implemented this rule inline and copied this error text, * so the two spellings of "not on this profile" could drift apart with nothing * to catch it. * * Case-INSENSITIVELY, because a host name is, and because the layer that * ENFORCES this rule says so: the server's `assertUrlInDomains` lowercases the * URL's hostname AND each declared domain before comparing. Compared raw, a * profile declaring `Example.com` refused `https://example.com/x` here while * the bridge would have accepted it one hop later — the same class of * divergence as the port one below, with the same resolution: the protocol's * rule binds and this pre-flight only reports it early. `capture-redirect`'s * bare host is the argument that can arrive cased in either direction, since * `new URL()` has already lowercased a hostname for `assertUrlOnProfile`. * * The DECLARED spelling comes back, never a normalised copy: the return is * threaded to `request()` as `{ domain }`, which the server resolves with an * exact `domains.includes(domain)` against the very array the profile * supplied. */ export declare function assertHostOnProfile(host: string, profile: Profile): string; /** * The same rule for a URL, returning the matching declared apex. * * `runFetch` threads that apex to `request()` as `{ domain }`: the server calls * `resolveBaseDomain(opts.domain)` eagerly (even for absolute URLs) and throws * when a profile declares >1 domain and none is passed, so a multi-domain * profile needs the resolved domain on every call. * * `hostname`, never `host`: `host` carries the port, and both layers that * actually ENFORCE this rule compare the port-less name — the server's * `assertUrlInDomains` and the extension's `isUrlAllowedForDomain`. On `host`, * a profile declaring `example.com` refused `https://example.com:8443/x` here * and the bridge accepted it one hop later, so the pre-flight refusal * contradicted the rule it exists to report early. */ export declare function assertUrlOnProfile(url: string, profile: Profile): string; export declare function runFetch(cmd: Extract, profile: Profile, io: Io, makeServer?: VerbServerFactory): Promise;