Skip to content

Commit

Permalink
chore: upgrade to latest envelop/response-cache
Browse files Browse the repository at this point in the history
  • Loading branch information
n1ru4l committed Jul 28, 2022
1 parent bcc25fa commit 0faeebb
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 17 deletions.
122 changes: 122 additions & 0 deletions packages/plugins/response-cache/__tests__/response-cache.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { createYoga } from 'graphql-yoga'
import { useResponseCache } from '@graphql-yoga/plugin-response-cache'

it('cache a query operation', async () => {
const yoga = createYoga({
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: true,
hit: false,
ttl: null,
},
},
})

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

it('cache a query operation per session', async () => {
const yoga = createYoga({
plugins: [
useResponseCache({
session: (_, request) => request.headers.get('x-session-id') ?? null,
includeExtensionMetadata: true,
}),
],
})
function fetch(sessionId: string) {
return yoga.fetch('http://localhost:3000/graphql', {
method: 'POST',
headers: {
'content-type': 'application/json',
'x-session-id': sessionId,
},
body: JSON.stringify({ query: '{__typename}' }),
})
}

let response = await fetch('1')

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

response = await fetch('1')
expect(response.status).toEqual(200)
body = await response.json()
expect(body).toEqual({
data: {
__typename: 'Query',
},
extensions: {
responseCache: {
hit: true,
},
},
})

response = await fetch('2')

expect(response.status).toEqual(200)
body = await response.json()
expect(body).toEqual({
data: {
__typename: 'Query',
},
extensions: {
responseCache: {
didCache: true,
hit: false,
ttl: null,
},
},
})
})
3 changes: 1 addition & 2 deletions packages/plugins/response-cache/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@
"access": "public"
},
"dependencies": {
"@envelop/response-cache": "2.4.0",
"tslib": "^2.3.1"
"@envelop/response-cache": "^3.0.0"
},
"peerDependencies": {
"graphql": "^15.2.0 || ^16.0.0",
Expand Down
28 changes: 13 additions & 15 deletions packages/plugins/response-cache/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@ import {
BuildResponseCacheKeyFunction,
createInMemoryCache,
defaultBuildResponseCacheKey,
GetDocumentStringFromContextFunction,
useResponseCache as useEnvelopResponseCache,
UseResponseCacheParameter as UseEnvelopResponseCacheParameter,
} from '@envelop/response-cache'
import { GraphQLParams, Maybe, Plugin, YogaInitialContext } from 'graphql-yoga'
import {
GraphQLParams,
Maybe,
Plugin,
PromiseOrValue,
YogaInitialContext,
} from 'graphql-yoga'

export type UseResponseCacheParameter = Omit<
UseEnvelopResponseCacheParameter,
'getDocumentStringFromContext' | 'session'
'getDocumentString' | 'session'
> & {
session: (params: GraphQLParams, request: Request) => Maybe<string>
session: (
params: GraphQLParams,
request: Request,
) => PromiseOrValue<Maybe<string>>
enabled?: (params: GraphQLParams, request: Request) => boolean
}

// Probably this is not used but somehow if Envelop plugin needs that
const getDocumentStringFromContext: GetDocumentStringFromContextFunction = (
context,
) => context.query as string

const operationIdByRequest = new WeakMap<Request, string>()

// We trick Envelop plugin by passing operationId as sessionId so we can take it from cache key builder we pass to Envelop
function sessionFactoryForEnvelop({ request }: YogaInitialContext) {
return operationIdByRequest.get(request)
}
const buildResponseCacheKeyForEnvelop: BuildResponseCacheKeyFunction = async ({
sessionId,
}) => sessionId!

export function useResponseCache(options: UseResponseCacheParameter): Plugin {
const buildResponseCacheKey: BuildResponseCacheKeyFunction =
Expand All @@ -42,9 +42,7 @@ export function useResponseCache(options: UseResponseCacheParameter): Plugin {
useEnvelopResponseCache({
...options,
cache,
getDocumentStringFromContext,
session: sessionFactoryForEnvelop,
buildResponseCacheKey: buildResponseCacheKeyForEnvelop,
}),
)
},
Expand All @@ -56,7 +54,7 @@ export function useResponseCache(options: UseResponseCacheParameter): Plugin {
documentString: params.query!,
variableValues: params.variables,
operationName: params.operationName,
sessionId: options.session(params, request),
sessionId: await options.session(params, request),
})
const cachedResponse = await cache.get(operationId)
if (cachedResponse) {
Expand Down

0 comments on commit 0faeebb

Please sign in to comment.