import { httpBatchLink } from "@trpc/client"; import { createTRPCReact } from "@trpc/react-query"; import { useCallback, useEffect, useRef, useState, type ReactNode, } from "react"; import SuperJSON from "superjson"; import { useAccounts } from "@/contexts/AccountsContext"; import { useAuthClient, useSession } from "@/contexts/AuthContext"; import { getAuthCookieHeaders } from "@/lib/auth-cookie"; import { performAuthReset } from "@/lib/auth-session"; import { createAppQueryClient } from "@/lib/query-client"; import type { AppRouter } from "beenvoice/server/api/root"; export const api = createTRPCReact(); export function TRPCProvider({ apiUrl, children, }: { apiUrl: string; children: ReactNode; }) { const authClient = useAuthClient(); const { authStoragePrefix, activeAccountId, clearActiveAccount } = useAccounts(); const { refetch } = useSession(); const authStoragePrefixRef = useRef(authStoragePrefix); authStoragePrefixRef.current = authStoragePrefix; const mountedRef = useRef(true); const resettingRef = useRef(false); useEffect(() => { mountedRef.current = true; return () => { mountedRef.current = false; }; }, []); const handleUnauthorized = useCallback(async () => { if (!activeAccountId || resettingRef.current || !mountedRef.current) return; const session = await authClient.getSession(); if (session.data?.user || !mountedRef.current) return; resettingRef.current = true; try { await performAuthReset({ authClient, clearActiveAccount, activeAccountId, refetchSession: refetch, }); } finally { resettingRef.current = false; } }, [authClient, clearActiveAccount, activeAccountId, refetch]); const onUnauthorizedRef = useRef(handleUnauthorized); onUnauthorizedRef.current = handleUnauthorized; const [queryClient] = useState(() => createAppQueryClient(() => { void onUnauthorizedRef.current(); }), ); const [trpcClient] = useState(() => api.createClient({ links: [ httpBatchLink({ url: `${apiUrl}/api/trpc`, transformer: SuperJSON, headers() { return getAuthCookieHeaders( authClient, authStoragePrefixRef.current, ); }, }), ], }), ); return ( {children} ); }