import "server-only"; import { PERMS } from "@/lib/permission-slugs"; import { authorizeHousekeeping } from "../../../foundation/authorization"; import { anyCapability, fail, type HousekeepingQuery, ok, } from "../../../foundation/contracts"; export interface SystemSettingRow { readonly key: string; readonly value: string; readonly comment?: string | null; } export interface SystemEmulatorTextResult { readonly rows: readonly SystemSettingRow[]; readonly total: number; } export interface SystemConfigurationAdapters { loadWebsiteSettings(): Promise; loadEmulatorSettings(): Promise; loadEmulatorTexts(): Promise; } export type SystemConfigurationQueryInput = | { readonly routeId: "system.configuration.settings" } | { readonly routeId: "system.configuration.emulator" }; export type SystemConfigurationQueryData = | { readonly kind: "settings"; readonly settings: readonly SystemSettingRow[]; readonly partialDependencies: readonly string[]; } | { readonly kind: "emulator"; readonly settings: readonly SystemSettingRow[]; readonly texts: readonly SystemSettingRow[]; readonly textsTotal: number; readonly partialDependencies: readonly string[]; }; const configurationCapability = anyCapability(PERMS.SETTINGS_VIEW); function unavailable(correlationId: string) { return fail( "DEPENDENCY_UNAVAILABLE", "errors.housekeeping.dependencyUnavailable", correlationId, ); } export function createSystemConfigurationQuery( adapters: SystemConfigurationAdapters, ): HousekeepingQuery< SystemConfigurationQueryInput, SystemConfigurationQueryData > { return { id: "system.configuration.query", owner: "system", capability: configurationCapability, async run(context, input) { const authorization = authorizeHousekeeping( context, configurationCapability, ); if (!authorization.ok) return authorization; const correlationId = authorization.correlationId; if (input.routeId === "system.configuration.settings") { try { return ok( { kind: "settings" as const, settings: await adapters.loadWebsiteSettings(), partialDependencies: [], }, correlationId, ); } catch { return unavailable(correlationId); } } const [settingsResult, textsResult] = await Promise.allSettled([ adapters.loadEmulatorSettings(), adapters.loadEmulatorTexts(), ]); if ( settingsResult.status === "rejected" && textsResult.status === "rejected" ) { return unavailable(correlationId); } const partialDependencies: string[] = []; if (settingsResult.status === "rejected") { partialDependencies.push("emulator-settings"); } if (textsResult.status === "rejected") { partialDependencies.push("emulator-texts"); } const textData = textsResult.status === "fulfilled" ? textsResult.value : { rows: [], total: 0 }; return ok( { kind: "emulator", settings: settingsResult.status === "fulfilled" ? settingsResult.value : [], texts: textData.rows, textsTotal: textData.total, partialDependencies, }, correlationId, ); }, }; } export const systemConfigurationAdapters: SystemConfigurationAdapters = { async loadWebsiteSettings() { const [{ asc }, { db, WebsiteSetting }] = await Promise.all([ import("drizzle-orm"), import("@/lib/db"), ]); return db .select({ key: WebsiteSetting.key, value: WebsiteSetting.value, comment: WebsiteSetting.comment, }) .from(WebsiteSetting) .orderBy(asc(WebsiteSetting.key)); }, async loadEmulatorSettings() { const [{ asc }, { db, EmulatorSettings }] = await Promise.all([ import("drizzle-orm"), import("@/lib/db"), ]); return db .select({ key: EmulatorSettings.key, value: EmulatorSettings.value }) .from(EmulatorSettings) .orderBy(asc(EmulatorSettings.key)); }, async loadEmulatorTexts() { const [{ asc, count }, { db, EmulatorTexts }] = await Promise.all([ import("drizzle-orm"), import("@/lib/db"), ]); const [rows, totals] = await Promise.all([ db .select({ key: EmulatorTexts.key, value: EmulatorTexts.value }) .from(EmulatorTexts) .orderBy(asc(EmulatorTexts.key)) .limit(300), db.select({ total: count() }).from(EmulatorTexts), ]); return { rows, total: Number(totals[0]?.total ?? 0) }; }, }; export const systemConfigurationQuery = createSystemConfigurationQuery( systemConfigurationAdapters, );