DocTreen

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.

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.

On this page