import express from 'express'; import cors from 'cors'; import helmet from 'helmet'; import { config } from './src/config/index.js'; import logger from './src/utils/logger.js'; import routes from './src/routes/index.js'; import { CronService } from './src/services/CronService.js'; import { ViteService } from './src/services/ViteService.js'; import fs from 'fs'; import path from 'path'; import { CloudflareService } from './src/services/CloudflareService.js'; const app = express(); // Middleware app.use(helmet()); app.use(cors({ origin: config.cors.origin, credentials: true })); app.use(express.json({ limit: '10mb' })); app.use(express.urlencoded({ extended: true, limit: '10mb' })); // Request logging app.use((req, res, next) => { if (req.path.startsWith('/api')) { logger.info(`${req.method} ${req.path}`, { ip: req.ip, userAgent: req.get('User-Agent') }); } next(); }); // Routes app.use(routes); // Error handling middleware app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { logger.error('Unhandled error:', { error: err.message, stack: err.stack, path: req.path, method: req.method, body: req.body }); res.status(500).json({ success: false, message: config.server.env === 'production' ? 'Internal server error' : err.message }); }); // Initialize application async function initializeApp() { try { // Ensure required directories exist const directories = [ 'logs', 'data', 'certs', 'nginx' ]; directories.forEach(dir => { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); logger.info(`Created directory: ${dir}`); } }); // Initialize cron service CronService.init(); // Initialize Cloudflare service const cloudflare = CloudflareService.getInstance() cloudflare.init({ apiToken: config.cloudflare.apiToken, active: config.cloudflare.active }); // Setup Vite middleware for frontend const isProduction = config.server.env === 'production'; await ViteService.setupMiddleware(app, isProduction, '/'); // 404 handler - must be after Vite middleware setup app.use('*', (req, res) => { res.status(404).json({ success: false, message: 'Route not found' }); }); // Start server app.listen(config.server.port, () => { logger.info(`🚀 NGINX Proxy Manager API started on port ${config.server.port}`); logger.info(`📝 Environment: ${config.server.env}`); logger.info(`🔒 JWT Secret: ${config.jwt.secret.substring(0, 10)}...`); logger.info(`🗄️ Database: ${config.database.path}`); logger.info(`⚡ Health check: http://localhost:${config.server.port}/api/health`); }); } catch (error) { logger.error('Failed to initialize application:', error); process.exit(1); } } // Graceful shutdown process.on('SIGTERM', () => { logger.info('SIGTERM received. Shutting down gracefully...'); CronService.stop(); ViteService.stop(); process.exit(0); }); process.on('SIGINT', () => { logger.info('SIGINT received. Shutting down gracefully...'); CronService.stop(); ViteService.stop(); process.exit(0); }); // Handle uncaught exceptions process.on('uncaughtException', (error) => { logger.error('Uncaught Exception:', error); process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled Rejection at:', promise, 'reason:', reason); process.exit(1); }); // Initialize the application initializeApp();