import { and, eq } from 'drizzle-orm'; import * as z from 'zod'; import { settings } from '~~/drizzle/schema'; import { db } from '~~/server/lib/db'; const appearanceSchema = z.object({ colorScheme: z.enum(['light', 'dark', 'system']).optional(), accent: z.string().optional(), neutral: z.string().optional(), hinting: z.number().min(0).max(100).optional(), fontSize: z.string().optional(), }); const updateSettingsSchema = z.object({ systemAssistants: z.any().optional(), appearance: appearanceSchema.optional(), }); export default defineEventHandler(async (event) => { await protectRoute(event); const userId = event.context.user!.id as string; const body = await readBody(event); const parseResult = updateSettingsSchema.safeParse(body); if (!parseResult.success) { throw createError({ statusCode: 400, message: parseResult.error.issues[0]!.message, }); } const updates = parseResult.data; const existing = await db.query.settings.findFirst({ where: { userId }, }); if (!existing) { throw createError({ statusCode: 404, statusMessage: 'Settings not found', }); } const existingId: string = existing.id; const mergeAppearance = ( existingAppearance: Record | null, incoming: typeof updates.appearance, ): Record => { const base = existingAppearance || {}; if (!incoming) return base; return { ...base, ...incoming }; }; const mergeSystemAssistants = ( existingSA: Record | null, incoming: typeof updates.systemAssistants, ): Record => { const base = existingSA || {}; if (!incoming) return base; return { ...base, ...incoming }; }; const newAppearance = mergeAppearance( existing.appearance as Record | null, updates.appearance, ); const newSystemAssistants = mergeSystemAssistants( existing.systemAssistants as Record | null, updates.systemAssistants, ); await db.update(settings) .set({ appearance: newAppearance, systemAssistants: newSystemAssistants, }) .where(and(eq(settings.id, existingId))); const updated = await db.select() .from(settings) .where(and(eq(settings.id, existingId))) .limit(1); return updated[0]; });