RouteGraph v1.0.0 is out. It's stable, it's typed, it's not going to rewrite your framework of choice into a decorator soup. → Try it in 90 seconds
DocsOpenAPI Export

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.json

Runs 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

ZodJSON 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.