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<StorageObjectSummary>; 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<SupabaseAuthInput> & Record<string, unknown> = {},
) {
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,
})
}