| 1 | "use client"; |
| 2 | |
| 3 | import type { AuthClient } |
| 4 | import { |
| 5 | useAuth, |
| 6 | useSession, |
| 7 | type UseSessionOptions, |
| 8 | } from "@better-auth-ui/react"; |
| 9 | import { useEffect } |
| 10 | |
| 11 | /** Whether an unauthenticated visitor should be bounced to sign-in. `useSession` serves the stale `null` from a signed-out visit while the refetch is in flight, and redirecting on it loops straight back to sign-in. An in-flight fetch is undecided. */ |
| 12 | export function shouldRedirectToSignIn(session |
| 13 | data: unknown |
| 14 | isPending: boolean |
| 15 | isFetching: boolean |
| 16 | }) { |
| 17 | return !session.data |
| 18 | } |
| 19 | |
| 20 | /** `useSession` plus a redirect to sign-in for unauthenticated visitors, with the current URL preserved as `redirectTo`. Drop-in replacement for `@better-auth-ui/react`'s `useAuthenticate`, which redirects on a stale session value. */ |
| 21 | export function useAuthenticate<TAuthClient |
| 22 | authClient: TAuthClient |
| 23 | options?: UseSessionOptions |
| 24 | ) { |
| 25 | const { basePaths, |
| 26 | const session = |
| 27 | const { data, |
| 28 | |
| 29 | useEffect(() => |
| 30 | if (!shouldRedirectToSignIn({ |
| 31 | |
| 32 | const currentURL = |
| 33 | const redirectTo = |
| 34 | |
| 35 | navigate({ |
| 36 | to: `${basePaths. |
| 37 | replace: true, |
| 38 | }); |
| 39 | }, [ |
| 40 | basePaths.auth, |
| 41 | data, |
| 42 | isFetching, |
| 43 | isPending, |
| 44 | navigate, |
| 45 | viewPaths.auth.signIn |
| 46 | ]); |
| 47 | |
| 48 | return session; |
| 49 | } |