{"_id":"@caseyzandbergen/rate-limiter","name":"@caseyzandbergen/rate-limiter","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@caseyzandbergen/rate-limiter","version":"1.0.0","description":"Token bucket rate limiter for HTTP clients. Zero dependencies.","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"scripts":{"build":"tsc","test":"vitest run","test:watch":"vitest","prepublishOnly":"npm run build && npm test"},"devDependencies":{"@types/node":"^25.9.1","typescript":"^5.4.0","vitest":"^2.0.0"},"keywords":["rate-limiter","token-bucket","throttle","http","fetch"],"license":"MIT","repository":{"type":"git","url":"git+https://github.com/caseyzandbergen/rate-limiter.git"},"gitHead":"be26762e6a5d06c08c3e4426e662a634e434bf85","_id":"@caseyzandbergen/rate-limiter@1.0.0","bugs":{"url":"https://github.com/caseyzandbergen/rate-limiter/issues"},"homepage":"https://github.com/caseyzandbergen/rate-limiter#readme","_nodeVersion":"26.0.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-GxKT3toGcY80v+xMinqED2l0RsWY9x6HCGEPe3l/K5h9yDhGt1IyKAohm0Yr2H9FC0OqGgkE7qFQGQOWSNNMOQ==","shasum":"634e87795868ba220d4c96e1edadbb0d9d0fb5a9","tarball":"https://registry.npmjs.org/@caseyzandbergen/rate-limiter/-/rate-limiter-1.0.0.tgz","fileCount":6,"unpackedSize":15136,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC4LECSlXKbpFijmsunwUxgc2y5GaWmq9LZnUTqhWMp1gIgJ4+1u18hP1vC+FvUM4z8VoZ0p0zJkjliC8NNFQBnKLU="}]},"_npmUser":{"name":"caseyzandbergen","email":"casey.zandbergen@gmail.com"},"directories":{},"maintainers":[{"name":"caseyzandbergen","email":"casey.zandbergen@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rate-limiter_1.0.0_1779646819375_0.3949347733134543"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-24T18:20:19.259Z","1.0.0":"2026-05-24T18:20:19.519Z","modified":"2026-05-24T18:20:19.684Z"},"maintainers":[{"name":"caseyzandbergen","email":"casey.zandbergen@gmail.com"}],"description":"Token bucket rate limiter for HTTP clients. Zero dependencies.","homepage":"https://github.com/caseyzandbergen/rate-limiter#readme","keywords":["rate-limiter","token-bucket","throttle","http","fetch"],"repository":{"type":"git","url":"git+https://github.com/caseyzandbergen/rate-limiter.git"},"bugs":{"url":"https://github.com/caseyzandbergen/rate-limiter/issues"},"license":"MIT","readme":"# @caseyzandbergen/rate-limiter\n\nToken bucket rate limiter for HTTP clients. Zero dependencies.\n\n## Install\n\n```bash\nnpm install @caseyzandbergen/rate-limiter\n```\n\n## Usage\n\n### Basic\n\n```ts\nimport { RateLimiter, rateLimitFetch } from '@caseyzandbergen/rate-limiter'\n\nconst limiter = new RateLimiter({ rpsLimit: 10 })\nconst fetch = rateLimitFetch(globalThis.fetch, limiter)\n\n// All requests through this fetch are throttled to 10 RPS\nconst res = await fetch('https://api.example.com/data')\n```\n\n### Singleton\n\n```ts\nimport { getGlobalLimiter, rateLimitFetch } from '@caseyzandbergen/rate-limiter'\n\nconst fetch = rateLimitFetch(globalThis.fetch, getGlobalLimiter({ rpsLimit: 5 }))\n```\n\n### Options\n\n```ts\nnew RateLimiter({\n  rpsLimit: 10,    // requests per second (default: 10)\n  burst: 20,       // max burst tokens (default: rpsLimit)\n  enabled: true,   // set false to disable (useful in tests)\n  envPrefix: 'MY_APP', // read config from env vars (default: 'RATE_LIMIT')\n  log: false,      // log events to console (default: false)\n})\n```\n\n### Environment variable config\n\nSet `envPrefix` once; the rest comes from env vars:\n\n| Option | Env var (prefix = `MY_APP`) | Default |\n|--------|-----------------------------|---------|\n| `rpsLimit` | `MY_APP_RPS` | `10` |\n| `burst` | `MY_APP_BURST` | `rpsLimit` |\n| `enabled` | `MY_APP_ENABLED` | `true` |\n| `log` | `MY_APP_LOG` | `false` |\n\n```ts\n// reads MY_APP_RPS, MY_APP_BURST, MY_APP_ENABLED, MY_APP_LOG\nnew RateLimiter({ envPrefix: 'MY_APP' })\n```\n\nSet `envPrefix: null` to skip env vars entirely and use only the constructor options.\n\n### Non-blocking check\n\n```ts\nconst limiter = new RateLimiter({ rpsLimit: 5 })\n\nif (limiter.tryAcquire()) {\n  // token available — make the request\n} else {\n  // no token available — skip or queue\n}\n```\n\n### Debug status\n\n```ts\nconst { tokens, rpsLimit, burst, enabled } = limiter.getStatus()\nconsole.log(`${tokens.toFixed(1)} / ${burst} tokens available`)\n```\n\n## API\n\n### `new RateLimiter(options?)`\n\n| Option | Type | Default |\n|--------|------|---------|\n| `rpsLimit` | `number` | `10` |\n| `burst` | `number` | `rpsLimit` |\n| `enabled` | `boolean` | `true` |\n| `envPrefix` | `string \\| null` | `'RATE_LIMIT'` |\n| `log` | `boolean` | `false` |\n\n### `limiter.acquire(): Promise<void>`\n\nBlocks until a token is available, then consumes it. If disabled, returns immediately.\n\n### `limiter.tryAcquire(): boolean`\n\nNon-blocking. Returns `true` if a token was consumed, `false` if none available.\n\n### `limiter.getStatus()`\n\nReturns `{ tokens, rpsLimit, burst, enabled }` for debugging.\n\n### `rateLimitFetch(fetchFn, limiter)`\n\nWraps any fetch-compatible function. Calls `limiter.acquire()` before each request.\n\n### `getGlobalLimiter(options?)`\n\nReturns a shared singleton instance. Options only apply on first call.\n\n### `resetGlobalLimiter()`\n\nClears the singleton — intended for use in tests.\n\n## How it works\n\nToken bucket algorithm: a bucket starts full at `burst` tokens. Each request consumes one token. Tokens refill at `rpsLimit` per second. When the bucket is empty, `acquire()` waits for the next token.\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-43742c5acc328f6453d4c7adff1ef962"}