In-memory rate limiter and pub/sub adapter for WS-Kit
npm install @ws-kit/memoryIn-memory adapters for WS-Kit. Provides a zero-dependency pub/sub registry and token-bucket rate limiter for single-instance development and tests (Bun/Node.js).
- Local development, unit tests, or single-server deployments
- Exact subscriber counts without external brokers
- Deterministic rate-limit testing via injectable clocks
- ⚠️ Not distributed — no cross-process/state persistence
- memoryPubSub() — In-memory topic index (Map). Implements publish, subscribe, unsubscribe, getSubscribers, listTopics, hasTopic, and replace for bulk topic swaps. excludeSelf filtering is handled by the pubsub plugin layer.
- memoryRateLimiter(policy, opts?) — Token-bucket limiter with per-key mutex to prevent double spending. Supports prefix isolation, getPolicy(), dispose(), and optional clock injection for deterministic tests.
- Types: MemoryPubSubAdapter, MemoryRateLimiterOptions, Clock.
``bash`
bun add @ws-kit/memory
`typescript
import { createRouter, withZod, message } from "@ws-kit/zod";
import { withPubSub } from "@ws-kit/plugins";
import { memoryPubSub } from "@ws-kit/memory";
import { z } from "zod";
const Notify = message("NOTIFY", { text: z.string() });
const router = createRouter()
.plugin(withZod())
.plugin(withPubSub({ adapter: memoryPubSub() })); // exact local fan-out
router.on(Notify, async (ctx) => {
await ctx.topics.subscribe("room:lobby");
await ctx.publish("room:lobby", Notify, { text: "Hi!" });
});
`
`typescript
import { createRouter } from "@ws-kit/core";
import { rateLimit, keyPerUserPerType } from "@ws-kit/rate-limit";
import { memoryRateLimiter } from "@ws-kit/memory";
const limiter = memoryRateLimiter({
capacity: 100, // bucket size
tokensPerSecond: 10, // refill rate
prefix: "api:", // optional isolation when sharing a backend
});
const router = createRouter().use(
rateLimit({
limiter,
key: keyPerUserPerType,
cost: () => 1,
}),
);
`
- Pub/sub is process-local only; restart clears subscriptions.
- Rate limiter is process-local; use @ws-kit/redis or a Durable Objects adapter for shared limits.{ clock: { now: () => number } }
- For deterministic tests, pass to memoryRateLimiter()`.