Files
skills/docs/api-stack/api/api-plugin-rate-limit/README.md
2026-05-29 08:20:56 +01:00

134 lines
7.2 KiB
Markdown

# @suaveplan/api-plugin-rate-limit - Rate-limit plugin for @suaveplan/api. Wraps @suaveplan/rate-limiter as a definePlugin descriptor: per-route + per-tenant configuration, parameterised path matcher, IP whitelist, tenant multiplier applied to numeric limit, Hono middleware factory, 429 + Retry-After + X-RateLimit-* / RateLimit-* headers, OTel counters, RFC 7807 Problem+JSON body. Registers `rateLimitService` in the host ServiceRegistry.
Rate-limit plugin for `@suaveplan/api`. Wraps `@suaveplan/rate-limiter`
as a `definePlugin` descriptor exposing per-route + per-tenant
configuration, parameterised path matching, IP whitelist, applied
tenant multiplier, Hono middleware, `X-RateLimit-*` / `RateLimit-*` /
`Retry-After` headers, RFC 7807 Problem+JSON 429 body, and OTel
counters / histogram. Registers a typed `rateLimitService` slot in the
host `ServiceRegistry` so sibling plugins can run manual checks.
<!-- begin:auto-docs -->
## Documentation tree
- [error-codes](./src/error-codes/error-codes.md) — Provides the stable, namespaced error-code registry every failure path in `@suaveplan/api-plugin-rate-limit` reports th…
- [error-codes](./src/error-codes/error-codes.md) — Provides the stable, namespaced error-code registry every failure path in `@suaveplan/api-plugin-rate-limit` reports th…
- [headers](./src/headers/headers.md) — Builds the HTTP response headers and Problem+JSON body the rate-limit middleware writes onto every response (allowed AN…
- [headers](./src/headers/headers.md) — Builds the HTTP response headers and Problem+JSON body the rate-limit middleware writes onto every response (allowed AN…
- [context-augmentation](./src/middleware/context-augmentation.md) — Augments Hono's `ContextVariableMap` interface so handlers calling `c.get("rateLimit")` get a typed `RateLimitDecision`…
- [rate-limit](./src/middleware/rate-limit.md) — Constructs a Hono `MiddlewareHandler` that consults a `RateLimitService` on every request, emits the configured `X-Rate…
- [otel](./src/otel/instruments.md) — Builds (and caches) the bundle of OpenTelemetry instruments the rate-limit plugin emits on every check. Operators wirin…
- [instruments](./src/otel/instruments.md) — Builds (and caches) the bundle of OpenTelemetry instruments the rate-limit plugin emits on every check. Operators wirin…
- [path-matcher](./src/path-matcher/path-matcher.md) — Compiles a Hono-style path pattern string into a regular expression
- [path-matcher](./src/path-matcher/path-matcher.md) — Compiles a Hono-style path pattern string into a regular expression
- [plugin](./src/plugin/plugin.md) — Factory that returns a typed `PluginDescriptor` for the rate-limit plugin, ready to be passed to `@suaveplan/api`'s plu…
- [plugin](./src/plugin/plugin.md) — Factory that returns a typed `PluginDescriptor` for the rate-limit plugin, ready to be passed to `@suaveplan/api`'s plu…
- [schemas](./src/schemas/options.md) — Validates the caller-supplied `RateLimitPluginOptions` at the boundary and fills in defaults for every optional field,…
- [options](./src/schemas/options.md) — Validates the caller-supplied `RateLimitPluginOptions` at the boundary and fills in defaults for every optional field,…
- [rate-limit-service](./src/services/rate-limit-service.md) — Wraps the universal `@suaveplan/rate-limiter` core in the plugin's policy layer: IP whitelist, tenant bypass, tenant mu…
- [registry-augmentation](./src/services/registry-augmentation.md) — Augments the `ServiceRegistry` interface owned by `@suaveplan/api-plugin/service-registry` so consumers see the `rateLi…
- [types](./src/types/types.md) — Defines the public type surface every other module in the package references — the caller-facing `RateLimitPluginOption…
- [types](./src/types/types.md) — Defines the public type surface every other module in the package references — the caller-facing `RateLimitPluginOption…
<!-- end:auto-docs -->
## Install
```bash
bun add @suaveplan/api-plugin-rate-limit
```
## Quick start
```ts
import { createApi } from "@suaveplan/api";
import { createRateLimitPlugin } from "@suaveplan/api-plugin-rate-limit";
const api = createApi();
api.use(
createRateLimitPlugin({
defaultLimit: 100,
defaultWindowMs: 60_000,
routes: [
{
path: "/api/login",
method: "POST",
limit: 5,
windowMs: 60_000,
id: "login",
},
{ path: "/api/users/:id", limit: 30, windowMs: 60_000 },
],
tenants: [
{ tenantId: "enterprise", multiplier: 10 },
{ tenantId: "internal", bypass: true },
],
ipWhitelist: ["127.0.0.1"],
headerStyle: "both",
})
);
```
Every request flowing through the host Hono app is now rate-limited.
Responses carry both legacy `X-RateLimit-Limit` / `X-RateLimit-Remaining`
/ `X-RateLimit-Reset` and IETF `RateLimit-Limit` / `RateLimit-Remaining`
/ `RateLimit-Reset` headers. Denied requests return `429` with
`Content-Type: application/problem+json` and a `Retry-After` header.
## Manual `service.check(...)` from sibling plugins
```ts
import {
rateLimitExceeded,
type RateLimitService,
} from "@suaveplan/api-plugin-rate-limit";
const service = ctx.getService("rateLimitService") as RateLimitService;
const decision = await service.check({
ip,
tenantId,
path: "/api/billing/invoice",
method: "POST",
});
if (!decision.allowed) throw rateLimitExceeded(decision);
```
## The 3-way plug-and-play contract
This package follows the same contract every `@suaveplan/api-plugin-*`
package follows: it owns its boundary Zod schemas
(`RateLimitPluginOptionsSchema`), registers a typed slot in the host
`ServiceRegistry` (`rateLimitService`), and installs a global Hono
middleware via `app.use("*", rateLimit({ service }))` from its
canonical 6-step `onInit` lifecycle (resolve services → build storage
→ construct service → register slot → install middleware → log
readiness).
## Modules
- [`src/error-codes/error-codes.md`](src/error-codes/error-codes.md) —
`RATE_LIMIT_PLUGIN_CODES` registry + `RateLimitPluginError`.
- [`src/types/types.md`](src/types/types.md) — public type surface.
- [`src/schemas/options.md`](src/schemas/options.md) — Zod schema for
caller-supplied options.
- [`src/path-matcher/path-matcher.md`](src/path-matcher/path-matcher.md)
— Hono-compatible path-pattern compilation + matching.
- [`src/headers/headers.md`](src/headers/headers.md) — header bag +
Problem+JSON body construction.
- [`src/otel/instruments.md`](src/otel/instruments.md) — OpenTelemetry
instruments bundle.
- [`src/services/rate-limit-service.md`](src/services/rate-limit-service.md)
— `RateLimitService` factory.
- [`src/services/registry-augmentation.md`](src/services/registry-augmentation.md)
— `ServiceRegistry` module augmentation.
- [`src/middleware/rate-limit.md`](src/middleware/rate-limit.md) —
Hono middleware factory.
- [`src/middleware/context-augmentation.md`](src/middleware/context-augmentation.md)
— Hono `ContextVariableMap` augmentation.
- [`src/plugin/plugin.md`](src/plugin/plugin.md) —
`createRateLimitPlugin` factory.
## Status
`0.1.0` — initial ship. Surface is final for the 0.1.x line.