import type { z } from 'zod/v4';
import type { HttpStatusCode, WildcardStatusCodeKey } from '../HttpStatusCodes.ts';
export type ResponseOptions = {
    readonly description?: string;
};
export type SseSchemaByEventName = Record<string, z.ZodType>;
export type TypedJsonResponse = z.ZodType;
export declare const isJsonResponse: (value: ApiContractResponse | ResponseEntry) => value is TypedJsonResponse;
export type TypedApiContractResponse = TypedJsonResponse;
export type ApiContractResponse = TypedApiContractResponse;
/** Opaque binary body; the media type is supplied by the content-map key. */
export type BlobBody = {
    readonly _tag: 'BlobBody';
};
export declare const blobBody: () => BlobBody;
/**
 * Lazy, single-consume accessor over a `blobResponse()` body — the client-side value a blob
 * response resolves to. Mirrors the accessor surface of Fetch's `Response`/`Blob`.
 *
 * The underlying body is a one-shot stream: the first accessor you call consumes it; calling a
 * second throws. Pick one. Draining the body (any accessor except a lazy `stream()`, or `cancel()`)
 * is also what releases the connection — a handle you never touch keeps it open.
 */
export interface BlobResponseHandle {
    /** Raw stream, for piping/backpressure. You own draining or cancelling it. */
    stream(): ReadableStream<Uint8Array>;
    /** Buffer the whole body into a `Blob`. The common case; echoes `blobResponse()`. */
    blob(): Promise<Blob>;
    /** Buffer the whole body and decode it as UTF-8 text. */
    text(): Promise<string>;
    /** Buffer the whole body into an `ArrayBuffer`. */
    arrayBuffer(): Promise<ArrayBuffer>;
    /** Discard the body without materializing it, releasing the connection. */
    cancel(): Promise<void>;
}
export declare const isBlobBody: (value: BodyDescriptor) => value is BlobBody;
/** Server-Sent Events body; the media type is supplied by the content-map key. */
export type SseBody<T extends SseSchemaByEventName = SseSchemaByEventName> = {
    readonly _tag: 'SseBody';
    readonly schemaByEventName: T;
};
export declare const sseBody: <T extends SseSchemaByEventName>(schemaByEventName: T) => SseBody<T>;
export declare const isSseBody: (value: BodyDescriptor) => value is SseBody;
export declare const isJsonBody: (value: BodyDescriptor) => value is z.ZodType;
/**
 * A value in a {@link ResponseContentMap}; the media type is the map key, so a
 * descriptor never carries a content type itself. A bare Zod schema is JSON.
 */
export type BodyDescriptor = z.ZodType | BlobBody | SseBody;
/** Commonly used response media types, offered as autocomplete suggestions. */
export type CommonResponseContentType = 'application/json' | 'application/octet-stream' | 'application/pdf' | 'application/x-ndjson' | 'application/xml' | 'application/zip' | 'audio/mpeg' | 'audio/ogg' | 'image/gif' | 'image/jpeg' | 'image/png' | 'image/svg+xml' | 'image/webp' | 'text/csv' | 'text/event-stream' | 'text/html' | 'text/plain' | 'video/mp4' | 'video/webm';
/**
 * A response media type. Common values are autocompleted; any other string
 * (e.g. a vendored variant like `application/json+01`) is accepted too.
 */
export type ResponseContentType = CommonResponseContentType | (string & {});
/**
 * Maps a response media type (e.g. `application/json`) to the body it carries.
 * {@link CommonResponseContentType} keys are autocompleted; any other media type is accepted too.
 */
export type ResponseContentMap = Partial<Record<CommonResponseContentType, BodyDescriptor>> & Record<string, BodyDescriptor>;
/** A content-map response carrying a body for one or more media types. */
export type BodyContentResponseEntry = {
    readonly description?: string;
    readonly content: ResponseContentMap;
    readonly allowNoBody?: boolean;
};
/** A content-map response that never carries a body. */
export type NoBodyContentResponseEntry = {
    readonly description?: string;
    readonly content?: never;
    readonly allowNoBody: true;
};
/**
 * A content-map response entry. Either a body response (`content` required,
 * optionally `allowNoBody`) or a no-body response (`allowNoBody: true`, no
 * `content`). The union forces at least one of `content` / `allowNoBody`.
 */
export type ResponseEntry = BodyContentResponseEntry | NoBodyContentResponseEntry;
export declare const isContentResponseEntry: (value: ApiContractResponse | ResponseEntry) => value is ResponseEntry;
/**
 * Declares a no-body response (e.g. `204`).
 */
export declare const noBodyResponse: (options?: ResponseOptions) => NoBodyContentResponseEntry;
/**
 * Declares a binary/opaque response for a single media type.
 */
export declare const blobResponse: <TContentType extends ResponseContentType>(contentType: TContentType, options?: ResponseOptions) => {
    readonly content: { readonly [K in TContentType]: BlobBody; };
    readonly description?: string | undefined;
};
/**
 * Declares a Server-Sent Events response.
 */
export declare const sseResponse: <T extends SseSchemaByEventName>(schemaByEventName: T, options?: ResponseOptions) => {
    readonly content: {
        readonly 'text/event-stream': SseBody<T>;
    };
    readonly description?: string | undefined;
};
export type ResponsesByStatusCode = Partial<Record<HttpStatusCode | WildcardStatusCodeKey, ApiContractResponse | ResponseEntry>>;
export type ResponseKind = {
    kind: 'noContent';
} | {
    kind: 'blob';
} | {
    kind: 'json';
    schema: z.ZodType;
} | {
    kind: 'sse';
    schemaByEventName: SseSchemaByEventName;
};
/**
 * Resolves a contract's response entry for a given status code into a concrete `ResponseKind`,
 * taking the response `content-type` into account.
 *
 * Returns `null` when the content-type cannot be matched to any entry in the contract,
 * indicating the response is unexpected and should be treated as an error by the caller.
 *
 * @param schemaEntry - The contract entry for the matched status code (a Zod schema,
 *   `noBodyResponse`, or a content-map entry).
 * @param contentType - The `content-type` header value from the actual HTTP response,
 *   or `undefined` when the header is absent.
 * @param strict - When `true` (default), returns `null` if the `content-type` is absent or does
 *   not match the contract entry. When `false`, falls back to the entry's declared kind instead of
 *   returning `null` — only applies to single-entry responses.
 */
export declare const resolveContractResponse: (schemaEntry: ApiContractResponse | ResponseEntry, contentType: string | undefined, strict?: boolean) => ResponseKind | null;
/**
 * Combines status-code lookup and content-type resolution into a single call.
 * Lookup precedence: exact code → range key (e.g. `'4xx'`) → `'default'`.
 * Returns `null` when no entry matches or the content-type cannot be matched.
 */
export declare function resolveResponseEntry(responsesByStatusCode: ResponsesByStatusCode, statusCode: number, contentType: string | undefined, strictContentType: boolean): ResponseKind | null;
