skillbox/client/src/graphql/client.js

140 lines
4.4 KiB
JavaScript

import {InMemoryCache, defaultDataIdFromObject} from 'apollo-cache-inmemory/lib/index'
import {createHttpLink} from 'apollo-link-http'
import {onError} from 'apollo-link-error';
import {ApolloClient} from 'apollo-client'
import {ApolloLink, Observable} from 'apollo-link'
import fetch from 'unfetch'
import {typeDefs} from '@/graphql/typedefs';
import {resolvers} from '@/graphql/resolvers';
const writeLocalCache = cache => {
// we use the cache as our local state
cache.writeData({
data: {
scrollPosition: {
__typename: 'ScrollPosition',
scrollTo: ''
},
sidebar: {
__typename: 'Sidebar',
open: false
},
helloEmail: {
__typename: 'HelloEmail',
email: ''
},
}
});
};
export default function (uri, networkErrorCallback) {
const httpLink = createHttpLink({
// uri: process.env.NODE_ENV !== 'production' ? 'http://localhost:8000/api/graphql/' : '/api/graphql/',
uri,
credentials: 'include',
fetch: fetch,
headers: {
'X-CSRFToken': document.cookie.replace(/(?:(?:^|.*;\s*)csrftoken\s*=\s*([^;]*).*$)|^.*$/, '$1')
}
});
const consoleLink = new ApolloLink((operation, forward) => {
// console.log(`starting request for ${operation.operationName}`);
return forward(operation).map((data) => {
// console.log(`ending request for ${operation.operationName}`);
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(({response, operation, networkError, graphQLErrors}) => {
if (networkError && networkErrorCallback) {
networkErrorCallback(networkError.statusCode);
return Observable.of();
}
if (graphQLErrors) {
graphQLErrors.forEach(({message, locations, path}) =>
console.log(
`[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
return Observable.of();
}
});
const composedLink = ApolloLink.from([createOmitTypenameLink, consoleLink, errorLink, httpLink]);
const cache = new InMemoryCache({
dataIdFromObject: obj => {
switch (obj.__typename) {
case 'InstrumentNode':
case 'ModuleNode':
return `${obj.__typename}:${obj.slug}`;
default:
return defaultDataIdFromObject(obj);
}
},
cacheRedirects: {
Query: {
contentBlock: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ContentBlockNode', id: args.id}),
chapter: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ChapterNode', id: args.id}),
assignment: (_, args, {getCacheKey}) => getCacheKey({__typename: 'AssignmentNode', id: args.id}),
objective: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveNode', id: args.id}),
objectiveGroup: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ObjectiveGroupNode', id: args.id}),
projectEntry: (_, args, {getCacheKey}) => getCacheKey({__typename: 'ProjectEntryNode', id: args.id}),
}
}
});
// TODO: Monkey-patching in a fix for an open issue suggesting that
// `readQuery` should return null or undefined if the query is not yet in the
// cache: https://github.com/apollographql/apollo-feature-requests/issues/1
cache.originalReadQuery = cache.readQuery;
cache.readQuery = (...args) => {
try {
return cache.originalReadQuery(...args);
} catch (err) {
console.error(err);
return undefined;
}
};
writeLocalCache(cache);
// Create the apollo client
const client = new ApolloClient({
link: composedLink,
// link: httpLink,
cache,
connectToDevTools: true,
typeDefs,
resolvers
});
client.onResetStore(() => {
writeLocalCache(cache);
});
return client;
}