// EXPO_PUBLIC_* vars are inlined at bundle time by Expo's Babel plugin (or // shipped via EAS Secrets for EAS builds — see apps/mobile/README.md). // We pull them through a Proxy so missing vars throw on first READ, not at // module-eval time. That keeps the throw inside the React tree where the // boundary can render it as a readable screen instead of a blank // white window. function required(name: string): string { const v = process.env[name]; if (!v || v.length === 0) { throw new Error( 'Missing required env var ' + name + '. Set it via `eas secret:create --scope project --name ' + name + ' --value ...` or in apps/mobile/.env.local for local dev (see .env.example).', ); } return v; } interface EnvShape { supabaseUrl: string; supabaseAnonKey: string; authRedirectUrl: string; } function readEnv(): EnvShape { return { supabaseUrl: required('EXPO_PUBLIC_SUPABASE_URL'), supabaseAnonKey: required('EXPO_PUBLIC_SUPABASE_ANON_KEY'), authRedirectUrl: process.env.EXPO_PUBLIC_AUTH_REDIRECT_URL ?? 'netralax://auth/callback', }; } let cached: EnvShape | null = null; export const env: EnvShape = new Proxy({} as EnvShape, { get(_target, key: string | symbol): unknown { cached ??= readEnv(); return cached[key as keyof EnvShape]; }, });