import swaggerJsdoc from 'swagger-jsdoc'; import swaggerUi from 'swagger-ui-express'; import { Express } from 'express'; const options: swaggerJsdoc.Options = { definition: { openapi: '3.0.0', info: { title: 'API Documentation', version: '1.0.0', description: 'Comprehensive API documentation for the TypeScript application', contact: { name: 'API Support', email: 'support@example.com' }, license: { name: 'MIT', url: 'https://opensource.org/licenses/MIT' } }, servers: [ { url: process.env.API_URL || 'http://localhost:8000', description: 'Development server' }, { url: 'https://api.production.com', description: 'Production server' } ], components: { securitySchemes: { bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' }, apiKey: { type: 'apiKey', in: 'header', name: 'X-API-Key' } }, schemas: { ApiResponse: { type: 'object', properties: { success: { type: 'boolean', example: true }, message: { type: 'string', example: 'Operation completed successfully' }, data: { type: 'object', description: 'Response data' }, error: { type: 'string', description: 'Error message if success is false' } } }, PaginatedResponse: { type: 'object', properties: { success: { type: 'boolean', example: true }, data: { type: 'array', items: { type: 'object' } }, pagination: { type: 'object', properties: { page: { type: 'integer', example: 1 }, limit: { type: 'integer', example: 10 }, total: { type: 'integer', example: 100 }, totalPages: { type: 'integer', example: 10 }, hasNext: { type: 'boolean', example: true }, hasPrev: { type: 'boolean', example: false } } } } }, ErrorResponse: { type: 'object', properties: { success: { type: 'boolean', example: false }, message: { type: 'string', example: 'An error occurred' }, error: { type: 'string', example: 'ValidationError' }, statusCode: { type: 'integer', example: 400 } } }, ValidationError: { type: 'object', properties: { field: { type: 'string', example: 'email' }, message: { type: 'string', example: 'Email is required' } } } } }, security: [ { bearerAuth: [] } ], tags: [ { name: 'Authentication', description: 'User authentication and authorization' }, { name: 'Health', description: 'API health check endpoints' } ] }, apis: [ './src/routes/*.ts', './src/controllers/*.ts', './src/models/*.ts' ] }; const specs = swaggerJsdoc(options); export const setupSwagger = (app: Express): void => { const swaggerOptions = { explorer: true, customCss: ` .swagger-ui .topbar { display: none } .swagger-ui .info .title { color: #3b82f6; } .swagger-ui .scheme-container { background: #f8fafc; padding: 10px; border-radius: 4px; } `, customSiteTitle: '{{PROJECT_NAME}} API Documentation', swaggerOptions: { persistAuthorization: true, displayRequestDuration: true, docExpansion: 'list', filter: true, showExtensions: true, showCommonExtensions: true, defaultModelsExpandDepth: 2, defaultModelExpandDepth: 2, tryItOutEnabled: true } }; // Primary documentation endpoint - /docs/api app.use('/docs/api', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions)); // Legacy endpoint for backward compatibility app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs, swaggerOptions)); // Swagger JSON endpoints app.get('/docs/api.json', (req, res) => { res.setHeader('Content-Type', 'application/json'); res.send(specs); }); app.get('/api-docs.json', (req, res) => { res.setHeader('Content-Type', 'application/json'); res.send(specs); }); // Documentation redirect routes app.get('/docs', (req, res) => { res.redirect('/docs/api'); }); }; export { specs }; export default setupSwagger;