@envelop/response-cache 3.0.0-alpha-4ba70ab.0 → 3.0.0-alpha-868cc42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -0
- package/index.js +108 -111
- package/index.mjs +109 -112
- package/package.json +3 -3
- package/plugin.d.ts +9 -8
package/README.md
CHANGED
|
@@ -8,6 +8,18 @@
|
|
|
8
8
|
|
|
9
9
|
[Check out the GraphQL Response Cache Guide for more information](https://envelop.dev/docs/guides/adding-a-graphql-response-cache)
|
|
10
10
|
|
|
11
|
+
> Watch [Episode #34 of `graphql.wtf`](https://graphql.wtf/episodes/34-response-cache-plugin-with-envelop) for a quick introduction to using Response Cache plugin with Envelop:
|
|
12
|
+
|
|
13
|
+
<iframe
|
|
14
|
+
width="100%"
|
|
15
|
+
height="400"
|
|
16
|
+
src="https://www.youtube.com/embed/1EBphPltkA4"
|
|
17
|
+
title="YouTube video player"
|
|
18
|
+
frameBorder="0"
|
|
19
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
20
|
+
allowFullScreen
|
|
21
|
+
></iframe>
|
|
22
|
+
|
|
11
23
|
## Getting Started
|
|
12
24
|
|
|
13
25
|
```bash
|
package/index.js
CHANGED
|
@@ -124,7 +124,7 @@ const hashSHA256 = async (text) => {
|
|
|
124
124
|
if (nodeCrypto) {
|
|
125
125
|
return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
|
|
126
126
|
}
|
|
127
|
-
|
|
127
|
+
if (webCrypto) {
|
|
128
128
|
let buf;
|
|
129
129
|
if (typeof TextEncoder !== 'undefined') {
|
|
130
130
|
buf = new TextEncoder().encode(text);
|
|
@@ -154,7 +154,6 @@ const hashSHA256 = async (text) => {
|
|
|
154
154
|
};
|
|
155
155
|
|
|
156
156
|
const contextSymbol = Symbol('responseCache');
|
|
157
|
-
const rawDocumentStringSymbol = Symbol('rawDocumentString');
|
|
158
157
|
/**
|
|
159
158
|
* Default function used for building the response cache key.
|
|
160
159
|
* It is exported here for advanced use-cases. E.g. if you want to short circuit and serve responses from the cache on a global level in order to completely by-pass the GraphQL flow.
|
|
@@ -184,31 +183,40 @@ const defaultShouldCacheResult = (params) => {
|
|
|
184
183
|
}
|
|
185
184
|
return true;
|
|
186
185
|
};
|
|
187
|
-
const
|
|
188
|
-
function
|
|
186
|
+
const documentStringByDocument = new WeakMap();
|
|
187
|
+
function defaultGetDocumentString(executionArgs) {
|
|
188
|
+
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
189
|
+
if (!documentString) {
|
|
190
|
+
documentString = graphql.print(executionArgs.document);
|
|
191
|
+
documentStringByDocument.set(executionArgs.document, documentString);
|
|
192
|
+
}
|
|
193
|
+
return documentString;
|
|
194
|
+
}
|
|
195
|
+
function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
|
|
189
196
|
// eslint-disable-next-line dot-notation
|
|
190
197
|
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
|
|
198
|
+
const appliedTransform = Symbol('responseCache.appliedTransform');
|
|
191
199
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
192
|
-
const schemaCache = new WeakMap();
|
|
193
200
|
// never cache Introspections
|
|
194
201
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
195
202
|
return {
|
|
196
|
-
onSchemaChange(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
203
|
+
onSchemaChange({ schema, replaceSchema }) {
|
|
204
|
+
var _a;
|
|
205
|
+
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
206
|
+
if (((_a = schema.extensions) === null || _a === void 0 ? void 0 : _a[appliedTransform]) === true) {
|
|
207
|
+
return;
|
|
201
208
|
}
|
|
202
|
-
|
|
209
|
+
const patchedSchema = applyResponseCacheLogic(schema, idFields);
|
|
210
|
+
patchedSchema.extensions = {
|
|
211
|
+
...patchedSchema.extensions,
|
|
212
|
+
[appliedTransform]: true,
|
|
213
|
+
};
|
|
214
|
+
replaceSchema(patchedSchema);
|
|
203
215
|
},
|
|
204
|
-
onParse(
|
|
205
|
-
return function onParseEnd(
|
|
206
|
-
if (
|
|
207
|
-
|
|
208
|
-
const rawDocumentString = typeof source === 'string' ? source : source.body;
|
|
209
|
-
ctx.extendContext({
|
|
210
|
-
[rawDocumentStringSymbol]: rawDocumentString,
|
|
211
|
-
});
|
|
216
|
+
onParse({ params: { source } }) {
|
|
217
|
+
return function onParseEnd({ result }) {
|
|
218
|
+
if (result != null && !(result instanceof Error)) {
|
|
219
|
+
documentStringByDocument.set(result, source.toString());
|
|
212
220
|
}
|
|
213
221
|
};
|
|
214
222
|
},
|
|
@@ -253,102 +261,91 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
253
261
|
},
|
|
254
262
|
};
|
|
255
263
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
264
|
+
const operationId = await buildResponseCacheKey({
|
|
265
|
+
documentString: getDocumentString(ctx.args),
|
|
266
|
+
variableValues: ctx.args.variableValues,
|
|
267
|
+
operationName: ctx.args.operationName,
|
|
268
|
+
sessionId: session(ctx.args.contextValue),
|
|
269
|
+
});
|
|
270
|
+
if (((_a = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : true) === true) {
|
|
271
|
+
const cachedResponse = await cache.get(operationId);
|
|
272
|
+
if (cachedResponse != null) {
|
|
273
|
+
if (includeExtensionMetadata) {
|
|
274
|
+
ctx.setResultAndStopExecution({
|
|
275
|
+
...cachedResponse,
|
|
276
|
+
extensions: {
|
|
277
|
+
responseCache: {
|
|
278
|
+
hit: true,
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
ctx.setResultAndStopExecution(cachedResponse);
|
|
285
|
+
}
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (ttlPerSchemaCoordinate) {
|
|
290
|
+
const typeInfo = new graphql.TypeInfo(ctx.args.schema);
|
|
291
|
+
graphql.visit(ctx.args.document, graphql.visitWithTypeInfo(typeInfo, {
|
|
292
|
+
Field(fieldNode) {
|
|
293
|
+
const parentType = typeInfo.getParentType();
|
|
294
|
+
if (parentType) {
|
|
295
|
+
const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
|
|
296
|
+
const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
|
|
297
|
+
if (maybeTtl !== undefined) {
|
|
298
|
+
context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
|
|
280
299
|
}
|
|
281
|
-
return;
|
|
282
300
|
}
|
|
301
|
+
},
|
|
302
|
+
}));
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
onExecuteDone({ result, setResult }) {
|
|
306
|
+
var _a;
|
|
307
|
+
if (core.isAsyncIterable(result)) {
|
|
308
|
+
// eslint-disable-next-line no-console
|
|
309
|
+
console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
|
|
310
|
+
return;
|
|
283
311
|
}
|
|
284
|
-
if (
|
|
285
|
-
|
|
286
|
-
graphql.visit(ctx.args.document, graphql.visitWithTypeInfo(typeInfo, {
|
|
287
|
-
Field(fieldNode) {
|
|
288
|
-
const parentType = typeInfo.getParentType();
|
|
289
|
-
if (parentType) {
|
|
290
|
-
const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
|
|
291
|
-
const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
|
|
292
|
-
if (maybeTtl !== undefined) {
|
|
293
|
-
context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
},
|
|
297
|
-
}));
|
|
312
|
+
if (context.skip) {
|
|
313
|
+
return;
|
|
298
314
|
}
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
// we only use the global ttl if no currentTtl has been determined.
|
|
314
|
-
const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
|
|
315
|
-
if (finalTtl === 0) {
|
|
316
|
-
if (includeExtensionMetadata) {
|
|
317
|
-
setResult({
|
|
318
|
-
...result,
|
|
319
|
-
extensions: {
|
|
320
|
-
responseCache: {
|
|
321
|
-
hit: false,
|
|
322
|
-
didCache: false,
|
|
323
|
-
},
|
|
324
|
-
},
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
330
|
-
if (includeExtensionMetadata) {
|
|
331
|
-
setResult({
|
|
332
|
-
...result,
|
|
333
|
-
extensions: {
|
|
334
|
-
responseCache: {
|
|
335
|
-
hit: false,
|
|
336
|
-
didCache: true,
|
|
337
|
-
ttl: finalTtl,
|
|
338
|
-
},
|
|
315
|
+
if (!shouldCacheResult({ result })) {
|
|
316
|
+
return;
|
|
317
|
+
}
|
|
318
|
+
// we only use the global ttl if no currentTtl has been determined.
|
|
319
|
+
const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
|
|
320
|
+
if (finalTtl === 0) {
|
|
321
|
+
if (includeExtensionMetadata) {
|
|
322
|
+
setResult({
|
|
323
|
+
...result,
|
|
324
|
+
extensions: {
|
|
325
|
+
responseCache: {
|
|
326
|
+
hit: false,
|
|
327
|
+
didCache: false,
|
|
339
328
|
},
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
335
|
+
if (includeExtensionMetadata) {
|
|
336
|
+
setResult({
|
|
337
|
+
...result,
|
|
338
|
+
extensions: {
|
|
339
|
+
responseCache: {
|
|
340
|
+
hit: false,
|
|
341
|
+
didCache: true,
|
|
342
|
+
ttl: finalTtl,
|
|
343
|
+
},
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
};
|
|
352
349
|
},
|
|
353
350
|
};
|
|
354
351
|
}
|
|
@@ -412,6 +409,6 @@ function applyResponseCacheLogic(schema, idFieldNames) {
|
|
|
412
409
|
exports.createInMemoryCache = createInMemoryCache;
|
|
413
410
|
exports.defaultBuildEntityId = defaultBuildEntityId;
|
|
414
411
|
exports.defaultBuildResponseCacheKey = defaultBuildResponseCacheKey;
|
|
415
|
-
exports.
|
|
412
|
+
exports.defaultGetDocumentString = defaultGetDocumentString;
|
|
416
413
|
exports.defaultShouldCacheResult = defaultShouldCacheResult;
|
|
417
414
|
exports.useResponseCache = useResponseCache;
|
package/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import LRU from 'lru-cache';
|
|
2
2
|
import { isAsyncIterable } from '@envelop/core';
|
|
3
3
|
import { mapSchema, MapperKind } from '@graphql-tools/utils';
|
|
4
|
-
import { defaultFieldResolver, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
|
|
4
|
+
import { print, defaultFieldResolver, TypeInfo, visit, visitWithTypeInfo } from 'graphql';
|
|
5
5
|
import jsonStableStringify from 'fast-json-stable-stringify';
|
|
6
6
|
|
|
7
7
|
const createInMemoryCache = (params) => {
|
|
@@ -118,7 +118,7 @@ const hashSHA256 = async (text) => {
|
|
|
118
118
|
if (nodeCrypto) {
|
|
119
119
|
return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
if (webCrypto) {
|
|
122
122
|
let buf;
|
|
123
123
|
if (typeof TextEncoder !== 'undefined') {
|
|
124
124
|
buf = new TextEncoder().encode(text);
|
|
@@ -148,7 +148,6 @@ const hashSHA256 = async (text) => {
|
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
const contextSymbol = Symbol('responseCache');
|
|
151
|
-
const rawDocumentStringSymbol = Symbol('rawDocumentString');
|
|
152
151
|
/**
|
|
153
152
|
* Default function used for building the response cache key.
|
|
154
153
|
* It is exported here for advanced use-cases. E.g. if you want to short circuit and serve responses from the cache on a global level in order to completely by-pass the GraphQL flow.
|
|
@@ -178,31 +177,40 @@ const defaultShouldCacheResult = (params) => {
|
|
|
178
177
|
}
|
|
179
178
|
return true;
|
|
180
179
|
};
|
|
181
|
-
const
|
|
182
|
-
function
|
|
180
|
+
const documentStringByDocument = new WeakMap();
|
|
181
|
+
function defaultGetDocumentString(executionArgs) {
|
|
182
|
+
let documentString = documentStringByDocument.get(executionArgs.document);
|
|
183
|
+
if (!documentString) {
|
|
184
|
+
documentString = print(executionArgs.document);
|
|
185
|
+
documentStringByDocument.set(executionArgs.document, documentString);
|
|
186
|
+
}
|
|
187
|
+
return documentString;
|
|
188
|
+
}
|
|
189
|
+
function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentString = defaultGetDocumentString, shouldCacheResult = defaultShouldCacheResult,
|
|
183
190
|
// eslint-disable-next-line dot-notation
|
|
184
191
|
includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
|
|
192
|
+
const appliedTransform = Symbol('responseCache.appliedTransform');
|
|
185
193
|
const ignoredTypesMap = new Set(ignoredTypes);
|
|
186
|
-
const schemaCache = new WeakMap();
|
|
187
194
|
// never cache Introspections
|
|
188
195
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
189
196
|
return {
|
|
190
|
-
onSchemaChange(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
197
|
+
onSchemaChange({ schema, replaceSchema }) {
|
|
198
|
+
var _a;
|
|
199
|
+
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
200
|
+
if (((_a = schema.extensions) === null || _a === void 0 ? void 0 : _a[appliedTransform]) === true) {
|
|
201
|
+
return;
|
|
195
202
|
}
|
|
196
|
-
|
|
203
|
+
const patchedSchema = applyResponseCacheLogic(schema, idFields);
|
|
204
|
+
patchedSchema.extensions = {
|
|
205
|
+
...patchedSchema.extensions,
|
|
206
|
+
[appliedTransform]: true,
|
|
207
|
+
};
|
|
208
|
+
replaceSchema(patchedSchema);
|
|
197
209
|
},
|
|
198
|
-
onParse(
|
|
199
|
-
return function onParseEnd(
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
const rawDocumentString = typeof source === 'string' ? source : source.body;
|
|
203
|
-
ctx.extendContext({
|
|
204
|
-
[rawDocumentStringSymbol]: rawDocumentString,
|
|
205
|
-
});
|
|
210
|
+
onParse({ params: { source } }) {
|
|
211
|
+
return function onParseEnd({ result }) {
|
|
212
|
+
if (result != null && !(result instanceof Error)) {
|
|
213
|
+
documentStringByDocument.set(result, source.toString());
|
|
206
214
|
}
|
|
207
215
|
};
|
|
208
216
|
},
|
|
@@ -247,102 +255,91 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
247
255
|
},
|
|
248
256
|
};
|
|
249
257
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
if (
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
258
|
+
const operationId = await buildResponseCacheKey({
|
|
259
|
+
documentString: getDocumentString(ctx.args),
|
|
260
|
+
variableValues: ctx.args.variableValues,
|
|
261
|
+
operationName: ctx.args.operationName,
|
|
262
|
+
sessionId: session(ctx.args.contextValue),
|
|
263
|
+
});
|
|
264
|
+
if (((_a = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : true) === true) {
|
|
265
|
+
const cachedResponse = await cache.get(operationId);
|
|
266
|
+
if (cachedResponse != null) {
|
|
267
|
+
if (includeExtensionMetadata) {
|
|
268
|
+
ctx.setResultAndStopExecution({
|
|
269
|
+
...cachedResponse,
|
|
270
|
+
extensions: {
|
|
271
|
+
responseCache: {
|
|
272
|
+
hit: true,
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
ctx.setResultAndStopExecution(cachedResponse);
|
|
279
|
+
}
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (ttlPerSchemaCoordinate) {
|
|
284
|
+
const typeInfo = new TypeInfo(ctx.args.schema);
|
|
285
|
+
visit(ctx.args.document, visitWithTypeInfo(typeInfo, {
|
|
286
|
+
Field(fieldNode) {
|
|
287
|
+
const parentType = typeInfo.getParentType();
|
|
288
|
+
if (parentType) {
|
|
289
|
+
const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
|
|
290
|
+
const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
|
|
291
|
+
if (maybeTtl !== undefined) {
|
|
292
|
+
context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
|
|
274
293
|
}
|
|
275
|
-
return;
|
|
276
294
|
}
|
|
295
|
+
},
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
onExecuteDone({ result, setResult }) {
|
|
300
|
+
var _a;
|
|
301
|
+
if (isAsyncIterable(result)) {
|
|
302
|
+
// eslint-disable-next-line no-console
|
|
303
|
+
console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
|
|
304
|
+
return;
|
|
277
305
|
}
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
visit(ctx.args.document, visitWithTypeInfo(typeInfo, {
|
|
281
|
-
Field(fieldNode) {
|
|
282
|
-
const parentType = typeInfo.getParentType();
|
|
283
|
-
if (parentType) {
|
|
284
|
-
const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
|
|
285
|
-
const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
|
|
286
|
-
if (maybeTtl !== undefined) {
|
|
287
|
-
context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
},
|
|
291
|
-
}));
|
|
306
|
+
if (context.skip) {
|
|
307
|
+
return;
|
|
292
308
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
}
|
|
307
|
-
// we only use the global ttl if no currentTtl has been determined.
|
|
308
|
-
const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
|
|
309
|
-
if (finalTtl === 0) {
|
|
310
|
-
if (includeExtensionMetadata) {
|
|
311
|
-
setResult({
|
|
312
|
-
...result,
|
|
313
|
-
extensions: {
|
|
314
|
-
responseCache: {
|
|
315
|
-
hit: false,
|
|
316
|
-
didCache: false,
|
|
317
|
-
},
|
|
318
|
-
},
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
324
|
-
if (includeExtensionMetadata) {
|
|
325
|
-
setResult({
|
|
326
|
-
...result,
|
|
327
|
-
extensions: {
|
|
328
|
-
responseCache: {
|
|
329
|
-
hit: false,
|
|
330
|
-
didCache: true,
|
|
331
|
-
ttl: finalTtl,
|
|
332
|
-
},
|
|
309
|
+
if (!shouldCacheResult({ result })) {
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// we only use the global ttl if no currentTtl has been determined.
|
|
313
|
+
const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
|
|
314
|
+
if (finalTtl === 0) {
|
|
315
|
+
if (includeExtensionMetadata) {
|
|
316
|
+
setResult({
|
|
317
|
+
...result,
|
|
318
|
+
extensions: {
|
|
319
|
+
responseCache: {
|
|
320
|
+
hit: false,
|
|
321
|
+
didCache: false,
|
|
333
322
|
},
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
323
|
+
},
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
329
|
+
if (includeExtensionMetadata) {
|
|
330
|
+
setResult({
|
|
331
|
+
...result,
|
|
332
|
+
extensions: {
|
|
333
|
+
responseCache: {
|
|
334
|
+
hit: false,
|
|
335
|
+
didCache: true,
|
|
336
|
+
ttl: finalTtl,
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
};
|
|
346
343
|
},
|
|
347
344
|
};
|
|
348
345
|
}
|
|
@@ -403,4 +400,4 @@ function applyResponseCacheLogic(schema, idFieldNames) {
|
|
|
403
400
|
});
|
|
404
401
|
}
|
|
405
402
|
|
|
406
|
-
export { createInMemoryCache, defaultBuildEntityId, defaultBuildResponseCacheKey,
|
|
403
|
+
export { createInMemoryCache, defaultBuildEntityId, defaultBuildResponseCacheKey, defaultGetDocumentString, defaultShouldCacheResult, useResponseCache };
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envelop/response-cache",
|
|
3
|
-
"version": "3.0.0-alpha-
|
|
3
|
+
"version": "3.0.0-alpha-868cc42.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@envelop/core": "2.
|
|
6
|
+
"@envelop/core": "^2.3.3",
|
|
7
7
|
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"repository": {
|
|
15
15
|
"type": "git",
|
|
16
|
-
"url": "https://github.com/
|
|
16
|
+
"url": "https://github.com/n1ru4l/envelop.git",
|
|
17
17
|
"directory": "packages/plugins/response-cache"
|
|
18
18
|
},
|
|
19
19
|
"author": "Kamil Kisiela <kamilkisiela@gmail.com>",
|
package/plugin.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plugin, Maybe
|
|
1
|
+
import { Plugin, Maybe } from '@envelop/core';
|
|
2
2
|
import { ExecutionArgs, ExecutionResult } from 'graphql';
|
|
3
3
|
import type { Cache } from './cache';
|
|
4
4
|
/**
|
|
@@ -14,7 +14,7 @@ export declare type BuildResponseCacheKeyFunction = (params: {
|
|
|
14
14
|
/** optional sessionId for make unique cache keys based on the session. */
|
|
15
15
|
sessionId?: Maybe<string>;
|
|
16
16
|
}) => Promise<string>;
|
|
17
|
-
export declare type
|
|
17
|
+
export declare type GetDocumentStringFunction = (executionArgs: ExecutionArgs) => string;
|
|
18
18
|
export declare type ShouldCacheResultFunction = (params: {
|
|
19
19
|
result: ExecutionResult;
|
|
20
20
|
}) => Boolean;
|
|
@@ -72,12 +72,13 @@ export declare type UseResponseCacheParameter<C = any> = {
|
|
|
72
72
|
*/
|
|
73
73
|
buildResponseCacheKey?: BuildResponseCacheKeyFunction;
|
|
74
74
|
/**
|
|
75
|
-
* Function used for reading the document string that is used for building the response cache key from the
|
|
76
|
-
* By default, the useResponseCache plugin hooks into onParse and
|
|
75
|
+
* Function used for reading the document string that is used for building the response cache key from the execution arguments.
|
|
76
|
+
* By default, the useResponseCache plugin hooks into onParse and caches the original operation string in a WeakMap.
|
|
77
77
|
* If you are hard overriding parse you need to set this function, otherwise responses will not be cached or served from the cache.
|
|
78
|
-
* Defaults to `
|
|
78
|
+
* Defaults to `defaultGetDocumentString`
|
|
79
|
+
*
|
|
79
80
|
*/
|
|
80
|
-
|
|
81
|
+
getDocumentString?: GetDocumentStringFunction;
|
|
81
82
|
/**
|
|
82
83
|
* Include extension values that provide useful information, such as whether the cache was hit or which resources a mutation invalidated.
|
|
83
84
|
* Defaults to `true` if `process.env["NODE_ENV"]` is set to `"development"`, otherwise `false`.
|
|
@@ -104,5 +105,5 @@ export declare const defaultBuildResponseCacheKey: BuildResponseCacheKeyFunction
|
|
|
104
105
|
* By default, results with errors (unexpected, EnvelopError, or GraphQLError) are not cached.
|
|
105
106
|
*/
|
|
106
107
|
export declare const defaultShouldCacheResult: ShouldCacheResultFunction;
|
|
107
|
-
export declare
|
|
108
|
-
export declare function useResponseCache({ cache, ttl: globalTtl, session, enabled, ignoredTypes, ttlPerType, ttlPerSchemaCoordinate, idFields, invalidateViaMutation, buildResponseCacheKey,
|
|
108
|
+
export declare function defaultGetDocumentString(executionArgs: ExecutionArgs): string;
|
|
109
|
+
export declare function useResponseCache({ cache, ttl: globalTtl, session, enabled, ignoredTypes, ttlPerType, ttlPerSchemaCoordinate, idFields, invalidateViaMutation, buildResponseCacheKey, getDocumentString, shouldCacheResult, includeExtensionMetadata, }?: UseResponseCacheParameter): Plugin;
|