@jongleberry/api-server
v1.1.0
Published
A Node.js HTTP server library
Downloads
16,407
Maintainers
Readme
@jongleberry/api-server
A lightweight Node.js HTTP server library built on a trie router with automatic compression, ETag caching, streaming, and a dev-friendly request logger.
Install
npm install @jongleberry/api-serverRequires Node.js ≥ 24.
Quick start
import http from "node:http";
import { Application } from "@jongleberry/api-server";
const app = new Application();
app.route("/hello").get((ctx) => {
ctx.json({ hello: "world" });
});
app.route("/users/:id").get((ctx) => {
ctx.json({ id: ctx.params.id });
});
http.createServer(app.callback()).listen(3000);Or use the factory shorthand:
import { createApp } from "@jongleberry/api-server";
const app = createApp();
app.route("/").get((ctx) => ctx.json({ ok: true }));Features
- Trie router —
find-my-wayunder the hood; zero regex overhead on the hot path - Buffered responses —
ctx.json(),ctx.response.text(),.html(),.xml(),.buffer() - Streaming —
ctx.pipeline(readable, ...transforms)with back-pressure and error propagation - Automatic ETag — SHA-256 ETag on every buffered 2xx;
If-None-Match→ 304 - Compression —
br/gzip/deflatenegotiation; 1 KB threshold;SYNC_FLUSHfor streams - Server-Timing — response latency as a
Server-Timingheader (buffered) or trailer (streaming) - Abort signals —
ctx.signal/ctx.abortControllerwired to client disconnect - Request body limits —
ctx.request.buffer()and.json()use a safe 1 MB default, with per-call overrides - AsyncLocalStorage — per-request store via
app.setAsyncLocalStorage(als) - Cookies —
ctx.cookies.get()/.set()with fullSet-Cookieoptions - Cache-Control —
ctx.cacheControl(visibility, maxAge)helper - Trusted client IP — proxy headers are opt-in via
trustProxy; standalone helpers support Node, Deno, and Bun - Dev logger — concurrent-request bar, color-coded status codes, timing thresholds; silent in
NODE_ENV=productionandNODE_ENV=test - Error safety net — error handlers that throw or return without a response still guarantee the client receives a response
Requirements
- Node.js ≥ 24.0.0
- ESM (
"type": "module"or.mjsimports)
Documentation
See docs/ for full API reference:
| Topic | Description |
| -------------------------------------------------- | --------------------------------------------------- |
| Getting started | Install, hello world, mounting on http.createServer |
| Routing | Route registration, params, notFoundHandler |
| Context | Full ctx API surface |
| Request | Body parsing, size limits, content-type detection |
| Response | Buffered and streaming responses |
| ETag and caching | Automatic ETags, 304s, Cache-Control |
| Compression | br/gzip/deflate negotiation |
| Server-Timing | Response latency headers and trailers |
| Cookies | Reading and writing cookies |
| Error handling | errorHandler, notFoundHandler, http-errors |
| Async local storage | Per-request store |
| Abort signals | Client-disconnect propagation |
| Logger | Dev logger configuration |
| Trusted client IP | Node, Deno, and Bun client IP helpers |
| Extending context | Adding methods to ctx |
| Testing | Testing patterns with vitest and supertest |
Design
- No middleware stack. Routes are registered directly on the application; request processing runs top-to-bottom in a single async function per request.
- No magic.
ctx.reqandctx.resare the raw Node.jsIncomingMessageandServerResponseobjects. - Body is pull-based.
ctx.request.buffer()andctx.request.json()are explicit calls; the body is never automatically parsed and defaults to a 1 MB limit. - Responses are explicit. You choose buffered or streaming; the library doesn't buffer a stream or stream a buffer behind your back.
License
MIT © Jonathan Ong 2026
