feat: ditch triplit, move to postgresql + drizzle orm

This commit is contained in:
Zoe
2026-04-08 17:03:07 -05:00
parent c341c96798
commit e2e3ac6e86
121 changed files with 6680 additions and 4373 deletions
+34
View File
@@ -0,0 +1,34 @@
import { and, eq } from 'drizzle-orm';
import { settings } from '~~/drizzle/schema';
import { db } from '~~/server/lib/db';
const defaultAppearance = {
colorScheme: 'system' as const,
accent: 'violet',
neutral: 'zinc',
hinting: 0,
fontSize: 'md',
};
export default defineEventHandler(async (event) => {
await protectRoute(event);
const userId = event.context.user!.id as string;
const existing = await db.query.settings.findFirst({
where: { userId },
});
if (existing) {
return existing;
}
const [created] = await db.insert(settings)
.values({
userId,
systemAssistants: {},
appearance: defaultAppearance,
})
.returning();
return created;
});
+87
View File
@@ -0,0 +1,87 @@
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<string, unknown> | null,
incoming: typeof updates.appearance,
): Record<string, unknown> => {
const base = existingAppearance || {};
if (!incoming) return base;
return { ...base, ...incoming };
};
const mergeSystemAssistants = (
existingSA: Record<string, unknown> | null,
incoming: typeof updates.systemAssistants,
): Record<string, unknown> => {
const base = existingSA || {};
if (!incoming) return base;
return { ...base, ...incoming };
};
const newAppearance = mergeAppearance(
existing.appearance as Record<string, unknown> | null,
updates.appearance,
);
const newSystemAssistants = mergeSystemAssistants(
existing.systemAssistants as Record<string, unknown> | 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];
});