L1 — Minimal HTTP
The smallest useful Nwire program: typed routes, OpenAPI, graceful shutdown. No DI, no plugins, no domain primitives.
What you need
@nwire/http— typed routes, OpenAPI, the Koa adapter@nwire/endpoint— boot + graceful shutdownzod— schemas
The shape
ts
import { httpInterface, endpoint } from "@nwire/http"
import { z } from "zod"
const api = httpInterface()
api.get("/health", () => ({ ok: true }))
api.post(
"/echo",
{ input: z.object({ message: z.string() }) },
({ input }) => input,
)
await endpoint("hello", { port: 3000 }).serve(api).run()That's it. The runtime gives you:
| Concern | How |
|---|---|
| 400 on bad input | input schema validated automatically; structured error response |
| OpenAPI | GET /openapi.json reflects the live config |
| Docs UI | GET /docs (Scalar from CDN) |
| Health probes | endpoint(...).health({ liveness, readiness }) |
| Shutdown | SIGTERM → drain → exit; bounded by hardTimeout |
When to stay at L1
- You're prototyping a single endpoint.
- You're writing a thin proxy.
- You're integrating into an existing Express / Koa / Fastify app — in that case, use the standalone packages instead.
When to climb to L2
The moment you have a second route that needs the same dependency (a DB handle, a logger, an HTTP client) and you don't want to thread it through every handler argument, pull in @nwire/container.