/** * Nexus Per-Action Rate Limiter — Sliding Window Algorithm. * * Unlike middleware-level rate limiting (which throttles the entire API), * Nexus allows granular limits per Server Action. You define the policy * alongside the action handler — not in a separate config file. * * Usage: * * ```ts * export const capture = createAction({ * rateLimit: { window: '1m', max: 3, keyFn: (req) => req.userId }, * handler: async (data) => { ... } * }); * ``` * * Algorithm: Sliding window log — stores timestamps of each request. * Timestamps older than `window` are evicted before checking the limit. * This is more accurate than the fixed window approach (no edge-of-window bursts). * * Memory: O(max * unique_keys). For typical SaaS usage with 10K users and * max=10, this is ~100K timestamp entries — well within Node.js limits. * For high-scale, replace the Map with Redis ZSET. */ export interface RateLimitConfig { /** * Time window for the limit. * Formats: '30s', '1m', '5m', '15m', '1h', '6h', '24h' */ window: string; /** Maximum requests allowed within the window. */ max: number; /** * Function to derive the rate limit key from the request. * Default: IP address extracted from common proxy headers. * Override for user-specific limits: (req) => req.headers.get('x-user-id') ?? 'anon' */ keyFn?: (request: Request) => string; } export interface RateLimitResult { allowed: boolean; remaining: number; limit: number; resetAt: number; retryAfter?: number; } export interface RateLimiter { check(request: Request): RateLimitResult; /** Reset the limit for a specific key (useful in tests or after user verification). */ reset(key: string): void; /** Returns a headers object to add to the response for RFC 6585 compliance. */ headers(result: RateLimitResult): Record; } export declare function parseWindow(window: string): number; /** * Creates a reusable sliding-window rate limiter. * * @example * const captureLimit = createRateLimiter({ window: '1m', max: 3 }); * // In your action handler: * const result = captureLimit.check(request); * if (!result.allowed) throw new RateLimitError(result); */ export declare function createRateLimiter(config: RateLimitConfig): RateLimiter; export declare class RateLimitError extends Error { readonly result: RateLimitResult; constructor(result: RateLimitResult); } export declare function registerLimiter(name: string, limiter: RateLimiter): void; export declare function getLimiter(name: string): RateLimiter | undefined; //# sourceMappingURL=rate-limit.d.ts.map