@ws-kit/memory
v0.10.0
Published
In-memory rate limiter and pub/sub adapter for WS-Kit
Readme
@ws-kit/memory
In-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).
When to use
- 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
What you get
memoryPubSub()— In-memory topic index (Map<topic, Set<clientId>>). Implementspublish,subscribe,unsubscribe,getSubscribers,listTopics,hasTopic, andreplacefor bulk topic swaps.excludeSelfis unsupported (no sender context).memoryRateLimiter(policy, opts?)— Token-bucket limiter with per-key mutex to prevent double spending. Supportsprefixisolation,getPolicy(),dispose(), and optionalclockinjection for deterministic tests.- Types:
MemoryPubSubAdapter,MemoryRateLimiterOptions,Clock.
Installation
bun add @ws-kit/memoryQuick start: pub/sub (development)
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!" });
});Quick start: rate limiting
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,
}),
);Notes
- Pub/sub is process-local only; restart clears subscriptions.
- Rate limiter is process-local; use
@ws-kit/redisor a Durable Objects adapter for shared limits. - For deterministic tests, pass
{ clock: { now: () => number } }tomemoryRateLimiter().
