134 lines
No EOL
3.6 KiB
TypeScript
134 lines
No EOL
3.6 KiB
TypeScript
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(); |