koa-okapi-router
v0.1.4
Published
Koa Router-wrapper adding type-safety, schema validation and openapi generation.
Readme
koa-okapi-router
Zod-aware router abstraction for Koa, providing a declarative Fastify-style schema declaration and type-safe middleware input/output
Features
- Declare routes with Zod schemas
- Type-safe
ctx: ParameterizedContextin route handling middleware - Support for zod v3 and v4
- Generate openapi.json
- Can co-exist with vanilla KoaRouter and e.g, swagger-jsdoc in the same application
Usage
Creating an OkapiRouter
Create a router without asking any questions or taking down any names.
const router = makeOkapiRouter(new KoaRouter(), {
openapi: {
info: { title: `ONECore ${config.applicationName}` },
},
})Create a router with openapi metadata
const router = makeOkapiRouter(new KoaRouter(), {
openapi: {
info: {
title: `Exotic Animal Spotting API`
version: '1.2.3'
},
},
})Create a router by bringing your own zod instance. Useful when you rely on importing zod/v3 or zod/v4 and cannot
use the default zod import.
const router = makeOkapiRouter(new KoaRouter(), {
schema: {
zod: z
},
})Declaring routes with schemas
router.get(
'/contacts/by-phone-number/:phoneNumber',
{
summary: 'Get a single contact by phone number',
description: 'A somewhat more long-winded description',
tags: ['Contacts'],
params: {
phoneNumber: {
description: 'Phone number to search for',
schema: z.string(),
},
response: {
200: z.object({
content: ContactSchema,
meta: z.object({}),
}),
404: z.null(),
},
},
async (ctx) => {
// ...
}
)
app.use(router.routes())Registering schemas as components/entities
router.addEntity('Contact', ContactSchema)
router.get(
'/contacts/by-phone-number/:phoneNumber',
{
...
response: {
200: {
// Providing a canonical name for the response body registers it as a component entity
name: 'ContactResponse',
schema: z.object({
content: ContactSchema,
meta: z.object({})
})
}
...
}
...
)Serving Swagger with koa2-swagger-ui
app.use(
new KoaRouter()
.get(okapiRouter.openapiJsonUrl, async (ctx) => {
ctx.body = api.openapiJson()
})
.routes()
)
app.use(
koaSwagger({
routePrefix: '/swagger',
swaggerOptions: { url: api.openapiJsonUrl },
})
)Extending an existing OpenAPI json schema with Okapi routes and components
Adopting koa-okapi-router doesn't have to be all in, in terms of producing a single openapi.json either.
Existing projects looking to migrate can do so gradually by generating the json schema with
the current tools as long as you have access to the schema model object.
okapiRouter.extendOpenApiJson takes your existing schema as input, and generates the routes
and components from an okapiRouter into that schema.
// OpenAPI schema generated by swaggerJsDoc (or by other means)
const swaggerJsDocSchema = swaggerJsdoc(swaggerSpec) as any
// Combined schema to serve and in place of `swaggerJsDocSchema`
const openApiJson = okapiRouter.extendOpenApiJson(swaggerJsDocSchema)
Version History
See CHANGELOG.md for version history and unreleased changes.
License
© 2025 Sven Johansson. ISC Licensed
