import {
mutationPreview,
parseAction,
resendRequest,
unwrapList,
type MutationGuardInput,
type ResendAuthOptions,
} from './resend-core.ts'
/** GET /templates */
export async function listTemplates(input: ResendAuthOptions = {}) {
const body = await resendRequest({
path: '/templates',
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
return unwrapList(body)
}
/** GET /templates/{id} */
export async function getTemplate(input: ResendAuthOptions & { templateId: string }) {
if (!input.templateId) throw new Error('getTemplate: templateId is required')
return await resendRequest({
path: '/templates/' + encodeURIComponent(input.templateId),
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
}
export type CreateTemplateInput = MutationGuardInput & {
name: string
html: string
subject?: string
text?: string
from?: string
reply_to?: string | string[]
variables?: Array<{ key: string; type?: string; fallback_value?: unknown }>
}
/** POST /templates — create a draft. Publish explicitly before sending. */
export async function createTemplate(input: CreateTemplateInput) {
if (!input.name) throw new Error('createTemplate: name is required')
if (!input.html) throw new Error('createTemplate: html is required')
const body = {
name: input.name,
html: input.html,
subject: input.subject,
text: input.text,
from: input.from,
reply_to: input.reply_to,
variables: input.variables,
}
const preview = mutationPreview(input, {
action: 'create template ' + input.name,
method: 'POST',
path: '/templates',
body,
})
if (preview) return preview
return await resendRequest({
path: '/templates',
method: 'POST',
body,
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
}
export type UpdateTemplateInput = MutationGuardInput & {
templateId: string
name?: string
html?: string
subject?: string
text?: string
from?: string
reply_to?: string | string[]
variables?: Array<{ key: string; type?: string; fallback_value?: unknown }>
}
/** PATCH /templates/{id} — draft changes until publish. */
export async function updateTemplate(input: UpdateTemplateInput) {
if (!input.templateId) throw new Error('updateTemplate: templateId is required')
const body = {
name: input.name,
html: input.html,
subject: input.subject,
text: input.text,
from: input.from,
reply_to: input.reply_to,
variables: input.variables,
}
const preview = mutationPreview(input, {
action: 'update template ' + input.templateId,
method: 'PATCH',
path: '/templates/' + input.templateId,
body,
})
if (preview) return preview
return await resendRequest({
path: '/templates/' + encodeURIComponent(input.templateId),
method: 'PATCH',
body,
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
}
/** POST /templates/{id}/publish — make the latest draft live for sending. */
export async function publishTemplate(input: MutationGuardInput & { templateId: string }) {
if (!input.templateId) throw new Error('publishTemplate: templateId is required')
const preview = mutationPreview(input, {
action: 'publish template ' + input.templateId,
method: 'POST',
path: '/templates/' + input.templateId + '/publish',
requireConfirm: true,
})
if (preview) return preview
return await resendRequest({
path: '/templates/' + encodeURIComponent(input.templateId) + '/publish',
method: 'POST',
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
}
/** DELETE /templates/{id}. Destructive; requires confirm: true. */
export async function deleteTemplate(input: MutationGuardInput & { templateId: string }) {
if (!input.templateId) throw new Error('deleteTemplate: templateId is required')
const preview = mutationPreview(input, {
action: 'delete template ' + input.templateId,
method: 'DELETE',
path: '/templates/' + input.templateId,
requireConfirm: true,
})
if (preview) return preview
return await resendRequest({
path: '/templates/' + encodeURIComponent(input.templateId),
method: 'DELETE',
account: input.account,
secretName: input.secretName,
integration: input.integration,
})
}
const templateActions = [
'list-templates',
'get-template',
'create-template',
'update-template',
'publish-template',
'delete-template',
] as const
/** Templates dispatcher. Defaults to list-templates. */
export default async function templates(input: Record<string, unknown> = {}) {
const action = parseAction(input.action, templateActions, 'list-templates', 'templates')
switch (action) {
case 'list-templates':
return await listTemplates(input)
case 'get-template':
return await getTemplate(input as never)
case 'create-template':
return await createTemplate(input as CreateTemplateInput)
case 'update-template':
return await updateTemplate(input as UpdateTemplateInput)
case 'publish-template':
return await publishTemplate(input as never)
case 'delete-template':
return await deleteTemplate(input as never)
default: {
const exhaustive: never = action
throw new Error('Unhandled templates action: ' + String(exhaustive))
}
}
}