@matters/apollo-response-cache
Version:
Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL
52 lines (51 loc) • 2.57 kB
JavaScript
import { defaultFieldResolver } from 'graphql';
import { mapSchema, getDirective, MapperKind } from '@graphql-tools/utils';
import { invalidateFQC } from '../utils.js';
export const purgeCacheDirective = (directiveName = 'purgeCache') => ({
typeDef: `directive @${directiveName}(type: String! identifier: String = "id") on FIELD_DEFINITION`,
transformer: (schema, options) => {
return mapSchema(schema, {
[MapperKind.OBJECT_FIELD]: (fieldConfig) => {
const directive = getDirective(schema, fieldConfig, directiveName)?.[0];
if (directive) {
const { resolve = defaultFieldResolver } = fieldConfig;
fieldConfig.resolve = async (source, args, context, info) => {
const result = await resolve(source, args, context, info);
const { type, identifier } = directive;
const { __redis } = context;
if (!__redis) {
return result;
}
const results = Array.isArray(result) ? [...result] : [result];
const parsedResults = [];
const { typeResolver, idResolver, extraNodesPath } = options;
results.map((node) => {
const nodeType = typeResolver ? typeResolver(type, node) : type;
const nodeId = idResolver
? idResolver(type, node)
: node[identifier] || node['id'] || node['_id'];
if (!nodeType || !nodeId) {
return;
}
parsedResults.push({ type: nodeType, id: nodeId });
});
// merge results and extras
const extraNodes = extraNodesPath
? result[extraNodesPath] || []
: [];
const nodes = [...extraNodes, ...parsedResults];
// invalidate
nodes.forEach((node) => {
invalidateFQC({
node,
redis: __redis,
});
});
return result;
};
}
return fieldConfig;
},
});
},
});