Files
drone-detector/server/index.js
2025-08-18 05:42:33 +02:00

143 lines
4.5 KiB
JavaScript

const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
const compression = require('compression');
const rateLimit = require('express-rate-limit');
const { createServer } = require('http');
const { Server } = require('socket.io');
require('dotenv').config();
const { sequelize } = require('./models');
const routes = require('./routes');
const { initializeSocketHandlers } = require('./services/socketService');
const AlertService = require('./services/alertService');
const seedDatabase = require('./seedDatabase');
const errorHandler = require('./middleware/errorHandler');
const app = express();
const server = createServer(app);
const io = new Server(server, {
cors: {
origin: process.env.CORS_ORIGIN || "http://localhost:3000",
methods: ["GET", "POST", "PUT", "DELETE"]
}
});
// Rate limiting (exclude detections endpoint for testing)
const limiter = rateLimit({
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS) || 15 * 60 * 1000, // 15 minutes
max: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS) || 100,
message: 'Too many requests from this IP, please try again later.',
skip: (req) => {
// Skip rate limiting for drone detection endpoints during testing
return req.path.includes('/detections');
}
});
// Middleware
app.use(helmet());
app.use(compression());
app.use(morgan('combined'));
app.use(cors({
origin: process.env.CORS_ORIGIN || "http://localhost:3000",
credentials: true
}));
app.use(express.json({ limit: '10mb' }));
app.use(express.urlencoded({ extended: true }));
app.use('/api/', limiter);
// Make io available to routes
app.use((req, res, next) => {
req.io = io;
next();
});
// Routes
app.use('/api', routes);
// Health check endpoints
app.get('/health', (req, res) => {
res.status(200).json({
status: 'OK',
timestamp: new Date().toISOString(),
environment: process.env.NODE_ENV
});
});
app.use('/api/health', require('./routes/health'));
// Error handling
app.use(errorHandler);
// Socket.IO initialization
initializeSocketHandlers(io);
const PORT = process.env.PORT || 3001;
// Database connection and server startup
async function startServer() {
try {
await sequelize.authenticate();
console.log('Database connected successfully.');
// Always sync database in containerized environments or development
// Check if tables exist before syncing
try {
await sequelize.sync({ force: false, alter: false });
console.log('Database synchronized.');
// Seed database with initial data
await seedDatabase();
} catch (syncError) {
console.error('Database sync error:', syncError);
// If sync fails, try force sync (this will drop and recreate tables)
console.log('Attempting force sync...');
await sequelize.sync({ force: true });
console.log('Database force synchronized.');
// Seed database with initial data
await seedDatabase();
}
server.listen(PORT, () => {
console.log('\n🚀 Drone Detection System Started Successfully!');
console.log('================================================');
console.log(`📊 Environment: ${process.env.NODE_ENV || 'development'}`);
console.log(`🌐 Server Port: ${PORT}`);
console.log(`💾 Database: ${process.env.DB_HOST}:${process.env.DB_PORT}`);
console.log(`🔴 Redis: ${process.env.REDIS_HOST || 'localhost'}:${process.env.REDIS_PORT || 6379}`);
// Initialize AlertService to check SMS status
const alertService = new AlertService();
if (alertService.twilioEnabled) {
console.log('📱 SMS Alerts: ✅ Enabled');
} else {
console.log('📱 SMS Alerts: ⚠️ Disabled (no Twilio credentials)');
}
// Start periodic clear alert checking (every 2 minutes)
setInterval(async () => {
try {
await alertService.checkClearedAlerts();
} catch (error) {
console.error('Error checking cleared alerts:', error);
}
}, 2 * 60 * 1000); // Check every 2 minutes
console.log('🔄 Clear alert monitoring: ✅ Started');
console.log(`📊 Health check: http://localhost:${PORT}/health`);
console.log(`🌐 API endpoint: http://localhost:${PORT}/api`);
console.log('================================================\n');
});
} catch (error) {
console.error('Unable to start server:', error);
process.exit(1);
}
}
startServer();
module.exports = { app, server, io };