Stabilize mobile auth session handling

This commit is contained in:
2026-06-29 17:58:50 -04:00
parent 477459edd4
commit 57e1aa658a
25 changed files with 1126 additions and 192 deletions
+50 -10
View File
@@ -1,25 +1,65 @@
import { httpBatchLink } from "@trpc/client";
import { createTRPCReact } from "@trpc/react-query";
import { useCallback, useRef, useState, type ReactNode } from "react";
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<AppRouter>();
export function TRPCProvider({ apiUrl, children }: { apiUrl: string; children: ReactNode }) {
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) {
await authClient.signOut();
await refetch();
if (session.data?.user || !mountedRef.current) return;
resettingRef.current = true;
try {
await performAuthReset({
authClient,
clearActiveAccount,
activeAccountId,
refetchSession: refetch,
});
} finally {
resettingRef.current = false;
}
}, [authClient, refetch]);
}, [authClient, clearActiveAccount, activeAccountId, refetch]);
const onUnauthorizedRef = useRef(handleUnauthorized);
onUnauthorizedRef.current = handleUnauthorized;
@@ -37,10 +77,10 @@ export function TRPCProvider({ apiUrl, children }: { apiUrl: string; children: R
url: `${apiUrl}/api/trpc`,
transformer: SuperJSON,
headers() {
const cookie = (
authClient as { getCookie?: () => string | null | undefined }
).getCookie?.();
return cookie ? { cookie } : {};
return getAuthCookieHeaders(
authClient,
authStoragePrefixRef.current,
);
},
}),
],