"use client"; import { useState, useEffect } from 'react'; interface ConfigData { appName: string; jmapServerUrl: string; oauthEnabled: boolean; oauthClientId: string; oauthIssuerUrl: string; rememberMeEnabled: boolean; devMode: boolean; } interface AppConfig extends ConfigData { isLoading: boolean; error: string | null; } let configCache: ConfigData | null = null; let configPromise: Promise | null = null; async function fetchConfig(): Promise { // Return cached config if available if (configCache) { return configCache; } // If a fetch is already in progress, wait for it if (configPromise) { return configPromise; } // Start a new fetch configPromise = fetch('/api/config') .then((res) => { if (!res.ok) { throw new Error('Failed to fetch config'); } return res.json(); }) .then((data) => { configCache = data; return data; }) .finally(() => { configPromise = null; }); return configPromise; } /** * Hook to fetch runtime configuration * * Fetches app configuration from /api/config endpoint, which reads * environment variables at runtime (not build time). * * The config is cached after first fetch to avoid unnecessary requests. */ export function useConfig(): AppConfig { const [config, setConfig] = useState({ appName: configCache?.appName || 'Webmail', jmapServerUrl: configCache?.jmapServerUrl || '', oauthEnabled: configCache?.oauthEnabled || false, oauthClientId: configCache?.oauthClientId || '', oauthIssuerUrl: configCache?.oauthIssuerUrl || '', rememberMeEnabled: configCache?.rememberMeEnabled || false, devMode: configCache?.devMode || false, isLoading: !configCache, error: null, }); useEffect(() => { // If already cached, no need to fetch if (configCache) { setConfig({ appName: configCache.appName, jmapServerUrl: configCache.jmapServerUrl, oauthEnabled: configCache.oauthEnabled, oauthClientId: configCache.oauthClientId, oauthIssuerUrl: configCache.oauthIssuerUrl, rememberMeEnabled: configCache.rememberMeEnabled, devMode: configCache.devMode, isLoading: false, error: null, }); return; } fetchConfig() .then((data) => { setConfig({ appName: data.appName, jmapServerUrl: data.jmapServerUrl, oauthEnabled: data.oauthEnabled, oauthClientId: data.oauthClientId, oauthIssuerUrl: data.oauthIssuerUrl, rememberMeEnabled: data.rememberMeEnabled, devMode: data.devMode, isLoading: false, error: null, }); }) .catch((err) => { setConfig((prev) => ({ ...prev, isLoading: false, error: err.message, })); }); }, []); return config; }