/**
 * Error thrown when an operation is aborted via an `AbortSignal`.
 *
 * This error is used in asynchronous operations
 * to indicate that the caller explicitly cancelled
 * the request by invoking `AbortController.abort()`.
 */
declare class AbortError extends Error {
    constructor(message?: string);
}

/**
 * Optional settings that control the behavior of a wait operation.
 */
interface ThrottlerWaitOptions<T extends Throttler = Throttler> {
    /**
     * An `AbortSignal` that allows the wait to be cancelled early.
     *
     * If the signal is already aborted or is aborted before the wait completes,
     * the returned promise will reject with an `AbortError`.
     */
    signal?: AbortSignal;
    /**
     *  A callback invoked before each retry.
     *
     * Receives the time to wait before the operation will be retried,
     * in milliseconds. If the callback returns `false`, the wait will be
     * aborted and a `RetryError` will be thrown.
     *
     * @param ms - The time to wait for the next retry attempt, in milliseconds.
     *
     * @returns `false` to cancel the retry; any other value continues retrying.
     */
    onRetry?: (ms: number, throttler: T) => unknown;
    /**
     * Maximum duration to wait before timing out, in milliseconds.
     *
     * If the wait has not completed within this duration, the returned promise
     * will reject with a `TimeoutError`.
     */
    timeout?: number;
}
/**
 * An interface for throttlers that regulate the pacing
 * of operations to conform to a specified rate.
 */
declare abstract class Throttler {
    /**
     * Attempts to acquire permission to proceed with a request.
     *
     * If the request is allowed, this should return {@link ACQUIRED}.
     *
     * Otherwise, it should return a timestamp (from `performance.now()`)
     * indicating when the caller should retry.
     */
    protected abstract tryAcquire(): number;
    /**
     * Attempts to proceed immediately without waiting.
     *
     * Performs a non-blocking check to determine whether the operation
     * can be executed immediately based on the throttler's state.
     *
     * @returns `true` if the operation can proceed immediately,
     * `false` if it must be delayed.
     */
    tryWait(): boolean;
    /**
     * Waits until the operation is allowed to proceed.
     *
     * Blocks until the throttler permits execution based on its
     * rate-limiting logic. Supports optional timeout, abort signal,
     * and a retry callback that can cancel retries.
     *
     * @param options Optional settings for aborting, timing out, or
     *                controlling retry behavior.
     *
     * @returns A promise that resolves when the caller is permitted to proceed,
     *          or rejects if aborted, timed out, or the retry is cancelled.
     *
     * @throws {AbortError} if the provided signal is aborted before resolution.
     *
     * @throws {RetryError} if the retry is cancelled by the `onRetry` callback returning `false`.
     *
     * @throws {TimeoutError} if the wait exceeds the specified timeout.
     */
    wait({ signal, onRetry, timeout }?: ThrottlerWaitOptions): Promise<void>;
}

/**
 * Configuration options for creating a {@link FixedWindowThrottler}.
 *
 * @example
 * // 5 requests per second
 * {
 *  duration: 1000, // milliseconds
 *  limit: 5
 * }
 */
interface FixedWindowThrottlerConfig {
    /**
     * The size of the window in milliseconds.
     */
    duration: number;
    /**
     * The number of requests allowed per window.
     *
     * Requests above this limit will be delayed.
     */
    limit: number;
}
/**
 * A throttler that uses the fixed window algorithm.
 *
 * This throttler counts the number of requests within
 * each fixed-duration window. Once the limit is reached,
 * additional requests are delayed until future windows.
 *
 * Note: This approach can cause bursts of traffic at
 * window boundaries.
 */
declare class FixedWindowThrottler extends Throttler {
    /**
     * The size of the window in milliseconds.
     */
    readonly duration: number;
    /**
     * The number of requests allowed per window.
     */
    readonly limit: number;
    /**
     * Timestamp marking the end of the current window.
     */
    private windowEnd;
    /**
     * Number of accepted requests in the current window.
     */
    private count;
    constructor({ duration, limit }: FixedWindowThrottlerConfig);
    /**
     * Attempts to acquire permission to proceed with a request.
     *
     * If the current window has capacity, the request is accepted.
     *
     * Otherwise, returns the timestamp marking the end of the
     * current window to indicate how long the caller should
     * wait before retrying.
     */
    protected tryAcquire(): number;
}

/**
 * Configuration options for creating a {@link LeakyBucketThrottler}.
 *
 * @example
 * // Allow bursts of up to 10 requests, with a drain of 5 per second
 * {
 *   capacity: 10,
 *   leakRate: 5
 * }
 */
interface LeakyBucketThrottlerConfig {
    /**
     * Maximum number of tokens the bucket can hold.
     *
     * This defines the burst capacity. Requests beyond this
     * limit are throttled until enough leakage has occurred.
     */
    capacity: number;
    /**
     * Rate at which tokens leak per second.
     *
     * A higher rate allows faster throughput.
     */
    leakRate: number;
}
/**
 * A throttler that uses the leaky bucket algorithm.
 *
 * Tokens are added to a "bucket" which drains at a steady rate
 * defined by `leakRate`. If the bucket overflows (`capacity` exceeded),
 * further requests are throttled until enough leakage has occurred.
 *
 * This method smooths bursts over time, providing a steady output rate.
 */
declare class LeakyBucketThrottler extends Throttler {
    /**
     * Maximum capacity of the bucket.
     */
    readonly capacity: number;
    /**
     * Timestamp of the last leakage calculation.
     */
    private leakedAt;
    /**
     * Rate at which tokens are leaked, per second.
     */
    readonly leakRate: number;
    /**
     * Current number of tokens in the bucket.
     */
    private tokens;
    constructor({ capacity, leakRate }: LeakyBucketThrottlerConfig);
    /**
     * Attempts to acquire permission to proceed with a request.
     *
     * First, the number of leaked tokens since the last check
     * is calculated and the bucket's level is updated accordingly.
     *
     * If the bucket has capacity, the request is accepted.
     *
     * Otherwise, returns the timestamp of when enough leakage
     * will occur to allow the request.
     */
    protected tryAcquire(): number;
}

/**
 * Configuration options for creating a {@link LinearThrottler}.
 *
 * @example
 * // Allow one request every 500 milliseconds
 * {
 *  duration: 500
 * }
 */
interface LinearThrottlerConfig {
    /**
     * The minimum duration between requests, in milliseconds.
     */
    duration: number;
}
/**
 * A throttler that enforces a fixed delay between requests.
 *
 * This throttler ensures that each request occurs at least
 * `duration` milliseconds after the previous one, providing
 * consistent pacing without bursts.
 */
declare class LinearThrottler extends Throttler {
    /**
     * The minimum duration between requests, in milliseconds.
     */
    readonly duration: number;
    /**
     * Timestamp of when the next request is allowed.
     */
    private slot;
    constructor({ duration }: LinearThrottlerConfig);
    /**
     * Attempts to acquire permission to proceed with the operation.
     *
     * Allows the request if the current time is past `slot`.
     *
     * Otherwise, returns the timestamp when the next
     * request is allowed to indicate how long the caller
     * should wait before retrying.
     */
    protected tryAcquire(): number;
}

/**
 * Error thrown when a retry loop is explicitly cancelled.
 *
 * This error is used to indicate that a retry was cancelled
 * from an `onRetry` callback returning `false`.
 */
declare class RetryError extends Error {
    constructor(message?: string);
}

/**
 * Configuration options for creating a {@link SlidingWindowThrottler}.
 *
 * @example
 * // 5 requests per second
 * {
 *  duration: 1000, // milliseconds
 *  limit: 5
 * }
 */
interface SlidingWindowThrottlerConfig {
    /**
     * The size of the window in milliseconds.
     */
    duration: number;
    /**
     * The number of requests allowed per window.
     *
     * Requests above this limit will be delayed.
     */
    limit: number;
}
/**
 * A throttler that uses the sliding window algorithm.
 *
 * This throttler spreads requests across a moving time window,
 * tracking the timestamps of accepted requests and ensuring
 * no more than a fixed number occur within any given interval.
 */
declare class SlidingWindowThrottler extends Throttler {
    /**
     * The size of the window in milliseconds.
     */
    readonly duration: number;
    /**
     * Points to the oldest slot in the current window.
     */
    private index;
    /**
     * The number of requests allowed per window.
     */
    readonly limit: number;
    /**
     * Timestamps of the last `limit` accepted requests.
     *
     * These are used to determine if a new request falls
     * within the allowed window, and to delay if necessary.
     */
    private slots;
    constructor({ duration, limit }: SlidingWindowThrottlerConfig);
    /**
     * Attempts to acquire permission to proceed with a request.
     *
     * If the number of requests within the sliding window is
     * below the limit, the request is accepted and its expiration
     * timestamp (i.e. when it falls out of the window) is
     * recorded in the current slot.
     *
     * If the limit has been reached, the expiration time of the
     * oldest request is returned to indicate how long the caller
     * should wait before retrying.
     */
    protected tryAcquire(): number;
}

/**
 * Error thrown when an operation exceeds its allowed time limit.
 *
 * This error is used in asynchronous operations to indicate
 * that the operation took too long to complete and was
 * terminated based on a timeout setting.
 */
declare class TimeoutError extends Error {
    constructor(message?: string);
}

/**
 * Configuration options for creating a {@link TokenBucketThrottler}.
 *
 * @example
 *
 * // Allow bursts of up to 10 requests, refilling at 5 per second
 * {
 *  capacity: 10,
 *  refillRate: 5
 * }
 */
interface TokenBucketThrottlerConfig {
    /**
     * Maximum number of tokens the bucket can hold.
     *
     * This defines the burst capacity. Requests beyond this
     * limit are throttled until enough refill has occurred.
     */
    capacity: number;
    /**
     * Rate at which tokens refill per second.
     *
     * A higher rate allows faster throughput.
     */
    refillRate: number;
}
/**
 * A throttler that uses the token bucket algorithm.
 *
 * Allows requests to be made at a steady rate, while
 * still supporting occasional bursts.
 *
 * Each request consumes one token. Tokens are added
 * continuously over time based on the configured refill rate.
 */
declare class TokenBucketThrottler extends Throttler {
    /**
     * Maximum number of tokens in the bucket.
     */
    readonly capacity: number;
    /**
     * Timestamp of the last refill calculation.
     */
    private refilledAt;
    /**
     * Rate at which tokens are added, per second.
     */
    readonly refillRate: number;
    /**
     * Current number of tokens in the bucket.
     */
    private tokens;
    constructor({ capacity, refillRate }: TokenBucketThrottlerConfig);
    /**
     * Attempts to acquire permission to proceed with a request.
     *
     * First, the number of refilled tokens since the last check
     * is calculated and the bucket's level is updated accordingly.
     *
     * If at least one token is available, the request is accepted.
     *
     * Otherwise, returns the timestamp when a token will become
     * available to allow the request.
     */
    protected tryAcquire(): number;
}

export { AbortError, FixedWindowThrottler, type FixedWindowThrottlerConfig, LeakyBucketThrottler, type LeakyBucketThrottlerConfig, LinearThrottler, type LinearThrottlerConfig, RetryError, SlidingWindowThrottler, type SlidingWindowThrottlerConfig, Throttler, type ThrottlerWaitOptions, TimeoutError, TokenBucketThrottler, type TokenBucketThrottlerConfig };
