import { projectAuth } from './setup.ts'
import { assertMutationAllowed, readMutationFlags } from './safety.ts'
import { asLive, projectRequest } from './client.ts'
import { summarizeAuthUser } from './list-users.ts'
import {
isRecord,
optionalBoolean,
optionalString,
requireString,
type DryRunResult,
type JsonRecord,
type SupabaseAuthInput,
} from './types.ts'
export type UpdateUserInput = SupabaseAuthInput & {
userId: string
email?: string
phone?: string
password?: string
emailConfirm?: boolean
phoneConfirm?: boolean
banDuration?: string
userMetadata?: JsonRecord
appMetadata?: JsonRecord
dryRun?: boolean
confirm?: boolean
}
/**
* Update an Auth user. Requires `confirm: true`, or use `dryRun: true`.
* @example
* import updateUser from 'kody:@kody/supabase/update-user'
* const preview = await updateUser({
* projectRef: 'abcdefghijklmnop',
* userId: '00000000-0000-0000-0000-000000000000',
* banDuration: '24h',
* dryRun: true,
* })
*/
export async function updateUser(input: UpdateUserInput) {
const userId = requireString(input.userId, 'userId')
const flags = readMutationFlags(input)
const body: JsonRecord = {
email: optionalString(input.email, 'email'),
phone: optionalString(input.phone, 'phone'),
password: optionalString(input.password, 'password'),
email_confirm: optionalBoolean(input.emailConfirm, 'emailConfirm'),
phone_confirm: optionalBoolean(input.phoneConfirm, 'phoneConfirm'),
ban_duration: optionalString(input.banDuration, 'banDuration'),
user_metadata: input.userMetadata,
app_metadata: input.appMetadata,
}
const previewBody = { ...body, password: body.password ? '[redacted]' : undefined }
const allowed = assertMutationAllowed(flags, 'update-user')
const path = `/auth/v1/admin/users/${encodeURIComponent(userId)}`
if (allowed.dryRun) {
const preview: DryRunResult = {
dryRun: true,
method: 'PUT',
path,
body: previewBody,
}
return preview
}
const live = asLive<{ data: unknown }>(
await projectRequest({
auth: projectAuth(input),
method: 'PUT',
path,
body,
}),
)
return summarizeAuthUser(live.data, true)
}
/**
* Update an Auth user. Requires `confirm: true`, or use `dryRun: true`.
* @example
* import updateUser from 'kody:@kody/supabase/update-user'
* const preview = await updateUser({ projectRef: 'abcdefghijklmnop', userId: '00000000-0000-0000-0000-000000000000', dryRun: true })
*/
export default async function updateUserEntrypoint(
params: Partial<UpdateUserInput> & Record<string, unknown> = {},
) {
return await updateUser({
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'),
userId: requireString(params.userId ?? params.id, 'userId'),
email: optionalString(params.email, 'email'),
phone: optionalString(params.phone, 'phone'),
password: optionalString(params.password, 'password'),
emailConfirm: optionalBoolean(params.emailConfirm, 'emailConfirm'),
phoneConfirm: optionalBoolean(params.phoneConfirm, 'phoneConfirm'),
banDuration: optionalString(params.banDuration, 'banDuration'),
userMetadata: isRecord(params.userMetadata) ? params.userMetadata : undefined,
appMetadata: isRecord(params.appMetadata) ? params.appMetadata : undefined,
dryRun: optionalBoolean(params.dryRun, 'dryRun'),
confirm: optionalBoolean(params.confirm, 'confirm'),
})
}