import { eq, inArray } from "drizzle-orm"; import type { AppDatabase } from "../database-context.js"; import { documentBrandingAssets, type DocumentBrandingAsset, } from "../schema/document-branding-assets.js"; import { documentBrandingSettings } from "../schema/document-branding-settings.js"; // Plain repository without revision semantics: branding is global office // configuration, not a project mutation. export class DocumentBrandingRepository { constructor(private readonly db: AppDatabase) {} get(key: string): DocumentBrandingAsset | undefined { return this.db .select() .from(documentBrandingAssets) .where(eq(documentBrandingAssets.key, key)) .get(); } upsert(asset: { key: string; mimeType: string; fileName: string | null; data: Buffer; }): DocumentBrandingAsset { const updatedAt = new Date(); return this.db .insert(documentBrandingAssets) .values({ ...asset, updatedAt }) .onConflictDoUpdate({ target: documentBrandingAssets.key, set: { mimeType: asset.mimeType, fileName: asset.fileName, data: asset.data, updatedAt, }, }) .returning() .get(); } delete(key: string): boolean { return ( this.db .delete(documentBrandingAssets) .where(eq(documentBrandingAssets.key, key)) .run().changes > 0 ); } getSettings(keys: readonly TKey[]): Record { const rows = this.db .select() .from(documentBrandingSettings) .where(inArray(documentBrandingSettings.key, [...keys])) .all(); return Object.fromEntries( keys.map((key) => [key, rows.find((row) => row.key === key)?.value ?? null]) ) as Record; } /** Stores the given values atomically; `null` removes a setting. */ setSettings(values: Record) { const updatedAt = new Date(); this.db.transaction((tx) => { for (const [key, value] of Object.entries(values)) { if (value === null) { tx.delete(documentBrandingSettings) .where(eq(documentBrandingSettings.key, key)) .run(); } else { tx.insert(documentBrandingSettings) .values({ key, value, updatedAt }) .onConflictDoUpdate({ target: documentBrandingSettings.key, set: { value, updatedAt }, }) .run(); } } }); } }