Skip to content

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

Package listing

@kody/planetscale

src/loop-helpers.ts

86 lines · 2.9 KB · TypeScript
import type { JsonRecord, LoopConfig, PlanetscaleAnomalySummary, PlanetscaleWebhookPayload } from './types.ts'
import { optionalString, requireRecord } from './types.ts'

export type GithubRepoRef = {
	owner: string
	repo: string
	fullName: string
	issuePath: string
	repositoryUrl: string
}

export function asLoopConfig(value: unknown): LoopConfig {
	if (!value || typeof value !== 'object' || Array.isArray(value)) return {}
	return value as LoopConfig
}

export function githubRefFromConfig(input: {
	githubOwner?: string
	githubRepo?: string
	repositoryUrl?: string
}): GithubRepoRef | null {
	const repositoryUrl = optionalString(input.repositoryUrl, 'repositoryUrl')
	const owner = optionalString(input.githubOwner, 'githubOwner')
	const repo = optionalString(input.githubRepo, 'githubRepo')

	if (owner && repo && !repo.includes('/')) {
		return {
			owner,
			repo,
			fullName: `${owner}/${repo}`,
			issuePath: `/repos/${owner}/${repo}/issues`,
			repositoryUrl: repositoryUrl ?? `https://github.com/${owner}/${repo}`,
		}
	}

	const fromRepo = repo?.includes('/') ? repo : undefined
	const fromUrl = repositoryUrl?.match(/github\.com\/([^/]+)\/([^/#?]+)/i)
	const fullName = fromRepo ?? (fromUrl ? `${fromUrl[1]}/${fromUrl[2].replace(/\.git$/, '')}` : undefined)
	if (!fullName) return null
	const [parsedOwner, parsedRepo] = fullName.split('/')
	if (!parsedOwner || !parsedRepo) return null
	return {
		owner: parsedOwner,
		repo: parsedRepo,
		fullName: `${parsedOwner}/${parsedRepo}`,
		issuePath: `/repos/${parsedOwner}/${parsedRepo}/issues`,
		repositoryUrl: repositoryUrl ?? `https://github.com/${parsedOwner}/${parsedRepo}`,
	}
}

export function pickActiveAnomaly(
	anomalies: Array<PlanetscaleAnomalySummary>,
	anomalyId?: string,
): PlanetscaleAnomalySummary | undefined {
	if (anomalyId) return anomalies.find((item) => item.id === anomalyId)
	return anomalies.find((item) => item.active === true) ?? anomalies[0]
}

export function unwrapWebhookPayload(input: unknown): PlanetscaleWebhookPayload {
	if (typeof input === 'string') {
		try {
			return unwrapWebhookPayload(JSON.parse(input))
		} catch {
			throw new Error('PlanetScale webhook body must be JSON.')
		}
	}
	const record = requireRecord(input ?? {}, 'webhook')
	const request = record.request
	if (request && typeof request === 'object' && !Array.isArray(request)) {
		const inbound = request as JsonRecord
		if (inbound.json && typeof inbound.json === 'object') {
			return unwrapWebhookPayload(inbound.json)
		}
		if (typeof inbound.body === 'string') {
			return unwrapWebhookPayload(inbound.body)
		}
	}
	const nested = record.body ?? record.payload ?? record.data
	if (nested && typeof nested === 'object' && !Array.isArray(nested)) {
		const inner = nested as JsonRecord
		if (inner.event || inner.resource || inner.organization) {
			return inner as PlanetscaleWebhookPayload
		}
	}
	return record as PlanetscaleWebhookPayload
}