Swagger / OpenAPI
Muzu provides built-in Swagger/OpenAPI 3.0 documentation support with zero external dependencies. Generate interactive API documentation automatically from your decorators.
Quick Start
Enable Swagger by passing configuration to MuzuServer:
import { MuzuServer } from 'muzu';
const app = new MuzuServer({
swagger: {
enabled: true,
path: '/swagger',
info: {
title: 'My API',
version: '1.0.0',
description: 'API documentation',
contact: {
name: 'API Support',
email: 'support@example.com'
}
}
}
});
app.listen(3000);
Access your documentation:
- Swagger UI: http://localhost:3000/swagger
- OpenAPI JSON: http://localhost:3000/swagger.json
Configuration Options
const app = new MuzuServer({
swagger: {
enabled: true, // Enable/disable Swagger
path: '/swagger', // Swagger UI path (default: /swagger)
debug: true, // Enable debug logs (default: false)
info: {
title: 'My API', // API title
version: '1.0.0', // API version
description: 'API docs', // API description
contact: {
name: 'Support',
email: 'support@example.com',
url: 'https://example.com/support'
},
license: {
name: 'MIT',
url: 'https://opensource.org/licenses/MIT'
}
},
servers: [ // Optional server definitions
{
url: 'http://localhost:3000',
description: 'Development server'
},
{
url: 'https://api.example.com',
description: 'Production server'
}
]
}
});
Documenting Controllers
Use @ApiTags to tag controllers:
import { Controller, Get, ApiTags } from 'muzu';
// Simple string tags
@Controller('/users')
@ApiTags('Users')
class UserController {
@Get()
getUsers() {
return { users: [] };
}
}
// Tags with descriptions
@Controller('/products')
@ApiTags({ name: 'Products', description: 'Product management endpoints' })
class ProductController {
@Get()
getProducts() {
return { products: [] };
}
}
Documenting Operations
Use @ApiOperation to document route details:
import { Get, Post, ApiOperation } from 'muzu';
@Controller('/users')
class UserController {
@Get()
@ApiOperation({
summary: 'Get all users',
description: 'Returns a list of all users in the system',
operationId: 'getAllUsers'
})
getUsers() {
return { users: [] };
}
@Post()
@ApiOperation({
summary: 'Create a new user',
description: 'Creates a new user with the provided information'
})
createUser(req: Request) {
return { created: true };
}
}
Documenting Responses
Use @ApiResponse to document responses:
import { Get, ApiResponse } from 'muzu';
class UserResponseDto {
@IsString()
id: string;
@IsString()
username: string;
@IsEmail()
email: string;
}
@Controller('/users')
class UserController {
@Get()
@ApiResponse({
status: 200,
description: 'Successful response',
type: UserResponseDto,
isArray: true
})
@ApiResponse({
status: 500,
description: 'Internal server error'
})
getUsers() {
return { users: [] };
}
@Get(':id')
@ApiResponse({
status: 200,
description: 'User found',
type: UserResponseDto
})
@ApiResponse({
status: 404,
description: 'User not found'
})
getUser(req: Request) {
return { user: {} };
}
}
Documenting Parameters
Use @ApiParameter to document path/query/header parameters:
import { Get, ApiParameter } from 'muzu';
@Controller('/users')
class UserController {
@Get(':id')
@ApiParameter({
name: 'id',
in: 'path',
description: 'User ID',
required: true,
type: 'string',
example: '123'
})
getUser(req: Request) {
return { userId: req.params.id };
}
@Get()
@ApiParameter({
name: 'page',
in: 'query',
description: 'Page number',
required: false,
type: 'integer',
example: 1
})
@ApiParameter({
name: 'limit',
in: 'query',
description: 'Items per page',
required: false,
type: 'integer',
example: 10
})
@ApiParameter({
name: 'Authorization',
in: 'header',
description: 'Bearer token',
required: true,
type: 'string',
example: 'Bearer abc123'
})
getUsers(req: Request) {
return { users: [] };
}
}
Documenting Request Body
Use @ApiBody to document request bodies:
import { Post, ApiBody, ValidateBody } from 'muzu';
class CreateUserDto {
@IsString()
@MinLength(3)
username: string;
@IsEmail()
email: string;
@IsNumber()
@Min(18)
age: number;
}
@Controller('/users')
class UserController {
@Post()
@ApiBody({
description: 'User data',
required: true,
type: CreateUserDto
})
@ValidateBody(CreateUserDto)
createUser(req: Request) {
return { created: true };
}
}
Automatic Schema Generation
Muzu automatically generates JSON schemas from your DTOs:
class CreateUserDto {
@IsString()
@MinLength(3)
@MaxLength(20)
username: string; // → { type: 'string', minLength: 3, maxLength: 20 }
@IsEmail()
email: string; // → { type: 'string', format: 'email' }
@IsNumber()
@Min(18)
@Max(100)
age: number; // → { type: 'number', minimum: 18, maximum: 100 }
@IsEnum(UserRole)
role: UserRole; // → { enum: ['admin', 'user', 'guest'] }
}
The schema appears in Swagger UI automatically when you use @ApiBody or @ApiResponse with type: CreateUserDto.
Complete Example
Here's a fully documented controller:
import {
Controller,
Get,
Post,
Put,
Delete,
ApiTags,
ApiOperation,
ApiResponse,
ApiParameter,
ApiBody,
ValidateBody,
IsString,
IsEmail,
IsNumber,
Min,
Max,
MinLength
} from 'muzu';
// DTOs
class CreateUserDto {
@IsString()
@MinLength(3)
username: string;
@IsEmail()
email: string;
@IsNumber()
@Min(18)
@Max(100)
age: number;
}
class UserResponseDto {
@IsString()
id: string;
@IsString()
username: string;
@IsEmail()
email: string;
@IsNumber()
age: number;
}
// Controller
@Controller('/api/users')
@ApiTags({ name: 'Users', description: 'User management endpoints' })
export class UserController {
@Get()
@ApiOperation({
summary: 'Get all users',
description: 'Returns a list of all users in the system'
})
@ApiResponse({
status: 200,
description: 'Successful response',
type: UserResponseDto,
isArray: true
})
getUsers() {
return {
users: [
{ id: '1', username: 'alice', email: 'alice@example.com', age: 25 },
{ id: '2', username: 'bob', email: 'bob@example.com', age: 30 }
]
};
}
@Get(':id')
@ApiOperation({
summary: 'Get user by ID',
description: 'Returns a single user by their ID'
})
@ApiParameter({
name: 'id',
in: 'path',
description: 'User ID',
required: true,
type: 'string'
})
@ApiResponse({
status: 200,
description: 'User found',
type: UserResponseDto
})
@ApiResponse({
status: 404,
description: 'User not found'
})
getUser(req: Request) {
const { id } = req.params;
return {
id,
username: 'alice',
email: 'alice@example.com',
age: 25
};
}
@Post()
@ApiOperation({
summary: 'Create a new user',
description: 'Creates a new user with the provided information'
})
@ApiBody({
description: 'User data',
required: true,
type: CreateUserDto
})
@ApiResponse({
status: 201,
description: 'User created successfully',
type: UserResponseDto
})
@ApiResponse({
status: 400,
description: 'Invalid input'
})
@ValidateBody(CreateUserDto)
createUser(req: Request, res: Response) {
res.statusCode = 201;
return {
id: '123',
...req.body
};
}
}
Automatic Tag Collection
Tags are automatically collected from @ApiTags decorators:
// ✅ Tags are auto-collected
@Controller('/users')
@ApiTags({ name: 'Users', description: 'User management' })
class UserController { }
@Controller('/products')
@ApiTags({ name: 'Products', description: 'Product management' })
class ProductController { }
// ❌ No need to define tags in config
const app = new MuzuServer({
swagger: {
// tags: [...] // Not needed! Muzu collects them automatically
info: { ... }
}
});
You can use either format:
- String:
@ApiTags('Users', 'Products') - Object:
@ApiTags({ name: 'Users', description: '...' }) - Mixed:
@ApiTags('Auth', { name: 'Users', description: '...' })
Debug Mode
Enable debug mode to see Swagger generation warnings:
const app = new MuzuServer({
swagger: {
enabled: true,
debug: true, // Show warnings in console
info: { ... }
}
});
Debug mode shows warnings for:
- Failed spec generation
- Failed operation building
- Failed schema generation
Multiple Responses
Document multiple response codes:
@Get(':id')
@ApiResponse({
status: 200,
description: 'User found',
type: UserResponseDto
})
@ApiResponse({
status: 404,
description: 'User not found'
})
@ApiResponse({
status: 401,
description: 'Unauthorized'
})
@ApiResponse({
status: 500,
description: 'Internal server error'
})
getUser(req: Request) {
// ...
}
Array Responses
Document array responses:
@Get()
@ApiResponse({
status: 200,
description: 'List of users',
type: UserResponseDto,
isArray: true // Important!
})
getUsers() {
return { users: [] };
}
Nested DTOs
Swagger automatically handles nested DTOs:
class AddressDto {
@IsString()
street: string;
@IsString()
city: string;
}
class UserDto {
@IsString()
name: string;
@ValidateNested()
address: AddressDto; // Nested DTO
}
@Post()
@ApiBody({
type: UserDto // Automatically includes AddressDto schema
})
@ValidateBody(UserDto)
createUser(req: Request) {
return { created: true };
}
Best Practices
Document All Public Endpoints
// ✅ Good - Fully documented
@Get(':id')
@ApiOperation({ summary: 'Get user by ID' })
@ApiParameter({ name: 'id', in: 'path', type: 'string' })
@ApiResponse({ status: 200, type: UserDto })
@ApiResponse({ status: 404, description: 'Not found' })
getUser() { }
// ❌ Bad - No documentation
@Get(':id')
getUser() { }
Use Descriptive Messages
// ✅ Good - Clear descriptions
@ApiOperation({
summary: 'Get user by ID',
description: 'Retrieves a single user by their unique identifier'
})
// ❌ Bad - Vague descriptions
@ApiOperation({
summary: 'Get user',
description: 'Gets user'
})
Group Related Endpoints
// ✅ Good - Grouped with tags
@Controller('/users')
@ApiTags({ name: 'Users', description: 'User management' })
class UserController { }
@Controller('/posts')
@ApiTags({ name: 'Posts', description: 'Post management' })
class PostController { }
// ❌ Bad - No grouping
@Controller('/users')
class UserController { } // No tags
Document Error Responses
// ✅ Good - Error responses documented
@Get(':id')
@ApiResponse({ status: 200, type: UserDto })
@ApiResponse({ status: 404, description: 'User not found' })
@ApiResponse({ status: 500, description: 'Internal server error' })
getUser() { }
// ❌ Bad - Only success response
@Get(':id')
@ApiResponse({ status: 200, type: UserDto })
getUser() { }
Swagger UI Features
The generated Swagger UI includes:
- Try it out - Test endpoints directly from the browser
- Schema viewer - View request/response schemas
- Example values - See example payloads
- Authentication - Test with auth tokens
- Download - Export OpenAPI spec as JSON/YAML
Next Steps
- Learn about Exception Handling for error responses
- See Validation for request validation
- Explore Middleware for authentication docs