/// <reference types="node" />

import { Agent } from 'node:http';
import { Readable } from 'node:stream';
import { ReadStream } from 'node:fs';

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>;
}

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_2;
        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_2, _config: {
        url: string;
        options: FinalRequestOptions;
    }): Promise<void>;
    protected parseHeaders(headers: HeadersInit_2 | 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_2, init: RequestInit_2 | 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 declare interface APIClientOptions {
    baseURL: string;
    maxRetries?: number | undefined;
    timeout?: number | undefined;
    httpAgent?: Agent | undefined;
    fetch?: Fetch | undefined;
}

export declare class APIConnectionError extends APIError {
    readonly status: undefined;
    constructor({ message, cause, }: {
        message?: string;
        cause?: Error | undefined;
    });
}

export declare class APIConnectionTimeoutError extends APIConnectionError {
    constructor({ message }?: {
        message?: string;
    });
}

export declare class APIError extends HttpException {
    readonly status: number | undefined;
    readonly headers: ReqHeaders | undefined;
    readonly error: NonNullable<unknown> | undefined;
    readonly code: string | null | undefined;
    readonly param: string | null | undefined;
    readonly type: string | undefined;
    constructor(status: number | undefined, error: NonNullable<unknown> | undefined, message: string | undefined, headers: ReqHeaders | undefined);
    private static makeMessage;
    static generate(status: number | undefined, errorResponse: NonNullable<unknown> | undefined, message: string | undefined, headers: ReqHeaders | undefined): APIError;
}

/**
 * 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 declare type APIResponseProps = {
    response: Response;
    options: FinalRequestOptions;
    controller: AbortController;
};

export declare class APIUserAbortError extends APIError {
    readonly status: undefined;
    constructor({ message }?: {
        message?: string;
    });
}

export declare class AuthenticationError extends APIError {
    readonly status: 401;
}

export declare class BadRequestError extends APIError {
    readonly status: 400;
}

/**
 * Intended to match web.Blob, node.Blob, node-fetch.Blob, etc.
 */
export declare interface BlobLike {
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/size) */
    readonly size: number;
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/type) */
    readonly type: string;
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/text) */
    text(): Promise<string>;
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/Blob/slice) */
    slice(start?: number, end?: number): BlobLike;
}

declare type BlobLikePart = string | ArrayBuffer | ArrayBufferView | BlobLike | Uint8Array | DataView;

declare type BlobPart_2 = string | ArrayBuffer | ArrayBufferView | Blob | Uint8Array | DataView;
export { BlobPart_2 as BlobPart }

export declare type Bytes = string | ArrayBuffer | Uint8Array | Buffer | null | undefined;

export declare const castToError: (err: any) => Error;

export declare class ConflictError extends APIError {
    readonly status: 409;
}

export declare const createForm: <T = Record<string, unknown>>(body: T | undefined) => Promise<FormData>;

export declare const createResponseHeaders: (headers: Awaited<ReturnType<Fetch>>['headers']) => Record<string, string>;

export declare function debug(action: string, ...args: any[]): void;

export declare function defaultParseResponse<T>(props: APIResponseProps): Promise<T>;

export declare type DefaultQuery = Record<string, string | undefined>;

export declare type Fetch = (url: RequestInfo_2, init?: RequestInit_2) => Promise<Response>;

/**
 * Intended to match web.File, node.File, node-fetch.File, etc.
 */
export declare interface FileLike extends BlobLike {
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/lastModified) */
    readonly lastModified: number;
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/File/name) */
    readonly name: string;
}

export declare type FinalRequestOptions<Req extends NonNullable<unknown> = Record<string, unknown> | Readable> = RequestOptions<Req> & {
    method: HTTPMethod;
    path: string;
};

export declare function hasOwn(obj: NonNullable<unknown>, key: string): boolean;

declare type HeadersInit_2 = globalThis.HeadersInit;

export declare class HttpException extends Error {
}

export declare type HTTPMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';

export declare class InternalServerError extends APIError {
}

export declare const isAbsoluteURL: (url: string) => boolean;

/**
 * The BlobLike type omits arrayBuffer() because `@types/node-fetch@^2.6.4` lacks it; but this check
 * adds the arrayBuffer() method type because it is available and used at runtime
 */
export declare const isBlobLike: (value: any) => value is BlobLike & {
    arrayBuffer(): Promise<ArrayBuffer>;
};

export declare function isEmptyObj(obj: NonNullable<unknown> | null | undefined): boolean;

export declare const isFileLike: (value: any) => value is FileLike;

export declare const isMultipartBody: (body: any) => body is MultipartBody;

export declare const isRequestOptions: (obj: unknown) => obj is RequestOptions<Record<string, unknown> | Readable>;

export declare const isResponseLike: (value: any) => value is ResponseLike;

export declare const isUploadable: (value: any) => value is Uploadable;

export declare type KeysEnum<T> = {
    [P in keyof Required<T>]: true;
};

/**
 * A re-implementation of httpx's `LineDecoder` in Python that handles incrementally
 * reading lines from text.
 *
 * https://github.com/encode/httpx/blob/920333ea98118e9cf617f246905d7b202510941c/httpx/_decoders.py#L258
 */
export declare class LineDecoder {
    static NEWLINE_CHARS: Set<string>;
    static NEWLINE_REGEXP: RegExp;
    buffer: string[];
    trailingCR: boolean;
    textDecoder: any;
    constructor();
    decode(chunk: Bytes): string[];
    decodeText(bytes: Bytes): string;
    flush(): string[];
}

/**
 * Returns a multipart/form-data request if any part of the given request body contains a File / Blob value.
 * Otherwise returns the request as is.
 */
export declare const maybeMultipartFormRequestOptions: <T extends {} = Record<string, unknown>>(opts: RequestOptions<T>) => Promise<RequestOptions<MultipartBody | T>>;

/**
 * Disclaimer: modules in _shims aren't intended to be imported by SDK users.
 */
declare class MultipartBody {
    body: any;
    constructor(body: any);
    get [Symbol.toStringTag](): string;
}

export declare const multipartFormRequestOptions: <T extends {} = Record<string, unknown>>(opts: RequestOptions<T>) => Promise<RequestOptions<MultipartBody | T>>;

export declare class NotFoundError extends APIError {
    readonly status: 404;
}

export declare type PageInfo = {
    url: URL;
} | {
    params: Record<string, unknown> | null;
};

/**
 * 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>;
}

export declare class PermissionDeniedError extends APIError {
    readonly status: 403;
}

export declare type PromiseOrValue<T> = T | Promise<T>;

export declare class RateLimitError extends APIError {
    readonly status: 429;
}

/**
 * Most browsers don't yet have async iterable support for ReadableStream,
 * and Node has a very different way of reading bytes from its "ReadableStream".
 *
 * This polyfill was pulled from https://github.com/MattiasBuelens/web-streams-polyfill/pull/122#issuecomment-1627354490
 */
export declare function readableStreamAsyncIterable<T>(stream: any): AsyncIterableIterator<T>;

export declare type ReqHeaders = Record<string, string | null | undefined>;

export declare type RequestClient = {
    fetch: Fetch;
};

declare type RequestInfo_2 = globalThis.RequestInfo;

declare type RequestInit_2 = globalThis.RequestInit;

export declare type RequestOptions<Req extends NonNullable<unknown> = Record<string, unknown> | Readable> = {
    method?: HTTPMethod;
    path?: string;
    query?: Req | undefined;
    body?: Req | undefined;
    headers?: ReqHeaders | undefined;
    maxRetries?: number;
    stream?: boolean | undefined;
    timeout?: number;
    httpAgent?: Agent;
    signal?: AbortSignal | undefined | null;
    idempotencyKey?: string;
    duplex?: 'half' | 'full' | undefined;
    __binaryResponse?: boolean | undefined;
};

/**
 * Intended to match web.Response, node.Response, node-fetch.Response, etc.
 */
export declare interface ResponseLike {
    url: string;
    blob(): Promise<BlobLike>;
}

export declare const safeJSON: (text: string) => any;

export declare type ServerSentEvent = {
    event: string | null;
    data: string;
    raw: string[];
};

export declare const sleep: (ms: number) => Promise<unknown>;

export declare class SSEDecoder {
    private data;
    private event;
    private chunks;
    constructor();
    decode(line: string): ServerSentEvent | null;
}

export declare class Stream<Item> implements AsyncIterable<Item> {
    private iterator;
    controller: AbortController;
    constructor(iterator: () => AsyncIterator<Item>, controller: AbortController);
    static fromSSEResponse<Item>(response: Response, controller: AbortController): Stream<Item>;
    /**
     * Generates a Stream from a newline-separated ReadableStream
     * where each item is a JSON value.
     */
    static fromReadableStream<Item>(readableStream: globalThis.ReadableStream, controller: AbortController): Stream<Item>;
    [Symbol.asyncIterator](): AsyncIterator<Item>;
    /**
     * Splits the stream into two streams which can be
     * independently read from at different speeds.
     */
    tee(): [Stream<Item>, Stream<Item>];
    /**
     * Converts this stream to a newline-separated ReadableStream of
     * JSON stringified values in the stream
     * which can be turned back into a Stream with `Stream.fromReadableStream()`.
     */
    toReadableStream(): globalThis.ReadableStream;
}

/**
 * Helper for creating a {@link File} to pass to an SDK upload method from a variety of different data formats
 * @param value - the raw content of the file.  Can be an {@link Uploadable}, {@link BlobLikePart}, or {@link AsyncIterable} of {@link BlobLikePart}s
 * @param name - the name of the file. If omitted, toFile will try to determine a file name from bits if possible
 * @param options - additional properties
 * @returns a {@link File} with the given properties
 */
export declare function toFile(value: ToFileInput | PromiseLike<ToFileInput>, name?: string | null | undefined, options?: FilePropertyBag | undefined): Promise<FileLike>;

export declare type ToFileInput = Uploadable | Exclude<BlobLikePart, string> | AsyncIterable<BlobLikePart>;

export declare class UnprocessableEntityError extends APIError {
    readonly status: 422;
}

/**
 * Typically, this is a native "File" class.
 *
 * We provide the {@link toFile} utility to convert a variety of objects
 * into the File class.
 *
 * For convenience, you can also pass a fetch Response, or in Node,
 * the result of fs.createReadStream().
 */
export declare type Uploadable = FileLike | ResponseLike | ReadStream;

/**
 * https://stackoverflow.com/a/2117523
 */
export declare const uuid4: () => string;

export declare const validatePositiveInteger: (name: string, n: unknown) => number;

export { }
