/**
 * Authenticated HTTP client for cloud relay server communication.
 * Uses Node built-in fetch() (Node 18+) with Bearer token auth.
 * Maps HTTP error responses to BridgeError for consistent error handling.
 */
export declare class HttpClient {
    private readonly baseUrl;
    private token;
    constructor(baseUrl: string, token: string);
    private headers;
    /**
     * fetch() with an AbortController timeout. Node's fetch has NO default
     * timeout, so a stalled relay connection would otherwise block forever and
     * stall the WS poll fallback. An abort maps to a NETWORK_TIMEOUT BridgeError;
     * every other rejection (DNS, connection refused, etc.) propagates unchanged.
     */
    private fetchWithTimeout;
    /**
     * Parse a SUCCESS body, turning an unparseable one into a BridgeError.
     *
     * 🔴 WHY THIS EXISTS. `throwMappedError` has always guarded the NON-2xx path, so an nginx 502 or
     * 413 HTML page arrives as a clean BridgeError. The 2xx path did not: `return resp.json()` let a
     * truncated or empty success body escape as a raw `SyntaxError` carrying no code, no suggestion,
     * and nothing in the signature to warn a caller it could happen — callers at
     * http-backend.ts (list peers / get history / health check) simply propagated it.
     *
     * That is the worst corner of the trade-off the vault describes (how much information a failure
     * carries vs how strictly consumers must handle it —
     * memory/typescript-master-vault/concepts/Error_Handling.md), in a codebase whose own
     * BridgeError(code, message, suggestion) is the answer to it.
     *
     * A 2xx with an unreadable body is REAL: @hono/node-server can answer with a null body or append
     * `Error: …` to an already-streaming response (handleResponseError), and any proxy may truncate a
     * long /poll body. STARTUP_FAILED is deliberately the same code throwMappedError falls back to
     * for a non-JSON error body, so both directions of "the relay said something we cannot read"
     * report identically rather than inventing a second vocabulary.
     */
    private parseJson;
    /**
     * Perform an authenticated GET request.
     * Appends query parameters to the URL if provided.
     */
    get<T>(path: string, query?: Record<string, string>): Promise<T>;
    /**
     * Perform an authenticated POST request with a JSON body.
     */
    post<T>(path: string, body: unknown): Promise<T>;
    /**
     * Perform an authenticated PATCH request with a JSON body.
     * Used to update existing resources (e.g., message response fields).
     */
    patch<T>(path: string, body: unknown): Promise<T>;
    /**
     * Perform an authenticated DELETE request.
     * Returns the RESPONSE HEADERS (a 204 carries no body, but the relay conveys
     * out-of-band signals — e.g. Cogent Mail F3's `X-Cogent-Mailbox-Deprovisioned` —
     * via headers, so callers that need them can read them without a body).
     *
     * When no body is provided, Content-Type is omitted so servers don't try
     * to parse an empty payload as JSON. This was the root cause of a
     * "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
     * any client (including third-party tools) DELETEd a peer without a body.
     */
    delete(path: string, body?: unknown): Promise<Headers>;
    /**
     * Update the Bearer token (e.g., after join-session returns a new token).
     */
    updateToken(newToken: string): void;
    /**
     * Parse an error response from the server and throw a BridgeError.
     * If the server returns a cogent ErrorCode, it is passed through.
     * For non-JSON error responses, STARTUP_FAILED is used as a fallback code.
     */
    private throwMappedError;
}
//# sourceMappingURL=http-client.d.ts.map