import { type ContractLike, type HttpContractConfig, type ResolveContract, type StandardErrorResponseBody, type StandardSchemaV1 } from "../contracts/index.js";
import type { CallArgs, ClientConfig, EndpointResult, InferEndpointErrorResponse, InferEndpointErrorResponseByStatus, InferEndpointErrorStatus, InferSuccessResponse } from "./types.js";
/**
 * Source category for a `ContractError`.
 */
export type ContractErrorSource = "http" | "client" | "network" | "contract";
/**
 * Narrow a contract error union by source.
 */
export type ContractErrorWithSource<TError, TSource extends ContractErrorSource> = Extract<TError, {
    readonly source: TSource;
}>;
/**
 * Narrow a contract error union by HTTP status.
 */
export type ContractErrorWithStatus<TError, TStatus extends number> = Extract<TError, {
    readonly status: TStatus;
}>;
/**
 * Narrow a contract error union by Beignet error code.
 */
export type ContractErrorWithCode<TError, TCode extends string> = Extract<TError, {
    readonly code: TCode;
}>;
/**
 * Error for a non-2xx HTTP response.
 */
export type HttpContractError<TBody = unknown, TStatus extends number = number> = ContractError<TBody, TStatus, "http"> & {
    readonly source: "http";
    readonly status: TStatus;
    readonly response: Response;
};
/**
 * Error created by the client before a network request is made.
 */
export type ClientContractError = ContractError<undefined, undefined, "client"> & {
    readonly source: "client";
    readonly status: undefined;
    readonly response: undefined;
};
/**
 * Error created when the network request itself fails.
 */
export type NetworkContractError = ContractError<undefined, undefined, "network"> & {
    readonly source: "network";
    readonly status: undefined;
    readonly response: undefined;
};
/**
 * Error created when a response violates the contract.
 */
export type ResponseContractError<TBody = unknown, TStatus extends number | undefined = number | undefined> = ContractError<TBody, TStatus, "contract"> & {
    readonly source: "contract";
    readonly status: TStatus;
};
/**
 * Union of all Beignet client error variants.
 */
export type AnyContractError = HttpContractError | ClientContractError | NetworkContractError | ResponseContractError;
type EndpointCatalogErrorDefinition<TContract extends HttpContractConfig> = TContract["metadata"] extends {
    errors: infer TErrors;
} ? TErrors extends Record<string, {
    code: string;
    status: number;
    message: string;
}> ? TErrors[keyof TErrors] : never : never;
type InferErrorDefinitionDetails<TDef> = TDef extends {
    details: StandardSchemaV1;
} ? StandardSchemaV1.InferOutput<TDef["details"]> : unknown;
type StandardErrorBodyForDefinition<TDef extends {
    code: string;
}> = StandardErrorResponseBody & {
    code: TDef["code"];
    details?: InferErrorDefinitionDetails<TDef>;
};
type EndpointCatalogContractError<TContract extends HttpContractConfig> = EndpointCatalogErrorDefinition<TContract> extends infer TDef ? TDef extends {
    code: string;
    status: number;
} ? HttpContractError<StandardErrorBodyForDefinition<TDef>, TDef["status"]> & {
    readonly code: TDef["code"];
    readonly details?: InferErrorDefinitionDetails<TDef>;
} : never : never;
/**
 * Infer route-owned error catalog codes declared by a contract.
 */
export type InferEndpointErrorCode<TContract extends HttpContractConfig> = EndpointCatalogErrorDefinition<TContract>["code"];
/**
 * Infer the full typed error union for a contract endpoint.
 */
export type InferEndpointContractError<TContract extends HttpContractConfig> = EndpointCatalogContractError<TContract> | {
    [TStatus in InferEndpointErrorStatus<TContract>]: HttpContractError<InferEndpointErrorResponseByStatus<TContract, TStatus>, TStatus>;
}[InferEndpointErrorStatus<TContract>] | HttpContractError<InferEndpointErrorResponse<TContract>, number> | ClientContractError | NetworkContractError | ResponseContractError<InferEndpointErrorResponse<TContract>, number | undefined>;
/**
 * Error thrown by Beignet contract clients.
 *
 * `source` distinguishes HTTP error responses, client-side request mistakes,
 * network failures, and contract drift such as response validation failures.
 */
export declare class ContractError<TBody = unknown, TStatus extends number | undefined = number | undefined, TSource extends ContractErrorSource = ContractErrorSource> extends Error {
    /**
     * Error source category.
     */
    readonly source: TSource;
    /**
     * HTTP status when a response was available.
     */
    readonly status: TStatus;
    /**
     * Stable error code.
     */
    readonly code?: string;
    /**
     * Parsed response body when available.
     */
    readonly body?: TBody;
    /**
     * Structured error details when available.
     */
    readonly details?: unknown;
    /**
     * Native fetch response when available.
     */
    readonly response?: Response;
    cause?: unknown;
    constructor(args: {
        source: TSource;
        status?: TStatus;
        code?: string;
        message: string;
        body?: TBody;
        details?: unknown;
        response?: Response;
        cause?: unknown;
    });
    /**
     * Check whether this error has a specific HTTP status code.
     */
    hasStatus<S extends number>(status: S): this is this & {
        readonly status: S;
    };
    /**
     * Check whether this error came from a specific source.
     */
    hasSource<S extends ContractErrorSource>(source: S): this is this & {
        readonly source: S;
    };
    /**
     * Check whether this error has a specific error code.
     */
    hasCode<C extends string>(code: C): this is this & {
        code: C;
    };
}
/**
 * Type guard to check if an unknown error is a ContractError,
 * optionally narrowing by HTTP status code.
 *
 * @example
 * ```ts
 * try { await endpoint.call(...) }
 * catch (err) {
 *   if (isContractError(err, 404)) {
 *     // err.status is 404
 *   }
 *   if (isContractError(err)) {
 *     // err is ContractError
 *   }
 * }
 * ```
 */
export declare function isContractError(err: unknown): err is AnyContractError;
export declare function isContractError<S extends number>(err: unknown, status: S): err is HttpContractError<unknown, S>;
export declare function isContractError<TError extends AnyContractError, S extends number>(err: TError, criteria: {
    status: S;
}): err is ContractErrorWithStatus<TError, S>;
export declare function isContractError<TError extends AnyContractError, S extends ContractErrorSource>(err: TError, criteria: {
    source: S;
}): err is ContractErrorWithSource<TError, S>;
export declare function isContractError<TError extends ContractError, Status extends number, Source extends ContractErrorSource>(err: TError, criteria: {
    status: Status;
    source: Source;
}): err is ContractErrorWithSource<ContractErrorWithStatus<TError, Status>, Source>;
export declare function isContractError<TError extends ContractError, Code extends string>(err: TError, criteria: {
    code: Code;
}): err is ContractErrorWithCode<TError, Code>;
export declare function isContractError<TError extends ContractError, Status extends number, Code extends string>(err: TError, criteria: {
    status: Status;
    code: Code;
}): err is ContractErrorWithCode<ContractErrorWithStatus<TError, Status>, Code>;
export declare function isContractError<TError extends ContractError, Source extends ContractErrorSource, Code extends string>(err: TError, criteria: {
    source: Source;
    code: Code;
}): err is ContractErrorWithCode<ContractErrorWithSource<TError, Source>, Code>;
export declare function isContractError<TError extends ContractError, Status extends number, Source extends ContractErrorSource, Code extends string>(err: TError, criteria: {
    status: Status;
    source: Source;
    code: Code;
}): err is ContractErrorWithCode<ContractErrorWithSource<ContractErrorWithStatus<TError, Status>, Source>, Code>;
export declare function isContractError<S extends number>(err: unknown, criteria: {
    status: S;
}): err is ContractError<unknown, S>;
export declare function isContractError<S extends ContractErrorSource>(err: unknown, criteria: {
    source: S;
}): err is ContractError<unknown, number | undefined, S>;
export declare function isContractError<Status extends number, Source extends ContractErrorSource>(err: unknown, criteria: {
    status: Status;
    source: Source;
}): err is ContractErrorWithSource<HttpContractError<unknown, Status>, Source>;
export declare function isContractError<Code extends string>(err: unknown, criteria: {
    code: Code;
}): err is ContractError<unknown, number | undefined> & {
    readonly code: Code;
};
/**
 * Typed client endpoint for one contract.
 */
export declare class Endpoint<TContract extends HttpContractConfig, TProvidedHeaders extends string = never> {
    private contract;
    private config;
    constructor(contract: TContract, config: ClientConfig<TProvidedHeaders>);
    /**
     * Check whether an unknown error is a `ContractError` for this endpoint.
     */
    isError(err: unknown): err is InferEndpointContractError<TContract>;
    isError<S extends InferEndpointErrorStatus<TContract>>(err: unknown, status: S): err is ContractErrorWithStatus<InferEndpointContractError<TContract>, S>;
    isError<S extends number>(err: unknown, status: S): err is HttpContractError<unknown, S>;
    isError<S extends InferEndpointErrorStatus<TContract>>(err: unknown, criteria: {
        status: S;
    }): err is ContractErrorWithStatus<InferEndpointContractError<TContract>, S>;
    isError<S extends ContractErrorSource>(err: unknown, criteria: {
        source: S;
    }): err is ContractErrorWithSource<InferEndpointContractError<TContract>, S>;
    isError<C extends InferEndpointErrorCode<TContract>>(err: unknown, criteria: {
        code: C;
    }): err is ContractErrorWithCode<InferEndpointContractError<TContract>, C>;
    isError<C extends string>(err: unknown, criteria: {
        code: C;
    }): err is InferEndpointContractError<TContract> & {
        readonly code: C;
    };
    isError<Status extends InferEndpointErrorStatus<TContract>, Source extends ContractErrorSource>(err: unknown, criteria: {
        status: Status;
        source: Source;
    }): err is ContractErrorWithSource<ContractErrorWithStatus<InferEndpointContractError<TContract>, Status>, Source>;
    isError<Status extends InferEndpointErrorStatus<TContract>, C extends InferEndpointErrorCode<TContract>>(err: unknown, criteria: {
        status: Status;
        code: C;
    }): err is ContractErrorWithCode<ContractErrorWithStatus<InferEndpointContractError<TContract>, Status>, C>;
    isError<Source extends ContractErrorSource, C extends InferEndpointErrorCode<TContract>>(err: unknown, criteria: {
        source: Source;
        code: C;
    }): err is ContractErrorWithCode<ContractErrorWithSource<InferEndpointContractError<TContract>, Source>, C>;
    isError<Status extends InferEndpointErrorStatus<TContract>, Source extends ContractErrorSource, C extends InferEndpointErrorCode<TContract>>(err: unknown, criteria: {
        status: Status;
        source: Source;
        code: C;
    }): err is ContractErrorWithCode<ContractErrorWithSource<ContractErrorWithStatus<InferEndpointContractError<TContract>, Status>, Source>, C>;
    /**
     * Call the endpoint and return the parsed success body.
     *
     * Throws `ContractError` when the request fails or the response violates the
     * contract.
     */
    call(...callArgs: CallArgs<TContract, TProvidedHeaders>): Promise<InferSuccessResponse<TContract>>;
    /**
     * Call the endpoint and return a typed result instead of throwing
     * `ContractError`.
     */
    safeCall(...callArgs: CallArgs<TContract, TProvidedHeaders>): Promise<EndpointResult<TContract, InferEndpointContractError<TContract>>>;
    /**
     * Build the full URL with path and query parameters
     */
    private buildUrl;
    private serializeQueryParam;
    private invalidQueryParam;
    /**
     * Build request headers
     */
    private buildHeaders;
    /**
     * Create a contract error
     */
    private createError;
}
/**
 * Client for making contract-based requests.
 */
export declare class Client<TProvidedHeaders extends string = never> {
    private config;
    constructor(config: ClientConfig<TProvidedHeaders>);
    /**
     * Create an endpoint wrapper for a contract.
     *
     * Accepts either a plain `HttpContractConfig` or a builder with a `.config`
     * property.
     */
    endpoint<TContractLike extends ContractLike>(contract: TContractLike): Endpoint<ResolveContract<TContractLike>, TProvidedHeaders>;
}
/**
 * Create a configured Beignet client.
 */
export declare function createClient<const TProvidedHeaders extends string = never>(config?: ClientConfig<TProvidedHeaders>): Client<TProvidedHeaders>;
export {};
//# sourceMappingURL=client.d.ts.map