Zod integration
First-class Zod support on every adapter.
Zod is a first-class input format on every adapter. Pass any Zod schema
where DocTreen expects a schema — defineRoute, @DocRoute, individual
@Doc* decorators — and it is converted to DocTreen's internal SchemaNode
representation at definition time. No zodToSchemaNode() wrapper required.
const { defineRoute } = require('doctreen/express');
const { z } = require('zod');
const CreateUser = z.object({ name: z.string(), email: z.string().email() });
app.post('/users', defineRoute(
(req, res) => res.status(201).json({ id: 1, ...req.body }),
{
description: 'Create a user',
request: { body: CreateUser },
response: CreateUser.extend({ id: z.number() }),
errors: { 409: 'Email already in use' },
}
));The same shape works in doctreen/fastify, doctreen/hono, doctreen/koa,
and via @DocRoute({ ... }) in doctreen/nest.
zodToSchemaNode (standalone)
If you ever need the converter directly (e.g. to build a shared schema bag outside of an adapter), it remains available as a standalone export:
import { z } from 'zod';
import { zodToSchemaNode } from 'doctreen/zod';
const schema = z.object({
id: z.number(),
name: z.string(),
email: z.string().email(),
role: z.enum(['admin', 'user']).optional(),
tags: z.array(z.string()),
});
const node = zodToSchemaNode(schema);
// {
// type: 'object',
// properties: {
// id: { type: 'number' },
// name: { type: 'string' },
// email: { type: 'string' },
// role: { type: 'string', optional: true },
// tags: { type: 'array', items: { type: 'string' } },
// }
// }Supported Zod types
| Zod type | SchemaNode output |
|---|---|
z.string(), z.date() | { type: 'string' } |
z.number(), z.bigint() | { type: 'number' } |
z.boolean() | { type: 'boolean' } |
z.null(), z.undefined(), z.void() | { type: 'null' } |
z.any(), z.unknown() | { type: 'unknown' } |
z.object({...}) | { type: 'object', properties: {...} } |
z.array(T) | { type: 'array', items: T } |
z.tuple([T, ...]) | { type: 'array', items: T[0] } |
z.record(V) | { type: 'object', properties: {} } |
z.optional(T) | { ...T, optional: true } |
z.nullable(T) | { ...T, optional: true } |
z.default(T) | unwraps to T |
z.enum([...]) | { type: 'string' } |
z.nativeEnum(E) | { type: 'string' } or { type: 'number' } |
z.literal(v) | { type: typeof v } |
z.union([A, B]) | first option |
z.discriminatedUnion(...) | first option |
z.intersection(A, B) | merged object properties |
z.lazy(...) | resolved recursively |
.transform(), .pipe() | unwraps to input schema |
Zod schemas double as runtime validators via the same declaration — see Runtime validation.