Skip to content

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

Package listing

@kody/supabase

src/insert-rows.ts

105 lines · 3.1 KB · TypeScript
import { projectAuth } from './setup.ts'
import { assertMutationAllowed, readMutationFlags } from './safety.ts'
import { asLive, projectRequest } from './client.ts'
import {
	optionalSchema,
	profileHeaders,
	readRows,
	requireTable,
	restPath,
} from './table.ts'
import {
	optionalBoolean,
	optionalString,
	type DryRunResult,
	type JsonRecord,
	type SupabaseAuthInput,
} from './types.ts'

/**
 * Insert rows into a PostgREST table. Requires `confirm: true`, or use `dryRun: true`.
 * @example
 * import insertRows from 'kody:@kody/supabase/insert-rows'
 * const preview = await insertRows({
 *   projectRef: 'abcdefghijklmnop',
 *   table: 'items',
 *   rows: [{ name: 'Preview' }],
 *   dryRun: true,
 * })
 */
export async function insertRows(
	input: SupabaseAuthInput & {
		table: string
		schema?: string
		rows: Array<JsonRecord>
		upsert?: boolean
		onConflict?: string
		dryRun?: boolean
		confirm?: boolean
	},
) {
	const table = requireTable(input.table)
	const rows = input.rows
	if (!Array.isArray(rows) || rows.length === 0) {
		throw new Error('rows must be a non-empty array of objects.')
	}
	const allowed = assertMutationAllowed(readMutationFlags(input), 'insert-rows')
	const path = restPath(table)
	const prefer = input.upsert
		? 'return=representation,resolution=merge-duplicates'
		: 'return=representation'
	if (allowed.dryRun) {
		const preview: DryRunResult = {
			dryRun: true,
			method: 'POST',
			path,
			headers: { Prefer: prefer },
			query: input.onConflict ? { on_conflict: input.onConflict } : undefined,
			body: rows,
		}
		return preview
	}
	const live = asLive<{ data: unknown }>(
		await projectRequest({
			auth: projectAuth(input),
			method: 'POST',
			path,
			headers: {
				...profileHeaders(optionalSchema(input.schema)),
				Prefer: prefer,
			},
			query: input.onConflict ? { on_conflict: input.onConflict } : undefined,
			body: rows,
		}),
	)
	const items = Array.isArray(live.data) ? (live.data as Array<JsonRecord>) : []
	return { items, count: items.length }
}

/**
 * Insert rows into a PostgREST table. Requires `confirm: true`, or use `dryRun: true`.
 * @example
 * import insertRows from 'kody:@kody/supabase/insert-rows'
 * const preview = await insertRows({ projectRef: 'abcdefghijklmnop', table: 'items', rows: [{ name: 'Preview' }], dryRun: true })
 */
export default async function insertRowsEntrypoint(
	params: Partial<SupabaseAuthInput> & Record<string, unknown> = {},
) {
	return await insertRows({
		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),
		rows: readRows(params.rows),
		upsert: optionalBoolean(params.upsert, 'upsert'),
		onConflict: optionalString(params.onConflict, 'onConflict'),
		dryRun: optionalBoolean(params.dryRun, 'dryRun'),
		confirm: optionalBoolean(params.confirm, 'confirm'),
	})
}