export interface AuthConfig { signInUrl: string; signUpUrl: string; salesEmail: string; salesMailto: string; } interface EnvLike { PUBLIC_AUTH_SIGNIN_URL?: string; PUBLIC_AUTH_SIGNUP_URL?: string; PUBLIC_SALES_EMAIL?: string; } function requireHttps(name: string, value: string | undefined): string { if (!value) { throw new Error(`${name} is required`); } if (!value.startsWith('https://')) { throw new Error(`${name} must be https (got: ${value})`); } return value; } function requireEmail(name: string, value: string | undefined): string { if (!value) { throw new Error(`${name} is required`); } // RFC-5322-ish minimal check — we just want to catch typos, not validate against RFC. if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) { throw new Error(`${name} must look like an email (got: ${value})`); } return value; } export function resolveAuthConfig(env: EnvLike): AuthConfig { const signInUrl = requireHttps('PUBLIC_AUTH_SIGNIN_URL', env.PUBLIC_AUTH_SIGNIN_URL); const signUpUrl = requireHttps('PUBLIC_AUTH_SIGNUP_URL', env.PUBLIC_AUTH_SIGNUP_URL); const salesEmail = requireEmail('PUBLIC_SALES_EMAIL', env.PUBLIC_SALES_EMAIL); return { signInUrl, signUpUrl, salesEmail, salesMailto: `mailto:${salesEmail}`, }; } // Lazy accessor for Astro usage. Not evaluated at module load (so vitest can // import this file without the PUBLIC_* env vars being set). Each call after // the first returns the cached config. let _cached: AuthConfig | null = null; export function getAuthConfig(): AuthConfig { if (_cached === null) { _cached = resolveAuthConfig(import.meta.env as unknown as EnvLike); } return _cached; }