hono-auto-docs
v0.1.2
Published
Auto-generate OpenAPI 3.0 spec from Hono routes with JSDoc - zero config, maximum automation
Maintainers
Readme
@bacaxnot/hono-auto-docs
Auto-generate OpenAPI 3.0 spec from Hono routes with JSDoc - zero config, maximum automation
Features
- Zero Configuration: Point to your main app file and auto-discover all routes
- JSDoc-Based: All metadata lives in your code via JSDoc comments
- Convention Over Configuration: Automatic prefix and name generation from filenames
- Two Modes:
- Fully Automatic (
appPath): Discover routes from main app.route()calls - Semi-Automatic (
apis): List route files with JSDoc overrides for complex setups
- Fully Automatic (
- CLI (
hono-auto-docs generate):- Extract route
AppTypedefinitions via ts-morph - Generate merged
openapi.jsonspec
- Extract route
- Full TypeScript support (TS & JS config files, inference via
defineConfig)
Philosophy
Metadata lives in code, not in config files.
This package enforces a JSDoc-based approach where all route metadata (@prefix, @name, @summary, @description, @tags) is defined directly in your route files. No verbose object configuration needed.
Table of Contents
- Install
- Quick Start
- JSDoc Annotations
- Configuration Reference
- Serving the OpenAPI Docs
- CLI Usage
- Programmatic Usage
- Limitations
- Development
- Contributing
- License
Install
# using bun
bun add -d @bacaxnot/hono-auto-docs
# using npm
npm install --save-dev @bacaxnot/hono-auto-docs
# using yarn
yarn add -D @bacaxnot/hono-auto-docsQuick Start
Mode 1: Fully Automatic (Recommended)
For simple single-file route mounting patterns, just point to your main app file:
Create a config file (
hono-docs.ts):import { defineConfig } from "@bacaxnot/hono-auto-docs"; export default defineConfig({ tsConfigPath: "./tsconfig.json", openApi: { openapi: "3.0.0", info: { title: "My API", version: "1.0.0" }, servers: [{ url: "http://localhost:8000" }], }, outputs: { openApiJson: "./openapi.json", }, // ✅ Single entry point - auto-discovers all routes appPath: "src/index.ts", });Your main app (
src/index.ts):import { Hono } from "hono"; import { accountsApp } from "./routes/accounts"; import { transactionsApp } from "./routes/transactions"; export const app = new Hono() .route("/accounts", accountsApp) // Auto-discovered: /accounts .route("/transactions", transactionsApp); // Auto-discovered: /transactionsYour route files (
src/routes/accounts.ts):import { Hono } from "hono"; /** * @name Accounts */ export const accountsApp = new Hono() .get("/", (c) => { /* ... */ }) .post("/", (c) => { /* ... */ }); export type AppType = typeof accountsApp;Run the CLI:
bunx hono-auto-docs generate --config ./hono-docs.ts
That's it! 🎉
Mode 2: Semi-Automatic (Complex Setups)
For complex mounting patterns (nested routes, conditional mounting, etc.), list route files explicitly:
import { defineConfig } from "@bacaxnot/hono-auto-docs";
export default defineConfig({
tsConfigPath: "./tsconfig.json",
openApi: {
openapi: "3.0.0",
info: { title: "My API", version: "1.0.0" },
servers: [{ url: "http://localhost:8000" }],
},
outputs: {
openApiJson: "./openapi.json",
},
// ✅ List route files - uses JSDoc @prefix or filename convention
apis: [
"src/routes/accounts.ts",
"src/routes/transactions.ts",
"src/routes/categories.ts",
],
});Route file with JSDoc overrides (src/routes/accounts.ts):
import { Hono } from "hono";
/**
* @prefix /accounts
* @name Accounts
*/
export const accountsApp = new Hono()
.get("/", (c) => {
/* ... */
})
.post("/", (c) => {
/* ... */
});
export type AppType = typeof accountsApp;Without @prefix, the prefix is auto-generated from the filename (accounts.ts → /accounts).
JSDoc Annotations
Route-Level JSDoc (on Hono app export)
Annotate your route app export to customize OpenAPI metadata:
/**
* @prefix /custom-prefix // Optional: Override URL prefix
* @name My Route Group // Optional: Override display name
*/
export const myApp = new Hono()
.get("/", (c) => { /* ... */ });| Tag | Description | Fallback |
|-----|-------------|----------|
| @prefix | URL prefix for all routes | Filename convention (accounts.ts → /accounts) |
| @name | Display name in OpenAPI tags | Filename convention (accounts.ts → Accounts) |
Endpoint-Level JSDoc (on route handlers)
Annotate individual route handlers for rich endpoint documentation:
export const accountsApp = new Hono()
/**
* List all accounts
* @summary Get all accounts for the current user
* @description Returns a paginated list of all accounts owned by the authenticated user
* @tags Accounts, Finance
*/
.get("/", (c) => {
/* ... */
})
/**
* Create a new account
* @summary Create account
* @description Creates a new financial account with the provided details
* @tags Accounts
*/
.post("/", (c) => {
/* ... */
});| Tag | Description |
|-----|-------------|
| @summary | Short summary for the endpoint |
| @description | Detailed description |
| @tags | Comma-separated tags for categorization |
Configuration Reference
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| tsConfigPath | string | Yes | Path to your tsconfig.json |
| openApi | OpenAPIConfig | Yes | Static OpenAPI fields (info, servers, etc.) |
| outputs | { openApiJson: string } | Yes | Output path for generated openapi.json |
| appPath | string | No* | Path to main app file for auto-discovery |
| apis | string[] | No* | Array of route file paths (for manual listing) |
| preDefineTypeContent | string | No | Raw content injected at top of .d.ts snapshots |
* Either appPath or apis must be provided (mutually exclusive)
Serving the OpenAPI Docs
Install the Scalar viewer:
bun add @scalar/hono-api-referenceMount in your Hono app:
import { Hono } from "hono";
import { Scalar } from "@scalar/hono-api-reference";
import fs from "node:fs/promises";
const docsApp = new Hono()
.get("/", Scalar({ url: "/docs/openapi.json" }))
.get("/openapi.json", async (c) => {
const spec = await fs.readFile("./openapi.json", "utf-8");
return c.json(JSON.parse(spec));
});
export const app = new Hono()
.route("/docs", docsApp)
.route("/accounts", accountsApp);Visit /docs to see the interactive API documentation.
CLI Usage
# Generate OpenAPI spec
bunx hono-auto-docs generate --config ./hono-docs.ts
# Or add to package.json scripts
{
"scripts": {
"docs": "hono-auto-docs generate --config ./hono-docs.ts"
}
}Programmatic Usage
import { runGenerate } from "@bacaxnot/hono-auto-docs";
await runGenerate("./hono-docs.ts");Limitations
appPath Mode Limitations
The appPath auto-discovery only works for:
- ✅ Single-file method-chained
.route()calls - ✅ Simple import → mount patterns
It does not support:
- ❌ Nested/multi-level mounting
- ❌ Conditional route registration
- ❌ Non-chained registration patterns
- ❌ Re-exported route aggregators
Solution: Use apis mode with @prefix JSDoc overrides for complex setups.
AppType Requirement
You must export AppType from each route module:
export const accountsApp = new Hono()
.get("/", (c) => { /* ... */ });
// Required!
export type AppType = typeof accountsApp;Development
Clone & install dependencies:
git clone https://github.com/bacaxnot/hono-auto-docs.git cd hono-auto-docs bun installBuild and watch:
bun run build --watchTest locally via
bun linkorfile:install in a demo project.
Contributing
- Fork the repo
- Create a feature branch
- Open a PR with a clear description
- Ensure code passes linting
