import type { GalleryFeatures, ThemeTokens } from '@photo-gallery/sdk'; /** * Reads NEXT_PUBLIC_APG_* environment variables into props so the * whole gallery can be customized without touching code. Every value is optional * — anything unset falls back to the SDK's built-in defaults (dark/light/semi-dark). * * See docs/ENV.md for the full list. * * NOTE: Next.js only inlines NEXT_PUBLIC_* vars that are referenced statically, so * each one is read explicitly below (not via a dynamic key). */ const bool = (v: string | undefined): boolean | undefined => v === undefined || v === '' ? undefined : v === 'true' || v === '1'; const num = (v: string | undefined): number | undefined => { if (v === undefined || v === '') return undefined; const n = Number(v); return Number.isFinite(n) ? n : undefined; }; /** Drop undefined entries so partial objects don't clobber SDK defaults. */ function compact(obj: T): Partial { return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined)) as Partial; } export function getFeaturesFromEnv(): Partial { return compact({ editor: bool(process.env.NEXT_PUBLIC_APG_EDITOR), camera: bool(process.env.NEXT_PUBLIC_APG_CAMERA), ai: bool(process.env.NEXT_PUBLIC_APG_AI), map: bool(process.env.NEXT_PUBLIC_APG_MAP), import: bool(process.env.NEXT_PUBLIC_APG_IMPORT), export: bool(process.env.NEXT_PUBLIC_APG_EXPORT), sharing: bool(process.env.NEXT_PUBLIC_APG_SHARING), }); } export function getThemeTokensFromEnv(): ThemeTokens | undefined { const tokens = compact({ bgLight: process.env.NEXT_PUBLIC_APG_BG_LIGHT || undefined, bgDark: process.env.NEXT_PUBLIC_APG_BG_DARK || undefined, elevatedLight: process.env.NEXT_PUBLIC_APG_ELEVATED_LIGHT || undefined, elevatedDark: process.env.NEXT_PUBLIC_APG_ELEVATED_DARK || undefined, sidebarBgLight: process.env.NEXT_PUBLIC_APG_SIDEBAR_BG_LIGHT || undefined, sidebarBgDark: process.env.NEXT_PUBLIC_APG_SIDEBAR_BG_DARK || undefined, textLight: process.env.NEXT_PUBLIC_APG_TEXT_LIGHT || undefined, textDark: process.env.NEXT_PUBLIC_APG_TEXT_DARK || undefined, sidebarRadius: num(process.env.NEXT_PUBLIC_APG_SIDEBAR_RADIUS), accent: process.env.NEXT_PUBLIC_APG_ACCENT || undefined, }) as ThemeTokens; return Object.keys(tokens).length ? tokens : undefined; } export interface EnvGalleryConfig { features: Partial; themeTokens?: ThemeTokens; borderRadius?: number; theme?: 'system' | 'light' | 'dark' | 'semi-dark'; } export function getGalleryConfigFromEnv(): EnvGalleryConfig { const theme = process.env.NEXT_PUBLIC_APG_THEME as EnvGalleryConfig['theme'] | undefined; // Accent comes through themeTokens.accent (PhotoGallery reads it there) — no // separate accentColor field, to avoid a confusing double source for one env var. return { features: getFeaturesFromEnv(), themeTokens: getThemeTokensFromEnv(), borderRadius: num(process.env.NEXT_PUBLIC_APG_RADIUS), theme: theme || undefined, }; }