import { kody } from 'kody:runtime'
import type { PlanetscaleAuthInput } from './types.ts'
import { optionalString } from './types.ts'
import { DEFAULT_API_TOKEN_SECRET, missingCredentialsMessage } from './setup.ts'
export type ResolvedPlanetscaleAuth = {
secretName: string
authorization: string
}
function secretEntries(result: unknown): Array<{ name?: string; scope?: string }> {
if (
result &&
typeof result === 'object' &&
Array.isArray((result as { secrets?: unknown }).secrets)
) {
return (result as { secrets: Array<{ name?: string; scope?: string }> }).secrets
}
return Array.isArray(result) ? result : []
}
export async function listUserSecretNames(): Promise<Set<string>> {
const listed = await kody.secret_list({ scope: 'user' })
const names = new Set<string>()
for (const entry of secretEntries(listed)) {
if (entry?.name && (entry.scope === 'user' || !entry.scope)) {
names.add(entry.name)
}
}
return names
}
export function resolveSecretName(input: PlanetscaleAuthInput = {}): string {
const explicit = optionalString(input.secretName, 'secretName')
if (explicit) return explicit
const account = optionalString(input.account, 'account')
if (!account || account === 'default' || account === 'planetscale') {
return DEFAULT_API_TOKEN_SECRET
}
if (account.startsWith('planetscaleApiToken-')) return account
if (account.startsWith('planetscale-')) {
return `planetscaleApiToken-${account.slice('planetscale-'.length)}`
}
return `planetscaleApiToken-${account}`
}
export async function resolvePlanetscaleAuth(
input: PlanetscaleAuthInput = {},
): Promise<ResolvedPlanetscaleAuth> {
const secretName = resolveSecretName(input)
const secrets = await listUserSecretNames()
if (!secrets.has(secretName)) {
throw new Error(missingCredentialsMessage({ secretName }))
}
return {
secretName,
authorization: `{{secret:${secretName}}}`,
}
}
export async function planetscaleFetch(
auth: ResolvedPlanetscaleAuth,
url: string,
init: RequestInit,
): Promise<Response> {
const headers = new Headers(init.headers)
headers.set('Authorization', `{{secret:${auth.secretName}}}`)
return fetch(url, { ...init, headers })
}