const express = require('express'); const cors = require('cors'); const compression = require('compression'); const path = require('path'); const dotenv = require('dotenv'); const helmet = require('helmet'); const initializeDatabase = require('./config/initDatabase'); // Load environment variables dotenv.config(); console.log('Current Working Directory:', process.cwd()); console.log('__dirname:', __dirname); // Import configurations const config = require('./config'); const { securityHeaders, apiLimiter, validateRequest, corsOptions } = require('./middlewares/security'); const { errorHandler } = require('./middlewares/errorHandler'); const logger = require('./utils/logger'); const monitoring = require('./utils/monitoring'); // Import routes const authRoutes = require('./routes/auth'); const hospitalRoutes = require('./routes/hospitals'); const userRoutes = require('./routes/users'); const superAdminRoutes = require('./routes/superAdmins'); const documentRoutes = require('./routes/documents'); const pdfRoutes = require('./routes/pdfRoutes'); const onboardingRoutes = require('./routes/onboarding'); const appUserRoutes = require('./routes/appUsers'); const excelDataRoutes = require('./routes/exceldata'); const feedbackRoute = require('./routes/feedbacks'); const analyticsRoute = require('./routes/analysis'); // Import services const { refreshExpiredTokens } = require('./services/cronJobs'); const { repopulateQueueOnStartup } = require('./controllers/documentsController'); require('./services/webSocket'); require('./services/secondaryWebsocket'); // Create Express app const app = express(); // Apply security middleware app.use(helmet()); app.use(securityHeaders); app.use(compression({ level: 6, threshold: 1024, filter: (req, res) => { const contentType = res.getHeader('Content-Type'); return /text|json|javascript|css/.test(contentType); } })); // Apply rate limiting to all API routes app.use('/api/', apiLimiter); // Apply CORS app.use(cors(corsOptions)); // Request validation app.use(validateRequest); // Body parsing middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Static files app.use('/uploads', express.static(path.join(__dirname, '..', 'uploads'))); app.use('/public', express.static(path.join(__dirname, '..', 'public'))); // Request logging middleware app.use((req, res, next) => { const start = Date.now(); res.on('finish', () => { const duration = Date.now() - start; monitoring.trackRequest(req.path, req.method, res.statusCode, duration); logger.info(`${req.method} ${req.path} ${res.statusCode} - ${duration}ms`); }); next(); }); // Initialize database before starting the server async function startServer() { try { // Initialize database await initializeDatabase(); console.log('Database initialized successfully'); // API routes app.use('/api/auth', authRoutes); app.use('/api/hospitals', hospitalRoutes); app.use('/api/users', userRoutes); app.use('/api/superAdmins', superAdminRoutes); app.use('/api/onboarding', onboardingRoutes); app.use('/api/documents', documentRoutes); app.use('/api/pdf', pdfRoutes); app.use('/api/app_users', appUserRoutes); app.use('/api/process_excel', excelDataRoutes); app.use('/api/feedbacks', feedbackRoute); app.use('/api/analytics', analyticsRoute); // Health check endpoint app.get('/health', (req, res) => { res.json(monitoring.getHealthStatus()); }); // Database sync endpoint (protected by environment check) app.post('/api/sync-database', async (req, res) => { try { // Only allow in development or with proper authentication if (process.env.NODE_ENV === 'development' || req.headers['x-sync-token'] === process.env.DB_SYNC_TOKEN) { await initializeDatabase(); res.json({ message: 'Database synchronized successfully' }); } else { res.status(403).json({ error: 'Unauthorized' }); } } catch (error) { logger.error('Database sync failed:', error); res.status(500).json({ error: 'Database synchronization failed' }); } }); // Root endpoint app.get('/', (req, res) => { res.send("SpurrinAI Backend is running!"); }); console.log('checking automation!'); console.log('checking automation!'); console.log('checking automation!'); console.log('checking automation!'); console.log('checking automation!'); // Error handling middleware app.use(errorHandler); // Start server const PORT = config.server.port; const server = app.listen(PORT, () => { logger.info(`Server is running on http://localhost:${PORT}`); // Initialize background tasks refreshExpiredTokens(); // repopulateQueueOnStartup(); }); // Graceful shutdown const gracefulShutdown = async () => { logger.info('Received shutdown signal'); // Close server server.close(() => { logger.info('HTTP server closed'); }); // Close database connections const db = require('./config/database'); await db.closePool(); // Close WebSocket connections const wss = require('./services/webSocket'); wss.close(() => { logger.info('WebSocket server closed'); }); process.exit(0); }; process.on('SIGTERM', gracefulShutdown); process.on('SIGINT', gracefulShutdown); // Handle uncaught exceptions process.on('uncaughtException', (error) => { logger.error('Uncaught Exception:', error); gracefulShutdown(); }); // Handle unhandled promise rejections process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); gracefulShutdown(); }); return server; } catch (error) { console.error('Failed to start server:', error); process.exit(1); } } startServer(); module.exports = app;