const express = require('express'); const { MongoClient } = require('mongodb'); const cors = require('cors'); const path = require('path'); const app = express(); const PORT = process.env.PORT || 3001; // Middleware app.use(cors()); app.use(express.json()); // Serve static files from React build app.use(express.static(path.join(__dirname, '..', 'dist'))); // MongoDB connection - using host.docker.internal for Docker networking const mongoHost = process.env.MONGO_HOST || 'host.docker.internal'; const uri = `mongodb://admin:MongoPass2024!@${mongoHost}:27017/?authSource=admin`; const client = new MongoClient(uri); let db; let amigosCollection; // Array para almacenar las conexiones SSE let sseClients = []; // Connect to MongoDB async function connectDB() { try { await client.connect(); console.log('Connected to MongoDB'); db = client.db('testdb'); amigosCollection = db.collection('amigos'); } catch (error) { console.error('Error connecting to MongoDB:', error); // Retry connection after 5 seconds setTimeout(connectDB, 5000); } } // API Routes // Get all amigos app.get('/api/amigos', async (req, res) => { try { if (!amigosCollection) { return res.status(503).json({ error: 'Database not connected' }); } const amigos = await amigosCollection.find({}).toArray(); res.json(amigos); } catch (error) { res.status(500).json({ error: error.message }); } }); // SSE endpoint para cambios en tiempo real app.get('/api/stream', (req, res) => { // Configurar headers para SSE res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'Cache-Control' }); // Agregar cliente a la lista sseClients.push(res); // Manejar desconexión del cliente req.on('close', () => { sseClients = sseClients.filter(client => client !== res); }); // Enviar ping inicial res.write(`data: ${JSON.stringify({ type: 'connected', message: 'SSE connected' })}\n\n`); }); // Función para notificar a todos los clientes SSE function notifyClients(data) { sseClients.forEach(client => { try { client.write(`data: ${JSON.stringify(data)}\n\n`); } catch (error) { console.error('Error sending SSE data:', error); } }); } // Add new amigo app.post('/api/amigos', async (req, res) => { try { if (!amigosCollection) { return res.status(503).json({ error: 'Database not connected' }); } const { nombre } = req.body; if (!nombre) { return res.status(400).json({ error: 'Nombre es requerido' }); } const result = await amigosCollection.insertOne({ nombre }); const newAmigo = { _id: result.insertedId, nombre }; // Notificar a todos los clientes SSE notifyClients({ type: 'amigo_added', amigo: newAmigo }); res.status(201).json({ message: 'Amigo agregado exitosamente', id: result.insertedId, nombre }); } catch (error) { res.status(500).json({ error: error.message }); } }); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'ok', mongodb: amigosCollection ? 'connected' : 'disconnected' }); }); // Serve React app for all other routes app.use((req, res) => { res.sendFile(path.join(__dirname, '..', 'dist', 'index.html')); }); // Start server connectDB().then(() => { app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on http://0.0.0.0:${PORT}`); console.log(`MongoDB host: ${mongoHost}`); }); });