import { ApolloClient , createHttpLink , InMemoryCache , NormalizedCacheObject } from "@apollo/client" ; import { setContext } from "@apollo/client/link/context" ; import { useMemo , useState } from "react" ; import { GetUserProjectsDocument , GetUserProjectsQuery , GetUserProjectsQueryVariables , Project , UserProjectFragment } from "src/generated/queries" ; import firebase from "./firebase" ; let apolloClient ; const httpLink = createHttpLink ( { uri : process . env . NEXT_PUBLIC_GQL_URI } ) ; const authLink = setContext ( async ( _ , { headers } ) => { const token = await firebase . auth ( ) . currentUser ?. getIdToken ( ) ; if ( token === undefined ) return { } ; return { headers : { ... headers , authorization : token } } ; } ) ; export async function getToken ( ) { const token = await firebase . auth ( ) . currentUser ?. getIdToken ( ) ; if ( token === undefined ) return "" ; return token ; } const projectIsUserProject = ( proj ) => [ "id" , "name" , "isPublic" , "summary" , "updatedAt" , "userId" ] . every ( ( prop ) => Object . hasOwnProperty . call ( proj , prop ) ) ; if ( ! globalThis . userProjectsServerFetched ) { globalThis . userProjectsServerFetched = [ ] ; } export function useGetUserProjectsLazyQueryFixedCache ( ) { const [ loading , setLoading ] = useState ( false ) ; const [ data , setData ] = useState < GetUserProjectsQuery > ( ) ; async function getUserProjects ( uid ) { setLoading ( true ) ; if ( ! globalThis . userProjectsServerFetched . includes ( uid ) ) { await apolloClient . query < GetUserProjectsQuery , GetUserProjectsQueryVariables > ( { query : GetUserProjectsDocument , variables : { user : uid } } ) ; globalThis . userProjectsServerFetched . push ( uid ) ; } const cache = apolloClient . cache . extract ( ) ; const userProjects = Object . values ( cache ) . filter ( ( val ) => val . __typename === "Project" && val . userId === uid && projectIsUserProject ( val ) ) . sort ( ( a , b ) => ( new Date ( ( b as UserProjectFragment ) . updatedAt ) . valueOf ( ) - new Date ( ( a as UserProjectFragment ) . updatedAt ) . valueOf ( ) ) . valueOf ( ) ) as UserProjectFragment [ ] ; const newData = { projects : userProjects } ; setData ( newData ) ; setLoading ( false ) ; return newData ; } return [ getUserProjects , { loading , data } ] ; } const createApolloClient = ( ) => new ApolloClient ( { ssrMode : typeof window === "undefined" , link : authLink . concat ( httpLink ) , cache : new InMemoryCache ( { typePolicies : { Query : { fields : { project ( _ , { args , toReference } ) { return toReference ( { __typename : "Project" , id : args ?. id } ) ; } } } } } ) } ) ; export function initializeApollo ( initialState = null ) { const _apolloClient = apolloClient ?? createApolloClient ( ) ; if ( initialState ) { const existingCache = _apolloClient . extract ( ) ; _apolloClient . cache . restore ( { ... existingCache , ... initialState } ) ; } if ( typeof window === "undefined" ) return _apolloClient ; if ( ! apolloClient ) apolloClient = _apolloClient ; return _apolloClient ; } export function useApollo ( initialState ) { const store = useMemo ( ( ) => initializeApollo ( initialState ) , [ initialState ] ) ; return store ; }