import { z } from 'zod' import { requireStageTwoSafeText, requireStageTwoUser, stageTwoApiError, stageTwoDatabase } from '~/server/utils/stage-two-supabase' import { visibleProfile, type ProfileRecord } from '~/server/utils/profile' const ProfileUpdateSchema = z.object({ displayName: z.string().trim().min(1).max(80).optional(), description: z.string().trim().max(500).optional(), avatarPath: z.string().nullable().optional(), }).strict().refine(value => Object.keys(value).length > 0, 'At least one profile field is required.') export default defineEventHandler(async (event) => { try { const user = await requireStageTwoUser(event) const update = ProfileUpdateSchema.parse(await readBody(event)) const expectedAvatarPath = `${user.id}/avatar` if (update.avatarPath !== undefined && update.avatarPath !== null && update.avatarPath !== expectedAvatarPath) { throw createError({ statusCode: 400, statusMessage: 'Invalid profile picture path.' }) } if (update.displayName !== undefined) requireStageTwoSafeText(update.displayName) if (update.description !== undefined) requireStageTwoSafeText(update.description) const changes: Record = { updated_at: new Date().toISOString() } if (update.displayName !== undefined) changes.display_name = update.displayName if (update.description !== undefined) changes.description = update.description if (update.avatarPath !== undefined) changes.avatar_path = update.avatarPath const profiles = await stageTwoDatabase(`profiles?id=eq.${user.id}`, { method: 'PATCH', body: JSON.stringify(changes), prefer: 'return=representation', }) if (!profiles[0]) throw createError({ statusCode: 404, statusMessage: 'Profile not found.' }) return { profile: visibleProfile(profiles[0], useRuntimeConfig().supabaseUrl) } } catch (error) { stageTwoApiError(error) } })