Skip to content

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

Package listing

@kody/supabase

src/list-projects.ts

86 lines · 2.5 KB · TypeScript
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,
	})
}