71 lines
2.1 KiB
TypeScript
71 lines
2.1 KiB
TypeScript
import "server-only";
|
|
|
|
import { prisma } from "@/lib/db";
|
|
|
|
// Fixed id of the one-and-only AiSettings row (see prisma/schema.prisma).
|
|
const SETTINGS_ID = "singleton";
|
|
|
|
export interface AiSettingsView {
|
|
apiUrl: string | null;
|
|
model: string | null;
|
|
hasApiKey: boolean;
|
|
// Last 4 characters only (e.g. "••••••••f00d") -- enough to confirm
|
|
// *which* key is configured without ever sending the real one back to
|
|
// the browser. Null when no key is set.
|
|
apiKeyMasked: string | null;
|
|
}
|
|
|
|
function maskKey(key: string): string {
|
|
return `••••••••${key.slice(-4)}`;
|
|
}
|
|
|
|
/** The client-safe view of the AI settings -- never includes the real key. */
|
|
export async function getAiSettingsView(): Promise<AiSettingsView> {
|
|
const settings = await prisma.aiSettings.findUnique({ where: { id: SETTINGS_ID } });
|
|
return {
|
|
apiUrl: settings?.apiUrl ?? null,
|
|
model: settings?.model ?? null,
|
|
hasApiKey: !!settings?.apiKey,
|
|
apiKeyMasked: settings?.apiKey ? maskKey(settings.apiKey) : null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* The real, unmasked key -- for server-side use only (calling the
|
|
* provider). Never pass this to a client component or return it from a
|
|
* Server Action.
|
|
*/
|
|
export async function getAiCredentials(): Promise<{
|
|
apiUrl: string | null;
|
|
apiKey: string | null;
|
|
}> {
|
|
const settings = await prisma.aiSettings.findUnique({ where: { id: SETTINGS_ID } });
|
|
return { apiUrl: settings?.apiUrl ?? null, apiKey: settings?.apiKey ?? null };
|
|
}
|
|
|
|
/**
|
|
* `apiKey` omitted (or empty) means "leave the currently saved key
|
|
* alone" -- the form field is never prefilled with the real key, so
|
|
* there's nothing to resubmit when the admin isn't changing it.
|
|
*/
|
|
export async function saveAiSettings(data: {
|
|
apiUrl: string;
|
|
apiKey?: string;
|
|
model: string;
|
|
}): Promise<void> {
|
|
await prisma.aiSettings.upsert({
|
|
where: { id: SETTINGS_ID },
|
|
create: {
|
|
id: SETTINGS_ID,
|
|
apiUrl: data.apiUrl,
|
|
apiKey: data.apiKey || null,
|
|
model: data.model,
|
|
},
|
|
update: {
|
|
apiUrl: data.apiUrl,
|
|
model: data.model,
|
|
...(data.apiKey ? { apiKey: data.apiKey } : {}),
|
|
},
|
|
});
|
|
}
|