Skip to content
← Public packages

@kentcdodds/kit

Kit.com helpers for subscribers, tags, forms, sequences, and broadcasts.

src/sequence-emails.js

115 lines · 4.3 KB · JavaScript
import {
	callParsed,
	getV4SequencesSequenceIdEmailsId,
	postV4Sequences,
	postV4SequencesSequenceIdEmails,
	postV4SequencesSequenceIdSubscribers,
	putV4SequencesSequenceIdEmailsId,
	sequenceEmailSummary,
	subscriberSummary,
} from './kit-client.js'

/**
 * Create a sequence (email course / automated drip). Only `name` is required;
 * pass `email_address` to send from an alternate verified address (e.g.
 * `hello@kentcdodds.com`) and `active: true` to activate immediately.
 * @param {{ name: string, email_address?: string, email_template_id?: number, active?: boolean, repeat?: boolean } & Record<string, unknown>} input
 * @example
 * const seq = await createSequence({ name: 'Kody Waitlist Welcome', email_address: 'hello@kentcdodds.com', active: true })
 * // => { id, name, ... }
 */
export async function createSequence(input) {
	if (!input?.name) throw new Error('createSequence: name is required')
	const body = await callParsed(
		postV4Sequences,
		{ body: input },
		{ method: 'POST', path: '/v4/sequences' },
	)
	return /** @type {{ sequence?: Record<string, unknown> }} */ (body).sequence
}

/**
 * Create an email inside a sequence.
 * @param {number | string} sequenceId
 * @param {{ subject: string, content: string } & Record<string, unknown>} input
 */
export async function createSequenceEmail(sequenceId, input) {
	if (!sequenceId) throw new Error('createSequenceEmail: sequenceId is required')
	if (!input?.subject) throw new Error('createSequenceEmail: subject is required')
	const body = await callParsed(
		postV4SequencesSequenceIdEmails,
		{ params: { sequence_id: sequenceId }, body: input },
		{ method: 'POST', path: `/v4/sequences/${sequenceId}/emails` },
	)
	const email = /** @type {{ email?: Record<string, unknown> }} */ (body).email
	return { ...sequenceEmailSummary(email), content: email?.content }
}

/**
 * Enroll an existing subscriber into a sequence by email address.
 * @param {number | string} sequenceId
 * @param {string} emailAddress
 * @example
 * await addSubscriberToSequence(2757781, 'a@b.com')
 */
export async function addSubscriberToSequence(sequenceId, emailAddress) {
	if (!sequenceId) throw new Error('addSubscriberToSequence: sequenceId is required')
	if (!emailAddress) throw new Error('addSubscriberToSequence: emailAddress is required')
	const body = await callParsed(
		postV4SequencesSequenceIdSubscribers,
		{ params: { sequence_id: sequenceId }, body: { email_address: emailAddress } },
		{ method: 'POST', path: `/v4/sequences/${sequenceId}/subscribers` },
	)
	const subscriber = /** @type {{ subscriber?: Record<string, unknown> }} */ (body).subscriber
	return subscriberSummary(subscriber)
}

/**
 * @param {number} sequenceId
 * @param {number} emailId
 */
export async function getSequenceEmail(sequenceId, emailId) {
	if (!sequenceId) throw new Error('getSequenceEmail: sequenceId is required')
	if (!emailId) throw new Error('getSequenceEmail: emailId is required')
	const body = await callParsed(
		getV4SequencesSequenceIdEmailsId,
		{ params: { sequence_id: sequenceId, id: emailId } },
		{ method: 'GET', path: `/v4/sequences/${sequenceId}/emails/${emailId}` },
	)
	const email = /** @type {{ email?: Record<string, unknown> }} */ (body).email
	return {
		...sequenceEmailSummary(email),
		preview_text: email?.preview_text,
		content: email?.content,
		delay_value: email?.delay_value,
		delay_unit: email?.delay_unit,
		position: email?.position,
		email_template_id: email?.email_template_id,
	}
}

/**
 * Partial update — only included fields change.
 * @param {number} sequenceId
 * @param {number} emailId
 * @param {Record<string, unknown>} fields
 */
export async function updateSequenceEmail(sequenceId, emailId, fields) {
	if (!sequenceId) throw new Error('updateSequenceEmail: sequenceId is required')
	if (!emailId) throw new Error('updateSequenceEmail: emailId is required')
	const body = await callParsed(
		putV4SequencesSequenceIdEmailsId,
		{ params: { sequence_id: sequenceId, id: emailId }, body: fields },
		{ method: 'PUT', path: `/v4/sequences/${sequenceId}/emails/${emailId}` },
	)
	const email = /** @type {{ email?: Record<string, unknown> }} */ (body).email
	return {
		...sequenceEmailSummary(email),
		content: email?.content,
	}
}

/** @param {number} sequenceId @param {number} emailId */
export async function publishSequenceEmail(sequenceId, emailId) {
	return updateSequenceEmail(sequenceId, emailId, { published: true })
}