import "react-native-url-polyfill/auto"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { createClient } from "@supabase/supabase-js"; import Constants from "expo-constants"; const supabaseUrl = Constants.expoConfig?.extra?.supabaseUrl as string; const supabaseAnonKey = Constants.expoConfig?.extra?.supabaseAnonKey as string; if (!supabaseUrl || !supabaseAnonKey) { throw new Error( "Supabase URL und Anon Key müssen in app.config.ts (extra) gesetzt sein. " + "EXPO_PUBLIC_SUPABASE_URL + EXPO_PUBLIC_SUPABASE_ANON_KEY in env.", ); } export const supabase = createClient(supabaseUrl, supabaseAnonKey, { auth: { storage: AsyncStorage, autoRefreshToken: true, persistSession: true, detectSessionInUrl: false, }, realtime: { // WICHTIG: vsn '1.0.0' (reines JSON-Text-Protokoll) statt default '2.0.0' // (Phoenix-V2-Binary). Unser self-hosted Realtime-Container v2.28.32 hat // den V2-Binary-Decoder nicht — bekommt er einen Binary-Frame, crasht der // Channel-Process mit FunctionClauseError und reißt ALLE anderen Channels // auf demselben Socket mit (1011 / "socket closed 1011"). Spam von // notifRealtime/approvalRealtime + Call-Ring-Drops sind genau das. // Sobald der Realtime-Container auf >=v2.34 upgraded ist, kann dieser // Override entfernt werden. Repo-Memory: supabase-realtime-binary-crash.md vsn: '1.0.0', params: { apikey: supabaseAnonKey, }, // Auto-refresh Token on every heartbeat so Realtime keeps working across // long sessions. Without this, manual setAuth() calls in subscribe-hooks // set _manuallySetToken=true which blocks the internal token-refresh — after // 1h the cached access_token expires and Postgres-Changes silently stop // arriving. See `project_session_2026-05-15_push.md` for the full root-cause. accessToken: async () => { const { data } = await supabase.auth.getSession(); return data.session?.access_token ?? null; }, }, });