import { managementAuth } from './setup.ts' import { asLive, managementRequest } from './client.ts' import { clampInt, isRecord, optionalString, type SupabaseAuthInput, } from './types.ts' export type ProjectSummary = { id: string ref: string name: string region?: string status?: string organizationId?: string organizationSlug?: string createdAt?: string } export type ListProjectsResult = { items: Array count: number } function summarizeProject(value: unknown): ProjectSummary | null { if (!isRecord(value)) return null const ref = optionalString(value.ref, 'ref') ?? optionalString(value.id, 'id') const name = optionalString(value.name, 'name') if (!ref || !name) return null return { id: optionalString(value.id, 'id') ?? ref, ref, name, region: optionalString(value.region, 'region'), status: optionalString(value.status, 'status'), organizationId: optionalString(value.organization_id, 'organization_id'), organizationSlug: optionalString(value.organization_slug, 'organization_slug'), createdAt: optionalString(value.created_at, 'created_at'), } } /** * List Supabase projects visible to the saved personal access token. * @example * import listProjects from 'kody:@kody/supabase/list-projects' * const { items } = await listProjects({ limit: 25 }) */ export async function listProjects( input: SupabaseAuthInput & { limit?: number } = {}, ): Promise { const live = asLive<{ data: unknown }>( await managementRequest({ auth: managementAuth(input), method: 'GET', path: '/v1/projects', }), ) const rows = Array.isArray(live.data) ? live.data : [] const items = rows .map(summarizeProject) .filter((item): item is ProjectSummary => item !== null) .slice(0, clampInt(input.limit, 1, 200, itemsFallback(rows.length))) return { items, count: items.length } } function itemsFallback(count: number): number { return count > 0 ? count : 50 } /** * List Supabase projects visible to the saved personal access token. * @example * import listProjects from 'kody:@kody/supabase/list-projects' * const result = await listProjects() */ export default async function listProjectsEntrypoint( params: SupabaseAuthInput & { limit?: number } & Record = {}, ) { return await listProjects({ account: optionalString(params.account, 'account'), secretName: optionalString(params.secretName, 'secretName'), patSecretName: optionalString(params.patSecretName, 'patSecretName'), limit: typeof params.limit === 'number' ? params.limit : undefined, }) }