import type { Prisma } from '@prisma/client'; import { fetchWithTimeout } from '../../utils/timeout'; import { assertNotPrivateUrl } from './assert-webhook-url'; const WEBHOOK_TIMEOUT_MS = 10_000; export type WebhookCallResult = { success: boolean; responseCode: number; responseBody: Prisma.InputJsonValue | Prisma.JsonNullValueInput; responseHeaders: Record; }; const parseBody = (text: string): Prisma.InputJsonValue => { try { return JSON.parse(text); } catch { return text; } }; export const executeWebhookCall = async (options: { url: string; body: unknown; secret: string | null; }): Promise => { const { url, body, secret } = options; try { await assertNotPrivateUrl(url); const response = await fetchWithTimeout(url, { method: 'POST', body: JSON.stringify(body), redirect: 'manual', timeoutMs: WEBHOOK_TIMEOUT_MS, headers: { 'Content-Type': 'application/json', 'X-Documenso-Secret': secret ?? '', }, }); const text = await response.text(); return { success: response.ok, responseCode: response.status, responseBody: parseBody(text), responseHeaders: Object.fromEntries(response.headers.entries()), }; } catch (err) { return { success: false, responseCode: 0, responseBody: err instanceof Error ? err.message : 'Unknown error', responseHeaders: {}, }; } };