'use server' import type { SendTestWebhookResult } from './types' import { recordWebhookDelivery } from '@admin/actions/webhooks/record-webhook-delivery' import { requireRole, UserRole } from '@admin/auth/middleware' import db from '@admin/db' import { webhooks } from '@admin/db/schema' import { toActionError } from '@admin/utils/error/to-action-error' import { createWebhookEventId } from '@admin/utils/webhook/create-webhook-event-id' import { signWebhookPayload } from '@admin/utils/webhook/sign-webhook-payload' import { eq } from 'drizzle-orm' const TEST_REQUEST_TIMEOUT_MS = 10_000 export async function sendTestWebhook(id: string): Promise { await requireRole([UserRole.ADMIN]) try { const [endpoint] = await db .select({ id: webhooks.id, url: webhooks.url, secret: webhooks.secret }) .from(webhooks) .where(eq(webhooks.id, id)) .limit(1) if (!endpoint) return { success: false, error: 'Webhook not found' } const eventId = createWebhookEventId() const body = JSON.stringify({ id: eventId, event: 'webhook.test', timestamp: new Date().toISOString(), data: { message: 'This is a test webhook from BetterStart' } }) const timestamp = Math.floor(Date.now() / 1000).toString() const startedAt = Date.now() let statusCode: number | null = null let errorMessage: string | null = null try { const response = await fetch(endpoint.url, { method: 'POST', headers: { 'content-type': 'application/json', 'x-webhook-id': eventId, 'x-webhook-timestamp': timestamp, 'x-webhook-signature': signWebhookPayload(endpoint.secret, timestamp, body) }, body, signal: AbortSignal.timeout(TEST_REQUEST_TIMEOUT_MS) }) statusCode = response.status if (!response.ok) errorMessage = `Webhook returned status ${response.status}` } catch (error) { errorMessage = error instanceof Error ? error.message : 'Webhook request failed' } await recordWebhookDelivery({ webhookId: endpoint.id, event: 'webhook.test', eventId, attempt: 1, success: errorMessage === null, statusCode, durationMs: Date.now() - startedAt, error: errorMessage }) if (errorMessage !== null) { return { success: false, ...(statusCode !== null ? { statusCode } : {}), error: errorMessage } } return { success: true, ...(statusCode !== null ? { statusCode } : {}) } } catch (error) { console.error('Error sending test webhook:', error) return { success: false, error: toActionError(error, 'Failed to send test webhook') } } }