Skip to content

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

Package listing

@kody/supabase

src/select-rows.ts

88 lines · 2.6 KB · TypeScript
import { projectAuth } from './setup.ts'
import { asLive, projectRequest } from './client.ts'
import {
	filterQuery,
	optionalSchema,
	profileHeaders,
	readFilters,
	requireTable,
	restPath,
} from './table.ts'
import {
	clampInt,
	optionalString,
	type JsonRecord,
	type SupabaseAuthInput,
} from './types.ts'

/**
 * Read rows from a PostgREST table (service role, bypasses RLS).
 * @example
 * import selectRows from 'kody:@kody/supabase/select-rows'
 * const { items } = await selectRows({
 *   projectRef: 'abcdefghijklmnop',
 *   table: 'items',
 *   select: 'id,name',
 *   filters: { status: 'eq.active' },
 *   limit: 20,
 * })
 */
export async function selectRows(
	input: SupabaseAuthInput & {
		table: string
		schema?: string
		select?: string
		filters?: Record<string, string>
		order?: string
		limit?: number
		offset?: number
	},
): Promise<{ items: Array<JsonRecord>; count: number }> {
	const table = requireTable(input.table)
	const limit = clampInt(input.limit, 1, 1000, 50)
	const offset = clampInt(input.offset, 0, 1_000_000, 0, 'offset')
	const live = asLive<{ data: unknown }>(
		await projectRequest({
			auth: projectAuth(input),
			method: 'GET',
			path: restPath(table),
			headers: profileHeaders(optionalSchema(input.schema)),
			query: filterQuery(input.filters, {
				select: optionalString(input.select, 'select') ?? '*',
				order: optionalString(input.order, 'order'),
				limit,
				offset,
			}),
		}),
	)
	const items = Array.isArray(live.data) ? (live.data as Array<JsonRecord>) : []
	return { items, count: items.length }
}

/**
 * Read rows from a PostgREST table (service role, bypasses RLS).
 * @example
 * import selectRows from 'kody:@kody/supabase/select-rows'
 * const result = await selectRows({ projectRef: 'abcdefghijklmnop', table: 'items' })
 */
export default async function selectRowsEntrypoint(
	params: Partial<SupabaseAuthInput> & Record<string, unknown> = {},
) {
	return await selectRows({
		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'),
		table: requireTable(params.table),
		schema: optionalSchema(params.schema),
		select: optionalString(params.select, 'select'),
		filters: readFilters(params.filters),
		order: optionalString(params.order, 'order'),
		limit: typeof params.limit === 'number' ? params.limit : undefined,
		offset: typeof params.offset === 'number' ? params.offset : undefined,
	})
}