/** Trim values — .env files edited on Windows often include stray \\r */ function clean(value: string | undefined): string | undefined { return value?.trim().replace(/\r$/, "").replace(/\n$/, ""); } export function getSupabaseEnv() { const url = clean(process.env.NEXT_PUBLIC_SUPABASE_URL); const anonKey = clean( process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ?? process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY ); if (!url) { throw new Error( "Missing NEXT_PUBLIC_SUPABASE_URL in .env.local — restart dev server after editing." ); } if (url.includes("your-project") || url.includes("YOUR_REF")) { throw new Error( "NEXT_PUBLIC_SUPABASE_URL is still the placeholder. Set your real URL in .env.local (e.g. https://vcxpcyafnlyiyqmapyyy.supabase.co) and restart npm run dev." ); } if (!url.startsWith("https://") || !url.includes(".supabase.co")) { throw new Error( "NEXT_PUBLIC_SUPABASE_URL should look like https://YOUR_REF.supabase.co" ); } if (!anonKey) { throw new Error( "Missing NEXT_PUBLIC_SUPABASE_ANON_KEY in .env.local — use the anon or publishable key from Dashboard → API." ); } return { url, anonKey }; } export function formatAuthNetworkError(cause: unknown): string { if (cause instanceof Error && cause.message.includes("NEXT_PUBLIC")) { return cause.message; } const msg = cause instanceof Error ? cause.message : String(cause); if (msg === "Failed to fetch" || msg.includes("NetworkError")) { return [ "Cannot reach Supabase (network error).", "• Confirm project is active in the Supabase dashboard", "• Use the full API key from Dashboard → API (try the legacy anon key starting with eyJ… if publishable key fails)", "• Restart: npm run dev after changing .env.local", "• Add http://localhost:3000 to Auth → URL configuration → Redirect URLs", ].join("\n"); } if (msg.includes("429") || /rate limit/i.test(msg)) { return [ "Too many requests to Supabase Auth (rate limited).", "Wait about 60 minutes before trying password reset again.", "See docs/PASSWORD_RESET.md for dashboard and dev workarounds.", ].join("\n"); } return msg || "Something went wrong. Please try again."; }