fix(mobile): lazy env proxy so missing EXPO_PUBLIC vars throw inside React

This commit is contained in:
byGalax
2026-05-16 16:21:02 +02:00
parent 3b884b0415
commit c430a590fc
2 changed files with 61 additions and 9 deletions
+31 -9
View File
@@ -1,19 +1,41 @@
// EXPO_PUBLIC_* vars are inlined at bundle time by Expo's Babel plugin.
// We pull them through a single typed module so a missing var is a loud
// startup error rather than a confusing Supabase 401 later.
// 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
// <BootError> 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 in apps/mobile/.env.local — see .env.example.',
'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;
}
export const env = {
supabaseUrl: required('EXPO_PUBLIC_SUPABASE_URL'),
supabaseAnonKey: required('EXPO_PUBLIC_SUPABASE_ANON_KEY'),
authRedirectUrl: process.env.EXPO_PUBLIC_AUTH_REDIRECT_URL ?? 'netralax://auth/callback',
} as const;
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];
},
});