152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
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);
|
|
});
|