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<ProjectSummary>
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<ListProjectsResult> {
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<string, unknown> = {},
) {
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,
})
}