Skip to content

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

Package listing

@kody/planetscale

src/create-webhook.ts

87 lines · 2.8 KB · TypeScript
import { planetscaleRequest } from './client.ts'
import { PLANETSCALE_API_BASE_URL } from './setup.ts'
import type { JsonRecord, PlanetscaleAuthInput } from './types.ts'
import { optionalBoolean, optionalString, optionalStringArray, requireRecord, requireString } from './types.ts'

export type CreateWebhookInput = PlanetscaleAuthInput & {
	organization: string
	database: string
	url: string
	events?: Array<string>
	enabled?: boolean
	dryRun?: boolean
	confirm?: boolean
}

/**
 * Create a PlanetScale database webhook (default event: branch.anomaly).
 * Preview with dryRun. Live create requires confirm: true and write_database.
 * @example
 * import createWebhook from 'kody:@kody/planetscale/create-webhook'
 * await createWebhook({
 *   organization: 'acme',
 *   database: 'app',
 *   url: 'https://example.kody.run/webhooks/insights',
 *   dryRun: true,
 * })
 */
export async function createWebhook(input: CreateWebhookInput) {
	const organization = requireString(input.organization, 'organization')
	const database = requireString(input.database, 'database')
	const url = requireString(input.url, 'url')
	const events = input.events?.length ? input.events : ['branch.anomaly']
	const path = `/organizations/${encodeURIComponent(organization)}/databases/${encodeURIComponent(database)}/webhooks`
	const body: JsonRecord = {
		url,
		events,
		enabled: input.enabled ?? true,
	}

	if (input.dryRun) {
		return {
			dryRun: true,
			wouldCall: {
				method: 'POST',
				url: `${PLANETSCALE_API_BASE_URL}${path}`,
				body,
			},
		}
	}

	if (input.confirm !== true) {
		throw new Error(
			'Creating a PlanetScale webhook may mutate data. Pass confirm: true only after explicit user approval, or use dryRun: true.',
		)
	}

	return planetscaleRequest({
		...input,
		operation: 'webhooks.write',
		method: 'POST',
		path,
		body,
	})
}

/**
 * Create a PlanetScale database webhook (default event: branch.anomaly).
 * @example
 * import createWebhook from 'kody:@kody/planetscale/create-webhook'
 * await createWebhook({ organization: 'acme', database: 'app', url: 'https://example', dryRun: true })
 */
export default async function createWebhookEntrypoint(
	params: Partial<CreateWebhookInput> & Record<string, unknown> = {},
) {
	const input = requireRecord(params, 'create-webhook')
	return createWebhook({
		organization: requireString(input.organization, 'organization'),
		database: requireString(input.database, 'database'),
		url: requireString(input.url, 'url'),
		events: optionalStringArray(input.events, 'events'),
		enabled: optionalBoolean(input.enabled, 'enabled'),
		account: optionalString(input.account, 'account'),
		secretName: optionalString(input.secretName, 'secretName'),
		dryRun: optionalBoolean(input.dryRun, 'dryRun'),
		confirm: optionalBoolean(input.confirm, 'confirm'),
	})
}