TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { z } from "zod";2import { eq } from "drizzle-orm";3import { withUser, parseBody, json } from "@/lib/api";4import { getDb, userPreferences, users } from "@/db";56export const dynamic = "force-dynamic";78export async function loadPreferences(userId: string) {9 const db = getDb();10 let [row] = await db.select().from(userPreferences).where(eq(userPreferences.userId, userId)).limit(1);11 if (!row) {12 [row] = await db.insert(userPreferences).values({ userId }).onConflictDoNothing().returning();13 if (!row) [row] = await db.select().from(userPreferences).where(eq(userPreferences.userId, userId)).limit(1);14 }15 return row;16}1718export const GET = withUser(async ({ user }) => json({ preferences: await loadPreferences(user.id) }));1920const schema = z.object({21 theme: z.enum(["system", "light", "dark"]).optional(),22 language: z.string().max(8).optional(),23 defaultModelKey: z.string().max(120).nullable().optional(),24 defaultSystemPrompt: z.string().max(20_000).nullable().optional(),25 enterToSend: z.boolean().optional(),26 streaming: z.boolean().optional(),27 codeWrap: z.boolean().optional(),28 showReasoning: z.boolean().optional(),29 showCosts: z.boolean().optional(),30 autoTitle: z.boolean().optional(),31 onboardingCompleted: z.boolean().optional(),32 extra: z.record(z.string(), z.unknown()).optional(),33});3435export const PATCH = withUser(async ({ req, user }) => {36 const body = await parseBody(req, schema);37 const { onboardingCompleted, ...prefs } = body;38 const db = getDb();39 await loadPreferences(user.id);40 const [row] = await db41 .update(userPreferences)42 .set({ ...prefs, updatedAt: new Date() })43 .where(eq(userPreferences.userId, user.id))44 .returning();45 if (onboardingCompleted) await db.update(users).set({ onboardingCompletedAt: new Date() }).where(eq(users.id, user.id));46 return json({ preferences: row });47});48