Hybrid OpenAPI 3.x generator for Express.js with zero-config setup
Automatically generate OpenAPI 3.0/3.1 specifications and Swagger UI from Express.js REST APIs using decorators, JSDoc, and runtime capture.
- Zero-Config Onboarding: Works with legacy JavaScript apps out of the box
- Hybrid Generation Strategy: Choose from three approaches or mix them:
- Decorators: TypeScript-first with experimental decorators
- JSDoc: Comment-based documentation with YAML payloads
- Runtime Capture: Automatic schema inference from live requests (dev mode only)
- Validator-Aware Schema Extraction: Native support for Zod, Joi, and Yup with plugin architecture for custom validators
- Express 4 & 5 Compatible: Handles nested routers and middleware chains
- Performance Optimized: <50ms generation for 100-route apps
- Security First: Automatic masking of sensitive fields in runtime capture
The codebase is currently undergoing a comprehensive refactoring to add:
- MiddlewareAnalyzer: Detects authentication guards, validation, error handling, CORS, logging
- PathParameterExtractor: Extracts path parameters, query parameters, converts Express patterns to OpenAPI
- RouteMetadataEnricher: Enriches routes with intelligent tags, operation IDs, examples, and security information
- JoiSchemaParser: Parses Joi validation schemas and converts to OpenAPI format
- ControllerAnalyzer: Analyzes controller functions to infer request/response schemas
- SchemaExtractor: Orchestrates schema extraction from Joi validators, controllers, and JSDoc comments
- Phase 3: Advanced parsing with TypeScript AST support and decorator handling
- Phase 4: Integration into core RouteDiscovery and SpecGenerator
- Phase 5: Complete test suite and production release
See REFACTORING_PLAN_v0.3.0.md and PHASE_2_SCHEMA_EXTRACTION.md for detailed documentation.
npm install express-swagger-auto
# or
pnpm add express-swagger-auto
# or
yarn add express-swagger-autoimport express from 'express';
import { RouteDiscovery, SpecGenerator, createSwaggerUIMiddleware } from 'express-swagger-auto';
const app = express();
// Your existing routes
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice' }]);
});
// Auto-generate OpenAPI spec
const discovery = new RouteDiscovery();
const routes = discovery.discover(app);
const generator = new SpecGenerator({
info: {
title: 'My API',
version: '1.0.0',
description: 'Auto-generated API documentation',
},
});
const spec = generator.generate(routes);
// Mount Swagger UI
app.use(createSwaggerUIMiddleware({ spec }));
app.listen(3000, () => {
console.log('Swagger UI: http://localhost:3000/api-docs');
});import { Route, Parameter, Response } from 'express-swagger-auto/decorators';
class UserController {
@Route({
summary: 'Get user by ID',
tags: ['users'],
})
@Parameter({
name: 'id',
in: 'path',
required: true,
schema: { type: 'string' },
})
@Response({
statusCode: 200,
description: 'User found',
})
async getUser(req: Request, res: Response) {
// handler logic
}
}import { RouteDiscovery, JsDocParser, SpecGenerator } from 'express-swagger-auto';
/**
* @openapi
* @route GET /users/{id}
* @summary Get user by ID
* @tags users
* @param {string} id.path.required - User ID
* @response 200 - User found
* @response 404 - User not found
*/
app.get('/users/:id', (req, res) => {
// handler logic
});
// Automatic parsing from JSDoc comments
const parser = new JsDocParser({ sourceFiles: ['src/**/*.js'] });
const discovery = new RouteDiscovery();
const routes = discovery.discover(app, {
enableJsDocParsing: true,
jsDocParser: parser,
});
const generator = new SpecGenerator({ info: { title: 'My API', version: '1.0.0' } });
const spec = generator.generate(routes);π Complete JSDoc Tags Reference - Full documentation of all supported tags and syntax
import { runtimeCapture } from 'express-swagger-auto/middleware';
// Enable runtime capture in development
app.use(runtimeCapture({
enabled: process.env.NODE_ENV === 'development',
sensitiveFields: ['password', 'token', 'apiKey'],
}));
// Routes are automatically analyzed during execution
app.post('/users', (req, res) => {
// Schema inferred from actual request/response
res.json({ id: 1, name: 'Bob' });
});import { z } from 'zod';
import { ZodAdapter } from 'express-swagger-auto';
const userSchema = z.object({
name: z.string(),
email: z.string().email(),
age: z.number().int().positive(),
});
const adapter = new ZodAdapter();
const openApiSchema = adapter.convert(userSchema);
// Automatically converts to OpenAPI schema formatExplore complete working examples in the examples/ directory:
-
decorator-example: TypeScript decorators with Zod validation
- Demonstrates
@Route,@Parameter,@RequestBody,@Responsedecorators - Full CRUD user management API
- Type-safe request/response handling
- Demonstrates
-
jsdoc-example: JavaScript with JSDoc comments and Joi validation
- Product catalog API with pagination
- JSDoc-style inline documentation (Phase 3 parser coming)
- Manual route metadata with Joi schema conversion
-
runtime-example: Runtime schema capture with snapshot storage
- Zero-annotation blog API
- Automatic schema inference from request/response data
- Snapshot persistence with deduplication
Each example includes:
- Complete implementation with README
- Installation and usage instructions
- curl command examples
- Running Swagger UI integration
# Generate OpenAPI spec
npx express-swagger-auto generate --input ./src/app.ts --output ./openapi.json
# Serve Swagger UI standalone
npx express-swagger-auto serve --spec ./openapi.json --port 3000
# Validate OpenAPI spec
npx express-swagger-auto validate ./openapi.json
# Migrate from other tools
npx express-swagger-auto migrate swagger-jsdoc| Phase | Status | Focus |
|---|---|---|
| 1 | β Complete | Core foundation, route discovery, basic spec generation |
| 2 | β Complete | Schema extraction (Zod/Joi/Yup), plugin API, runtime inference |
| 3 | β Complete | JSDoc parser, decorator system, example merging |
| 4 | β Complete | Security detection, perf tuning, hot reload, CLI completion |
| 5 | β Complete | CI/CD workflows, npm publish preparation, community infrastructure |
| 6 | Current | Documentation site, additional examples, migration guides |
Phase 5 Completed: All release preparation including CI/CD, CHANGELOG, and community infrastructure complete! See PHASE_STATUS.md for details.
See CLAUDE.md for architecture guardrails and AGENTS.md for agent roster.
interface GeneratorConfig {
info: OpenAPIInfo; // Required: API title, version, description
servers?: OpenAPIServer[]; // API servers
specVersion?: '3.0.0' | '3.1.0'; // Default: '3.1.0'
enableRuntimeCapture?: boolean; // Default: false in production
securitySchemes?: Record<string, OpenAPISecurityScheme>;
outputPath?: string; // CLI output path
}- Route discovery: O(n) relative to layer count
- Spec generation: <50ms for 100 routes (Phase 4 target)
- CLI file watching: Debounce β₯500ms, throttle β€1Hz
- Runtime capture disabled by default in production
- Automatic sanitization of sensitive fields (password, token, apiKey, etc.)
- No secrets in generated specs or logs
This project has comprehensive test coverage with Vitest.
# Run all tests
pnpm test
# Run unit tests only
pnpm test:unit
# Run integration tests only
pnpm test:integration
# Run tests with coverage
pnpm test:coverage
# Run unit tests with coverage
pnpm test:unit:coverage| Category | Minimum |
|---|---|
| Lines | 85% |
| Functions | 85% |
| Branches | 85% |
| Statements | 85% |
For detailed testing documentation, see:
See AGENTS.md for agent collaboration protocol and docs/AGENT_LOG.md for development history.
MIT
- swagger-jsdoc - JSDoc-based OpenAPI generation
- tsoa - TypeScript decorators for Express/Koa
- express-oas-generator - Runtime-based generation
express-swagger-auto combines the best of all three approaches with zero-config hybrid support.