Named schemas
Register schemas under a name, reference them anywhere, dedup in OpenAPI export.
Register a schema under a name with defineSchema and reference it from
JSDoc with {TypeName} or {TypeName[]}:
const { defineSchema, s } = require('doctreen');
defineSchema('User', s.object({
id: s.number(),
name: s.string(),
email: s.string(),
active: s.boolean(),
bio: s.optional(s.string()),
}));
app.get('/users', function (req, res) {
/**
* @description List all users
* @returns {User[]}
*/
res.json([]);
});
app.get('/users/:id', function (req, res) {
/**
* @description Get a user by ID
* @returns {User}
*/
res.json({ id: 1, name: 'Alice', email: 'alice@example.com', active: true });
});defineSchema is also re-exported from all adapter packages.
Zod-defined named schemas v1.15
defineSchema works with Zod schemas, not just the s.* builder. Both are
first-class:
const { defineSchema } = require('doctreen/express');
const { z } = require('zod');
const User = defineSchema('User', z.object({
id: z.number(),
name: z.string(),
}));
// reuse `User` in any route's request/response → one components.schemas.User,
// referenced by $ref everywhere it appearsPreviously named schemas were matched by object identity, which the
Zod → SchemaNode conversion breaks — so a Zod-defined defineSchema('User', …)
used in a route fell through to anonymous Schema1 / Schema2 types. Now
Zod-defined named schemas emit $ref: '#/components/schemas/User' in the
OpenAPI export at the top level, nested inside other objects, and inside
arrays.
This makes Zod-defined named schemas the recommended way to express
recursive schemas: a self-reference emits a terminating $ref instead of
expanding forever.
With defineRoute (Zod or s)
const { s, defineSchema } = require('doctreen');
const { defineRoute } = require('doctreen/express');
const User = defineSchema('User', s.object({
id: s.number(),
name: s.string(),
email: s.string(),
}));
app.post('/users', defineRoute(handler, { request: { body: User }, response: User }));
app.get('/users/:id', defineRoute(handler, { response: User }));Every route that references the same object will share a single
$ref: '#/components/schemas/User' entry in the exported OpenAPI spec.
$ref dedup v1.11
Anonymous object schemas with three or more properties that appear two or
more times in the spec are also auto-promoted under stable Schema1,
Schema2, … names — you get the dedup benefit without naming every shape.