all repos — caroster @ 4e9d21c0ca253718b3f38dcd46c4bfa17db1e3f0

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