diff --git a/README.md b/README.md index c93be35..18c6343 100644 --- a/README.md +++ b/README.md @@ -70,17 +70,23 @@ type Mutation { You can also purge cache in the resolver: ```ts +const schema = makeExecutableSchema({ + schemaDirectives: { + purgeCache: PurgeCacheDirective({ extraNodesPath: '__invalid_nodes__' }), + }, +}) + const resolvers = { Mutation: { archiveArticle: (parent, args, context) => { // ... - article[CACHE_KEYWORD] = [ + article.__invalid_nodes__ = [ { - id: article.id, + id: '2', type: 'Article', }, { - id: comment.id, + id: '3', type: 'Comment', }, ] @@ -90,3 +96,10 @@ const resolvers = { }, } ``` + +### TODOs + +- [x] responseCachePlugin +- [x] @logCache +- [x] @purgeCache +- [ ] Unit Test diff --git a/package-lock.json b/package-lock.json index c4a475b..3d288aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@matters/apollo-response-cache", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 7a2a0d0..2390b13 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@matters/apollo-response-cache", - "version": "1.0.0", + "version": "1.1.0", "description": "Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL", "author": "Matters ", "license": "MIT", diff --git a/src/directives/logCache.ts b/src/directives/logCache.ts index 9630fe9..65d2579 100644 --- a/src/directives/logCache.ts +++ b/src/directives/logCache.ts @@ -5,7 +5,33 @@ import { get } from 'lodash' import { toNodeFQCKey } from '../utils' interface LogCacheDirectiveProps { - // Custom function to resolve node type + /** + * Custom function for resolving type from union and interface, or any other use cases. + * + * ``` + * // define + * const typeResolver = (type: string, result: any) => { + * if (['Node', 'Response'].indexOf(type) >= 0) { + * return result.__type + * } + * return type + * } + * + * const schema = makeExecutableSchema({ + * schemaDirectives: { + * purgeCache: PurgeCacheDirective({ typeResolver }), + * } + * }) + * + * type Query { + * node(input: NodeInput!): Node @logCache(type: "Node") + * } + * + * // resolved as `Article` + * const nodeResult = { id: '2', __type: 'Article' } + * + * ``` + */ typeResolver?: (type: string, node: any) => string } @@ -15,9 +41,9 @@ export const LogCacheDirective = ({ class BaseLogCacheDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field: GraphQLField): void { const { resolve = defaultFieldResolver } = field - const { type, identifier } = this.args - field.resolve = async function (...args) { + field.resolve = async (...args) => { + const { type, identifier } = this.args const [root, _, { __nodeFQCKeySet, __redis }] = args const result = await resolve.apply(this, args) diff --git a/src/directives/purgeCache.ts b/src/directives/purgeCache.ts index 4e31587..b8b5eb5 100644 --- a/src/directives/purgeCache.ts +++ b/src/directives/purgeCache.ts @@ -5,9 +5,38 @@ import { get } from 'lodash' import { invalidateFQC, Node } from '../utils' interface PurgeCacheDirectiveProps { - // The path to get extra nodes from result. + /** + * The path to get extra nodes from result object. + * + * ``` + * // define + * const schema = makeExecutableSchema({ + * schemaDirectives: { + * purgeCache: PurgeCacheDirective({ extraNodesPath: '__invalid_nodes__' }), + * } + * }) + * + * type Mutation { + * editArticle(id: ID!): Article! @purgeCache(type: "Article") + * } + * + * // @purgeCache will invalidate three nodes: Article:1, Article:2 and Comment:3. + * const editArticleResult = { + * id: '1', + * content: '...', + * __invalid_nodes__: [ + * { id: '2', type: 'Article' }, + * { id: '3', type: 'Comment' } + * ] + * } + * ``` + */ extraNodesPath?: string - // Custom function to resolve node type + /** + * Custom function for resolving type from union and interface, or any other use cases. + * + * Same as `@logCache`, see `logCache.ts` for details. + **/ typeResolver?: (type: string, node: any) => string } @@ -18,9 +47,9 @@ export const PurgeCacheDirective = ({ class BasePurgeCacheDirective extends SchemaDirectiveVisitor { visitFieldDefinition(field: GraphQLField): void { const { resolve = defaultFieldResolver } = field - const { type, identifier } = this.args - field.resolve = async function (...args) { + field.resolve = async (...args) => { + const { type, identifier } = this.args const [root, _, { __redis }] = args const result = await resolve.apply(this, args) diff --git a/src/index.ts b/src/index.ts index a101166..2892279 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,11 @@ import responseCachePlugin from './plugins/responseCachePlugin' import { LogCacheDirective } from './directives/logCache' import { PurgeCacheDirective } from './directives/purgeCache' +import { invalidateFQC } from './utils' -export { responseCachePlugin, LogCacheDirective, PurgeCacheDirective } +export { + responseCachePlugin, + LogCacheDirective, + PurgeCacheDirective, + invalidateFQC, +}