import { instrument } from 'succinct-async' import * as mailer from './mailer.js' import * as worker from './worker/index.js' import * as db from './database.js' export class ActionError extends Error { toString() { return this.message } } export type RegisterSubscriptionParams = { pubkey: string email: string frequency: string } export const registerSubscription = instrument( 'actions.registerSubscription', async ({ pubkey, email, frequency }: RegisterSubscriptionParams) => { const sub = await db.insertSubscription(pubkey, email, frequency) const callback = `${process.env.BASE_URL}/notify/${sub.id}` if (!sub.confirmed_at) { // New or email-changed subscription — send a confirmation email. await mailer.sendConfirm(sub) } else { // Already confirmed (e.g. frequency-only change) — reschedule the // cron job so it uses the new cadence immediately. worker.registerSubscription(sub) } return { key: sub.key, callback } }, ) export type ConfirmSubscriptionParams = { token: string } export const confirmSubscriptionAction = instrument( 'actions.confirmSubscription', async ({ token }: ConfirmSubscriptionParams) => { const result = await db.confirmSubscription(token) if (!result) { throw new ActionError('That confirmation code is invalid or has expired.') } // Only register the cron job when this is a fresh confirmation. // If already confirmed, the job is already running. if (!result.alreadyConfirmed) { worker.registerSubscription(result.sub) } return result }, ) export type UnsubscribeParams = { token: string } export const unsubscribeAction = instrument( 'actions.unsubscribe', async ({ token }: UnsubscribeParams) => { const sub = await db.unsubscribeSubscription(token) if (sub) { worker.unregisterSubscription(sub) } }, )