const express = require('express'); const cors = require('cors'); const helmet = require('helmet'); const morgan = require('morgan'); const prisma = require('./lib/prisma'); const { globalErrorHandler } = require('./middleware/errorHandler'); const experimentsRouter = require('./routes/experiments'); const animalsRouter = require('./routes/animals'); const dailyStatusesRouter = require('./routes/dailyStatuses'); const auditLogsRouter = require('./routes/auditLogs'); const app = express(); const PORT = process.env.PORT || 3001; // Security & utility middleware app.use(helmet()); app.use(cors({ origin: process.env.CORS_ORIGIN || '*', methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'], })); app.use(express.json({ limit: '1mb' })); app.use(morgan(process.env.NODE_ENV === 'production' ? 'combined' : 'dev')); // Health check app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); // API routes app.use('/api/experiments', experimentsRouter); app.use('/api/animals', animalsRouter); app.use('/api/daily-statuses', dailyStatusesRouter); app.use('/api/audit-logs', auditLogsRouter); // 404 handler for unknown routes app.use((req, res) => { res.status(404).json({ error: `Route ${req.method} ${req.path} not found` }); }); // Global error handler (must be last) app.use(globalErrorHandler); async function startServer() { try { await prisma.$connect(); console.log('Database connected successfully'); // Run migrations on startup in production if (process.env.NODE_ENV === 'production') { const { execSync } = require('child_process'); execSync('npx prisma migrate deploy', { stdio: 'inherit' }); } app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on port ${PORT}`); }); } catch (err) { console.error('Failed to start server:', err); process.exit(1); } } startServer(); module.exports = app; // export for testing