# rate-limiter / adapter _(no submodules)_ ## Purpose Normalises the `@suaveplan/rate-limiter` `TokenBucket` API onto the `ChunkRateLimiter` interface used internally by the streaming chunk queue. The `TokenBucket` does NOT throw on denial — it returns `{ allowed: boolean, retryAfter?: number }`. This adapter encodes the denial branch into the canonical `{ allowed: false, delay }` shape the queue understands, with a configurable fallback when `retryAfter` is missing. ## Features - Wraps any structurally compatible `TokenBucketLike`. - Returns `{ allowed: true, delay: 0 }` on admission. - Returns `{ allowed: false, delay }` on denial, using `retryAfter` when positive or a configurable fallback (default 100 ms) otherwise. - Stateless beyond the bucket reference — safe to share across queues. ## Usage: Basic ```ts import { TokenBucket } from "@suaveplan/rate-limiter"; import { TokenBucketRateLimiterAdapter } from "@suaveplan/streams-chunk-queue"; const bucket = new TokenBucket({ capacity: 1024 * 1024, refillRate: 1024 }); const limiter = new TokenBucketRateLimiterAdapter(bucket); ``` ## Usage: Advanced ```ts // Aggressive fallback for tightly-bound real-time streams. const limiter = new TokenBucketRateLimiterAdapter(bucket, 25); ``` ## API Reference ### `ChunkRateLimiter` ```ts interface ChunkRateLimiter { consume(bytes: number): { allowed: boolean; delay: number }; } ``` ### `TokenBucketLike` Structural subset of the `TokenBucket`: ```ts interface TokenBucketLike { consume(tokens?: number): { allowed: boolean; retryAfter?: number }; } ``` ### `TokenBucketRateLimiterAdapter` ```ts new TokenBucketRateLimiterAdapter( bucket: TokenBucketLike, fallbackDelayMs?: number, // default 100 ) ``` `consume(bytes)` calls `bucket.consume(bytes)` and normalises the result. The fallback delay is used only when the bucket denies AND omits / zeroes `retryAfter`. ### `DEFAULT_RATE_LIMIT_DELAY_MS` The constant `100`. Exposed for callers who want to reuse the default in their own diagnostics. ## Implementation Notes The structural `TokenBucketLike` keeps `@suaveplan/rate-limiter` an optional peer concern at the type boundary — tests inject a fake bucket and never need to spin up the real one. The adapter does not sleep itself; the queue is in charge of timing because it owns the `onRateLimit` hook and the `rate:limited` event.