Skip to content

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

Package listing

@kody/supabase

src/accounts.ts

91 lines · 2.6 KB · TypeScript
import { kody } from 'kody:runtime'
import {
	assertSecretName,
	resolveSecretNames,
	setupUrls,
} from './setup.ts'
import {
	optionalString,
	type SupabaseAuthInput,
} from './types.ts'

export type SupabaseAccountInfo = {
	account?: string
	purpose?: string
	patSecretName: string
	serviceRoleSecretName: string
	hasPatSecret: boolean
	hasServiceRoleSecret: boolean
	patAllowedHosts: Array<string>
	serviceRoleAllowedHosts: Array<string>
	setup: ReturnType<typeof setupUrls>
}

async function secretMeta(name: string) {
	const listed = await kody.secret_list({})
	const match = listed.secrets.find((secret) => secret.name === name)
	return {
		exists: Boolean(match),
		allowedHosts: match?.allowed_hosts ?? [],
	}
}

/**
 * Resolve which Supabase PAT / service-role secrets to use.
 *
 * - `account: 'work'` → `supabasePat-work` and `supabaseServiceRoleKey-work`
 * - `account: 'supabase-work'` → same
 * - omitted / `default` / `supabase` → `supabasePat` and `supabaseServiceRoleKey`
 * - `patSecretName` / `serviceRoleSecretName` / `secretName` override
 *
 * @example
 * import listSupabaseAccounts from 'kody:@kody/supabase/accounts'
 * const accounts = await listSupabaseAccounts()
 */
export async function accounts(
	params: SupabaseAuthInput = {},
): Promise<SupabaseAccountInfo> {
	const names = resolveSecretNames(params)
	const patName = assertSecretName(names.patSecretName, 'patSecretName')
	const serviceName = assertSecretName(
		names.serviceRoleSecretName,
		'serviceRoleSecretName',
	)
	const [pat, serviceRole] = await Promise.all([
		secretMeta(patName),
		secretMeta(serviceName),
	])
	return {
		account: params.account,
		purpose: names.purpose,
		patSecretName: patName,
		serviceRoleSecretName: serviceName,
		hasPatSecret: pat.exists,
		hasServiceRoleSecret: serviceRole.exists,
		patAllowedHosts: pat.allowedHosts,
		serviceRoleAllowedHosts: serviceRole.allowedHosts,
		setup: setupUrls(params),
	}
}

/**
 * Resolve which Supabase secrets to use.
 * @example
 * import listSupabaseAccounts from 'kody:@kody/supabase/accounts'
 * const info = await listSupabaseAccounts({ account: 'work' })
 */
export default async function accountsEntrypoint(
	params: SupabaseAuthInput & Record<string, unknown> = {},
) {
	return await accounts({
		account: optionalString(params.account, 'account'),
		secretName: optionalString(params.secretName, 'secretName'),
		patSecretName: optionalString(params.patSecretName, 'patSecretName'),
		serviceRoleSecretName: optionalString(
			params.serviceRoleSecretName,
			'serviceRoleSecretName',
		),
		projectRef: optionalString(params.projectRef, 'projectRef'),
		projectUrl: optionalString(params.projectUrl, 'projectUrl'),
	})
}