Generate TypeScript interfaces from OpenAPI 3.1.x specs
npm install cp-openapi-interface-generatorA TypeScript code generator that transforms OpenAPI 3.x specifications into production-ready TypeScript types, Express controller interfaces, and route definitions. Built with a modular architecture for maintainability and extensibility.
- TypeScript Type Generation: Individual model files with automatic dependency resolution
- Express Controller Interfaces: Strongly-typed controller interfaces organized by OpenAPI tags
- Route Generation: Express route definitions with middleware integration and dependency injection
- Enum Support: Full enum generation with x-enum-varnames extension support
- Parameter Type Reusability: Smart deduplication of path and query parameter types
- Reference Resolution: Complete support for OpenAPI $ref references
- Robust Error Handling: Comprehensive validation and clear error messages
- Fully Configurable: Customizable output paths and folder structure
---
``bash`
npm install --save-dev cp-openapi-interface-generator
Add this to your package.json:
`json`
{
"scripts": {
"generate": "cp-openapi-interface-generator --open-api-path=./openapi.yaml --generated-dir=./src/generated"
}
}
`bash`
cp-openapi-interface-generator \
--open-api-path=./openapi.yaml \
--generated-dir=./src/generated \
--controllers-folder=controllers \
--models-folder=models \
--routes-folder=routes \
--middleware-config-path=./middleware-config.js
`bash`
npm run generate
| Option | Description | Default |
| -------------------------- | ------------------------------------------ | ------------------------ |
| --open-api-path | Path to OpenAPI YAML file | ./openapi.yaml |--generated-dir
| | Base output folder for all generated files | ./src/generated |--controllers-folder
| | Folder for Express controller interfaces | controllers |--models-folder
| | Folder for TypeScript model files | models |--routes-folder
| | Folder for Express route definitions | routes |--middleware-config-path
| | Path to middleware configuration file | ./middleware-config.js |
`bash`
/src/generated
āāā models/
ā āāā index.ts <-- Exports all models
ā āāā UserModel.ts <-- Individual model files
ā āāā MessageModel.ts <-- with dependency imports
ā āāā ...
āāā controllers/
ā āāā user-interface.ts <-- Express controller interfaces
ā āāā message-interface.ts <-- organized by OpenAPI tags
ā āāā ...
āāā routes/
āāā user-routes.ts <-- Express route definitions
āāā message-routes.ts <-- with middleware integration
āāā ...
- Individual model files: One TypeScript file per schema type
- Dependency management: Automatic imports for referenced types
- Index file: Central export point for all models
- Reusable parameter types: Shared path and query parameter interfaces
- Express controller interfaces: Type-safe method signatures
- Request/Response typing: Strongly typed Express Request/Response objects
- Parameter typing: Path and query parameters with proper types
- Tag organization: One interface file per OpenAPI tag
- Express route definitions: Ready-to-use router configurations
- Middleware integration: Automatic middleware application based on configuration
- Controller binding: Proper method binding for controller interfaces
- Path conversion: OpenAPI paths converted to Express route format
Create a middleware-config.js file to define middleware for your routes:
`javascriptrequire('../middleware/${middlewareName}')
module.exports = {
getMiddleware: (operationId, method, tags) => {
// Return array of middleware function names
if (tags.includes('auth')) return ['authenticate', 'authorize'];
return [];
},
getMiddlewareImport: middlewareName => {
// Return import statement for middleware
return ;`
},
};
The generator is built with a clean modular architecture:
``
src/
āāā generate.ts # Main orchestrator
āāā config/
ā āāā constants.ts # Configuration constants
āāā types/
ā āāā index.ts # TypeScript interfaces
āāā utils/
ā āāā converters.ts # String conversions (PascalCase, kebab-case)
ā āāā file-writer.ts # File I/O operations
ā āāā openapi-resolver.ts # OpenAPI $ref resolution
āāā validators/
ā āāā enum-validator.ts # Enum validation and sanitization
āāā generators/
āāā enum-generator.ts # Enum generation
āāā interface-generator.ts # Interface/type generation
āāā parameter-extractor.ts # Parameter extraction
āāā model-generator.ts # Model file generation
āāā controller-generator.ts # Controller interface generation
āāā route-generator.ts # Express route generation
- Enum Generation: Robust enum handling with collision prevention and proper escaping
- Type Deduplication: Global tracking prevents duplicate type generation
- Parameter Reusability: Shared parameter types across endpoints reduce duplication
- Dependency Management: Automatic import generation for type dependencies
The generator provides robust enum support:
- String escaping: Handles special characters (backslashes, quotes, newlines, tabs)
- Key sanitization: Converts enum values to valid TypeScript identifiers
- Collision prevention: Automatic numbering for duplicate keys
- x-enum-varnames: Support for custom enum key names via OpenAPI extension
Example:
`yaml`OpenAPI spec
MessageType:
type: string
enum: [TEXT, IMAGE, VIDEO]
x-enum-varnames: [Text, Image, Video]
Generated TypeScript:
`typescript`
export enum MessageType {
Text = 'TEXT',
Image = 'IMAGE',
Video = 'VIDEO',
}
The generator intelligently reuses parameter types across endpoints:
`typescript
// Reused across multiple endpoints with same parameters
export interface ConversationIdPathParams {
conversationId: string;
}
// Used in controller interfaces
getConversation(
req: Request
res: Response
): Promise
`
Generated routes follow dependency injection for testability:
`typescript
// Generated route file
export function createRoutes(messageController: MessageInterface): Router {
const router = Router();
router.post('/', authenticate, messageController.createMessage.bind(messageController));
return router;
}
// Usage in your app
import { createRoutes } from './generated/routes/message-routes';
const messageRouter = createRoutes(new MessageController());
app.use('/api/messages', messageRouter);
`
After running the generator:
1. Create controller implementations
`typescript
import { MessageInterface } from './generated/controllers/message-interface';
export class MessageController implements MessageInterface {
async createMessage(req: Request, res: Response): Promise
// Your implementation
}
}
`
2. Wire up the generated routes
`typescript
import { createRoutes as createMessageRoutes } from './generated/routes/message-routes';
const messageController = new MessageController();
app.use('/api/messages', createMessageRoutes(messageController));
`
3. Import and use generated models
`typescript``
import { Message, User } from './generated/models';
The generator provides clear error messages for common issues:
- Missing OpenAPI spec: File not found errors with exact path
- Invalid spec structure: Validation errors for malformed OpenAPI files
- Invalid enum values: Detection of null/undefined in enum definitions
- File write errors: Detailed error messages with file paths
- Middleware config errors: Clear messages for missing or invalid middleware configuration