Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/postmark

src/servers.ts

203 lines · 5.4 KB · TypeScript
import {
	mutationPreview,
	pagingQuery,
	postmarkRequest,
	serverSummary,
	type MutationGuardInput,
	type PostmarkAuthOptions,
	type PostmarkObject,
} from './core.ts'

export type ServerColor =
	| 'Purple'
	| 'Blue'
	| 'Turquoise'
	| 'Green'
	| 'Red'
	| 'Yellow'
	| 'Grey'
	| 'Orange'
	| 'purple'
	| 'blue'
	| 'turquoise'
	| 'green'
	| 'red'
	| 'yellow'
	| 'grey'
	| 'orange'

export type ServerFields = {
	name?: string
	color?: ServerColor
	smtpApiActivated?: boolean
	rawEmailEnabled?: boolean
	deliveryType?: 'Live' | 'Sandbox'
	inboundHookUrl?: string
	inboundDomain?: string
	inboundSpamThreshold?: number
	trackOpens?: boolean
	trackLinks?: 'None' | 'HtmlAndText' | 'HtmlOnly' | 'TextOnly'
	includeBounceContentInHook?: boolean
	enableSmtpApiErrorHooks?: boolean
}

function serverBody(input: ServerFields) {
	return {
		Name: input.name,
		Color: input.color,
		SmtpApiActivated: input.smtpApiActivated,
		RawEmailEnabled: input.rawEmailEnabled,
		DeliveryType: input.deliveryType,
		InboundHookUrl: input.inboundHookUrl,
		InboundDomain: input.inboundDomain,
		InboundSpamThreshold: input.inboundSpamThreshold,
		TrackOpens: input.trackOpens,
		TrackLinks: input.trackLinks,
		IncludeBounceContentInHook: input.includeBounceContentInHook,
		EnableSmtpApiErrorHooks: input.enableSmtpApiErrorHooks,
	}
}

function auth(input: PostmarkAuthOptions) {
	return { account: input.account, secretName: input.secretName, accountSecretName: input.accountSecretName }
}

/** GET /server — current server for the Server API token. ApiTokens are stripped. */
export async function getServer(input: PostmarkAuthOptions = {}) {
	const raw = (await postmarkRequest({
		path: '/server',
		tokenKind: 'server',
		...auth(input),
	})) as PostmarkObject
	return {
		...((serverSummary(raw) ?? {}) as PostmarkObject),
		raw,
	}
}

/** PUT /server — edit the current server. Preview with `dryRun: true`. */
export async function editServer(input: MutationGuardInput & ServerFields) {
	const body = serverBody(input)
	const preview = mutationPreview(input, {
		action: 'edit current server',
		method: 'PUT',
		path: '/server',
		body,
		tokenKind: 'server',
	})
	if (preview) return preview
	return await postmarkRequest({
		path: '/server',
		method: 'PUT',
		body,
		tokenKind: 'server',
		...auth(input),
	})
}

export type ListServersInput = PostmarkAuthOptions & {
	count?: number
	offset?: number
	name?: string
}

/** GET /servers — account-wide server list. Requires `postmark-account`. */
export async function listServers(input: ListServersInput = {}) {
	const paging = pagingQuery(input)
	const body = (await postmarkRequest({
		path: '/servers',
		tokenKind: 'account',
		query: { ...paging, name: input.name },
		...auth(input),
	})) as { TotalCount?: number; Servers?: PostmarkObject[] }
	const servers = Array.isArray(body.Servers) ? body.Servers : []
	return {
		totalCount: body.TotalCount ?? servers.length,
		servers: servers.map((server) => serverSummary(server)).filter(Boolean),
	}
}

/** GET /servers/{id} — one server by id. Requires `postmark-account`. */
export async function getAccountServer(input: PostmarkAuthOptions & { serverId: number | string }) {
	if (input.serverId == null || input.serverId === '') {
		throw new Error('getAccountServer: serverId is required')
	}
	const raw = (await postmarkRequest({
		path: '/servers/' + encodeURIComponent(String(input.serverId)),
		tokenKind: 'account',
		...auth(input),
	})) as PostmarkObject
	return { ...(serverSummary(raw) ?? {}), raw }
}

/** POST /servers — create a server. Requires `postmark-account`. */
export async function createServer(input: MutationGuardInput & ServerFields) {
	if (!input.name) throw new Error('createServer: name is required')
	const body = serverBody(input)
	const preview = mutationPreview(input, {
		action: 'create server ' + input.name,
		method: 'POST',
		path: '/servers',
		body,
		tokenKind: 'account',
	})
	if (preview) return preview
	const raw = (await postmarkRequest({
		path: '/servers',
		method: 'POST',
		body,
		tokenKind: 'account',
		...auth(input),
	})) as PostmarkObject
	return { ...(serverSummary(raw) ?? {}), raw }
}

/** PUT /servers/{id} — edit a server by id. Requires `postmark-account`. */
export async function editAccountServer(
	input: MutationGuardInput & ServerFields & { serverId: number | string },
) {
	if (input.serverId == null || input.serverId === '') {
		throw new Error('editAccountServer: serverId is required')
	}
	const body = serverBody(input)
	const path = '/servers/' + encodeURIComponent(String(input.serverId))
	const preview = mutationPreview(input, {
		action: 'edit server ' + input.serverId,
		method: 'PUT',
		path,
		body,
		tokenKind: 'account',
	})
	if (preview) return preview
	return await postmarkRequest({
		path,
		method: 'PUT',
		body,
		tokenKind: 'account',
		...auth(input),
	})
}

/** DELETE /servers/{id} — delete a server. Requires `confirm: true`. */
export async function deleteServer(input: MutationGuardInput & { serverId: number | string }) {
	if (input.serverId == null || input.serverId === '') {
		throw new Error('deleteServer: serverId is required')
	}
	const path = '/servers/' + encodeURIComponent(String(input.serverId))
	const preview = mutationPreview(input, {
		action: 'delete server ' + input.serverId,
		method: 'DELETE',
		path,
		requireConfirm: true,
		tokenKind: 'account',
	})
	if (preview) return preview
	return await postmarkRequest({
		path,
		method: 'DELETE',
		tokenKind: 'account',
		...auth(input),
	})
}

export default getServer