all repos — caroster @ 512757d6ae90dfc3ddae08bb34ddb889ee3ec54f

[Octree] Group carpool to your event https://caroster.io

frontend/lib/apolloClient.ts (view raw)

 1import {useMemo} from 'react';
 2import {ApolloClient, HttpLink, InMemoryCache, from} from '@apollo/client';
 3import {setContext} from '@apollo/client/link/context';
 4import {onError} from '@apollo/client/link/error';
 5import merge from 'deepmerge';
 6import isEqual from 'lodash/isEqual';
 7import {useSession} from 'next-auth/react';
 8import {Session} from 'next-auth';
 9
10export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__';
11let apolloClient: ApolloClient<any>;
12
13const authLink = (session: Session | null) =>
14  setContext(async (_, {headers}) => {
15    const token = session?.token?.jwt;
16    // return the headers to the context so httpLink can read them
17    return {
18      headers: {
19        ...headers,
20        authorization: token ? `Bearer ${token}` : '',
21      },
22    };
23  });
24
25const errorLink = onError(({graphQLErrors = [], operation}) => {
26  console.error({graphQLErrors, operation});
27  const message = graphQLErrors?.[0]?.message;
28
29  if (message === 'Forbidden') window.location.href = '/auth/login';
30});
31
32const httpLink = (uri: string) =>
33  new HttpLink({
34    uri, // Server URL (must be absolute)
35    credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
36  });
37
38const createApolloClient = (uri: string, session: Session | null) => {
39  return new ApolloClient({
40    ssrMode: typeof window === 'undefined',
41    link: from([authLink(session), errorLink, httpLink(uri)]),
42    cache: new InMemoryCache(),
43  });
44};
45
46export const initializeApollo = (
47  uri: string,
48  session: Session | null,
49  initialState = null
50) => {
51  const _apolloClient = apolloClient ?? createApolloClient(uri, session);
52
53  // If your page has Next.js data fetching methods that use Apollo Client, the initial state gets hydrated here
54  if (initialState) {
55    // Get existing cache, loaded during client side data fetching
56    const existingCache = _apolloClient.extract();
57    // Merge the existing cache into data passed from getStaticProps/getServerSideProps
58    const data = merge(initialState, existingCache, {
59      // Combine arrays using object equality (like in sets)
60      arrayMerge: (destinationArray, sourceArray) => [
61        ...sourceArray,
62        ...destinationArray.filter(d => sourceArray.every(s => !isEqual(d, s))),
63      ],
64    });
65    // Restore the cache with the merged data
66    _apolloClient.cache.restore(data);
67  }
68
69  // For SSG and SSR always create a new Apollo Client
70  if (typeof window === 'undefined') return _apolloClient;
71
72  // Create the Apollo Client once in the client
73  if (!apolloClient) apolloClient = _apolloClient;
74  return _apolloClient;
75};
76
77export const addApolloState = (client: ApolloClient<any>, pageProps: any) => {
78  if (pageProps?.props) {
79    pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
80  }
81  return pageProps;
82};
83
84export const useApollo = (pageProps: any) => {
85  const state = pageProps[APOLLO_STATE_PROP_NAME];
86  const {data: session} = useSession();
87  return useMemo(() => initializeApollo('', session, state), [state, session]);
88};