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'),
})
}