npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@chaeco/auto-api-docs

v0.0.3

Published

Automatic API documentation generator for Node.js frameworks. OpenAPI 3.0 (JSON/YAML), self-contained HTML, Postman Collection 2.1, and Markdown from @chaeco/auto-router's route registry.

Readme

@chaeco/auto-api-docs

npm version License: MIT Node.js Version

Automatic API documentation generator for Node.js frameworks. Reads @chaeco/auto-router's route registry and produces OpenAPI 3.0 (JSON/YAML), a self-contained static HTML doc site, a Postman Collection 2.1, and Markdown — from the same route metadata you already write.

Features

  • 🚀 Zero-config — point it at your app, get four documentation formats
  • 📄 OpenAPI 3.0 (JSON + YAML) — drop into Swagger UI, Stoplight, or any codegen tool
  • 🌐 Self-contained HTML doc site — single file, no CDN, dark/light theme, search
  • 📮 Postman Collection 2.1 — ready to import, with {{baseUrl}} / {{token}} variables
  • 📝 Markdown — tag-grouped, version-control friendly
  • 🧬 Rich schema metadata — requestBody, queryParams, pathParams, responses via createHandler meta
  • ✅ zod support — declare schemas with zod, converted to JSON Schema automatically
  • 🔒 Auth-aware — bearerAuth security scheme generated from requiresAuth
  • 🧩 Structural decoupling — no runtime dependency on @chaeco/auto-router

Installation

npm install @chaeco/auto-api-docs

Using zod schemas in route meta? Install the converter (this package never imports zod):

npm install zod zod-to-json-schema

AI Tool Skills

This package includes AI agent skills for Claude Code and OpenAI Codex. After installation, run this once:

npx @chaeco/auto-api-docs init-skills

This copies skill files into your project's .claude/skills/auto-api-docs/ and .codex/skills/auto-api-docs/. AI tools will then enforce schema-declaration conventions and best practices when writing routes.


Table of Contents


Quick Start

import { autoRouter } from '@chaeco/auto-router'
import { autoApiDocs } from '@chaeco/auto-api-docs'

const app = new YourFramework()

app.extend(autoRouter({ dir: './controllers', prefix: '/api' }))
app.extend(autoApiDocs({ outDir: './docs', baseUrl: 'http://localhost:3000' }))

After app.listen() (or immediately if your framework resolves plugins synchronously), ./docs/ contains:

docs/
├── openapi.json             # OpenAPI 3.0 spec (JSON)
├── openapi.yaml             # OpenAPI 3.0 spec (YAML)
├── index.html               # Self-contained HTML doc site
├── postman-collection.json  # Postman Collection 2.1
└── api.md                   # Markdown documentation

Open docs/index.html in a browser — it has search, tag filters, and a dark/light theme toggle with no server needed.

Pure function (no app)

import { generateApiDocs } from '@chaeco/auto-api-docs'

// From an app-like object, or a bare RouteInfo[]:
const docs = await generateApiDocs(app, { formats: { openapi: true } })
// docs.openapiSpec — raw spec for serving in-app
// docs.openapi.json / docs.openapi.yaml — serialized strings

Declaring Route Schemas

Schemas are declared where your routes are defined — in the meta argument of createHandler from @chaeco/auto-router:

import { z } from 'zod'
import { createHandler } from '@chaeco/auto-router'

const LoginSchema = z.object({
  username: z.string().min(1),
  password: z.string().min(1),
})

export default createHandler(
  async (ctx) => {
    const result = LoginSchema.safeParse(ctx.req?.body ?? {})
    if (!result.success) { ctx.res.status = 400; return }
    ctx.res.body = { token: 'jwt' }
  },
  {
    summary: 'User login',
    description: 'Authenticates a user and returns a JWT token.',
    tags: ['Auth'],
    requestBody: { schema: LoginSchema, description: 'Credentials' },
    responses: {
      '200': { description: 'Login succeeded', schema: z.object({ token: z.string() }) },
      '400': { description: 'Validation failed' },
      '401': { description: 'Invalid credentials' },
    },
  },
)

Meta fields

| Field | Type | Description | |-------|------|-------------| | summary | string | Short operation title (falls back to description, then "METHOD path") | | description | string | Longer operation description | | tags | string[] | Logical grouping for docs (Auth, Users, Posts, …) | | operationId | string | Explicit OpenAPI operationId | | deprecated | boolean | Marks the operation deprecated | | requestBody | Schema \| zod \| RequestBodySpec | Request body schema | | queryParams | Record<string, ParamSpec> \| Schema \| zod | Query parameters | | pathParams | Record<string, ParamSpec> | Path parameter metadata | | responses | Record<string, ResponseSpec> | Response schemas keyed by status ('200', '404', 'default') |

ParamSpec: { description?, required?, type?, enum?, default?, example?, schema? }type accepts 'string' | 'number' | 'integer' | 'boolean'.

RequestBodySpec: { schema, required?, description?, contentType? }.

ResponseSpec: { description?, schema?, content? }content is a media-type → schema map.

JSON Schema vs zod

Both work anywhere a schema is accepted:

// Plain JSON Schema
requestBody: { schema: { type: 'object', required: ['name'], properties: { name: { type: 'string' } } } }

// zod — converted automatically
requestBody: { schema: z.object({ name: z.string() }) }

zod schemas are detected by duck-typing and converted with zod-to-json-schema resolved from your node_modules (so it runs against your zod instance). No zod import in this package. If the converter is missing you get a descriptive error, or you can inject your own (see Customizing zod conversion).

Type augmentation: importing @chaeco/auto-api-docs augments @chaeco/auto-router's RouteMeta so the fields above are typed when you write createHandler(fn, meta).


Output Formats

OpenAPI 3.0

  • openapi: '3.0.3', servers[0].url from baseUrl.
  • Multiple methods grouped under one path item.
  • components.securitySchemes.bearerAuth added only when at least one route has requiresAuth; protected operations get security: [{ bearerAuth: [] }], public ones security: [].
  • operationId derived (GET /api/users/:userIdgetApiUsersUserId) or taken from meta, de-duplicated.
  • Path params (:param{param}) always required, default { type: 'string' }; enriched by pathParams.
  • requestBody, responses, tags, deprecated mapped from meta; unknown meta keys pass through to the operation object.

Static HTML

  • Single self-contained file — inline CSS/JS, system font stack, no CDN, no webfonts, no external requests.
  • Dark/light theme toggle (persisted), default follows prefers-color-scheme.
  • Search filters by method/path/summary/description/tags; tag chips filter sections.
  • Endpoints as expandable rows: parameters table, request-body JSON, responses table.
  • Method-colored badges, tabular-nums stats, dividers between tag sections.

Postman Collection 2.1

  • Variables: {{baseUrl}} (from baseUrl) and {{token}}.
  • Folder per tag (default) or per first path segment (groupBy: 'path'); untagged routes go to a Default folder.
  • Protected requests get bearer auth ({{token}}); path params become URL variables; optional query params are disabled.
  • Requests with a requestBody include a raw JSON body derived from the schema.

Markdown

  • # title, description, stats, base URL, table of contents.
  • ## tag### path#### \METHOD /path``; parameter/query tables, request-body JSON block, responses table.
  • Untagged routes → ## Default.

Configuration

Plugin options

app.extend(autoApiDocs({
  outDir: './docs',                     // output directory
  title: 'My API',                      // document title
  version: '1.0.0',                     // document version
  description: 'My public API',         // document description
  baseUrl: 'https://api.example.com',   // OpenAPI servers + Postman {{baseUrl}}
  includeTags: ['Auth', 'Users'],       // only these tags
  excludeTags: ['Internal'],            // drop these tags
  includePaths: ['/api/users', 'GET /api/auth/*'],
  excludePaths: ['/api/admin/*'],
  groupBy: 'tag',                       // 'tag' | 'path'
  logging: true,
  onLog: (level, msg) => myLogger[level](msg),
}))

Output overrides

app.extend(autoApiDocs({
  outDir: './docs',
  outputs: {
    openapi: { json: 'spec.json', yaml: false },  // custom path, skip YAML
    html: 'api.html',                              // custom HTML path
    postman: false,                                // skip Postman
    // markdown omitted → writes api.md
  },
}))

Filtering

  • includeTags / excludeTags — keep/drop routes whose tags intersect the list.
  • includePaths / excludePaths — same pattern semantics as auto-router's forcePublic/forceProtected:
    • Path only (all methods): '/api/users', '/api/admin/*'
    • Method + path: 'GET /api/users'
    • Wildcard /* matches sub-paths, not the base itself

Customizing zod conversion

For bundler-constrained environments or zod-4 users, pass your own converter:

import { zodToJsonSchema } from 'zod-to-json-schema'

app.extend(autoApiDocs({
  zodToJsonSchema: (schema) => zodToJsonSchema(schema),
}))

Integration with auto-router

autoApiDocs reads app.$routes.all — the same registry autoRouter() / staticAutoRouter() populate. The input type is structurally compatible with auto-router's RouteInfo, so no casts or glue code are needed. There is no runtime dependency on @chaeco/auto-router; if you don't use auto-router, pass your own RouteInfo[] to generateApiDocs().


API Reference

autoApiDocs(options)

Returns a plugin (app) => Promise<void> for app.extend(). Reads app.$routes.all, generates all four formats, writes them to outDir. Throws if app.$routes.all is missing (run autoRouter() first).

generateApiDocs(input, options)

Pure generator. input is an app-like { $routes: { all: [...] } } or a bare RouteInfo[]. options.formats is an allowlist ({ openapi: true } → only OpenAPI). Throws auto-api-docs: no routes found when empty. Returns { openapi?, html?, postman?, markdown?, openapiSpec?, postmanCollection?, warnings }.

Exported types

ApiDocsOptions, GenerateApiDocsOptions, AutoApiDocsOptions, ApiDocsOutputOptions, GeneratedDocs, GeneratedArtifacts, ApiRouteMeta, ApiRouteInfo, RouteRegistryLike, AppLike, ApiDocsSource, Schema, ZodSchemaLike, ParamSpec, ResponseSpec, RequestBodySpec, ApiDoc, ApiOperation, ApiParam, ApiResponse, ApiRequestBody, GroupBy, RouteMeta.


Example Project

See example/ for a runnable demo: a mock app registering routes with auto-router, rich meta including zod schemas, and autoApiDocs() writing all four formats to ./docs.


License

MIT