skillbox/client/src/graphql/cache.ts

178 lines
4.6 KiB
TypeScript

import { ContentBlockNode, HighlightNode } from '@/__generated__/graphql';
import { makeVar, InMemoryCache } from '@apollo/client/core';
const showNavigationSidebarVar = makeVar(false);
const showProfileSidebarVar = makeVar(false);
const scrollToElementVar = makeVar('');
const currentFilterVar = makeVar('');
const helloEmailVar = makeVar('');
const languageVar = makeVar('de');
const idToRefFactory =
(__typename: string) =>
(_, { args, toReference }) => {
//log.debug(`Referencing ${__typename} with ${args.id}`);
return toReference({
__typename,
id: args.id,
});
};
const typePolicies = {
ProjectNode: {
keyFields: ['slug'],
},
InstrumentNode: {
keyFields: ['slug'],
fields: {
highlights: {
merge(_existing: HighlightNode[], incoming: HighlightNode[]) {
return incoming;
},
},
},
},
RoomNode: {
keyFields: ['slug'],
},
ChapterNode: {
fields: {
contentBlocks: {
merge(_existing: ContentBlockNode[], incoming: ContentBlockNode[]) {
// always replace the whole array
return incoming;
},
},
},
},
ModuleNode: {
fields: {
inEditMode: {
read(previous: boolean | undefined) {
return previous !== undefined ? previous : false;
},
},
highlights: {
merge(_existing: HighlightNode[], incoming: HighlightNode[]) {
return incoming;
},
},
},
keyFields: ['slug'],
},
PrivateUserNode: {
fields: {
language: {
read() {
console.log(`returning language ${languageVar()}`);
return languageVar();
},
},
},
},
RoomEntryNode: {
keyFields: ['slug'],
},
ContentBlockNode: {
fields: {
highlights: {
merge(_existing: HighlightNode[], incoming: HighlightNode[]) {
// always replace the whole array
return incoming;
},
},
},
},
// https://www.apollographql.com/docs/react/local-state/managing-state-with-field-policies/#example
Query: {
fields: {
sidebar: {
read() {
return {
profile: showProfileSidebarVar(),
navigation: showNavigationSidebarVar(),
};
},
},
scrollPosition: {
read() {
return {
scrollTo: scrollToElementVar(),
};
},
},
instrumentFilter: {
read() {
return {
currentFilter: currentFilterVar(),
};
},
},
helloEmail: {
read() {
return {
email: helloEmailVar(),
};
},
},
// these used to be in cacheRedirects, now here
contentBlock: { read: idToRefFactory('ContentBlockNode') },
chapter: { read: idToRefFactory('ChapterNode') },
assignment: { read: idToRefFactory('AssignmentNode') },
objective: { read: idToRefFactory('ObjectiveNode') },
objectiveGroup: { read: idToRefFactory('ObjectiveGroupNode') },
projectEntry: { read: idToRefFactory('ProjectEntryNode') },
},
},
};
const possibleTypes = {
ContentBlockInterface: ['ContentBlockNode', 'SnapshotContentBlockNode'],
ChapterInterface: ['ChapterNode', 'SnapshotChapterNode'],
HighlightableNode: ['ContentBlockNode', 'InstrumentNode'],
};
const cache = new InMemoryCache({
// used to 'override' the behavior in resolving different types. We use it for local state management
// https://www.apollographql.com/docs/react/local-state/managing-state-with-field-policies/#example
typePolicies,
possibleTypes,
// todo: document what this does, or link the doc for it at least
// dataIdFromObject: obj => {
// switch (obj.__typename) {
// case 'InstrumentNode':
// case 'ModuleNode':
// case 'RoomEntryNode':
// return `${obj.__typename}:${obj.slug}`;
// default:
// return defaultDataIdFromObject(obj);
// }
// },
});
// 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
// probably not needed any more, as per https://github.com/apollographql/apollo-client/pull/7098
// cache.originalReadQuery = cache.readQuery;
// cache.readQuery = (...args) => {
// try {
// return cache.originalReadQuery(...args);
// } catch (err) {
// console.error(err);
// return undefined;
// }
// };
export {
showProfileSidebarVar,
showNavigationSidebarVar,
scrollToElementVar,
currentFilterVar,
helloEmailVar,
languageVar,
cache,
};
export default cache;