import { Application } from 'express'; import swaggerJSDoc from 'swagger-jsdoc'; import swaggerUi from 'swagger-ui-express'; /** * EN: Swagger/OpenAPI configuration for API documentation * VI: Cấu hình Swagger/OpenAPI cho tài liệu API */ const options = { definition: { openapi: '3.0.0', info: { title: 'Microservice Template API', version: '1.0.0', description: 'A production-ready microservice template with comprehensive features', contact: { name: 'Development Team', email: 'dev@goodgo.com', }, license: { name: 'MIT', url: 'https://opensource.org/licenses/MIT', }, }, servers: [ { url: 'http://localhost:{port}', description: 'Development server', variables: { port: { default: '5000', description: 'Port number for the development server', }, }, }, { url: 'https://api.example.com', description: 'Production server', }, ], components: { securitySchemes: { bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT', description: 'JWT Authorization header using the Bearer scheme', }, }, schemas: { ApiResponse: { type: 'object', properties: { success: { type: 'boolean', description: 'Indicates if the request was successful', }, data: { description: 'Response data (varies by endpoint)', }, message: { type: 'string', description: 'Human-readable message', }, timestamp: { type: 'string', format: 'date-time', description: 'ISO 8601 timestamp of the response', }, }, required: ['success', 'timestamp'], }, ErrorResponse: { type: 'object', properties: { success: { type: 'boolean', example: false, }, error: { type: 'object', properties: { code: { type: 'string', description: 'Error code for programmatic handling', example: 'VALIDATION_ERROR', }, message: { type: 'string', description: 'Human-readable error message', example: 'Validation failed', }, details: { description: 'Additional error details (optional)', }, }, required: ['code', 'message'], }, timestamp: { type: 'string', format: 'date-time', }, }, required: ['success', 'error', 'timestamp'], }, Feature: { type: 'object', properties: { id: { type: 'string', description: 'Unique identifier', example: 'clh1x8qkq0000abcdefghijk', }, name: { type: 'string', description: 'Unique feature name', example: 'user-management', }, title: { type: 'string', description: 'Human-readable title', example: 'User Management', }, description: { type: 'string', description: 'Detailed description', example: 'Complete user management system', }, config: { type: 'object', description: 'Feature-specific configuration', example: { enabled: true, priority: 1 }, }, enabled: { type: 'boolean', description: 'Whether the feature is enabled', example: true, }, version: { type: 'string', description: 'Feature version', example: '1.0.0', }, tags: { type: 'array', items: { type: 'string' }, description: 'Categorization tags', example: ['auth', 'users'], }, createdAt: { type: 'string', format: 'date-time', description: 'Creation timestamp', }, updatedAt: { type: 'string', format: 'date-time', description: 'Last update timestamp', }, }, required: ['id', 'name', 'enabled', 'tags', 'createdAt', 'updatedAt'], }, CreateFeatureRequest: { type: 'object', properties: { name: { type: 'string', minLength: 1, maxLength: 100, description: 'Unique feature name', example: 'new-feature', }, title: { type: 'string', maxLength: 200, description: 'Human-readable title', example: 'New Feature', }, description: { type: 'string', maxLength: 1000, description: 'Detailed description', example: 'A new feature for the system', }, config: { type: 'object', description: 'Feature configuration', example: { enabled: true }, }, tags: { type: 'array', items: { type: 'string' }, description: 'Categorization tags', example: ['feature', 'new'], }, }, required: ['name'], }, UpdateFeatureRequest: { type: 'object', properties: { title: { type: 'string', maxLength: 200, description: 'Human-readable title', }, description: { type: 'string', maxLength: 1000, description: 'Detailed description', }, config: { type: 'object', description: 'Feature configuration', }, enabled: { type: 'boolean', description: 'Whether the feature is enabled', }, tags: { type: 'array', items: { type: 'string' }, description: 'Categorization tags', }, }, }, UserInfo: { type: 'object', properties: { userId: { type: 'string', description: 'Unique user identifier', example: 'user-123', }, email: { type: 'string', format: 'email', description: 'User email address', example: 'user@example.com', }, role: { type: 'string', description: 'User role', example: 'admin', enum: ['admin', 'user', 'moderator'], }, iat: { type: 'number', description: 'Token issued at timestamp', }, exp: { type: 'number', description: 'Token expiration timestamp', }, }, required: ['userId', 'email', 'role'], }, HealthResponse: { type: 'object', properties: { success: { type: 'boolean', example: true }, data: { type: 'object', properties: { status: { type: 'string', example: 'ok' }, timestamp: { type: 'string', format: 'date-time' }, }, }, timestamp: { type: 'string', format: 'date-time' }, }, }, ReadinessResponse: { type: 'object', properties: { success: { type: 'boolean', example: true }, data: { type: 'object', properties: { status: { type: 'string', example: 'ready' }, }, }, timestamp: { type: 'string', format: 'date-time' }, }, }, LivenessResponse: { type: 'object', properties: { success: { type: 'boolean', example: true }, data: { type: 'object', properties: { status: { type: 'string', example: 'live' }, }, }, timestamp: { type: 'string', format: 'date-time' }, }, }, }, }, security: [ { bearerAuth: [], }, ], }, apis: ['./src/routes/*.ts', './src/modules/*/feature.module.ts'], // Paths to files containing OpenAPI definitions }; /** * EN: Generate OpenAPI specification * VI: Tạo OpenAPI specification */ const specs = swaggerJSDoc(options); /** * EN: Setup Swagger UI middleware * VI: Thiết lập Swagger UI middleware */ export const setupSwagger = (app: Application, basePath: string = '/api-docs') => { // EN: Swagger page // VI: Trang Swagger app.use(basePath, swaggerUi.serve, swaggerUi.setup(specs, { explorer: true, swaggerOptions: { persistAuthorization: true, displayRequestDuration: true, docExpansion: 'none', filter: true, showExtensions: true, showCommonExtensions: true, syntaxHighlight: { activate: true, theme: 'arta', }, }, customCss: ` .swagger-ui .topbar { display: none } .swagger-ui .info .title { color: #3b4151 } `, customSiteTitle: 'Microservice Template API Documentation', customfavIcon: '/favicon.ico', })); // EN: Swagger JSON endpoint // VI: Endpoint Swagger JSON app.get(`${basePath}.json`, (_req, res) => { res.setHeader('Content-Type', 'application/json'); res.send(specs); }); // EN: Swagger YAML endpoint // VI: Endpoint Swagger YAML app.get(`${basePath}.yaml`, (_req, res) => { res.setHeader('Content-Type', 'application/yaml'); // Note: Would need yaml package for full YAML support res.send(JSON.stringify(specs, null, 2)); }); console.log(`📚 Swagger documentation available at: http://localhost:5000${basePath}`); }; export { specs }; export default specs;