UNPKG

@adonisjs/limiter

Version:

Rate limiting package for AdonisJS framework

147 lines (146 loc) 5.23 kB
import type { HttpContext } from '@adonisjs/core/http'; import type { MiddlewareFn } from '@adonisjs/core/types/http'; import { Limiter } from './limiter.ts'; import { HttpLimiter } from './http_limiter.ts'; import type { LimiterConsumptionOptions, LimiterManagerStoreFactory } from './types.ts'; import { MultiLimiter } from './multi_limiter.ts'; /** * Manages multiple rate limiter stores and creates limiter instances. * Supports creating limiters with runtime configuration for requests, * duration, and block duration. * * Limiter instances are cached based on their configuration to optimize performance. */ export declare class LimiterManager<KnownStores extends Record<string, LimiterManagerStoreFactory>> { #private; config: { default: keyof KnownStores; stores: KnownStores; }; constructor(config: { default: keyof KnownStores; stores: KnownStores; }); /** * Generates a unique cache key for a limiter instance based on its configuration. * Used internally to cache and reuse limiter instances. * * @param store - The store name * @param options - Consumption options for the limiter */ protected makeLimiterKey(store: keyof KnownStores, options: LimiterConsumptionOptions): string; /** * Creates a multi-limiter that can execute operations across multiple limiters atomically. * Useful for applying rate limits across different dimensions (e.g., per user and per IP). * * @param store - Store name or array of limiter options with keys * @param options - Array of limiter options with keys (when store is specified) * * @example * ```ts * const multi = limiter.multi([ * { key: 'user:123', requests: 100, duration: '1 hour' }, * { key: 'ip:192.168.1.1', requests: 1000, duration: '1 hour' } * ]) * * await multi.consume() * ``` */ multi(options: (LimiterConsumptionOptions & { key: string | number; })[]): MultiLimiter; multi<K extends keyof KnownStores>(store: K, options: (LimiterConsumptionOptions & { key: string | number; })[]): MultiLimiter; /** * Creates or retrieves a cached limiter instance with the specified configuration. * Instances are cached for the lifetime of the process based on their unique configuration. * * @param store - Store name or consumption options * @param options - Consumption options (when store is specified) * * @example * ```ts * // Use default store * const limiter = limiterManager.use({ * requests: 100, * duration: '1 hour' * }) * * // Use specific store * const redisLimiter = limiterManager.use('redis', { * requests: 1000, * duration: '1 day' * }) * ``` */ use(options: LimiterConsumptionOptions): Limiter; use<K extends keyof KnownStores>(store: K, options: LimiterConsumptionOptions): Limiter; /** * Clears rate limit data from the specified stores or all stores. * * @param stores - Optional array of store names to clear. Clears all stores if not specified. * * @example * ```ts * // Clear all stores * await limiterManager.clear() * * // Clear specific stores * await limiterManager.clear(['redis', 'memory']) * ``` */ clear(stores?: Extract<keyof KnownStores, string>[]): Promise<void>; /** * Creates an HTTP limiter builder with the specified number of allowed requests. * This is the starting point for defining HTTP rate limiting middleware. * * @param requests - Number of requests to allow * * @example * ```ts * const httpLimiter = limiterManager * .allowRequests(100) * .every('1 hour') * ``` */ allowRequests(requests: number): HttpLimiter<KnownStores>; /** * Returns null to disable rate limiting for specific routes or users. * Useful in middleware when you want to conditionally skip rate limiting. * * @example * ```ts * router.get('/api/data', [ * limiter.define('api', async (ctx) => { * if (ctx.auth.user?.isAdmin) { * return limiter.noLimit() * } * return limiter.allowRequests(100).every('1 hour') * }) * ]) * ``` */ noLimit(): null; /** * Defines a named rate limiting middleware for HTTP routes. * The builder function is called for each request to determine rate limiting behavior. * * @param name - Unique name for the middleware (used as key prefix) * @param builder - Function that returns an HttpLimiter or null to skip limiting * * @example * ```ts * export const apiLimiter = limiter.define('api', (ctx) => { * return limiter * .allowRequests(100) * .every('1 hour') * .usingKey(ctx.auth.user.id) * }) * * // Apply to routes * router.get('/api/data', [apiLimiter], controller.index) * ``` */ define(name: string, builder: (ctx: HttpContext) => HttpLimiter<any> | null | Promise<HttpLimiter<any>> | Promise<null>): MiddlewareFn; }