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 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) : [] 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 & Record = {}, ) { 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'), }) }