UNPKG

@owlrelay/webhook

Version:

OwlRelay Webhook utilities

72 lines (67 loc) 2.31 kB
import { fetch } from 'ofetch'; function arrayBufferToBase64(arrayBuffer) { return btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))); } function base64ToArrayBuffer(base64) { return new Uint8Array(atob(base64).split("").map((char) => char.charCodeAt(0))).buffer; } async function signBody({ bodyBuffer, secret }) { const encoder = new TextEncoder(); const keyData = encoder.encode(secret); const key = await crypto.subtle.importKey("raw", keyData, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]); const signature = await crypto.subtle.sign("HMAC", key, bodyBuffer); const signatureBase64 = arrayBufferToBase64(signature); return { signature: signatureBase64 }; } async function verifySignature({ bodyBuffer, signature: base64Signature, secret }) { const encoder = new TextEncoder(); const keyData = encoder.encode(secret); const key = await crypto.subtle.importKey("raw", keyData, { name: "HMAC", hash: "SHA-256" }, false, ["verify"]); const signatureBuffer = base64ToArrayBuffer(base64Signature); return crypto.subtle.verify("HMAC", key, signatureBuffer, bodyBuffer); } function serializeEmailForWebhook({ email }) { const body = new FormData(); const { attachments = [], ...rest } = email; body.append("email", JSON.stringify(rest)); for (const attachment of attachments ?? []) { body.append("attachments[]", new File([attachment.content], attachment.filename ?? "file", { type: attachment.mimeType })); } return { body }; } async function triggerWebhook({ email, webhookUrl, webhookSecret, httpClient = fetch }) { const { body } = serializeEmailForWebhook({ email }); const bodyResponse = new Response(body); const headers = Object.fromEntries(bodyResponse.headers.entries()); const bodyBuffer = await bodyResponse.arrayBuffer(); if (webhookSecret) { const { signature } = await signBody({ bodyBuffer, secret: webhookSecret }); headers["X-Signature"] = signature; } const response = await httpClient( webhookUrl, { method: "POST", body: bodyBuffer, headers: { "User-Agent": "owlrelay-webhook-client", ...headers } } ); return response; } export { serializeEmailForWebhook, signBody, triggerWebhook, verifySignature }; //# sourceMappingURL=index.mjs.map