portal-www
Version:
Nova Portal Website. Based on Next starter by Ueno
121 lines (101 loc) • 3.47 kB
text/typescript
import { ApolloClient, ApolloLink, FetchMoreOptions } from '@apollo/client';
import {
defaultDataIdFromObject,
InMemoryCache,
NormalizedCacheObject,
} from '@apollo/client/cache';
import { setContext } from '@apollo/client/link/context';
import { onError } from '@apollo/client/link/error';
import { captureException } from '@sentry/browser';
import { createUploadLink } from 'apollo-upload-client';
import fetch from 'isomorphic-unfetch';
import getConfig from 'next/config';
import { IContext } from 'typings/context';
import { isValid, refreshAuth } from './auth';
interface IApolloOptions {
fetchOptions?: FetchMoreOptions;
token: () => string;
appContext?: IContext;
pathname?: string;
isWhiteListed?: boolean;
}
const { publicRuntimeConfig } = getConfig();
const isBrowser = typeof window !== 'undefined';
let apolloClient: ApolloClient<NormalizedCacheObject> | null = null;
// Polyfill fetch() on the server (used by apollo-client)
if (!isBrowser) {
global.fetch = fetch;
}
function createClient(
initalState: NormalizedCacheObject,
{ fetchOptions, token, isWhiteListed }: IApolloOptions,
) {
const uploadLink = createUploadLink({
uri: publicRuntimeConfig.API_ENDPOINT,
fetchOptions,
});
const authLink = setContext((_, { headers }) => {
// Set set token from storage to auth header here
const _token = token();
if (!isValid(_token) && isBrowser && !isWhiteListed) {
refreshAuth(
_token,
`${window.location.pathname}${window.location.search && '?'}${window.location.search}`,
);
}
return {
...headers,
headers: {
['accept-language']: 'is-IS', // Send selected locale when start using translations
Authorization: _token ? `Bearer ${_token}` : '',
},
};
});
const errorLink = onError(({ operation, graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path, extensions }: any) => {
const { code } = extensions;
const graphError = `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}, Code: ${code}`;
console.error(graphError); // eslint-disable-line no-console
captureException(graphError);
});
}
if (networkError) {
console.error(`[Network error]: ${networkError} ${operation.operationName}`); // eslint-disable-line no-console
}
});
const link = ApolloLink.from([errorLink, authLink, uploadLink]);
const client = new ApolloClient({
connectToDevTools: isBrowser,
ssrMode: !isBrowser,
link,
cache: new InMemoryCache({
dataIdFromObject: (object) => {
switch (object.__typename) {
case 'Account':
return object.ssn;
case 'Profile':
return object.subscriptionId; // use `key` as the primary key
case 'FiberOrderAvailableAppointmentSlots':
return object.startTime;
default:
return defaultDataIdFromObject(object); // fall back to default handling
}
},
}).restore(initalState),
});
return client;
}
export default function initApollo(initialState: NormalizedCacheObject, options: IApolloOptions) {
if (!isBrowser) {
const fetchOptions = {};
return createClient(initialState, {
...options,
fetchOptions,
});
}
if (!apolloClient) {
apolloClient = createClient(initialState, options);
}
return apolloClient;
}