interface RateLimitAlgorithm<T extends AlgorithmValues> {
    /**
     * Maximum amount of points that client can consume
     */
    limit: number;
    /**
     * Duration of time in milliseconds when algorithm updates its counter
     */
    windowMs: number;
    /**
     * Store which contains clients data based on chosen algorithm
     */
    store: ToStore<T>;
    /**
     * Consume points from a client's bucket.
     * @async
     * @param {string} clientId - The identifier for a client
     * @param {number} [weight=1] - Amount of points to consume per request.  Defaults to 1
     * @returns {Promise<boolean>} - Whether the client is allowed to proceed with the request.
     */
    consume: (clientId: string, weight?: number) => Promise<ConsumeResult<T>>;
}
type ConsumeResult<T extends AlgorithmValues> = {
    /**
     * Is client allowed to proceed with request
     */
    isAllowed: boolean;
    /**
     * An array of rate limit headers in pairs of [name,value]
     */
    clientData: T;
};
interface Store<T extends AlgorithmValues> {
    /**
     * Gets client data from a store
     * @async
     * @param {string} clientId - The identifier for a client
     * @returns {Promise<T | undefined>} - Client data from a store
     */
    get: (clientId: string) => Promise<T | undefined>;
    /**
     * Saves client data in a store
     * @async
     * @param {string} clientId - The identifier for a client
     * @returns {Promise<T>} - Current client data
     */
    set: (clientId: string, value: T) => Promise<T>;
    /**
     * Deletes client data from a store
     * @async
     * @param {string} clientId - The identifier for a client
     */
    remove: (clientId: string) => Promise<void>;
    /**
     * Resets all clients data in a store
     * @async
     */
    reset: () => Promise<void>;
    /**
     * Sets TTL - time period when expired clients will be removed in milliseconds
     */
    setTTL: (TTL: number) => void;
    /**
     * Clean shutdown for the store
     */
    shutdown?: () => Promise<void>;
}
type ToStore<T> = T extends AlgorithmValues ? Store<T> : never;
type AlgorithmOptions<T extends AlgorithmValues> = {
    /**
     * Maximum amount of points that client can consume
     */
    limit: number;
    /**
     * Duration of time in milliseconds when algorithm updates its counter
     */
    windowMs: number;
    /**
     * Store which contains clients data based on chosen algorithm
     */
    store?: Store<T>;
};
type TokenBucketValues = {
    /**
     * Current number of points remaining to consume
     */
    points: number;
    /**
     * Time in milliseconds when token bucket was last refilled
     */
    lastRefillTimeMs: number;
};
/**
 * Queue of timestamps ordered from lowest to highest
 */
type SlidingWindowLogValues = number[];
type SlidingWindowCounterValues = {
    /**
     * Points from previous window
     */
    prevPoints: number;
    /**
     * Points from current window
     */
    currPoints: number;
    /**
     * Time in milliseconds which separates previous and current windows
     */
    edgeTimeMs: number;
};
type FixedWindowCounterValues = {
    /**
     * Current number of points consumed
     */
    points: number;
    /**
     * Time in milliseconds when  window was updated
     */
    lastWindowResetTimeMs: number;
};
type AlgorithmValues = TokenBucketValues | SlidingWindowLogValues | SlidingWindowCounterValues | FixedWindowCounterValues;
type TokenBucketConfig = AlgorithmOptions<TokenBucketValues>;
type SlidingWindowLogConfig = AlgorithmOptions<SlidingWindowLogValues>;
type SlidingWindowCounterConfig = AlgorithmOptions<SlidingWindowCounterValues>;
type FixedWindowCounterConfig = AlgorithmOptions<FixedWindowCounterValues>;
type TokenBucketOptions = {
    /**
     * Token bucket algorithm
     */
    algorithm: "token-bucket";
} & TokenBucketConfig;
type SlidingWindowCounterOptions = {
    /**
     * Sliding window counter algorithm
     */
    algorithm: "sliding-window-counter";
} & SlidingWindowCounterConfig;
type SlidingWindowLogsOptions = {
    /**
     * Sliding window logs algorithm
     */
    algorithm: "sliding-window-logs";
} & SlidingWindowLogConfig;
type FixedWindowCounterOptions = {
    /**
     * Fixed window counter algorithm
     */
    algorithm: "fixed-window-counter";
} & FixedWindowCounterConfig;
/**
 * @type {ConfigOptions} config
 * @property {string} algorithm - Algorithm type
 * @property {number} limit - Maximum amount of points client can consume
 * @property {number} windowMs - Duration of time in milliseconds when algorithm updates its counter
 * @property {Store | undefined} store - Store which contains clients data based on chosen algorithm
 */
type ConfigOptions = TokenBucketOptions | SlidingWindowCounterOptions | SlidingWindowLogsOptions | FixedWindowCounterOptions;

declare class RateLimiter implements RateLimitAlgorithm<AlgorithmValues> {
    readonly limit: number;
    readonly windowMs: number;
    readonly store: ToStore<AlgorithmValues>;
    consume: (clientId: string, weight?: number) => Promise<ConsumeResult<AlgorithmValues>>;
    private getRemainingPoints;
    private getResetTime;
    /**
     * @constructor
     * @param {ConfigOptions} config - Rate limiter config options
     */
    constructor(config: ConfigOptions);
    /**
     * Get rate limit headers for a client.
     * @param {AlgorithmValues} clientData - Retrieved data for a client
     * @returns {[string,string][]} - An array of rate limit headers in pairs of [name,value]
     */
    getHeaders(clientData: AlgorithmValues): [string, string][];
    private setDefaults;
    private getAlgorithm;
    private validateConfig;
    private checkForInvalidClientId;
}

declare class MemoryStore<T extends AlgorithmValues> implements Store<T> {
    /**
     * 'oldClients' are retained temporarily before being removed completely based on an interval timer.
     * Clients are moved from 'activeClients' to 'oldClients' when interval timer triggers.
     * Clients are moved from 'oldClients' to 'activeClients' when they are doing a request
     */
    private oldClients;
    private activeClients;
    private TTL;
    private interval?;
    constructor();
    get(clientId: string): Promise<T | undefined>;
    set(clientId: string, value: T): Promise<T>;
    remove(clientId: string): Promise<void>;
    reset(): Promise<void>;
    setTTL(TTL: number): void;
    shutdown(): Promise<void>;
    private clearExpired;
}

type RedisOptions = {
    rawCall: (...args: string[]) => Promise<unknown>;
    prefix?: string;
};
declare class RedisStore<T extends AlgorithmValues> implements Store<T> {
    private prefix;
    private rawCall;
    private TTL;
    constructor(options: RedisOptions);
    get(clientId: string): Promise<T | undefined>;
    set(clientId: string, value: T): Promise<T>;
    remove(clientId: string): Promise<void>;
    reset(): Promise<void>;
    setTTL(TTL: number): void;
    private prefixedKey;
    shutdown(): Promise<void>;
}

export { MemoryStore, RateLimiter, RedisStore };
