all repos — caroster @ 4c733c75c7cd8b445013383eee26c32cc30621c6

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