import { projectAuth } from './setup.ts' import { asLive, projectRequest } from './client.ts' import { clampInt, isRecord, optionalString, requireString, type SupabaseAuthInput, } from './types.ts' export type StorageObjectSummary = { name: string id?: string updatedAt?: string createdAt?: string size?: number mimeType?: string } /** * List objects in a Storage bucket. This Storage endpoint is POST, but it is a read. * @example * import listObjects from 'kody:@kody/supabase/list-objects' * const { items } = await listObjects({ * projectRef: 'abcdefghijklmnop', * bucket: 'avatars', * prefix: 'public/', * }) */ export async function listObjects( input: SupabaseAuthInput & { bucket: string prefix?: string search?: string limit?: number offset?: number }, ): Promise<{ items: Array; count: number }> { const bucket = requireString(input.bucket, 'bucket') const live = asLive<{ data: unknown }>( await projectRequest({ auth: projectAuth(input), method: 'POST', path: `/storage/v1/object/list/${encodeURIComponent(bucket)}`, body: { prefix: optionalString(input.prefix, 'prefix') ?? '', search: optionalString(input.search, 'search'), limit: clampInt(input.limit, 1, 1000, 100), offset: clampInt(input.offset, 0, 1_000_000, 0, 'offset'), sortBy: { column: 'name', order: 'asc' }, }, }), ) const rows = Array.isArray(live.data) ? live.data : [] const items = rows .map((row) => { if (!isRecord(row)) return null const name = optionalString(row.name, 'name') if (!name) return null const metadata = isRecord(row.metadata) ? row.metadata : undefined return { name, id: optionalString(row.id, 'id'), updatedAt: optionalString(row.updated_at, 'updated_at'), createdAt: optionalString(row.created_at, 'created_at'), size: typeof metadata?.size === 'number' ? metadata.size : undefined, mimeType: optionalString(metadata?.mimetype, 'mimetype'), } }) .filter((item): item is StorageObjectSummary => item !== null) return { items, count: items.length } } /** * List objects in a Storage bucket. * @example * import listObjects from 'kody:@kody/supabase/list-objects' * const result = await listObjects({ projectRef: 'abcdefghijklmnop', bucket: 'avatars' }) */ export default async function listObjectsEntrypoint( params: Partial & Record = {}, ) { return await listObjects({ account: optionalString(params.account, 'account'), secretName: optionalString(params.secretName, 'secretName'), serviceRoleSecretName: optionalString( params.serviceRoleSecretName, 'serviceRoleSecretName', ), projectRef: optionalString(params.projectRef, 'projectRef'), projectUrl: optionalString(params.projectUrl, 'projectUrl'), bucket: requireString(params.bucket, 'bucket'), prefix: optionalString(params.prefix, 'prefix'), search: optionalString(params.search, 'search'), limit: typeof params.limit === 'number' ? params.limit : undefined, offset: typeof params.offset === 'number' ? params.offset : undefined, }) }