Skip to content

Commit

Permalink
feat(plugin-response-cache): add @CacheControl compatibility (#2887)
Browse files Browse the repository at this point in the history
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
EmrysMyrddin and github-actions[bot] committed Jun 28, 2023
1 parent c4113b0 commit 9688249
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-yoga/plugin-response-cache': patch
---
dependencies updates:
- Updated dependency [`@envelop/response-cache@^5.1.0` ↗︎](https://www.npmjs.com/package/@envelop/response-cache/v/5.1.0) (from `^5.0.0`, in `dependencies`)
5 changes: 5 additions & 0 deletions .changeset/orange-grapes-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@graphql-yoga/plugin-response-cache': minor
---

Add @cacheControl directive to configure cache in a schema first approach
65 changes: 65 additions & 0 deletions packages/plugins/response-cache/__tests__/response-cache.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { cacheControlDirective } from '@envelop/response-cache'
import { useResponseCache } from '@graphql-yoga/plugin-response-cache'
import { createSchema, createYoga } from 'graphql-yoga'

Expand Down Expand Up @@ -326,3 +327,67 @@ it('should skip response caching with `enabled` option', async () => {
},
})
})

it('should work with @cacheControl directive', async () => {
const yoga = createYoga({
schema: createSchema({
typeDefs: /* GraphQL */ `
${cacheControlDirective}
type Query @cacheControl(maxAge: 0) {
_: String
}
`,
resolvers: {
Query: {
_: () => 'DUMMY',
},
},
}),
plugins: [
useResponseCache({
session: () => null,
includeExtensionMetadata: true,
}),
],
})
function fetch() {
return yoga.fetch('http://localhost:3000/graphql', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({ query: '{__typename}' }),
})
}

let response = await fetch()

expect(response.status).toEqual(200)
let body = await response.json()
expect(body).toEqual({
data: {
__typename: 'Query',
},
extensions: {
responseCache: {
didCache: false,
hit: false,
},
},
})

response = await fetch()
expect(response.status).toEqual(200)
body = await response.json()
expect(body).toMatchObject({
data: {
__typename: 'Query',
},
extensions: {
responseCache: {
hit: false,
},
},
})
})
2 changes: 1 addition & 1 deletion packages/plugins/response-cache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"access": "public"
},
"dependencies": {
"@envelop/response-cache": "^5.0.0"
"@envelop/response-cache": "^5.1.0"
},
"peerDependencies": {
"graphql": "^15.2.0 || ^16.0.0",
Expand Down
11 changes: 6 additions & 5 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions website/src/pages/docs/features/response-caching.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ Either globally, based on [schema coordinates](https://github.com/graphql/graphq

If a query operation result contains multiple objects of the same or different types, the lowest TTL is picked.

### Using plugin configuration

```ts filename="Response Cache configuration with TTL"
useResponseCache({
session: () => null,
Expand All @@ -112,6 +114,31 @@ useResponseCache({
})
```

### Using Schema directive directive `@cacheControl`

For a schema first approach, the `@cacheControl` directive can be used to define the TTL.

Notice that the global default TTL can only be define in the plugin options `ttl` and not via the directive.

```ts filenmae="Response Cache configuration with TTL using @cacheControl directive"
import { cacheControlDirective } from '@graphql-yoga/plugin-response-cache'

const typeDefs = /* GraphQL */ `
# the directive needs to be defined in the schema
${cacheControlDirective}
type Query {
# cache operations selecting Query.lazy for 10 seconds
lazy: Something @cacheControl(maxAge: 10000)
}
# only cache query operations containing User for 500ms
type User @cacheControl(maxAge: 500) {
#...
}
`
```

## Invalidations via Mutation

When executing a mutation operation the cached query results that contain type entities within the Mutation result will be automatically be invalidated.
Expand Down

0 comments on commit 9688249

Please sign in to comment.