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
}