import express, { Application, Request, Response, NextFunction } from 'express'; import cors from 'cors'; import helmet from 'helmet'; import rateLimit from 'express-rate-limit'; import dotenv from 'dotenv'; import path from 'path'; import fs from 'fs'; import mongoose from 'mongoose'; import { connectDB } from './config/database'; import { errorHandler } from './middleware/errorHandler'; import { setupSwagger } from './config/swagger'; // Read version from package.json const getAppVersion = (): string => { try { const pkgPath = path.join(__dirname, '..', 'package.json'); const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); return pkg.version || '0.0.0'; } catch { return '0.0.0'; } }; // Import routes import indexRoutes from './routes/index'; import authRoutes from './routes/auth'; dotenv.config(); const app: Application = express(); const PORT: number = parseInt(process.env.PORT || '8000'); // Connect to MongoDB connectDB(); // Security middleware app.use(helmet()); app.use(cors({ origin: process.env.FRONTEND_URL || 'http://localhost:5000', credentials: true })); // Rate limiting const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs message: 'Too many requests from this IP, please try again later.' }); app.use('/api/', limiter); // Body parsing middleware app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true })); // Setup Swagger documentation setupSwagger(app); // Routes app.use('/api', indexRoutes); app.use('/api/auth', authRoutes); // Health check endpoint app.get('/health', (req: Request, res: Response) => { res.status(200).json({ status: 'OK', timestamp: new Date().toISOString(), uptime: process.uptime(), environment: process.env.NODE_ENV || 'development', version: getAppVersion() }); }); // Error handling middleware (should be last) app.use(errorHandler); // 404 handler app.use('*', (req: Request, res: Response) => { res.status(404).json({ success: false, message: 'Route not found', path: req.originalUrl }); }); // Graceful shutdown const gracefulShutdown = async (signal: string) => { console.log(`\n${signal} received. Shutting down gracefully...`); try { await mongoose.connection.close(); console.log('MongoDB connection closed.'); } catch (err) { console.error('Error closing MongoDB connection:', err); } process.exit(0); }; process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); process.on('SIGINT', () => gracefulShutdown('SIGINT')); app.listen(PORT, '0.0.0.0', () => { console.log(`🚀 Server running on port ${PORT}`); console.log(`📱 Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`📚 API Documentation: http://localhost:${PORT}/api-docs`); }); export default app;