const express = require('express'); const http = require('http'); const cors = require('cors'); const helmet = require('helmet'); const rateLimit = require('express-rate-limit'); require('dotenv').config(); const authRoutes = require('./routes/authRoutes'); const domainRoutes = require('./routes/domainRoutes'); const messagingRoutes = require('./routes/messagingRoutes'); const messagesRoutes = require('./routes/messagesRoutes'); const channelsRoutes = require('./routes/channelsRoutes'); const voiceRoutes = require('./routes/voiceRoutes'); const gameforgeRoutes = require('./routes/gameforgeRoutes'); const callRoutes = require('./routes/callRoutes'); const messageApiRoutes = require('./routes/messageApiRoutes'); const channelApiRoutes = require('./routes/channelApiRoutes'); const realtimeMessagesRoutes = require('./routes/realtimeMessagesRoutes'); const voiceCallRoutes = require('./routes/voiceCallRoutes'); const liveKitRoutes = require('./routes/liveKitRoutes'); const chatRoutes = require('./routes/chatRoutes'); const serverRoutes = require('./routes/serverRoutes'); const socketService = require('./services/socketService'); const path = require('path'); const app = express(); const httpServer = http.createServer(app); const PORT = process.env.PORT || 3000; // Trust proxy for Codespaces/containers app.set('trust proxy', 1); // Security middleware app.use(helmet()); app.use(cors({ origin: function(origin, callback) { const allowed = [ 'https://atx-connect.up.railway.app', process.env.FRONTEND_URL ]; // Allow localhost on any port in dev if (!origin || origin.includes('localhost') || origin.includes('127.0.0.1')) { return callback(null, true); } if (allowed.includes(origin)) { return callback(null, true); } callback(new Error('CORS not allowed')); }, credentials: true })); // Rate limiting 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.', standardHeaders: true, legacyHeaders: false, }); app.use('/api/', limiter); // Body parsing middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); // Serve React frontend build const frontendPath = path.join(__dirname, '../frontend/dist'); app.use(express.static(frontendPath)); // API routes app.use('/api/auth', authRoutes); app.use('/api/passport/domain', domainRoutes); app.use('/api/messaging', messagingRoutes); app.use('/api/messages', messagesRoutes); app.use('/api/channels', channelsRoutes); app.use('/api/gameforge', gameforgeRoutes); app.use('/api/calls', callRoutes); app.use('/api/message', messageApiRoutes); app.use('/api/channel', channelApiRoutes); app.use('/api/realtime/messages', realtimeMessagesRoutes); app.use('/api/voice', voiceCallRoutes); app.use('/api/livekit', liveKitRoutes); app.use('/api/chat', chatRoutes); app.use('/api/servers', serverRoutes); // Initialize Socket.io const io = socketService.initialize(httpServer); app.set('io', io); // Make io available in routes // SPA fallback - serve index.html for all non-API routes (React Router) app.get('*', (req, res) => { // Don't serve index.html for API routes if (req.path.startsWith('/api/')) { return res.status(404).json({ success: false, error: 'Endpoint not found' }); } res.sendFile(path.join(__dirname, '../frontend/dist/index.html')); }); // Error handler app.use((err, req, res, next) => { console.error('Server error:', err); res.status(500).json({ success: false, error: process.env.NODE_ENV === 'development' ? err.message : 'Internal server error' }); }); // Start server - bind to 0.0.0.0 for Railway/containers httpServer.listen(PORT, '0.0.0.0', () => { console.log(` ╔═══════════════════════════════════════════════════════╗ ║ AeThex Connect - Communication Platform ║ ║ Server running on port ${PORT} ║ ║ Environment: ${process.env.NODE_ENV || 'development'} ║ ╚═══════════════════════════════════════════════════════╝ `); console.log(`Health check: http://localhost:${PORT}/health`); console.log(`API Base URL: http://localhost:${PORT}/api`); console.log(`Socket.io: Enabled`); }); // Graceful shutdown process.on('SIGTERM', () => { console.log('SIGTERM received, shutting down gracefully...'); process.exit(0); }); process.on('SIGINT', () => { console.log('SIGINT received, shutting down gracefully...'); process.exit(0); }); module.exports = app;