| import { getLoginUrl } from "@/const"; |
| import { trpc } from "@/lib/trpc"; |
| import { TRPCClientError } from "@trpc/client"; |
| import { useCallback, useEffect, useMemo } from "react"; |
|
|
| type UseAuthOptions = { |
| redirectOnUnauthenticated?: boolean; |
| redirectPath?: string; |
| }; |
|
|
| export function useAuth(options?: UseAuthOptions) { |
| const { redirectOnUnauthenticated = false, redirectPath = getLoginUrl() } = |
| options ?? {}; |
| const utils = trpc.useUtils(); |
|
|
| const meQuery = trpc.auth.me.useQuery(undefined, { |
| retry: false, |
| refetchOnWindowFocus: false, |
| }); |
|
|
| const logoutMutation = trpc.auth.logout.useMutation({ |
| onSuccess: () => { |
| utils.auth.me.setData(undefined, null); |
| }, |
| }); |
|
|
| const logout = useCallback(async () => { |
| try { |
| await logoutMutation.mutateAsync(); |
| } catch (error: unknown) { |
| if ( |
| error instanceof TRPCClientError && |
| error.data?.code === "UNAUTHORIZED" |
| ) { |
| return; |
| } |
| throw error; |
| } finally { |
| utils.auth.me.setData(undefined, null); |
| await utils.auth.me.invalidate(); |
| } |
| }, [logoutMutation, utils]); |
|
|
| const state = useMemo(() => { |
| localStorage.setItem( |
| "manus-runtime-user-info", |
| JSON.stringify(meQuery.data) |
| ); |
| return { |
| user: meQuery.data ?? null, |
| loading: meQuery.isLoading || logoutMutation.isPending, |
| error: meQuery.error ?? logoutMutation.error ?? null, |
| isAuthenticated: Boolean(meQuery.data), |
| }; |
| }, [ |
| meQuery.data, |
| meQuery.error, |
| meQuery.isLoading, |
| logoutMutation.error, |
| logoutMutation.isPending, |
| ]); |
|
|
| useEffect(() => { |
| if (!redirectOnUnauthenticated) return; |
| if (meQuery.isLoading || logoutMutation.isPending) return; |
| if (state.user) return; |
| if (typeof window === "undefined") return; |
| if (window.location.pathname === redirectPath) return; |
|
|
| window.location.href = redirectPath |
| }, [ |
| redirectOnUnauthenticated, |
| redirectPath, |
| logoutMutation.isPending, |
| meQuery.isLoading, |
| state.user, |
| ]); |
|
|
| return { |
| ...state, |
| refresh: () => meQuery.refetch(), |
| logout, |
| }; |
| } |
|
|