70 lines
1.7 KiB
JavaScript
70 lines
1.7 KiB
JavaScript
/**
|
|
* @fileoverview REST Hook subscribe/unsubscribe and HTTP delivery.
|
|
* @module services/webhookService
|
|
*/
|
|
|
|
import { createWebhook, deleteWebhook } from '../store/webhooks.js';
|
|
import { createDebugger } from '../debug/logger.js';
|
|
|
|
const log = createDebugger('webhooks');
|
|
|
|
const ALLOWED_EVENTS = new Set(['timestamp.completed', 'timestamp.failed']);
|
|
|
|
/**
|
|
* @param {object} ctx - auth context
|
|
* @param {{ targetUrl: string, event: string }} params
|
|
*/
|
|
export function subscribe(ctx, { targetUrl, event }) {
|
|
if (!targetUrl) {
|
|
throw new Error('targetUrl is required');
|
|
}
|
|
if (!ALLOWED_EVENTS.has(event)) {
|
|
throw new Error(`Unsupported event: ${event}`);
|
|
}
|
|
|
|
return createWebhook({
|
|
tenantId: ctx.tenantId,
|
|
targetUrl,
|
|
event,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {object} ctx
|
|
* @param {{ hookId?: string, targetUrl?: string }} params
|
|
*/
|
|
export function unsubscribe(ctx, { hookId, targetUrl }) {
|
|
const removed = deleteWebhook({
|
|
tenantId: ctx.tenantId,
|
|
hookId,
|
|
targetUrl,
|
|
});
|
|
|
|
if (!removed) {
|
|
throw new Error('Webhook subscription not found');
|
|
}
|
|
|
|
return { removed: true };
|
|
}
|
|
|
|
/**
|
|
* POST payload to Zapier target URL.
|
|
* @param {string} targetUrl
|
|
* @param {object} payload
|
|
* @returns {Promise<{ ok: boolean, status: number }>}
|
|
*/
|
|
export async function deliverWebhook(targetUrl, payload) {
|
|
log.debug('deliverWebhook', { targetUrl, event: payload?.event });
|
|
|
|
const response = await fetch(targetUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'User-Agent': 'Verae-Zapier-Middleware/1.0',
|
|
},
|
|
body: JSON.stringify(payload),
|
|
});
|
|
|
|
log.debug('deliverWebhook result', { status: response.status, ok: response.ok });
|
|
return { ok: response.ok, status: response.status };
|
|
}
|