import { gql } from '@apollo/client'; import { Session } from '@generated/types'; import { createContext, useContext } from 'react'; import { sessionFragment } from '../fragments'; import { useToastMutation } from '../hooks/useToastMutation'; import { url } from '../main'; interface AuthContextProps { headers: Session | null; setHeaders: (session: Session) => void; } export const AuthContext = createContext(null); export const AuthProvider = AuthContext.Provider; interface UseAuthOutput extends AuthContextProps { isAuthenticated: boolean; login: (value: { email: string; password: string }) => Promise; } export function useAuth(): UseAuthOutput { const authContext = useContext(AuthContext); const { update: login } = useToastMutation<{ login: Session }>({ mutation: loginMutation, successMsg: 'Logged in successfully.' }); if (!authContext) throw new Error('useAuth must be used within an AuthProvider'); return { ...authContext, isAuthenticated: authContext.headers != null, login: async ({ email, password }: { email: string; password: string }) => { const { data } = await login({ variables: { input: { email, password } } }); if (data != null) { authContext.setHeaders(data.login); return data.login; } return data; } }; } interface UseRestAuthOutput { refreshToken: () => Promise; } export function useRestAuth(): UseRestAuthOutput { return { refreshToken: async () => { try { const response = await fetch(`${url}/api/refreshAccessToken`, { credentials: 'include' }); if (!response.ok) { throw new Error(`[error]: ${response.status}`); } const session = await response.json(); return session; } catch (error) { console.error(error); } } }; } const loginMutation = gql` mutation AuthLogin($input: LoginInput!) { login(input: $input) { ...Session } } ${sessionFragment} `;