feat: add multi-dashboard routing support for n8n
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m36s
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m36s
- Refactor `sendToN8n` service to accept dynamic webhook URLs. - Update `order-status` controller to fan-out payload to both STATUS and GRAPHS webhooks. - Add new endpoints and controllers for stock and graphs updates (`/stock-update`, `/graphs-update`). - Maintain backward compatibility with existing `N8N_WEBHOOK_URL` environment variable.
This commit is contained in:
@@ -110,9 +110,84 @@ export const handleTinyOrderUpdate = async (req: Request, res: Response): Promis
|
|||||||
};
|
};
|
||||||
|
|
||||||
console.log('Forwarding formatted payload to n8n...');
|
console.log('Forwarding formatted payload to n8n...');
|
||||||
await sendToN8n(finalPayload);
|
|
||||||
|
// 1. Send to the Status Dashboard
|
||||||
|
const statusUrl = process.env.N8N_WEBHOOK_STATUS || process.env.N8N_WEBHOOK_URL;
|
||||||
|
if (statusUrl) {
|
||||||
|
console.log('-> Sending to Status Workflow...');
|
||||||
|
// We don't await here so they send in parallel, or we can await them one by one.
|
||||||
|
// Awaiting sequentially is safer for error handling.
|
||||||
|
await sendToN8n(finalPayload, statusUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Send a copy to the Graphs Dashboard (it will just use the data it needs, like values and dates)
|
||||||
|
const graphsUrl = process.env.N8N_WEBHOOK_GRAPHS;
|
||||||
|
if (graphsUrl) {
|
||||||
|
console.log('-> Sending copy to Graphs Workflow...');
|
||||||
|
await sendToN8n(finalPayload, graphsUrl);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error handling Tiny webhook:', error);
|
console.error('Error handling Tiny webhook:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const handleTinyStockUpdate = async (req: Request, res: Response): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const expectedToken = process.env.TINY_WEBHOOK_SECRET;
|
||||||
|
const providedToken = req.query.token;
|
||||||
|
|
||||||
|
if (expectedToken && providedToken !== expectedToken) {
|
||||||
|
console.warn('Unauthorized webhook attempt on stock. Invalid or missing token.');
|
||||||
|
res.status(401).json({ error: 'Unauthorized' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.status(200).send('OK');
|
||||||
|
|
||||||
|
const targetUrl = process.env.N8N_WEBHOOK_STOCK;
|
||||||
|
if (!targetUrl) {
|
||||||
|
console.warn('N8N_WEBHOOK_STOCK is not defined in environment variables. Skipping forward.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Received stock webhook from Tiny. Forwarding to n8n...');
|
||||||
|
let payload = req.body || {};
|
||||||
|
if (payload && typeof payload.dados === 'string') {
|
||||||
|
try { payload.dados = JSON.parse(payload.dados); } catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendToN8n(payload, targetUrl);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error handling Tiny stock webhook:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const handleTinyGraphsUpdate = async (req: Request, res: Response): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const expectedToken = process.env.TINY_WEBHOOK_SECRET;
|
||||||
|
const providedToken = req.query.token;
|
||||||
|
|
||||||
|
if (expectedToken && providedToken !== expectedToken) {
|
||||||
|
console.warn('Unauthorized webhook attempt on graphs. Invalid or missing token.');
|
||||||
|
res.status(401).json({ error: 'Unauthorized' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
res.status(200).send('OK');
|
||||||
|
|
||||||
|
const targetUrl = process.env.N8N_WEBHOOK_GRAPHS;
|
||||||
|
if (!targetUrl) {
|
||||||
|
console.warn('N8N_WEBHOOK_GRAPHS is not defined in environment variables. Skipping forward.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Received graphs webhook from Tiny. Forwarding to n8n...');
|
||||||
|
let payload = req.body || {};
|
||||||
|
if (payload && typeof payload.dados === 'string') {
|
||||||
|
try { payload.dados = JSON.parse(payload.dados); } catch (e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
await sendToN8n(payload, targetUrl);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error handling Tiny graphs webhook:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { Router } from 'express';
|
import { Router } from 'express';
|
||||||
import { handleTinyOrderUpdate } from '../controllers/webhook.controller';
|
import { handleTinyOrderUpdate, handleTinyStockUpdate, handleTinyGraphsUpdate } from '../controllers/webhook.controller';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.post('/tiny/order-status', handleTinyOrderUpdate);
|
router.post('/tiny/order-status', handleTinyOrderUpdate);
|
||||||
|
router.post('/tiny/stock-update', handleTinyStockUpdate);
|
||||||
|
router.post('/tiny/graphs-update', handleTinyGraphsUpdate);
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
export const sendToN8n = async (data: any): Promise<void> => {
|
export const sendToN8n = async (data: any, targetWebhookUrl?: string): Promise<void> => {
|
||||||
const n8nWebhookUrl = process.env.N8N_WEBHOOK_URL;
|
const n8nWebhookUrl = targetWebhookUrl || process.env.N8N_WEBHOOK_URL;
|
||||||
const n8nAuthToken = process.env.N8N_AUTH_TOKEN;
|
const n8nAuthToken = process.env.N8N_AUTH_TOKEN;
|
||||||
|
|
||||||
if (!n8nWebhookUrl) {
|
if (!n8nWebhookUrl) {
|
||||||
|
|||||||
Reference in New Issue
Block a user