const express = require('express'); const compression = require('compression'); const { applySecurityMiddleware } = require('./middleware/security.js'); const requestLogger = require('./middleware/requestLogger.js'); const metricsMiddleware = require('./middleware/metrics.js'); const { errorHandler, notFoundHandler } = require('./middleware/errorHandler.js'); const { createSessionMiddleware } = require('./config/session.js'); const { languageMiddleware } = require('./middleware/language.js'); const { setupSwagger, generatePostmanCollection } = require('./config/swagger.js'); /** * Create and configure Express application */ const createApp = () => { const app = express(); // Setup Swagger API documentation (skip in test environment) if (process.env.NODE_ENV !== 'test') { setupSwagger(app); } // Apply security middleware (helmet, cors, rate limiting) applySecurityMiddleware(app); // Body parsing middleware app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Compression middleware app.use(compression()); // Session middleware with Redis store (skip in test environment) if (process.env.NODE_ENV !== 'test') { app.use(createSessionMiddleware()); } // Request logging middleware app.use(requestLogger); // Metrics collection middleware app.use(metricsMiddleware); // Language detection middleware app.use(languageMiddleware); // Response formatter middleware (converts all responses to unified format) const responseFormatter = require('./middleware/responseFormatter'); app.use(responseFormatter); // Serve static files from uploads directory const path = require('path'); const config = require('./config/env'); app.use('/uploads', express.static(path.resolve(config.upload.path))); // Health check and metrics endpoints const healthRoutes = require('./routes/healthRoutes'); app.use('/health', healthRoutes); app.get('/metrics', (req, res, next) => { // Forward to health routes metrics endpoint req.url = '/metrics'; healthRoutes(req, res, next); }); // Postman collection export endpoint app.get('/api-docs/postman', (req, res) => { const collection = generatePostmanCollection(); res.setHeader('Content-Type', 'application/json'); res.setHeader('Content-Disposition', 'attachment; filename="overseas-appointment-api.postman_collection.json"'); res.send(JSON.stringify(collection, null, 2)); }); // API routes const authRoutes = require('./routes/authRoutes'); app.use('/api/v1/auth', authRoutes); const userRoutes = require('./routes/userRoutes'); app.use('/api/v1/users', userRoutes); const serviceRoutes = require('./routes/serviceRoutes'); app.use('/api/v1', serviceRoutes); const appointmentRoutes = require('./routes/appointmentRoutes'); app.use('/api/v1/appointments', appointmentRoutes); const notificationRoutes = require('./routes/notificationRoutes'); app.use('/api/v1/notifications', notificationRoutes); const invitationRoutes = require('./routes/invitationRoutes'); app.use('/api/v1/invitations', invitationRoutes); const commissionRoutes = require('./routes/commissionRoutes'); app.use('/api/v1/commissions', commissionRoutes); const withdrawalRoutes = require('./routes/withdrawalRoutes'); app.use('/api/v1/withdrawals', withdrawalRoutes); const uploadRoutes = require('./routes/uploadRoutes'); app.use('/api/v1/upload', uploadRoutes); const qrcodeRoutes = require('./routes/qrcodeRoutes'); app.use('/api/v1/qrcode', qrcodeRoutes); const adminAuthRoutes = require('./routes/adminAuthRoutes'); app.use('/api/v1/admin', adminAuthRoutes); const adminUserRoutes = require('./routes/adminUserRoutes'); app.use('/api/v1/admin/users', adminUserRoutes); const adminAppointmentRoutes = require('./routes/adminAppointmentRoutes'); app.use('/api/v1/admin/appointments', adminAppointmentRoutes); const adminWithdrawalRoutes = require('./routes/adminWithdrawalRoutes'); app.use('/api/v1/admin/withdrawals', adminWithdrawalRoutes); const adminServiceRoutes = require('./routes/adminServiceRoutes'); app.use('/api/v1/admin/services', adminServiceRoutes); const adminStatisticsRoutes = require('./routes/adminStatisticsRoutes'); app.use('/api/v1/admin/statistics', adminStatisticsRoutes); const adminTranslationRoutes = require('./routes/adminTranslationRoutes'); app.use('/api/v1/admin/translations', adminTranslationRoutes); const adminUploadRoutes = require('./routes/adminUploadRoutes'); app.use('/api/v1/admin/upload', adminUploadRoutes); const configRoutes = require('./routes/configRoutes'); app.use('/api/v1/config', configRoutes); const homeRoutes = require('./routes/homeRoutes'); app.use('/api/v1/home', homeRoutes); const bookingRuleRoutes = require('./routes/bookingRuleRoutes'); app.use('/api/v1/booking-rules', bookingRuleRoutes); const adminConfigRoutes = require('./routes/adminConfigRoutes'); app.use('/api/v1/admin/config', adminConfigRoutes); const adminHomeRoutes = require('./routes/adminHomeRoutes'); app.use('/api/v1/admin/home', adminHomeRoutes); const adminCategoryRoutes = require('./routes/adminCategoryRoutes'); app.use('/api/v1/admin/categories', adminCategoryRoutes); const adminNotificationRoutes = require('./routes/adminNotificationRoutes'); app.use('/api/v1/admin/notifications', adminNotificationRoutes); const adminPaymentOrderRoutes = require('./routes/adminPaymentOrderRoutes'); app.use('/api/v1/admin/payment-orders', adminPaymentOrderRoutes); const adminCommissionRoutes = require('./routes/adminCommissionRoutes'); app.use('/api/v1/admin/commissions', adminCommissionRoutes); const adminBookingRuleRoutes = require('./routes/adminBookingRuleRoutes'); app.use('/api/v1/admin/booking-rules', adminBookingRuleRoutes); // 404 handler app.use(notFoundHandler); // Global error handler (must be last) app.use(errorHandler); return app; }; module.exports = createApp;