all repos — caroster @ 3f36f7140b41721e898b57f036cd828e2c6e29ea

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