/** * Per-key fixed-window request-rate limiter. Every `consume()` counts toward * the limit; once the window's count hits `maxRequests`, subsequent consumes * return `allowed: false` until the window rolls over. * * Use this for *throughput* limiting (e.g. "15 req/min on /admin"). For * *failure-rate* limiting with lockout (e.g. brute-force protection), use * {@link FailureLimiter} instead. */ import { type Clock } from './keyed-store.js'; export type RateLimiterConfig = { maxRequests: number; windowMs: number; /** How long to retain idle keys before sweep. Defaults to 4× windowMs. */ staleAfterMs?: number; clock?: Clock; }; /** * Flat rather than tagged-union: project's tsconfig has `strict: false`, which * disables boolean discriminator narrowing through `if (!x.allowed)`. Both * fields are always populated — `retryAfterMs` is 0 on success, `remaining` * is 0 on block. */ export type RateLimitDecision = { allowed: boolean; remaining: number; retryAfterMs: number; }; export declare class RateLimiter { private readonly store; private readonly clock; private readonly maxRequests; private readonly windowMs; constructor(cfg: RateLimiterConfig); consume(key: string): RateLimitDecision; /** @internal Test hook. */ resetForTests(): void; destroy(): void; }