@routegraph/koa
v1.0.1
Published
Koa v2 adapter for RouteGraph.
Readme
@routegraph/koa
Koa adapter for RouteGraph — built on @koa/router.
Installation
pnpm add @routegraph/koa @routegraph/core koa @koa/router koa-body zodkoa (>=2.0.0) and @koa/router (>=12.0.0) are peer dependencies. koa-body is not a dependency of this package at all — it's your choice of body parser; see why below.
createKoaRouter(graph)
function createKoaRouter(graph: RouteGraph): Router // @koa/router's RouterUsage
import Koa from 'koa'
import { koaBody } from 'koa-body'
import { RouteGraph } from '@routegraph/core'
import { createKoaRouter } from '@routegraph/koa'
const graph = new RouteGraph({ routesDir: './routes' })
await graph.load()
const app = new Koa()
app.use(koaBody()) // must come before the router — see below
const router = createKoaRouter(graph)
router.prefix('/api')
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)Why koa-body must be applied before RouteGraph
Koa itself ships with no body parsing built in — ctx.request.body simply doesn't exist until something populates it. The adapter reads it structurally (getRequestBody() narrows unknown rather than importing koa-body's types, since this package doesn't depend on any specific body parser — see DECISIONS.md), so whichever body parser you choose (koa-body is what this monorepo's own example uses) must run before createKoaRouter(graph)'s router in the middleware chain, or every route with a body schema will see undefined and fail validation.
Usage with router.routes() + router.allowedMethods()
Both are required, in that order, for @koa/router to behave correctly — router.routes() dispatches matched requests, router.allowedMethods() handles 405/501 responses for methods RouteGraph didn't register at a matched path. This is standard @koa/router usage, not something RouteGraph changes.
Accessing the raw Koa context
const handler: RouteHandler<typeof config> = async (req, res) => {
const ctx = req.raw as import('koa').Context
console.log(ctx.ip)
}Validation error format
{ "error": "Validation failed", "issues": [{ "field": "params.id", "message": "Invalid uuid", "code": "invalid_string" }] }Hot reload
Routes are looked up fresh per request (graph.getRoute(method, urlPath)), so @routegraph/watcher's graph.reload() is reflected immediately without re-registering anything with @koa/router.
