import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { createEdgeFunction, type EdgeFunctionContext } from '../_shared/edgeFunctionWrapper.ts'; import { corsHeaders } from '../_shared/cors.ts'; import { addSpanEvent } from '../_shared/logger.ts'; serve(createEdgeFunction({ name: 'novu-webhook', requireAuth: false, // Webhooks don't use standard auth useServiceRole: true, // Need service role to update notification_logs corsHeaders, }, async (req, { span, supabase, requestId }: EdgeFunctionContext) => { const event = await req.json(); addSpanEvent(span, 'received_webhook_event', { eventType: event.type }); // Handle different webhook events switch (event.type) { case 'notification.sent': await handleNotificationSent(supabase, event, span); break; case 'notification.delivered': await handleNotificationDelivered(supabase, event, span); break; case 'notification.read': await handleNotificationRead(supabase, event, span); break; case 'notification.failed': await handleNotificationFailed(supabase, event, span); break; default: addSpanEvent(span, 'unhandled_event_type', { eventType: event.type }); } return new Response( JSON.stringify({ success: true, requestId }), { headers: { 'Content-Type': 'application/json' }, status: 200, } ); })); async function handleNotificationSent(supabase: any, event: any, span: any) { const { transactionId, channel } = event.data; addSpanEvent(span, 'notification_sent_update', { transactionId, channel }); await supabase .from('notification_logs') .update({ status: 'sent' }) .eq('novu_transaction_id', transactionId); } async function handleNotificationDelivered(supabase: any, event: any, span: any) { const { transactionId } = event.data; addSpanEvent(span, 'notification_delivered_update', { transactionId }); await supabase .from('notification_logs') .update({ status: 'delivered', delivered_at: new Date().toISOString(), }) .eq('novu_transaction_id', transactionId); } async function handleNotificationRead(supabase: any, event: any, span: any) { const { transactionId } = event.data; addSpanEvent(span, 'notification_read_update', { transactionId }); await supabase .from('notification_logs') .update({ read_at: new Date().toISOString(), }) .eq('novu_transaction_id', transactionId); } async function handleNotificationFailed(supabase: any, event: any, span: any) { const { transactionId, error } = event.data; addSpanEvent(span, 'notification_failed_update', { transactionId, error }); await supabase .from('notification_logs') .update({ status: 'failed', error_message: error, }) .eq('novu_transaction_id', transactionId); }