/// <reference types="node" />
import { type Agent, type HeadersInit, type RequestInfo, type RequestInit } from './_shims/index';
import { APIError } from './error';
import type { APIResponseProps, DefaultQuery, Fetch, FinalRequestOptions, PromiseOrValue, ReqHeaders, RequestClient, RequestOptions } from './types';
export { maybeMultipartFormRequestOptions, multipartFormRequestOptions, createForm, type Uploadable, } from './uploads';
export declare function defaultParseResponse<T>(props: APIResponseProps): Promise<T>;
/**
 * A subclass of `Promise` providing additional helper methods
 * for interacting with the SDK.
 */
export declare class APIPromise<T> extends Promise<T> {
    private responsePromise;
    private parseResponse;
    private parsedPromise;
    constructor(responsePromise: Promise<APIResponseProps>, parseResponse?: (props: APIResponseProps) => PromiseOrValue<T>);
    _thenUnwrap<U>(transform: (data: T) => U): APIPromise<U>;
    /**
     * Gets the raw `Response` instance instead of parsing the response
     * data.
     *
     * If you want to parse the response body but still get the `Response`
     * instance, you can use {@link withResponse()}.
     */
    asResponse(): Promise<Response>;
    /**
     * Gets the parsed response data and the raw `Response` instance.
     *
     * If you just want to get the raw `Response` instance without parsing it,
     * you can use {@link asResponse()}.
     */
    withResponse(): Promise<{
        data: T;
        response: Response;
    }>;
    private parse;
    then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): Promise<TResult1 | TResult2>;
    catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
    finally(onfinally?: (() => void) | undefined | null): Promise<T>;
}
export interface APIClientOptions {
    baseURL: string;
    maxRetries?: number | undefined;
    timeout?: number | undefined;
    httpAgent?: Agent | undefined;
    fetch?: Fetch | undefined;
}
export declare class APIClient {
    baseURL: string;
    maxRetries: number;
    timeout: number;
    httpAgent: Agent | undefined;
    protected fetch: Fetch;
    protected idempotencyHeader?: string;
    constructor({ baseURL, maxRetries, timeout, // 10 minutes
    httpAgent, fetch: overrideFetch, }: APIClientOptions);
    /**
     * Override this to add your own auth headers.
     *
     * ```ts
     *  {
     *    Authorization: 'Bearer 123',
     *  }
     * ```
     */
    protected authHeaders(_opts: FinalRequestOptions): PromiseOrValue<ReqHeaders>;
    /**
     * Override this to add your own default headers.
     */
    protected defaultHeaders(opts: FinalRequestOptions): Promise<ReqHeaders>;
    protected defaultQuery(): DefaultQuery | undefined;
    /**
     * Override this to add your own headers validation:
     */
    protected validateHeaders(_headers: ReqHeaders, _customHeaders: ReqHeaders): void;
    protected defaultIdempotencyKey(): string;
    get<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    post<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    patch<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    put<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    delete<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    private methodRequest;
    getAPIList<Item, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(path: string, Page: new (...args: any[]) => PageClass, opts?: RequestOptions<any>): PagePromise<PageClass, Item>;
    private calculateContentLength;
    protected buildRequest<Req extends NonNullable<unknown>>(options: FinalRequestOptions<Req>): Promise<{
        req: RequestInit;
        url: string;
        timeout: number;
    }>;
    /**
     * Used as a callback for mutating the given `RequestInit` object.
     *
     * This is useful for cases where you want to add certain headers based off of
     * the request properties, e.g. `method` or `url`.
     */
    protected prepareRequest(_request: RequestInit, _config: {
        url: string;
        options: FinalRequestOptions;
    }): Promise<void>;
    protected parseHeaders(headers: HeadersInit | null | undefined): Record<string, string>;
    protected makeStatusError(status: number | undefined, error: NonNullable<unknown> | undefined, message: string | undefined, headers: ReqHeaders | undefined): APIError;
    request<Req extends NonNullable<unknown>, Rsp>(options: PromiseOrValue<FinalRequestOptions<Req>>, remainingRetries?: number | null): APIPromise<Rsp>;
    protected makeRequest(optionsInput: PromiseOrValue<FinalRequestOptions>, retriesRemaining: number | null): Promise<APIResponseProps>;
    simple<Req extends NonNullable<unknown>, Rsp>(path: string, opts?: PromiseOrValue<RequestOptions<Req>>): APIPromise<Rsp>;
    protected makeSimpleRequest(optionsInput: PromiseOrValue<FinalRequestOptions>, retriesRemaining?: number | null): Promise<APIResponseProps>;
    requestAPIList<Item = unknown, PageClass extends AbstractPage<Item> = AbstractPage<Item>>(Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass, options: FinalRequestOptions): PagePromise<PageClass, Item>;
    buildURL<Req extends Record<string, unknown>>(path: string, query: Req | null | undefined): string;
    protected stringifyQuery(query: Record<string, unknown>): string;
    fetchWithTimeout(url: RequestInfo, init: RequestInit | undefined, ms: number, controller: AbortController): Promise<Response>;
    protected getRequestClient(): RequestClient;
    private shouldRetry;
    private retryRequest;
    private calculateDefaultRetryTimeoutMillis;
    protected getUserAgent(): string;
    static create(baseURL: string, options?: Omit<APIClientOptions, 'baseURL'>): APIClient;
}
export type PageInfo = {
    url: URL;
} | {
    params: Record<string, unknown> | null;
};
export declare abstract class AbstractPage<Item> implements AsyncIterable<Item> {
    #private;
    protected options: FinalRequestOptions;
    protected response: Response;
    protected body: unknown;
    constructor(client: APIClient, response: Response, body: unknown, options: FinalRequestOptions);
    /**
     * @deprecated Use nextPageInfo instead
     */
    abstract nextPageParams(): Partial<Record<string, unknown>> | null;
    abstract nextPageInfo(): PageInfo | null;
    abstract getPaginatedItems(): Item[];
    hasNextPage(): boolean;
    getNextPage(): Promise<this>;
    iterPages(): AsyncGenerator<AbstractPage<Item>, void, unknown>;
    [Symbol.asyncIterator](): AsyncGenerator<Awaited<Item>, void, unknown>;
}
/**
 * This subclass of Promise will resolve to an instantiated Page once the request completes.
 *
 * It also implements AsyncIterable to allow auto-paginating iteration on an unawaited list call, eg:
 *
 * ```ts
 * for await (const item of client.items.list()) {
 *   console.log(item)
 * }
 * ```
 */
export declare class PagePromise<PageClass extends AbstractPage<Item>, Item = ReturnType<PageClass['getPaginatedItems']>[number]> extends APIPromise<PageClass> implements AsyncIterable<Item> {
    constructor(client: APIClient, request: Promise<APIResponseProps>, Page: new (...args: ConstructorParameters<typeof AbstractPage>) => PageClass);
    /**
     * Allow auto-paginating iteration on an un awaited list call, eg:
     *
     * ```ts
     * for await (const item of client.items.list()) {
     *   console.log(item)
     * }
     * ```
     */
    [Symbol.asyncIterator](): AsyncGenerator<Awaited<Item>, void, unknown>;
}
