UNPKG

@convex-dev/better-auth

Version:
96 lines 3.87 kB
import { jsx as _jsx } from "react/jsx-runtime"; import isNetworkError from "is-network-error"; import { createContext, useCallback, useContext, useEffect, useMemo, } from "react"; const ConvexAuthInternalContext = createContext(undefined); export function useAuth() { return useContext(ConvexAuthInternalContext); } export function AuthProvider({ client, authClient, children, }) { const { data: session, isPending: isSessionPending } = authClient.useSession(); const verbose = client.verbose ?? false; const logVerbose = useCallback((message) => { if (verbose) { console.debug(`${new Date().toISOString()} ${message}`); client.logger?.logVerbose(message); } }, [verbose]); const fetchToken = useCallback(async () => { const initialBackoff = 100; const maxBackoff = 1000; let retries = 0; const nextBackoff = () => { const baseBackoff = initialBackoff * Math.pow(2, retries); retries += 1; const actualBackoff = Math.min(baseBackoff, maxBackoff); const jitter = actualBackoff * (Math.random() - 0.5); return actualBackoff + jitter; }; const fetchWithRetry = async () => { try { const { data } = await authClient.convex.token(); return data?.token || null; } catch (e) { if (!isNetworkError(e)) { throw e; } if (retries > 10) { logVerbose(`fetchToken failed with network error, giving up`); throw e; } const backoff = nextBackoff(); logVerbose(`fetchToken failed with network error, attempting retrying in ${backoff}ms`); await new Promise((resolve) => setTimeout(resolve, backoff)); return fetchWithRetry(); } }; return fetchWithRetry(); }, [client]); const fetchAccessToken = useCallback(async ({ forceRefreshToken }) => { if (forceRefreshToken) { const token = await fetchToken(); logVerbose(`returning retrieved token`); return token; } return null; }, [fetchToken]); useEffect(() => { // eslint-disable-next-line @typescript-eslint/no-floating-promises (async () => { const url = new URL(window.location?.href); const token = url.searchParams.get("ott"); if (token) { const authClientWithCrossDomain = authClient; url.searchParams.delete("ott"); const result = await authClientWithCrossDomain.crossDomain.oneTimeToken.verify({ token, }); const session = result.data?.session; if (session) { await authClient.getSession({ fetchOptions: { headers: { Authorization: `Bearer ${session.token}`, }, }, }); authClientWithCrossDomain.updateSession(); } window.history.replaceState({}, "", url); } })(); }, // Explicitly chosen dependencies. // This effect should mostly only run once // on mount. [client, authClient]); const isAuthenticated = session !== null; const isLoading = isSessionPending; const authState = useMemo(() => ({ isLoading, isAuthenticated, fetchAccessToken, }), [fetchAccessToken, isLoading, isAuthenticated]); return (_jsx(ConvexAuthInternalContext.Provider, { value: authState, children: children })); } //# sourceMappingURL=client.js.map