Adapters
Serving
import { serve } from 's200/node';
const server = await serve(app, { port: 0 }); // 0 = ephemeral
// server: { server, url, port, close(): Promise<void> }
import { serve } from 's200/bun';
const server = serve(app, { port: 3000 });Both adapters expose the identical serve(app, options) surface; the core's handle(app, request) is the entire integration contract for any runtime with a fetch-shaped handler — s200/cloudflare (createHandler(app) as the module worker's default export) is the one-line adapter for that runtime.
Light mode
s200/node has an opt-in light mode — serve(app, { light: true }) swaps the platform's per-request Request/Response constructors for light-weight duck-typed ones (nothing global is patched, the Web Standard contract stays the default). On the light path ctx.req.headers/ctx.res.headers are LightHeaders — a duck Headers with the full structural API (get/set/has/append/delete/getSetCookie/iteration), case-insensitive, insertion-ordered, and a legal HeadersInit everywhere (platform constructors fill from its pair iterator); instanceof Headers is simply false there. Mutation is validated like undici: set/append throw a TypeError at call time for a CR/LF in a value (response splitting) or a non-token name, instead of failing later inside node's writeHead. See ../benchmarks.md: light mode buys ~28–35% whole-request throughput (machine-dependent) and lands between the real-Web-Standard class and the patched one. The batteries ride the light path too — compress/etag work off the light response's synchronous bytes (streamed bodies pipe through CompressionStream unchanged), stream/streamSSE ride the light response's stream body, serveStatic serves byte bodies, streamed files, and byte ranges, and the request body readers (readJson/readText/readForm/readStream) read the light request's stream — client disconnects abort ctx.signal here exactly like on the default path.
TLS
s200/node also serves TLS — HTTPS, or HTTP/2 over TLS — through the same dispatch pipeline. HTTPS combines with upgrade for WSS (the WebSocket handler runs on the decrypted connection); only http2: true forbids upgrade, since HTTP/2 has no upgrade event:
await serve(app, {
port: 443,
https: { key: await readFile('key.pem'), cert: await readFile('cert.pem') }, // node:https
});
await serve(app, {
port: 443,
https: { key, cert, http2: true }, // node:http2
});
await serve(app, {
port: 443,
https: { key, cert }, // WSS
upgrade: createUpgradeHandler(app),
});Once your adapter serves, the deployment guide covers the production wiring — health probes, graceful drain, Docker/systemd, and edge deploys.