const express = require('express'); const cors = require('cors'); const path = require('path'); const db = require('./db'); require('dotenv').config(); const app = express(); const PORT = process.env.PORT || 3000; app.use(cors()); app.use(express.json()); app.use(express.static(path.join(__dirname, 'public'))); // Store active Server-Sent Events (SSE) clients let sseClients = []; // SSE Registration Endpoint app.get('/api/sse', (req, res) => { res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); res.flushHeaders(); sseClients.push(res); console.log(`🔌 Client connected to SSE stream. Total clients: ${sseClients.length}`); req.on('close', () => { sseClients = sseClients.filter(client => client !== res); console.log(`🔌 Client disconnected. Total clients: ${sseClients.length}`); }); }); // Function to broadcast new request details to all connected SSE clients function broadcastNewRequest(request) { const data = JSON.stringify(request); sseClients.forEach(client => { client.write(`data: ${data}\n\n`); }); } // API: Get all requests (ordered by newest first) app.get('/api/requests', async (req, res) => { try { const rows = await db.query('SELECT * FROM requests ORDER BY created_at DESC'); res.json(rows); } catch (error) { console.error('Error fetching requests:', error); res.status(500).json({ error: 'Database query failed' }); } }); // API: Post new request (receives external data) app.post('/api/requests', async (req, res) => { const { title, description, external_id, status, payload, cedula } = req.body; const tipo_solicitud = req.body.tipo_solicitud || req.body['Tipo de solicitud'] || req.body.tipo_de_solicitud || null; if (!title) { return res.status(400).json({ error: 'Title is required' }); } try { const queryText = ` INSERT INTO requests (title, description, external_id, status, cedula, tipo_solicitud, payload) VALUES (?, ?, ?, ?, ?, ?, ?) `; const parsedPayload = payload ? (typeof payload === 'object' ? payload : { raw: payload }) : {}; const values = [ title, description || '', external_id || null, status || 'Pending', cedula || null, tipo_solicitud, JSON.stringify(parsedPayload) ]; const result = await db.query(queryText, values); const insertId = result.insertId; // Fetch the newly inserted record to broadcast const rows = await db.query('SELECT * FROM requests WHERE id = ?', [insertId]); const newRequest = rows[0]; // Broadcast the new request to UI clients in real time broadcastNewRequest(newRequest); res.status(201).json(newRequest); } catch (error) { console.error('Error saving new request:', error); res.status(500).json({ error: 'Database insertion failed' }); } }); // API: Update request (save status, handling time, and optionally payload) app.put('/api/requests/:id', async (req, res) => { const { id } = req.params; const { status, handling_time, payload } = req.body; try { if (payload !== undefined) { const parsedPayload = typeof payload === 'object' ? payload : { raw: payload }; await db.query( 'UPDATE requests SET status = ?, handling_time = ?, payload = ? WHERE id = ?', [status || 'Pending', handling_time || 0, JSON.stringify(parsedPayload), id] ); } else { await db.query( 'UPDATE requests SET status = ?, handling_time = ? WHERE id = ?', [status || 'Pending', handling_time || 0, id] ); } const rows = await db.query('SELECT * FROM requests WHERE id = ?', [id]); if (rows.length === 0) { return res.status(404).json({ error: 'Request not found' }); } res.json(rows[0]); } catch (error) { console.error('Error updating request:', error); res.status(500).json({ error: 'Database update failed' }); } }); // API: Delete request app.delete('/api/requests/:id', async (req, res) => { const { id } = req.params; try { await db.query('DELETE FROM requests WHERE id = ?', [id]); res.json({ success: true, message: 'Request deleted successfully' }); } catch (error) { console.error('Error deleting request:', error); res.status(500).json({ error: 'Database deletion failed' }); } }); // Start server after ensuring DB connection and schema setup async function startServer() { await db.initializeSchema(); app.listen(PORT, () => { console.log(`🚀 Claro Cases server running at http://localhost:${PORT}`); }); } startServer().catch(err => { console.error('💥 Server startup failed:', err); });