all repos — caroster @ c9431ff683ab033ba72e02b265828cc6d9fda700

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

frontend/lib/apolloClient.tsx (view raw)

 1import {useMemo} from 'react';
 2import {ApolloClient, HttpLink, InMemoryCache} 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 useAuthStore from '../stores/useAuthStore';
 8
 9const {STRAPI_URL = ''} = process.env;
10
11export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__';
12
13export let apolloClient;
14
15const httpLink = new HttpLink({
16  uri: `${STRAPI_URL}/graphql`, // Server URL (must be absolute)
17  credentials: 'same-origin', // Additional fetch() options like `credentials` or `headers`
18});
19
20const handleError = onError(({graphQLErrors = [], ...details}) => {
21  const [error] = graphQLErrors;
22  console.error({graphQLErrors, error, details});
23
24  if (error?.message === 'Invalid token.') {
25    useAuthStore.getState().logout();
26  } else if (error?.message == 'Forbidden') {
27    window.location.href = '/auth/login';
28  }
29});
30
31const createApolloClient = token => {
32  return new ApolloClient({
33    ssrMode: typeof window === 'undefined',
34    link: setContext((_, {headers}) => {
35      // return the headers to the context so httpLink can read them
36      return {
37        headers: {
38          ...headers,
39          authorization: token ? `Bearer ${token}` : '',
40        },
41      };
42    })
43      .concat(handleError)
44      .concat(httpLink),
45    cache: new InMemoryCache(),
46  });
47};
48
49export const initializeApollo = (
50  initialState: object = {},
51  token: string = ''
52) => {
53  const _apolloClient = createApolloClient(token);
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
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
69    // Restore the cache with the merged data
70    _apolloClient.cache.restore(data);
71  }
72  // For SSG and SSR always create a new Apollo Client
73  if (typeof window === 'undefined') return _apolloClient;
74  // Create the Apollo Client once in the client
75  if (!apolloClient) apolloClient = _apolloClient;
76
77  return _apolloClient;
78};
79
80export const addApolloState = (client, pageProps) => {
81  if (pageProps?.props) {
82    pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
83  }
84
85  return pageProps;
86};
87
88export const useApollo = pageProps => {
89  const state = pageProps[APOLLO_STATE_PROP_NAME];
90  const token = useAuthStore(s => s.token);
91  return useMemo(() => {
92    const newClient = initializeApollo(state, token);
93    apolloClient = newClient;
94    return newClient;
95  }, [state, token]);
96};