OpenAPI Export
Same Zod schemas you already wrote for validation and docs — one more output, no second definition to maintain.
toOpenAPISpec()
import { toOpenAPISpec } from '@routegraph/core'
const spec = toOpenAPISpec(graph, {
title: 'My API',
version: '1.0.0',
})Produces a full OpenAPI 3.1.0 document: paths, operations, request/response
schemas, tags — all derived from each route’s config.
Via the CLI
routegraph export-docs --format openapi --out ./openapi.jsonRuns as part of routegraph build too, so a CI pipeline can publish the
spec on every merge without a manual step.
How Zod maps to JSON Schema
| Zod | JSON Schema |
|---|---|
z.string() | { "type": "string" } |
z.string().email() | { "type": "string", "format": "email" } |
z.number().int() | { "type": "integer" } |
z.object({...}) | { "type": "object", "properties": {...}, "required": [...] } |
z.enum([...]) | { "type": "string", "enum": [...] } |
z.array(T) | { "type": "array", "items": <T> } |
.optional() | field omitted from required |
Importing it elsewhere
Postman: Import → File → select openapi.json → generates a full
collection with example requests per schema.
Insomnia: Import/Export → Import Data → From File → same spec, same result.
Swagger UI: point it at the exported file, or serve it directly:
import swaggerUi from 'swagger-ui-express'
app.use('/swagger', swaggerUi.serve, swaggerUi.setup(spec))Limitations
Not everything makes it into the spec today: custom onError response
shapes aren’t reflected, and route-level middleware isn’t represented
(OpenAPI has no first-class concept for it). Treat the export as a
faithful spec of your validated request/response contract, not a
complete description of runtime behavior.