@nwire/http — alone
Typed routes + OpenAPI 3.1 for any DI container — or none. Built on Koa under the hood, but the public surface is framework-agnostic.
What it does
httpInterface()returns a builder with.get/.post/.put/.delete/.patch.- Each route declares an optional
inputschema (zod4) for the body / query / params. - A live OpenAPI 3.1 document is generated from the routes at
/openapi.json. - The Scalar docs UI is served at
/docsfrom the CDN. - Returns a Koa app —
.toKoa()— or mounts onto an existing one.
Install
bash
pnpm add @nwire/http zodMinimal example
ts
import { httpInterface } from "@nwire/http"
import { z } from "zod"
const api = httpInterface()
api.get("/health", () => ({ ok: true }))
api.post(
"/users",
{ input: z.object({ email: z.string().email(), name: z.string() }) },
({ input }) => ({ id: "u_1", ...input }),
)
const koa = api.toKoa()
koa.listen(3000)With your own DI container
ts
import { httpInterface } from "@nwire/http"
import { Container, token } from "@nwire/container"
const Db = token<{ query: (sql: string) => Promise<unknown[]> }>("Db")
const container = new Container()
container.provideValue(Db, { query: async () => [] })
const api = httpInterface({ container })
api.get("/users", ({ resolve }) => resolve(Db).query("select * from users"))With Express
httpInterface() returns a Koa app, but the @nwire/http-express interop package gives you toExpress(api) (mounts the Nwire surface inside Express) and fromExpress(middleware) (mounts Express middleware inside an httpInterface()).
ts
import express from "express"
import { httpInterface } from "@nwire/http"
import { toExpress } from "@nwire/http-express"
const api = httpInterface()
api.get("/typed", () => ({ message: "from nwire" }))
const expressApp = express()
expressApp.use("/api", toExpress(api))
expressApp.listen(3000)OpenAPI output
Every action's input schema becomes a requestBody (or parameters for GET). The Studio-aware fields (persona, journeyStep, slo) become description and x-nwire-* extensions.
Dependencies
koa+@koa/router+koa-bodyparser(HTTP runtime)@asteasolutions/zod-to-openapi(zod → OpenAPI 3.1)zod4
No transitive Nwire dependencies beyond the optional @nwire/container.