A zero-config OpenAPI 3.0 generator for Express. The AST-based spiritual successor to swagger-autogen with automatic type inference.
npm install swagger-autogen-astZero-config OpenAPI 3.0 generation for Express.



---
This is the AST-based successor to swagger-autogen. It uses the TypeScript Compiler API to statically analyze your routes, types, and controller logic to generate a spec that matches your code.
Intended for use with swagger-ui-react and/or importing to Postman.
Swagger generators are annoying. They require tons of manual config or intrusive code annotations (both which I didn't want to do).
This tool aims to make OpenAPI generation effortless by inferring as much as possible from your existing TypeScript/Express code with zero config.
- Installation
- Usage
- Automatic Inference
- Overrides
- How it works
``bash`
npm install swagger-autogen-ast --save-dev
The generator automatically detects your tsconfig.json.
`bash`
npx swagger-autogen-ast ./src/index.ts ./swagger.json
For custom configurations:
`typescript
import { generateOpenApi } from "swagger-autogen-ast";
generateOpenApi({
entryFile: "./src/index.ts", // main Express app entry
outputFile: "./swagger.json",
tsconfigPath: "./tsconfig.json", // optional, auto-detected if not provided
info: {
title: "My API",
version: "1.0.0",
},
components: {
securitySchemes: {
bearerAuth: {
type: "http",
scheme: "bearer",
},
},
},
security: [{ bearerAuth: [] }],
servers: [{ url: "http://localhost:3000", description: "Local server" }],
});
`
See the /tests directory for a complete set of examples covering all supported features and mappings to OpenAPI outputs.
The tool relies on standard TypeScript/Express patterns.
The generator inspects Express Generics (preferred) and Type Assertions.
Using Generics:
It reads the 3rd argument (Body) and 4th argument (Query).
`typescript`
// Infers schema from CreateUserBody and params from UserQuery
router.post(
"/users",
(req: Request<{}, {}, CreateUserBody, UserQuery>, res) => { ... }
);
Using Assertions:
If you don't use generics, it scans the function body for as Type assertions.
`typescript
router.put("/users/:id", (req, res) => {
const body = req.body as UpdateUser; // Schema inferred
// Params inferred with descriptions
const { status } = req.query as {
/* Filter by status (active/inactive) /
status: string;
};
});
`
It scans for res.json, res.send, res.status, and res.sendStatus.
`typescript
router.get("/admin", async (req, res) => {
if (!auth) return res.sendStatus(403); // -> 403 Forbidden
const data: DashboardData = await getData();
return res.json(data); // -> 200 OK (application/json with DashboardData schema)
});
`
It detects direct access and type assertions on req.headers.
`typescript
router.get("/protected", (req, res) => {
// Automatically adds "x-api-key" (header) to parameters
const apiKey = req.headers["x-api-key"];
// Supports standard methods
const auth = req.header("Authorization");
});
`
`typescript`
// Infers 403 from authMiddleware, 400 from validation, and 200 from the handler
router.post("/users", authMiddleware, validationMiddleware, createUserHandler);
Manual overrides are supported with inline #swagger comments or JSDoc.
Variables defined in comments are evaluated and merged into the operation object.
`typescript
router.post("/upload", (req, res) => {
// #swagger.tags = ["Files"]
// #swagger.summary = "Upload file"
// #swagger.description = "Multipart upload only"
// #swagger.deprecated = true
// #swagger.security = [{ "bearerAuth": [] }]
res.status(200).send();
});
`
Standard JSDoc above the route works too.
`typescript`
/**
* @summary Get User
* @tags Users, Public
*/
router.get("/user/:id", handler);
The generator starts at your entryFile and performs a recursive AST traversal using the TypeScript Compiler API.
1. It follows router.use(path, handler) calls to build the full routing tree, resolving imports automatically.router.get
2. It locates route handlers (like ) and finds their original function declarations.#swagger
3. It scans these functions for JSDoc tags, comments, request type assertions, and res.status/res.json` calls.
4. It converts the inferred TypeScript types into OpenAPIV3 schemas.
MIT