import { and, asc, eq, ne } from 'drizzle-orm'; import { db } from '../db'; import { providers } from './schema'; export type Provider = typeof providers.$inferSelect; export type NewProvider = typeof providers.$inferInsert; export async function listProviders(): Promise { return db.select().from(providers).orderBy(asc(providers.name)); } export async function getProvider(id: string): Promise { const [row] = await db.select().from(providers).where(eq(providers.id, id)).limit(1); return row; } export async function getProviderByName(name: string): Promise { const [row] = await db.select().from(providers).where(eq(providers.name, name)).limit(1); return row; } /** * Which provider serves a request, in the order a caller would expect. * * 1. the model, if exactly one enabled provider offers it * 2. the model, preferring the default when several do — two keys for the same model is an * ordinary thing and the tie has to break somewhere stable * 3. the default provider, for a model nothing is configured for * * Step 3 is deliberate rather than a 404. Vendors ship models faster than rows get added, and the * request still names a model the adapter will happily pass along — refusing it would make Atelier * the reason a brand-new model cannot be used. */ export async function resolveProviderForModel(model: string | undefined): Promise { if (model) { const candidates = await db .select() .from(providers) .where(and(eq(providers.model, model), eq(providers.enabled, true))) .orderBy(asc(providers.createdAt)); const match = candidates.find((row) => row.isDefault) ?? candidates[0]; if (match) return match; } return defaultProvider(); } export async function defaultProvider(): Promise { const [byFlag] = await db .select() .from(providers) .where(and(eq(providers.isDefault, true), eq(providers.enabled, true))) .limit(1); if (byFlag) return byFlag; // No flag set — the oldest enabled row, so a single-provider install needs no configuration at all. const [oldest] = await db .select() .from(providers) .where(eq(providers.enabled, true)) .orderBy(asc(providers.createdAt)) .limit(1); return oldest; } export async function createProvider(values: NewProvider): Promise { const [row] = await db.insert(providers).values(values).returning(); if (row?.isDefault) await clearOtherDefaults(row.id); return row!; } export async function updateProvider(id: string, values: Partial): Promise { const [row] = await db .update(providers) .set({ ...values, updatedAt: new Date() }) .where(eq(providers.id, id)) .returning(); if (row?.isDefault) await clearOtherDefaults(id); return row; } export async function deleteProvider(id: string): Promise { await db.delete(providers).where(eq(providers.id, id)); } /** * Exactly one default. * * Enforced by clearing the others on write rather than by a partial unique index, because the write * that sets a new default would otherwise have to clear the old one first — two statements racing to * leave zero defaults instead of two. */ async function clearOtherDefaults(keepId: string): Promise { await db .update(providers) .set({ isDefault: false }) .where(and(eq(providers.isDefault, true), ne(providers.id, keepId))); }