import { randomUUID } from "crypto" import { UserSchema, JsonValueSchema, type OberonDatabaseAdapter } from "@oberoncms/core" import { and, eq } from "drizzle-orm" import { z } from "zod" import { type DatabaseClient } from "./client" import { user } from "./schema" import { images, kv, pages, site } from "./schema" export const getDatabaseAdapter: (db: () => DatabaseClient) => OberonDatabaseAdapter = (db) => ({ getSite: async () => { const result = await db() .select({ version: site.version, components: site.components, updatedAt: site.updatedAt, updatedBy: site.updatedBy, }) .from(site) .where(eq(site.id, 1)) .execute() return result[0] }, updateSite: async ({ version, components, updatedAt, updatedBy }) => { await db() .insert(site) .values({ id: 1, version, components, updatedAt, updatedBy }) .onConflictDoUpdate({ target: site.id, set: { version, components, updatedAt, updatedBy }, }) .execute() }, addImage: async (image) => { await db().insert(images).values(image).execute() }, deleteImage: async (key) => { await db().delete(images).where(eq(images.key, key)).execute() }, getAllImages: async () => { return await db() .select({ key: images.key, alt: images.alt, url: images.url, size: images.size, height: images.height, width: images.width, updatedAt: images.updatedAt, updatedBy: images.updatedBy, }) .from(images) .execute() }, addPage: async ({ key, data, updatedAt, updatedBy }) => { await db().insert(pages).values({ key, data, updatedAt, updatedBy }).execute() }, deletePage: async (key) => { await db().delete(pages).where(eq(pages.key, key)).execute() }, deleteKV: async (namespace, key) => { await db() .delete(kv) .where(and(eq(kv.namespace, namespace), eq(kv.key, key))) .execute() }, getPageData: async (key) => { const result = await db() .select({ data: pages.data, }) .from(pages) .where(eq(pages.key, key)) .execute() return result[0]?.data || null }, getKV: async (namespace, key) => { const result = await db() .select({ value: kv.value }) .from(kv) .where(and(eq(kv.namespace, namespace), eq(kv.key, key))) .execute() const value = result[0]?.value return value === undefined ? null : JsonValueSchema.parse(value) }, updatePageData: async ({ key, data, updatedAt, updatedBy }) => { await db() .insert(pages) .values({ key, data, updatedAt, updatedBy }) .onConflictDoUpdate({ target: pages.key, set: { data, updatedAt, updatedBy }, }) .execute() }, putKV: async (namespace, key, value) => { await db() .insert(kv) .values({ namespace, key, value }) .onConflictDoUpdate({ target: [kv.namespace, kv.key], set: { value }, }) .execute() }, getAllPages: async () => { return await db() .select({ key: pages.key, updatedAt: pages.updatedAt, updatedBy: pages.updatedBy, }) .from(pages) .execute() }, getAllUsers: async () => { return z .array(UserSchema) .parse( await db().select({ id: user.id, email: user.email, role: user.role }).from(user).execute(), ) }, addUser: async ({ email, role }) => { const result = await db() .insert(user) .values({ id: randomUUID(), name: email, email, role }) .returning({ id: user.id, email: user.email, role: user.role }) .execute() const createdUser = result[0] if (!createdUser) { throw new Error("Failed to create user.") } return UserSchema.parse(createdUser) }, deleteUser: async (id) => { await db().delete(user).where(eq(user.id, id)).execute() }, changeRole: async ({ role, id }) => { await db().update(user).set({ role }).where(eq(user.id, id)).execute() }, })