@coderbuzz/ken
v0.1.5
Published
The modern standard for TypeScript backends - runtime-agnostic HTTP framework for Bun, Node.js, and Deno.
Maintainers
Readme
Ken — @coderbuzz/ken
The Modern Standard for TypeScript Backends.
Ken is a next-generation TypeScript backend framework designed to run seamlessly across Node.js, Deno, and Bun. It focuses on clarity, speed, and a clean developer experience without unnecessary abstraction.
Built entirely with TypeScript, Ken is minimalist, high-performance, and fully type-safe. Designed for the modern JavaScript ecosystem, it ensures your application runs consistently across Node.js, Deno, and Bun. Write once, deploy everywhere, and unleash the true potential of your server-side code.
Engineered from the ground up to deliver unparalleled developer experience (DX) and superior performance, Ken leverages the power of modern TypeScript and a fluent, modular architecture to help developers build scalable APIs and services with absolute type safety — with full type inference, schema validation, and built-in WebSocket support.
Key Features
- Runtime Agnostic: Seamlessly run your application on Node.js, Deno, and Bun without code changes.
- TypeScript Native: Full type-checking and autocompletion support out of the box.
- Schema Validation: Validate request params, query, headers, cookies, and body with inline schemas.
- Built-in Middleware: JWT, CORS, sessions, compression, rate limiting, secure headers, and more.
- WebSocket Support: Real-time connections with pub/sub, ping/pong, and typed upgrade data.
- Performance-Driven: Minimal overhead engineered for high throughput and low latency.
- Modular & Extensible: Easily integrate with existing libraries and scale complexity as needed.
Installation
# Bun
bun add @coderbuzz/ken
# npm
npm install @coderbuzz/ken
# Deno
import { AppServer } from "npm:@coderbuzz/ken";For Node.js, also install a peer for ESM compatibility:
npm install tsx
node --import tsx/esm server.tsQuick Start
import { AppServer } from "@coderbuzz/ken";
const app = new AppServer({ port: 3000 });
app.get("/", "Hello, Ken!");
const { hostname, port } = await app.run();
console.log(`Listening on ${hostname}:${port}`);Routing
Static Routes
app.get("/", "Hello Ken!");
app.get("/health", "OK");
app.get("/version", { version: "1.0.0" }); // plain objects are JSON-serializedDynamic Params
app.get("/users/:id", (ctx) => new Response(`User ${ctx.params.id}`));
app.get(
"/posts/:postId/comments/:commentId",
(ctx) =>
new Response(`Post ${ctx.params.postId}, Comment ${ctx.params.commentId}`),
);Optional Params & Wildcards
app.get(
"/optional/:id?",
(ctx) => new Response(`ID: ${ctx.params.id ?? "none"}`),
);
app.get("/files/*", (ctx) => new Response(`File: ${ctx.params["*"]}`));HTTP Methods
app.post("/items", handler);
app.put("/items/:id", handler);
app.patch("/items/:id", handler);
app.delete("/items/:id", handler);Schema Validation
Ken validates request data inline via the schema object (first argument before
the handler). Use
@coderbuzz/kyo for schema
builders.
import {
boolean,
coerce,
number,
object,
optional,
string,
} from "@coderbuzz/kyo";Params
app.get("/products/:id", {
params: { id: coerce(number()) },
}, (ctx) => Response.json({ productId: ctx.params.id }));
// ctx.params.id is typed as numberQuery
app.get("/search", {
query: {
q: string({ min: 1 }),
page: coerce(number({ min: 1, max: 100 })),
limit: optional(coerce(number({ min: 10, max: 100 }))),
},
}, (ctx) => Response.json({ search: ctx.query.q, page: ctx.query.page }));Headers
app.get("/api/resource", {
headers: { "x-api-key": string({ min: 10 }) },
}, (ctx) => Response.json({ key: ctx.headers["x-api-key"] }));Cookies
app.get(
"/api/profile",
{
cookies: {
sessionId: string({ min: 5 }),
premium: optional(coerce(boolean())),
},
},
(ctx) =>
Response.json({
session: ctx.cookies.sessionId,
isPremium: ctx.cookies.premium,
}),
);JSON Body
app.post("/api/users", {
json: object({
name: string({ min: 2 }),
age: number({ min: 18 }),
active: boolean(),
email: optional(string()),
}),
}, async (ctx) => {
const body = await ctx.json;
return Response.json({ name: body.name, age: body.age });
});Text Body
app.post("/api/echo", {
text: string({ min: 5 }),
}, async (ctx) => new Response(await ctx.text));Form Body
app.post("/api/submit", {
form: { field: string({ min: 3 }) },
}, async (ctx) => {
const data = await ctx.form;
return new Response(data.field);
});Middleware & State
Middleware runs before the handler and returns typed state accessible via
ctx.state.
Per-Route State
app.get("/protected", {
state: {
auth: (ctx) => {
const token = ctx.headers["authorization"];
if (token !== "Bearer valid-token") {
throw new Response("Unauthorized", { status: 401 });
}
return { userId: "user123", role: "admin" };
},
},
}, (ctx) => Response.json({ user: ctx.state.auth.userId }));Async State
app.get("/data", {
state: {
data: async () => {
const result = await fetchFromDb();
return result;
},
},
}, (ctx) => Response.json(ctx.state.data));Multiple Guards
app.post("/admin/action", {
state: {
auth: (ctx) => {
const token = ctx.headers["authorization"];
if (!token) throw new Response("Unauthorized", { status: 401 });
return { userId: "admin1", role: "admin" };
},
permission: (ctx) => {
if ((ctx.state as any).auth.role !== "admin") {
throw new Response("Forbidden", { status: 403 });
}
},
},
}, () => Response.json({ message: "Action performed" }));onFinish Callback
app.get("/with-logging", {
state: {
logger: (ctx) => {
const start = Date.now();
ctx.onFinish((resp) => {
console.log(
`${ctx.method} ${ctx.url} - ${resp?.status} - ${
Date.now() - start
}ms`,
);
});
},
},
}, () => new Response("logged"));define() — Scoped Middleware
Apply middleware to a group of routes with full type inference:
app.define(
{
userId: (ctx) => ctx.headers["x-user-id"] || "guest",
isAdmin: (ctx) => ctx.headers["x-role"] === "admin",
},
(app) => {
app.get(
"/me",
(ctx) =>
Response.json({ userId: ctx.state.userId, isAdmin: ctx.state.isAdmin }),
);
app.get("/dashboard", (ctx) => {
if (!ctx.state.isAdmin) throw new Response("Forbidden", { status: 403 });
return Response.json({ admin: true });
});
},
);apply() — Global Middleware
// Side-effect middleware (logging, metrics)
app.apply("/*", (ctx) => {
console.log(ctx.method, ctx.url);
});
// State-producing middleware
app.apply("/*", { auth: (ctx) => verifyAuth(ctx) });use() — Mount Sub-Apps
const api = new App();
api.get("/users", handler);
api.get("/posts", handler);
app.use("/api/v1", api);Cookies
Reading Cookies
app.get("/profile", (ctx) => {
return Response.json({ theme: ctx.cookies.theme });
});Setting Cookies
app.get("/login", (ctx) => {
ctx.setCookie("session", "abc123", {
path: "/",
httpOnly: true,
secure: true,
sameSite: "Strict",
maxAge: 3600,
});
return new Response("Logged in");
});Error Handling
// Custom app-level error handler
app.onError((error, ctx) => {
console.error(ctx.method, ctx.url, error);
return Response.json(
{
message: error instanceof Error ? error.message : "Internal Server Error",
},
{ status: 500 },
);
});
// Custom 404 handler
app.notFound((ctx) => {
return Response.json({ error: "Not Found", path: ctx.url }, { status: 404 });
});
// Throw a Response to short-circuit with a specific status
app.get("/secret", (ctx) => {
throw new Response("Forbidden", { status: 403 });
});Built-in Middleware
CORS
import { cors } from "@coderbuzz/ken";
const api = cors({ origin: "https://example.com", credentials: true });
api.get("/", () => Response.json({ data: true }));
app.use("/api", api);JWT
import { jwt, signJwt } from "@coderbuzz/ken";
// Sign a token
app.get("/token", async () => {
const token = await signJwt({
sub: "user123",
exp: Math.floor(Date.now() / 1000) + 3600,
}, "secret");
return Response.json({ token });
});
// Protect a route
app.get("/secure", {
state: { auth: jwt({ secret: "secret" }) },
}, (ctx) => Response.json({ payload: ctx.state.auth }));Session
import { session } from "@coderbuzz/ken";
const userSession = session({
cookieName: "_sid",
validate: (cookieValue) => {
const user = db.getUser(cookieValue);
if (!user?.active) throw new Response("Unauthorized", { status: 401 });
return user;
},
});
app.get("/dashboard", {
state: { session: userSession },
}, (ctx) => Response.json({ user: ctx.state.session }));Basic Auth
import { basicAuth } from "@coderbuzz/ken";
app.get("/admin", {
state: { auth: basicAuth({ username: "admin", password: "secret" }) },
}, (ctx) => Response.json({ user: ctx.state.auth.username }));Bearer Auth
import { bearerAuth } from "@coderbuzz/ken";
app.get("/api/resource", {
state: { auth: bearerAuth({ token: "my-token" }) },
}, (ctx) => Response.json({ token: ctx.state.auth.token }));Logger
import { logger } from "@coderbuzz/ken";
app.use(logger());Request ID
import { requestId } from "@coderbuzz/ken";
app.get("/request", {
state: { reqId: requestId() },
}, (ctx) => Response.json({ id: ctx.state.reqId }));Secure Headers
import { secureHeaders } from "@coderbuzz/ken";
app.get("/page", {
state: { sec: secureHeaders() },
}, () => new Response("secure"));Compression
import { compress } from "@coderbuzz/ken";
app.get("/data", {
state: { encoding: compress() },
}, (ctx) => Response.json({ encoding: ctx.state.encoding.encoding }));Cache
import { cache } from "@coderbuzz/ken";
app.get("/static", {
state: { caching: cache({ maxAge: 3600, public: true }) },
}, () => new Response("cached content"));Rate Limiting / Body Limit
import { bodyLimit } from "@coderbuzz/ken";
app.post("/upload", {
state: { limit: bodyLimit({ maxSize: 1_000_000 }) }, // 1 MB
}, async (ctx) => {
const body = await ctx.json;
return Response.json({ received: body });
});Timeout
import { timeout } from "@coderbuzz/ken";
app.get("/slow", {
state: { timeoutSig: timeout({ duration: 5000 }) },
}, () => new Response("fast enough"));Timing
import { timing } from "@coderbuzz/ken";
app.get("/timed", {
state: { perf: timing() },
}, () => new Response("timed"));IP Restriction
import { ipRestriction } from "@coderbuzz/ken";
app.get("/internal", {
state: { ipCheck: ipRestriction({ allowList: ["127.0.0.1", "::1"] }) },
}, () => new Response("allowed"));CSRF Protection
import { csrf } from "@coderbuzz/ken";
app.post("/form", {
state: { protection: csrf({ origin: ["https://example.com"] }) },
}, () => Response.json({ success: true }));ETag
import { etag } from "@coderbuzz/ken";
app.get("/resource", {
state: { etagValue: etag() },
}, (ctx) => {
const tag = '"v1"';
if (ctx.state.etagValue === tag) return new Response(null, { status: 304 });
return new Response("content", { headers: { ETag: tag } });
});Combining Middleware
app.get("/combined", {
state: {
reqId: requestId(),
perf: timing(),
sec: secureHeaders(),
},
}, (ctx) => Response.json({ id: ctx.state.reqId }));WebSocket
Basic Echo
app.ws("/echo", {
message(peer, message) {
peer.send(message);
},
});Lifecycle Hooks
app.ws("/chat", {
open(peer) {
peer.send("connected");
},
message(peer, message) {
peer.send(`echo: ${message}`);
},
close(peer, code, reason) {
console.log("disconnected", code, reason);
},
});Typed Upgrade Data
app.ws<{ userId: string }>("/auth", {
upgrade(req) {
const url = new URL(req.url);
const userId = url.searchParams.get("userId");
if (!userId) return new Response("Unauthorized", { status: 401 });
return { userId };
},
open(peer) {
peer.send(`Hello ${peer.data.userId}`);
},
message(peer, message) {
peer.send(`${peer.data.userId}: ${message}`);
},
});Native Pub/Sub
app.ws("/chat", {
open(peer) {
peer.subscribe("chat");
peer.publish("chat", "someone joined");
},
message(peer, message) {
peer.publish("chat", message);
peer.send(`you: ${message}`);
},
close(peer) {
peer.publish("chat", "someone left");
},
});WsTopicHub (App-Level Pub/Sub)
import { WsTopicHub } from "@coderbuzz/ken";
const hub = new WsTopicHub();
app.ws("/notifications", {
open(peer) {
hub.subscribe(peer, "alerts");
},
close(peer) {
hub.unsubscribeAll(peer);
},
message(peer, _msg) {
hub.markAlive(peer);
},
});
// Publish from anywhere (e.g., another route)
app.post("/broadcast", async (ctx) => {
const { message } = await ctx.json;
hub.publish("alerts", message);
return Response.json({ sent: true });
});Ping/Pong (Heartbeat)
app.ws("/live", {
pong(peer) {
console.log(`${peer.remoteAddress} is alive`);
},
message(peer, msg) {
peer.send(msg);
},
}, { pingInterval: 30, pongTimeout: 10 });Streaming Response
app.get("/stream", () => {
const stream = new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode("chunk 1"));
controller.enqueue(new TextEncoder().encode("chunk 2"));
controller.close();
},
});
return new Response(stream);
});File Utilities
import {
listDirectory,
receiveFiles,
saveFile,
sendFile,
} from "@coderbuzz/ken";
// Serve a file
app.get("/download", (ctx) => sendFile(ctx, "./assets/file.pdf"));
// List directory
app.get("/files", (ctx) => listDirectory(ctx, "./uploads"));
// Receive uploaded files
app.post("/upload", async (ctx) => {
const files = await receiveFiles(ctx);
for (const file of files) {
await saveFile(file, "./uploads");
}
return Response.json({ count: files.length });
});Utilities
import {
compressString,
decompressString,
decryptString,
encryptString,
generateSecretKey,
getPathname,
memoize,
} from "@coderbuzz/ken";
// Encryption
const key = await generateSecretKey();
const encrypted = await encryptString("hello", key);
const decrypted = await decryptString(encrypted, key);
// Compression
const compressed = await compressString("large text...");
const original = await decompressString(compressed);
// Memoization
const cached = memoize(expensiveFn, { ttl: 60_000 });Runtime Detection
import { isBun, isDeno, isNode } from "@coderbuzz/ken";
if (isBun) console.log("Running on Bun");
if (isDeno) console.log("Running on Deno");
if (isNode) console.log("Running on Node.js");Remote Info
app.get("/ip", (ctx) => {
const { address, port } = ctx.remoteInfo;
return Response.json({ address, port });
});License
MIT © 2026 Indra Gunawan
