import { env } from "cloudflare:workers";
import { publicUrl } from "./events/emit";
import type { QueueMessage } from "./events/emit";
export type EmailQueueMessage = Extract<QueueMessage, { kind: "email.send" }>;
type EmailContent = { subject: string; text: string; html: string };
const HTML_ESCAPES: Record<string, string> = { "&": "&", "<": "<", ">": ">", '"': """, "'": "'" };
function escapeHtml(value: string): string {
return value.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char);
}
function forgeName(): string {
return env.FORGE_NAME || "gitfor";
}
function layout(heading: string, paragraphs: string[], action: { label: string; url: string } | null): string {
const body = paragraphs.map((text) => `<p style="margin:0 0 12px;color:#d4d4d8">${escapeHtml(text)}</p>`).join("");
const button = action
? `<p style="margin:20px 0"><a href="${escapeHtml(action.url)}" style="background:#f97316;color:#09090b;padding:10px 16px;border-radius:6px;text-decoration:none;font-weight:600">${escapeHtml(action.label)}</a></p>
<p style="margin:0;color:#71717a;font-size:12px">${escapeHtml(action.url)}</p>`
: "";
return `<!doctype html><html><body style="margin:0;background:#09090b;font-family:'IBM Plex Sans',system-ui,sans-serif">
<div style="max-width:560px;margin:0 auto;padding:32px 24px">
<div style="color:#fb923c;font-size:11px;letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px">${escapeHtml(forgeName())}</div>
<h1 style="color:#fafafa;font-size:20px;margin:0 0 16px">${escapeHtml(heading)}</h1>${body}${button}
</div></body></html>`;
}
function render(subject: string, paragraphs: string[], action: { label: string; url: string } | null): EmailContent {
const text = [...paragraphs, ...(action ? [`${action.label}: ${action.url}`] : [])].join("\n\n");
return { subject: `[${forgeName()}] ${subject}`, text, html: layout(subject, paragraphs, action) };
}
export const emailTemplates = {
verifyEmail(name: string, url: string): EmailContent {
return render(
"Verify your email address",
[`Hi ${name}, confirm this address to finish setting up your account.`, "The link expires in 24 hours."],