@envelop/response-cache 2.4.0-alpha-aca44e1.0 → 3.0.0-alpha-d0d0776.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/index.js +94 -108
- package/index.mjs +86 -103
- package/package.json +19 -7
package/index.js
CHANGED
|
@@ -2,19 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const LRU = _interopDefault(require('lru-cache'));
|
|
5
|
+
const LRU = require('lru-cache');
|
|
8
6
|
const core = require('@envelop/core');
|
|
9
7
|
const utils = require('@graphql-tools/utils');
|
|
10
8
|
const graphql = require('graphql');
|
|
11
|
-
const jsonStableStringify =
|
|
9
|
+
const jsonStableStringify = require('fast-json-stable-stringify');
|
|
10
|
+
|
|
11
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
12
|
+
|
|
13
|
+
const LRU__default = /*#__PURE__*/_interopDefaultLegacy(LRU);
|
|
14
|
+
const jsonStableStringify__default = /*#__PURE__*/_interopDefaultLegacy(jsonStableStringify);
|
|
12
15
|
|
|
13
16
|
const createInMemoryCache = (params) => {
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
max: params === null || params === void 0 ? void 0 : params.max,
|
|
17
|
+
const buildEntityId = params?.buildEntityId ?? defaultBuildEntityId;
|
|
18
|
+
const cachedResponses = new LRU__default["default"]({
|
|
19
|
+
max: params?.max,
|
|
18
20
|
stale: false,
|
|
19
21
|
noDisposeOnSet: true,
|
|
20
22
|
dispose(responseId) {
|
|
@@ -24,13 +26,12 @@ const createInMemoryCache = (params) => {
|
|
|
24
26
|
const entityToResponseIds = new Map();
|
|
25
27
|
const responseIdToEntityIds = new Map();
|
|
26
28
|
function purgeResponse(responseId, shouldRemove = true) {
|
|
27
|
-
var _a;
|
|
28
29
|
const entityIds = responseIdToEntityIds.get(responseId);
|
|
29
30
|
// get entities related to the response
|
|
30
31
|
if (entityIds !== undefined) {
|
|
31
32
|
for (const entityId of entityIds) {
|
|
32
33
|
// remove the response mapping from the entity
|
|
33
|
-
|
|
34
|
+
entityToResponseIds.get(entityId)?.delete(responseId);
|
|
34
35
|
}
|
|
35
36
|
// remove all the entity mappings from the response
|
|
36
37
|
responseIdToEntityIds.delete(responseId);
|
|
@@ -78,8 +79,7 @@ const createInMemoryCache = (params) => {
|
|
|
78
79
|
}
|
|
79
80
|
},
|
|
80
81
|
get(responseId) {
|
|
81
|
-
|
|
82
|
-
return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
|
|
82
|
+
return cachedResponses.get(responseId) ?? null;
|
|
83
83
|
},
|
|
84
84
|
invalidate(entitiesToRemove) {
|
|
85
85
|
for (const { typename, id } of entitiesToRemove) {
|
|
@@ -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);
|
|
@@ -159,15 +159,12 @@ const rawDocumentStringSymbol = Symbol('rawDocumentString');
|
|
|
159
159
|
* Default function used for building the response cache key.
|
|
160
160
|
* 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.
|
|
161
161
|
*/
|
|
162
|
-
const defaultBuildResponseCacheKey = params =>
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
(_c = params.sessionId) !== null && _c !== void 0 ? _c : '',
|
|
169
|
-
].join('|'));
|
|
170
|
-
};
|
|
162
|
+
const defaultBuildResponseCacheKey = params => hashSHA256([
|
|
163
|
+
params.documentString,
|
|
164
|
+
params.operationName ?? '',
|
|
165
|
+
jsonStableStringify__default["default"](params.variableValues ?? {}),
|
|
166
|
+
params.sessionId ?? '',
|
|
167
|
+
].join('|'));
|
|
171
168
|
/**
|
|
172
169
|
* Default function used to check if the result should be cached.
|
|
173
170
|
*
|
|
@@ -194,9 +191,8 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
194
191
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
195
192
|
return {
|
|
196
193
|
onSchemaChange({ schema, replaceSchema }) {
|
|
197
|
-
var _a;
|
|
198
194
|
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
199
|
-
if (
|
|
195
|
+
if (schema.extensions?.[appliedTransform] === true) {
|
|
200
196
|
return;
|
|
201
197
|
}
|
|
202
198
|
const patchedSchema = applyResponseCacheLogic(schema, idFields);
|
|
@@ -218,7 +214,6 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
218
214
|
};
|
|
219
215
|
},
|
|
220
216
|
async onExecute(ctx) {
|
|
221
|
-
var _a;
|
|
222
217
|
const identifier = new Map();
|
|
223
218
|
const types = new Set();
|
|
224
219
|
const context = {
|
|
@@ -258,107 +253,99 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
258
253
|
},
|
|
259
254
|
};
|
|
260
255
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
hit: true,
|
|
279
|
-
},
|
|
256
|
+
const documentString = getDocumentStringFromContext(ctx.args.contextValue);
|
|
257
|
+
if (documentString != null) {
|
|
258
|
+
const operationId = await buildResponseCacheKey({
|
|
259
|
+
documentString,
|
|
260
|
+
variableValues: ctx.args.variableValues,
|
|
261
|
+
operationName: ctx.args.operationName,
|
|
262
|
+
sessionId: session(ctx.args.contextValue),
|
|
263
|
+
});
|
|
264
|
+
if ((enabled?.(ctx.args.contextValue) ?? 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,
|
|
280
273
|
},
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
ctx.setResultAndStopExecution(cachedResponse);
|
|
285
|
-
}
|
|
286
|
-
return;
|
|
274
|
+
},
|
|
275
|
+
});
|
|
287
276
|
}
|
|
277
|
+
else {
|
|
278
|
+
ctx.setResultAndStopExecution(cachedResponse);
|
|
279
|
+
}
|
|
280
|
+
return;
|
|
288
281
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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;
|
|
311
|
-
}
|
|
312
|
-
if (context.skip) {
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
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,
|
|
328
|
-
},
|
|
329
|
-
},
|
|
330
|
-
});
|
|
282
|
+
}
|
|
283
|
+
if (ttlPerSchemaCoordinate) {
|
|
284
|
+
const typeInfo = new graphql.TypeInfo(ctx.args.schema);
|
|
285
|
+
graphql.visit(ctx.args.document, graphql.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);
|
|
331
293
|
}
|
|
332
|
-
return;
|
|
333
294
|
}
|
|
334
|
-
|
|
295
|
+
},
|
|
296
|
+
}));
|
|
297
|
+
}
|
|
298
|
+
return {
|
|
299
|
+
onExecuteDone({ result, setResult }) {
|
|
300
|
+
if (core.isAsyncIterable(result)) {
|
|
301
|
+
// eslint-disable-next-line no-console
|
|
302
|
+
console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (!shouldCacheResult({ result })) {
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
// we only use the global ttl if no currentTtl has been determined.
|
|
309
|
+
const finalTtl = context.currentTtl ?? globalTtl;
|
|
310
|
+
if (finalTtl === 0) {
|
|
335
311
|
if (includeExtensionMetadata) {
|
|
336
312
|
setResult({
|
|
337
313
|
...result,
|
|
338
314
|
extensions: {
|
|
339
315
|
responseCache: {
|
|
340
316
|
hit: false,
|
|
341
|
-
didCache:
|
|
342
|
-
ttl: finalTtl,
|
|
317
|
+
didCache: false,
|
|
343
318
|
},
|
|
344
319
|
},
|
|
345
320
|
});
|
|
346
321
|
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
325
|
+
if (includeExtensionMetadata) {
|
|
326
|
+
setResult({
|
|
327
|
+
...result,
|
|
328
|
+
extensions: {
|
|
329
|
+
responseCache: {
|
|
330
|
+
hit: false,
|
|
331
|
+
didCache: true,
|
|
332
|
+
ttl: finalTtl,
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
};
|
|
356
339
|
}
|
|
340
|
+
// eslint-disable-next-line no-console
|
|
341
|
+
console.warn(`[useResponseCache] Failed extracting document string from the context. The response will not be cached or served from the cache. ` +
|
|
342
|
+
`If you are overriding the 'parse' behavior make sure to pass a custom 'getDocumentStringFromContext' function for getting the document string, which is required for building the response cache key.`);
|
|
343
|
+
return undefined;
|
|
357
344
|
},
|
|
358
345
|
};
|
|
359
346
|
}
|
|
360
347
|
function isOperationDefinition(node) {
|
|
361
|
-
return
|
|
348
|
+
return node?.kind === 'OperationDefinition';
|
|
362
349
|
}
|
|
363
350
|
function calculateTtl(typeTtl, currentTtl) {
|
|
364
351
|
if (typeof currentTtl === 'number') {
|
|
@@ -384,8 +371,7 @@ function applyResponseCacheLogic(schema, idFieldNames) {
|
|
|
384
371
|
return {
|
|
385
372
|
...fieldConfig,
|
|
386
373
|
resolve(src, args, context, info) {
|
|
387
|
-
|
|
388
|
-
const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : graphql.defaultFieldResolver)(src, args, context, info);
|
|
374
|
+
const result = (fieldConfig.resolve ?? graphql.defaultFieldResolver)(src, args, context, info);
|
|
389
375
|
runWith(result, (id) => {
|
|
390
376
|
const ctx = context[contextSymbol];
|
|
391
377
|
if (ctx !== undefined) {
|
package/index.mjs
CHANGED
|
@@ -5,10 +5,9 @@ import { defaultFieldResolver, TypeInfo, visit, visitWithTypeInfo } from 'graphq
|
|
|
5
5
|
import jsonStableStringify from 'fast-json-stable-stringify';
|
|
6
6
|
|
|
7
7
|
const createInMemoryCache = (params) => {
|
|
8
|
-
|
|
9
|
-
const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
|
|
8
|
+
const buildEntityId = params?.buildEntityId ?? defaultBuildEntityId;
|
|
10
9
|
const cachedResponses = new LRU({
|
|
11
|
-
max: params
|
|
10
|
+
max: params?.max,
|
|
12
11
|
stale: false,
|
|
13
12
|
noDisposeOnSet: true,
|
|
14
13
|
dispose(responseId) {
|
|
@@ -18,13 +17,12 @@ const createInMemoryCache = (params) => {
|
|
|
18
17
|
const entityToResponseIds = new Map();
|
|
19
18
|
const responseIdToEntityIds = new Map();
|
|
20
19
|
function purgeResponse(responseId, shouldRemove = true) {
|
|
21
|
-
var _a;
|
|
22
20
|
const entityIds = responseIdToEntityIds.get(responseId);
|
|
23
21
|
// get entities related to the response
|
|
24
22
|
if (entityIds !== undefined) {
|
|
25
23
|
for (const entityId of entityIds) {
|
|
26
24
|
// remove the response mapping from the entity
|
|
27
|
-
|
|
25
|
+
entityToResponseIds.get(entityId)?.delete(responseId);
|
|
28
26
|
}
|
|
29
27
|
// remove all the entity mappings from the response
|
|
30
28
|
responseIdToEntityIds.delete(responseId);
|
|
@@ -72,8 +70,7 @@ const createInMemoryCache = (params) => {
|
|
|
72
70
|
}
|
|
73
71
|
},
|
|
74
72
|
get(responseId) {
|
|
75
|
-
|
|
76
|
-
return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
|
|
73
|
+
return cachedResponses.get(responseId) ?? null;
|
|
77
74
|
},
|
|
78
75
|
invalidate(entitiesToRemove) {
|
|
79
76
|
for (const { typename, id } of entitiesToRemove) {
|
|
@@ -118,7 +115,7 @@ const hashSHA256 = async (text) => {
|
|
|
118
115
|
if (nodeCrypto) {
|
|
119
116
|
return nodeCrypto.then(crypto => crypto.createHash('sha256').update(text).digest('hex'));
|
|
120
117
|
}
|
|
121
|
-
|
|
118
|
+
if (webCrypto) {
|
|
122
119
|
let buf;
|
|
123
120
|
if (typeof TextEncoder !== 'undefined') {
|
|
124
121
|
buf = new TextEncoder().encode(text);
|
|
@@ -153,15 +150,12 @@ const rawDocumentStringSymbol = Symbol('rawDocumentString');
|
|
|
153
150
|
* Default function used for building the response cache key.
|
|
154
151
|
* 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.
|
|
155
152
|
*/
|
|
156
|
-
const defaultBuildResponseCacheKey = params =>
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
(_c = params.sessionId) !== null && _c !== void 0 ? _c : '',
|
|
163
|
-
].join('|'));
|
|
164
|
-
};
|
|
153
|
+
const defaultBuildResponseCacheKey = params => hashSHA256([
|
|
154
|
+
params.documentString,
|
|
155
|
+
params.operationName ?? '',
|
|
156
|
+
jsonStableStringify(params.variableValues ?? {}),
|
|
157
|
+
params.sessionId ?? '',
|
|
158
|
+
].join('|'));
|
|
165
159
|
/**
|
|
166
160
|
* Default function used to check if the result should be cached.
|
|
167
161
|
*
|
|
@@ -188,9 +182,8 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
188
182
|
ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
|
|
189
183
|
return {
|
|
190
184
|
onSchemaChange({ schema, replaceSchema }) {
|
|
191
|
-
var _a;
|
|
192
185
|
// @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
|
|
193
|
-
if (
|
|
186
|
+
if (schema.extensions?.[appliedTransform] === true) {
|
|
194
187
|
return;
|
|
195
188
|
}
|
|
196
189
|
const patchedSchema = applyResponseCacheLogic(schema, idFields);
|
|
@@ -212,7 +205,6 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
212
205
|
};
|
|
213
206
|
},
|
|
214
207
|
async onExecute(ctx) {
|
|
215
|
-
var _a;
|
|
216
208
|
const identifier = new Map();
|
|
217
209
|
const types = new Set();
|
|
218
210
|
const context = {
|
|
@@ -252,107 +244,99 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
|
|
|
252
244
|
},
|
|
253
245
|
};
|
|
254
246
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
if (
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
hit: true,
|
|
273
|
-
},
|
|
247
|
+
const documentString = getDocumentStringFromContext(ctx.args.contextValue);
|
|
248
|
+
if (documentString != null) {
|
|
249
|
+
const operationId = await buildResponseCacheKey({
|
|
250
|
+
documentString,
|
|
251
|
+
variableValues: ctx.args.variableValues,
|
|
252
|
+
operationName: ctx.args.operationName,
|
|
253
|
+
sessionId: session(ctx.args.contextValue),
|
|
254
|
+
});
|
|
255
|
+
if ((enabled?.(ctx.args.contextValue) ?? true) === true) {
|
|
256
|
+
const cachedResponse = await cache.get(operationId);
|
|
257
|
+
if (cachedResponse != null) {
|
|
258
|
+
if (includeExtensionMetadata) {
|
|
259
|
+
ctx.setResultAndStopExecution({
|
|
260
|
+
...cachedResponse,
|
|
261
|
+
extensions: {
|
|
262
|
+
responseCache: {
|
|
263
|
+
hit: true,
|
|
274
264
|
},
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
ctx.setResultAndStopExecution(cachedResponse);
|
|
279
|
-
}
|
|
280
|
-
return;
|
|
265
|
+
},
|
|
266
|
+
});
|
|
281
267
|
}
|
|
268
|
+
else {
|
|
269
|
+
ctx.setResultAndStopExecution(cachedResponse);
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
282
272
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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;
|
|
305
|
-
}
|
|
306
|
-
if (context.skip) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
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,
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
});
|
|
273
|
+
}
|
|
274
|
+
if (ttlPerSchemaCoordinate) {
|
|
275
|
+
const typeInfo = new TypeInfo(ctx.args.schema);
|
|
276
|
+
visit(ctx.args.document, visitWithTypeInfo(typeInfo, {
|
|
277
|
+
Field(fieldNode) {
|
|
278
|
+
const parentType = typeInfo.getParentType();
|
|
279
|
+
if (parentType) {
|
|
280
|
+
const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
|
|
281
|
+
const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
|
|
282
|
+
if (maybeTtl !== undefined) {
|
|
283
|
+
context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
|
|
325
284
|
}
|
|
326
|
-
return;
|
|
327
285
|
}
|
|
328
|
-
|
|
286
|
+
},
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
onExecuteDone({ result, setResult }) {
|
|
291
|
+
if (isAsyncIterable(result)) {
|
|
292
|
+
// eslint-disable-next-line no-console
|
|
293
|
+
console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
if (!shouldCacheResult({ result })) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
// we only use the global ttl if no currentTtl has been determined.
|
|
300
|
+
const finalTtl = context.currentTtl ?? globalTtl;
|
|
301
|
+
if (finalTtl === 0) {
|
|
329
302
|
if (includeExtensionMetadata) {
|
|
330
303
|
setResult({
|
|
331
304
|
...result,
|
|
332
305
|
extensions: {
|
|
333
306
|
responseCache: {
|
|
334
307
|
hit: false,
|
|
335
|
-
didCache:
|
|
336
|
-
ttl: finalTtl,
|
|
308
|
+
didCache: false,
|
|
337
309
|
},
|
|
338
310
|
},
|
|
339
311
|
});
|
|
340
312
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
cache.set(operationId, result, identifier.values(), finalTtl);
|
|
316
|
+
if (includeExtensionMetadata) {
|
|
317
|
+
setResult({
|
|
318
|
+
...result,
|
|
319
|
+
extensions: {
|
|
320
|
+
responseCache: {
|
|
321
|
+
hit: false,
|
|
322
|
+
didCache: true,
|
|
323
|
+
ttl: finalTtl,
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
};
|
|
350
330
|
}
|
|
331
|
+
// eslint-disable-next-line no-console
|
|
332
|
+
console.warn(`[useResponseCache] Failed extracting document string from the context. The response will not be cached or served from the cache. ` +
|
|
333
|
+
`If you are overriding the 'parse' behavior make sure to pass a custom 'getDocumentStringFromContext' function for getting the document string, which is required for building the response cache key.`);
|
|
334
|
+
return undefined;
|
|
351
335
|
},
|
|
352
336
|
};
|
|
353
337
|
}
|
|
354
338
|
function isOperationDefinition(node) {
|
|
355
|
-
return
|
|
339
|
+
return node?.kind === 'OperationDefinition';
|
|
356
340
|
}
|
|
357
341
|
function calculateTtl(typeTtl, currentTtl) {
|
|
358
342
|
if (typeof currentTtl === 'number') {
|
|
@@ -378,8 +362,7 @@ function applyResponseCacheLogic(schema, idFieldNames) {
|
|
|
378
362
|
return {
|
|
379
363
|
...fieldConfig,
|
|
380
364
|
resolve(src, args, context, info) {
|
|
381
|
-
|
|
382
|
-
const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : defaultFieldResolver)(src, args, context, info);
|
|
365
|
+
const result = (fieldConfig.resolve ?? defaultFieldResolver)(src, args, context, info);
|
|
383
366
|
runWith(result, (id) => {
|
|
384
367
|
const ctx = context[contextSymbol];
|
|
385
368
|
if (ctx !== undefined) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envelop/response-cache",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha-d0d0776.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"peerDependencies": {
|
|
6
|
-
"@envelop/core": "
|
|
6
|
+
"@envelop/core": "3.0.0-alpha-d0d0776.0",
|
|
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>",
|
|
@@ -26,12 +26,24 @@
|
|
|
26
26
|
},
|
|
27
27
|
"exports": {
|
|
28
28
|
".": {
|
|
29
|
-
"require":
|
|
30
|
-
|
|
29
|
+
"require": {
|
|
30
|
+
"default": "./index.js",
|
|
31
|
+
"types": "./index.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"import": {
|
|
34
|
+
"default": "./index.mjs",
|
|
35
|
+
"types": "./index.d.ts"
|
|
36
|
+
}
|
|
31
37
|
},
|
|
32
38
|
"./*": {
|
|
33
|
-
"require":
|
|
34
|
-
|
|
39
|
+
"require": {
|
|
40
|
+
"default": "./*.js",
|
|
41
|
+
"types": "./*.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"import": {
|
|
44
|
+
"default": "./*.mjs",
|
|
45
|
+
"types": "./*.d.ts"
|
|
46
|
+
}
|
|
35
47
|
},
|
|
36
48
|
"./package.json": "./package.json"
|
|
37
49
|
}
|