import FormData from 'form-data';
import * as stream from 'stream';
import * as HttpErrors from '../httpErrors.js';
import { Credentials } from '../middlewares/credentials.js';
import { OperationDeadline } from './operationDeadline.js';
import Logger from '../resources/logger.js';
import { RequestMetrics } from './requestMetrics.js';
/**
 * RateLimiter is a wrapper function that you can provide to limit the rate of calls to the provider based on the
 * caller's credentials.
 *
 * When necessary, the Provider's Response headers can be inspected to update the rate limit before being returned.
 *
 * NOTE: make sure to return one of the supported HttpErrors from the SDK, otherwise the error will be translated to a
 * generic server (500) error.
 *
 * @param options - Rate-limit-relevant fields from the call's RequestOptions: `credentials`,
 *   `logger`, `requestMetrics`, and `operationDeadline`.
 * @param targetFunction - The function to call the provider.
 * @returns The response from the provider.
 * @throws RateLimitExceededError when the rate limit is exceeded.
 * @throws HttpError when the provider returns an error.
 */
export type RateLimiter = <T>(options: Pick<RequestOptions, 'credentials' | 'logger' | 'deadline' | 'requestMetrics'>, targetFunction: () => Promise<Response<T>>) => Promise<Response<T>>;
/**
 * RequestOptions are the options passed to the Provider's call.
 *
 * @property credentials - The credentials to use for the call.
 * @property logger - The logger to use during the call.
 * @property deadline: The operationDeadline object carrying the abortSignal for the call.
 * @property queryParams - The query parameters to add when calling the provider.
 * @property additionnalheaders - The headers to add when calling the provider.
 * @property rawBody - Whether to return the raw response body.
 */
export type RequestOptions = {
    credentials: Credentials;
    logger: Logger;
    deadline: OperationDeadline;
    queryParams?: {
        [key: string]: string;
    };
    additionnalheaders?: {
        [key: string]: string;
    };
    rawBody?: boolean;
    requestMetrics?: RequestMetrics;
};
/**
 * Response object returned by the Provider's method.
 *
 * Contains;
 * - the body typed as specified when calling the method
 * - the status code of the response
 * - the headers of the response.
 */
export type Response<T> = {
    body: T;
    status: number;
    headers: Record<string, string>;
};
export type PreparedRequest = {
    url: string;
    headers: Record<string, string>;
};
export type RequestBody = Record<string, unknown> | RequestBody[];
/**
 * The Provider class is a wrapper around the fetch function to call a provider's HTTP API.
 *
 * Defines methods for the following HTTP methods: GET, POST, PUT, PATCH, DELETE.
 *
 * Needs to be initialized with a prepareRequest function to define the Provider's base URL and any specific headers to
 * add to the requests, can also be configured to use a provided rate limiting function, and custom error handler.
 *
 * Multiple `Provider` instances can be created, with different configurations to call different providers APIs with
 * different rateLimiting functions, as needed.
 * @see {@link RateLimiter}
 * @see {@link prepareRequest}
 * @see {@link customErrorHandler}
 */
export declare class Provider {
    /**
     * The Rate Limiter function to use to limit the rate of calls made to the provider based on the caller's credentials.
     */
    protected rateLimiter: RateLimiter | undefined;
    private static recordingSeq;
    private static get recordingPath();
    /**
     * Function called before each request to define the Provider's base URL and any specific headers to add to the requests.
     *
     * This is applied at large to all requests made to the provider. If you need to add specific headers to a single request,
     * pass it through the RequestOptions object when calling the Provider's methods.
     */
    protected prepareRequest: (options: {
        credentials: Credentials;
        logger: Logger;
    }) => PreparedRequest | Promise<PreparedRequest>;
    /**
     * (Optional) Custom error handler to handle specific errors returned by the provider.
     *
     * If provided, this method should only care about custom errors returned by the provider and return the corresponding
     * HttpError from the SDK. If the error encountered is a standard error, it should return undefined and let the SDK handle it.
     *
     * The provider's response headers are passed through so integrations can inspect rate-limit signals (e.g. Retry-After)
     * when deciding how to map an error.
     *
     * @see buildHttpError for the list of standard errors the SDK can handle.
     */
    protected customErrorHandler: ((responseStatus: number, message: string, options: {
        credentials: Credentials;
        logger: Logger;
    }, responseHeaders?: Record<string, string>) => HttpErrors.HttpError | undefined) | undefined;
    /**
     * Initializes a Provider with the given options.
     *
     * @property {@link prepareRequest} - function to define the Provider's base URL and specific headers to add to the request.
     * @property {@link RateLimiter} - function to limit the rate of calls to the provider based on the caller's credentials.
     * @property {@link customErrorHandler} - function to handle specific errors returned by the provider.
     */
    constructor(options: {
        prepareRequest: typeof Provider.prototype.prepareRequest;
        rateLimiter: RateLimiter | undefined;
        customErrorHandler?: typeof Provider.prototype.customErrorHandler;
    });
    /**
     * Performs a GET request to the provider.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    get<T>(endpoint: string, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a GET request to the provider and return the response as a ReadableStream.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Accept: application/octet-stream
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (e.g. used to override default headers).
     * @returns The streaming {@link Response} extracted from the provider.
     */
    streamingGet(endpoint: string, options: RequestOptions): Promise<Response<ReadableStream<Uint8Array>>>;
    /**
     * Performs a POST request to the provider.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Content-Type: application/json',
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    post<T>(endpoint: string, body: RequestBody, options: RequestOptions): Promise<Response<T>>;
    postForm<T>(endpoint: string, form: FormData, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a POST request to the provider streaming a Readable directly without loading it into memory.
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param stream The Readable stream containing the binary data to be sent.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    postStream<T>(endpoint: string, stream: stream.Readable, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a PUT request to the provider.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Content-Type: application/json',
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    put<T>(endpoint: string, body: RequestBody, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a PUT request to the provider with a Buffer body, typically used for sending binary data.
     *
     * IMPORTANT: This method should ONLY be used as a last resort when FormData cannot be used.
     * It bypasses normal form handling and is used to **manually send chunked** binary data, which may not be appropriate
     * for all providers. Always be mindful not to load entire binary files in memory!
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Content-Type: application/octet-stream
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param body The Buffer containing the binary data to be sent.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    putBuffer<T>(endpoint: string, body: Buffer, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a PATCH request to the provider.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Content-Type: application/json',
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    patch<T>(endpoint: string, body: RequestBody, options: RequestOptions): Promise<Response<T>>;
    /**
     * Performs a DELETE request to the provider.
     *
     * Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
     * adds the following headers:
     * - Accept: application/json
     *
     * @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
     * @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
     * @returns The {@link Response} extracted from the provider.
     */
    delete<T = undefined>(endpoint: string, options: RequestOptions, body?: RequestBody | null): Promise<Response<T>>;
    private generateAbsoluteUrl;
    private fetchWrapper;
    /**
     * Normalizes Node.js IncomingHttpHeaders (which may have undefined or string[] values)
     * into a flat Record<string, string> by joining array values and dropping undefined entries.
     */
    private static normalizeNodeHeaders;
    private timedCallToProvider;
    private handleError;
}
