skillbox/client/src/graphql/client.js

100 lines
3.2 KiB
JavaScript

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 * as Sentry from '@sentry/vue';
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 (networkError.statusCode == 402) {
// not authenticated, we don't need to continue here
return;
}
}
if (graphQLErrors) {
graphQLErrors.forEach(({ message, locations, path }) => {
const err = `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`;
log.warn(err);
Sentry.captureMessage(err);
});
}
/*
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 (import.meta.env.MODE === '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,
});
}