UNPKG

@matters/apollo-response-cache

Version:

Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL

52 lines (51 loc) 2.57 kB
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; }, }); }, });