const express = require('express'); const cors = require('cors'); const bodyParser = require('body-parser'); const { Pool } = require('pg'); require('dotenv').config(); const app = express(); const PORT = process.env.PORT || 3004; const API_KEY = process.env.API_KEY || "nexstar_secret_key_123"; app.use(cors()); app.use(bodyParser.json()); // PostgreSQL Connection Pool const pool = new Pool({ connectionString: process.env.DATABASE_URL || 'postgres://graphuser:graphpassword@localhost:5432/graphdb', }); // Initialize Database Table const initDB = async () => { try { await pool.query(` CREATE TABLE IF NOT EXISTS orders ( id SERIAL PRIMARY KEY, cliente_nome VARCHAR(255), data_pedido VARCHAR(50), valor_pedido NUMERIC(10, 2), produto_id VARCHAR(100), produto_descricao TEXT, quantidade INTEGER, valor_unitario NUMERIC(10, 5), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); `); console.log("Database initialized successfully."); } catch (err) { console.error("Failed to initialize database:", err); } }; initDB(); // Middleware for Security const authenticate = (req, res, next) => { const apiKey = req.headers['x-api-key']; if (apiKey === API_KEY) { next(); } else { res.status(401).json({ error: 'Unauthorized: Invalid API Key' }); } }; // Helper to format rows to match the old JSON structure for the frontend const formatRow = (row) => ({ Nome_Cliente: row.cliente_nome, Data_Pedido: row.data_pedido, Valor_Pedido: parseFloat(row.valor_pedido), ID_Produto: row.produto_id, Descricao_Produto: row.produto_descricao, Quantidade: row.quantidade, Valor_Unitario: parseFloat(row.valor_unitario) }); // GET data (for the frontend) app.get('/api/data', async (req, res) => { try { const result = await pool.query('SELECT * FROM orders ORDER BY id ASC'); const formattedData = result.rows.map(formatRow); res.json(formattedData); } catch (error) { console.error("Error fetching data:", error); res.status(500).json({ error: 'Internal Server Error' }); } }); // POST data (for n8n) app.post('/api/data', async (req, res) => { // Respond IMMEDIATELY to prevent slowing down n8n / WhatsApp flows res.status(201).json({ message: 'Data received, processing in background' }); const newData = req.body; const payload = Array.isArray(newData) ? newData : [newData]; // Process asynchronously (async () => { const client = await pool.connect(); try { await client.query('BEGIN'); const insertQuery = ` INSERT INTO orders ( cliente_nome, data_pedido, valor_pedido, produto_id, produto_descricao, quantidade, valor_unitario ) VALUES ($1, $2, $3, $4, $5, $6, $7) `; for (const item of payload) { // Handle potential missing fields gracefully const values = [ item.Nome_Cliente || 'Unknown', item.Data_Pedido || '', item.Valor_Pedido || 0, item.ID_Produto || '', item.Descricao_Produto || '', item.Quantidade || 0, item.Valor_Unitario || 0 ]; await client.query(insertQuery, values); } await client.query('COMMIT'); } catch (error) { await client.query('ROLLBACK'); console.error("Database insert error:", error); } finally { client.release(); } })(); }); app.listen(PORT, '0.0.0.0', () => { console.log(\`Nexstar Backend running at http://localhost:\${PORT}\`); console.log(\`Endpoint for n8n: POST http://localhost:\${PORT}/api/data\`); });