import { onError } from '@apollo/client/link/error'; import { ApolloClient, ApolloLink, createHttpLink } from '@apollo/client/core'; import { typeDefs } from '@/graphql/typedefs'; import { resolvers } from '@/graphql/resolvers'; import cache from './cache'; import log from 'loglevel'; import { router } from '@/router'; export default function (uri, networkErrorCallback) { const httpLink = createHttpLink({ // uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/', uri, credentials: 'include', headers: { 'X-CSRFToken': document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*=\s*([^;]*).*$)|^.*$/, '$1'), }, }); const consoleLink = new ApolloLink((operation, forward) => { log.debug('operation', operation.operationName); return forward(operation).map((data) => { log.debug(`returned from server for ${operation.operationName}`, data); return data; }); }); // from https://github.com/apollographql/apollo-client/issues/1564#issuecomment-357492659 const omitTypename = (key, value) => { return key === '__typename' ? undefined : value; }; const createOmitTypenameLink = new ApolloLink((operation, forward) => { if (operation.variables) { operation.variables = JSON.parse(JSON.stringify(operation.variables), omitTypename); } return forward(operation); }); const errorLink = onError(({ networkError, graphQLErrors }) => { if (networkError && networkErrorCallback) { networkErrorCallback(networkError.statusCode); } if (graphQLErrors) { graphQLErrors.forEach(({ message, locations, path }) => log.warn(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`) ); } /* The server redirects to the HTML login page, but apollo expects a JSON response. This is fine, we'll just ignore it */ if (networkError && networkError.name === 'ServerParseError') { // workaround found here: https://github.com/apollographql/apollo-link/issues/855#issuecomment-485764697 } }); const notFoundLink = new ApolloLink((operation, forward) => { return forward(operation).map((response) => { const { data } = response; if (data) { if (data.topic && data.topic.__typename === 'NotFound') { // redirect to general 404 page. // todo: specific topic not found page, with navigation? router.push({ name: 'not-found', }); } } return response; }); }); let composedLink; if (process.env.NODE_ENV === 'production') { composedLink = ApolloLink.from([createOmitTypenameLink, errorLink, notFoundLink, httpLink]); } else { composedLink = ApolloLink.from([consoleLink, createOmitTypenameLink, errorLink, notFoundLink, httpLink]); } // Create the apollo client return new ApolloClient({ link: composedLink, cache, connectToDevTools: true, typeDefs, resolvers, }); }