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,
type DryRunResult,
type JsonRecord,
type SupabaseAuthInput,
} from './types.ts'
export type CreateUserInput = SupabaseAuthInput & {
email?: string
phone?: string
password?: string
emailConfirm?: boolean
phoneConfirm?: boolean
userMetadata?: JsonRecord
appMetadata?: JsonRecord
dryRun?: boolean
confirm?: boolean
}
/**
* Create an Auth user. Requires `confirm: true`, or use `dryRun: true`.
* @example
* import createUser from 'kody:@kody/supabase/create-user'
* const preview = await createUser({
* projectRef: 'abcdefghijklmnop',
* email: 'ada@example.com',
* dryRun: true,
* })
*/
export async function createUser(input: CreateUserInput) {
const flags = readMutationFlags(input)
const email = optionalString(input.email, 'email')
const phone = optionalString(input.phone, 'phone')
if (!email && !phone) {
throw new Error('create-user requires email or phone.')
}
const body: JsonRecord = {
email,
phone,
password: optionalString(input.password, 'password'),
email_confirm: optionalBoolean(input.emailConfirm, 'emailConfirm'),
phone_confirm: optionalBoolean(input.phoneConfirm, 'phoneConfirm'),
user_metadata: input.userMetadata,
app_metadata: input.appMetadata,
}
const previewBody = { ...body, password: body.password ? '[redacted]' : undefined }
const allowed = assertMutationAllowed(flags, 'create-user')
if (allowed.dryRun) {
const preview: DryRunResult = {
dryRun: true,
method: 'POST',
path: '/auth/v1/admin/users',
body: previewBody,
}
return preview
}
const live = asLive<{ data: unknown }>(
await projectRequest({
auth: projectAuth(input),
method: 'POST',
path: '/auth/v1/admin/users',
body,
}),
)
return summarizeAuthUser(live.data, true)
}
/**
* Create an Auth user. Requires `confirm: true`, or use `dryRun: true`.
* @example
* import createUser from 'kody:@kody/supabase/create-user'
* const preview = await createUser({ projectRef: 'abcdefghijklmnop', email: 'ada@example.com', dryRun: true })
*/
export default async function createUserEntrypoint(
params: Partial<CreateUserInput> & Record<string, unknown> = {},
) {
return await createUser({
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'),
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'),
userMetadata: isRecord(params.userMetadata) ? params.userMetadata : undefined,
appMetadata: isRecord(params.appMetadata) ? params.appMetadata : undefined,
dryRun: optionalBoolean(params.dryRun, 'dryRun'),
confirm: optionalBoolean(params.confirm, 'confirm'),
})
}