/** * Email queue types and dispatcher. * * All email sends are modelled as a discriminated union so the Cloudflare Queue * consumer can pattern-match on `msg.type` and call the right send*Email(). * * The `Queue` type used in context.ts / server.ts refers to the * CF runtime binding type (`import type { Queue } from "@cloudflare/workers-types"`). */ import { sendCancellationEmail, sendConfirmationEmail, sendPaymentConfirmationEmail, sendPaymentReminderEmail, sendReminder24hEmail, sendReminderEmail, sendSubscriptionConfirmationEmail, sendUpdateEmail, } from "./email"; import { sendDeductionEmail } from "./lib/drinkkaart-email"; // --------------------------------------------------------------------------- // Message types — one variant per send*Email function // --------------------------------------------------------------------------- export type ConfirmationMessage = { type: "registrationConfirmation"; to: string; firstName: string; managementToken: string; wantsToPerform: boolean; artForm?: string | null; giftAmount?: number; drinkCardValue?: number; signupUrl?: string; }; export type UpdateMessage = { type: "updateConfirmation"; to: string; firstName: string; managementToken: string; wantsToPerform: boolean; artForm?: string | null; giftAmount?: number; drinkCardValue?: number; }; export type CancellationMessage = { type: "cancellation"; to: string; firstName: string; }; export type SubscriptionConfirmationMessage = { type: "subscriptionConfirmation"; to: string; }; export type Reminder24hMessage = { type: "reminder24h"; to: string; firstName?: string | null; }; export type Reminder1hMessage = { type: "reminder1h"; to: string; firstName?: string | null; }; export type PaymentReminderMessage = { type: "paymentReminder"; to: string; firstName: string; managementToken: string; drinkCardValue?: number; giftAmount?: number; }; export type PaymentConfirmationMessage = { type: "paymentConfirmation"; to: string; firstName: string; managementToken: string; drinkCardValue?: number; giftAmount?: number; }; export type DeductionMessage = { type: "deduction"; to: string; firstName: string; amountCents: number; newBalanceCents: number; }; export type EmailMessage = | ConfirmationMessage | UpdateMessage | CancellationMessage | SubscriptionConfirmationMessage | Reminder24hMessage | Reminder1hMessage | PaymentReminderMessage | PaymentConfirmationMessage | DeductionMessage; // --------------------------------------------------------------------------- // Consumer-side dispatcher — called once per queue message // --------------------------------------------------------------------------- export async function dispatchEmailMessage(msg: EmailMessage): Promise { switch (msg.type) { case "registrationConfirmation": await sendConfirmationEmail(msg); break; case "updateConfirmation": await sendUpdateEmail(msg); break; case "cancellation": await sendCancellationEmail(msg); break; case "subscriptionConfirmation": await sendSubscriptionConfirmationEmail({ to: msg.to }); break; case "reminder24h": await sendReminder24hEmail(msg); break; case "reminder1h": await sendReminderEmail(msg); break; case "paymentReminder": await sendPaymentReminderEmail(msg); break; case "paymentConfirmation": await sendPaymentConfirmationEmail(msg); break; case "deduction": await sendDeductionEmail(msg); break; default: // Exhaustiveness check — TypeScript will catch unhandled variants at compile time msg satisfies never; } }