@envelop/response-cache 3.0.0-alpha-d0d0776.0 → 3.0.0-alpha-2869053.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.
Files changed (4) hide show
  1. package/index.js +113 -106
  2. package/index.mjs +109 -99
  3. package/package.json +6 -18
  4. package/plugin.d.ts +9 -8
package/index.js CHANGED
@@ -2,21 +2,19 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- const LRU = require('lru-cache');
5
+ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
+
7
+ const LRU = _interopDefault(require('lru-cache'));
6
8
  const core = require('@envelop/core');
7
9
  const utils = require('@graphql-tools/utils');
8
10
  const graphql = require('graphql');
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);
11
+ const jsonStableStringify = _interopDefault(require('fast-json-stable-stringify'));
15
12
 
16
13
  const createInMemoryCache = (params) => {
17
- const buildEntityId = params?.buildEntityId ?? defaultBuildEntityId;
18
- const cachedResponses = new LRU__default["default"]({
19
- max: params?.max,
14
+ var _a;
15
+ const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
16
+ const cachedResponses = new LRU({
17
+ max: params === null || params === void 0 ? void 0 : params.max,
20
18
  stale: false,
21
19
  noDisposeOnSet: true,
22
20
  dispose(responseId) {
@@ -26,12 +24,13 @@ const createInMemoryCache = (params) => {
26
24
  const entityToResponseIds = new Map();
27
25
  const responseIdToEntityIds = new Map();
28
26
  function purgeResponse(responseId, shouldRemove = true) {
27
+ var _a;
29
28
  const entityIds = responseIdToEntityIds.get(responseId);
30
29
  // get entities related to the response
31
30
  if (entityIds !== undefined) {
32
31
  for (const entityId of entityIds) {
33
32
  // remove the response mapping from the entity
34
- entityToResponseIds.get(entityId)?.delete(responseId);
33
+ (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
35
34
  }
36
35
  // remove all the entity mappings from the response
37
36
  responseIdToEntityIds.delete(responseId);
@@ -79,7 +78,8 @@ const createInMemoryCache = (params) => {
79
78
  }
80
79
  },
81
80
  get(responseId) {
82
- return cachedResponses.get(responseId) ?? null;
81
+ var _a;
82
+ return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
83
83
  },
84
84
  invalidate(entitiesToRemove) {
85
85
  for (const { typename, id } of entitiesToRemove) {
@@ -154,17 +154,19 @@ 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.
161
160
  */
162
- const defaultBuildResponseCacheKey = params => hashSHA256([
163
- params.documentString,
164
- params.operationName ?? '',
165
- jsonStableStringify__default["default"](params.variableValues ?? {}),
166
- params.sessionId ?? '',
167
- ].join('|'));
161
+ const defaultBuildResponseCacheKey = params => {
162
+ var _a, _b, _c;
163
+ return hashSHA256([
164
+ params.documentString,
165
+ (_a = params.operationName) !== null && _a !== void 0 ? _a : '',
166
+ jsonStableStringify((_b = params.variableValues) !== null && _b !== void 0 ? _b : {}),
167
+ (_c = params.sessionId) !== null && _c !== void 0 ? _c : '',
168
+ ].join('|'));
169
+ };
168
170
  /**
169
171
  * Default function used to check if the result should be cached.
170
172
  *
@@ -181,8 +183,16 @@ const defaultShouldCacheResult = (params) => {
181
183
  }
182
184
  return true;
183
185
  };
184
- const defaultGetDocumentStringFromContext = context => context[rawDocumentStringSymbol];
185
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext = defaultGetDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
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,
186
196
  // eslint-disable-next-line dot-notation
187
197
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
188
198
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -191,8 +201,9 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
191
201
  ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
192
202
  return {
193
203
  onSchemaChange({ schema, replaceSchema }) {
204
+ var _a;
194
205
  // @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
195
- if (schema.extensions?.[appliedTransform] === true) {
206
+ if (((_a = schema.extensions) === null || _a === void 0 ? void 0 : _a[appliedTransform]) === true) {
196
207
  return;
197
208
  }
198
209
  const patchedSchema = applyResponseCacheLogic(schema, idFields);
@@ -202,18 +213,15 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
202
213
  };
203
214
  replaceSchema(patchedSchema);
204
215
  },
205
- onParse(parseCtx) {
206
- return function onParseEnd(ctx) {
207
- if (ctx.result && 'kind' in ctx.result) {
208
- const source = parseCtx.params.source;
209
- const rawDocumentString = typeof source === 'string' ? source : source.body;
210
- ctx.extendContext({
211
- [rawDocumentStringSymbol]: rawDocumentString,
212
- });
216
+ onParse({ params: { source } }) {
217
+ return function onParseEnd({ result }) {
218
+ if (result != null && !(result instanceof Error)) {
219
+ documentStringByDocument.set(result, source.toString());
213
220
  }
214
221
  };
215
222
  },
216
223
  async onExecute(ctx) {
224
+ var _a;
217
225
  const identifier = new Map();
218
226
  const types = new Set();
219
227
  const context = {
@@ -253,99 +261,97 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
253
261
  },
254
262
  };
255
263
  }
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,
273
- },
264
+ const documentString = getDocumentString(ctx.args);
265
+ const operationId = await buildResponseCacheKey({
266
+ documentString,
267
+ variableValues: ctx.args.variableValues,
268
+ operationName: ctx.args.operationName,
269
+ sessionId: session(ctx.args.contextValue),
270
+ });
271
+ if (((_a = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : true) === true) {
272
+ const cachedResponse = await cache.get(operationId);
273
+ if (cachedResponse != null) {
274
+ if (includeExtensionMetadata) {
275
+ ctx.setResultAndStopExecution({
276
+ ...cachedResponse,
277
+ extensions: {
278
+ responseCache: {
279
+ hit: true,
274
280
  },
275
- });
276
- }
277
- else {
278
- ctx.setResultAndStopExecution(cachedResponse);
279
- }
280
- return;
281
+ },
282
+ });
281
283
  }
284
+ else {
285
+ ctx.setResultAndStopExecution(cachedResponse);
286
+ }
287
+ return;
282
288
  }
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);
293
- }
294
- }
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) {
311
- if (includeExtensionMetadata) {
312
- setResult({
313
- ...result,
314
- extensions: {
315
- responseCache: {
316
- hit: false,
317
- didCache: false,
318
- },
319
- },
320
- });
289
+ }
290
+ if (ttlPerSchemaCoordinate) {
291
+ const typeInfo = new graphql.TypeInfo(ctx.args.schema);
292
+ graphql.visit(ctx.args.document, graphql.visitWithTypeInfo(typeInfo, {
293
+ Field(fieldNode) {
294
+ const parentType = typeInfo.getParentType();
295
+ if (parentType) {
296
+ const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
297
+ const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
298
+ if (maybeTtl !== undefined) {
299
+ context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
321
300
  }
322
- return;
323
301
  }
324
- cache.set(operationId, result, identifier.values(), finalTtl);
302
+ },
303
+ }));
304
+ }
305
+ return {
306
+ onExecuteDone({ result, setResult }) {
307
+ var _a;
308
+ if (core.isAsyncIterable(result)) {
309
+ // eslint-disable-next-line no-console
310
+ console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
311
+ return;
312
+ }
313
+ if (context.skip) {
314
+ return;
315
+ }
316
+ if (!shouldCacheResult({ result })) {
317
+ return;
318
+ }
319
+ // we only use the global ttl if no currentTtl has been determined.
320
+ const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
321
+ if (finalTtl === 0) {
325
322
  if (includeExtensionMetadata) {
326
323
  setResult({
327
324
  ...result,
328
325
  extensions: {
329
326
  responseCache: {
330
327
  hit: false,
331
- didCache: true,
332
- ttl: finalTtl,
328
+ didCache: false,
333
329
  },
334
330
  },
335
331
  });
336
332
  }
337
- },
338
- };
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;
333
+ return;
334
+ }
335
+ cache.set(operationId, result, identifier.values(), finalTtl);
336
+ if (includeExtensionMetadata) {
337
+ setResult({
338
+ ...result,
339
+ extensions: {
340
+ responseCache: {
341
+ hit: false,
342
+ didCache: true,
343
+ ttl: finalTtl,
344
+ },
345
+ },
346
+ });
347
+ }
348
+ },
349
+ };
344
350
  },
345
351
  };
346
352
  }
347
353
  function isOperationDefinition(node) {
348
- return node?.kind === 'OperationDefinition';
354
+ return (node === null || node === void 0 ? void 0 : node.kind) === 'OperationDefinition';
349
355
  }
350
356
  function calculateTtl(typeTtl, currentTtl) {
351
357
  if (typeof currentTtl === 'number') {
@@ -371,7 +377,8 @@ function applyResponseCacheLogic(schema, idFieldNames) {
371
377
  return {
372
378
  ...fieldConfig,
373
379
  resolve(src, args, context, info) {
374
- const result = (fieldConfig.resolve ?? graphql.defaultFieldResolver)(src, args, context, info);
380
+ var _a;
381
+ const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : graphql.defaultFieldResolver)(src, args, context, info);
375
382
  runWith(result, (id) => {
376
383
  const ctx = context[contextSymbol];
377
384
  if (ctx !== undefined) {
@@ -403,6 +410,6 @@ function applyResponseCacheLogic(schema, idFieldNames) {
403
410
  exports.createInMemoryCache = createInMemoryCache;
404
411
  exports.defaultBuildEntityId = defaultBuildEntityId;
405
412
  exports.defaultBuildResponseCacheKey = defaultBuildResponseCacheKey;
406
- exports.defaultGetDocumentStringFromContext = defaultGetDocumentStringFromContext;
413
+ exports.defaultGetDocumentString = defaultGetDocumentString;
407
414
  exports.defaultShouldCacheResult = defaultShouldCacheResult;
408
415
  exports.useResponseCache = useResponseCache;
package/index.mjs CHANGED
@@ -1,13 +1,14 @@
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) => {
8
- const buildEntityId = params?.buildEntityId ?? defaultBuildEntityId;
8
+ var _a;
9
+ const buildEntityId = (_a = params === null || params === void 0 ? void 0 : params.buildEntityId) !== null && _a !== void 0 ? _a : defaultBuildEntityId;
9
10
  const cachedResponses = new LRU({
10
- max: params?.max,
11
+ max: params === null || params === void 0 ? void 0 : params.max,
11
12
  stale: false,
12
13
  noDisposeOnSet: true,
13
14
  dispose(responseId) {
@@ -17,12 +18,13 @@ const createInMemoryCache = (params) => {
17
18
  const entityToResponseIds = new Map();
18
19
  const responseIdToEntityIds = new Map();
19
20
  function purgeResponse(responseId, shouldRemove = true) {
21
+ var _a;
20
22
  const entityIds = responseIdToEntityIds.get(responseId);
21
23
  // get entities related to the response
22
24
  if (entityIds !== undefined) {
23
25
  for (const entityId of entityIds) {
24
26
  // remove the response mapping from the entity
25
- entityToResponseIds.get(entityId)?.delete(responseId);
27
+ (_a = entityToResponseIds.get(entityId)) === null || _a === void 0 ? void 0 : _a.delete(responseId);
26
28
  }
27
29
  // remove all the entity mappings from the response
28
30
  responseIdToEntityIds.delete(responseId);
@@ -70,7 +72,8 @@ const createInMemoryCache = (params) => {
70
72
  }
71
73
  },
72
74
  get(responseId) {
73
- return cachedResponses.get(responseId) ?? null;
75
+ var _a;
76
+ return (_a = cachedResponses.get(responseId)) !== null && _a !== void 0 ? _a : null;
74
77
  },
75
78
  invalidate(entitiesToRemove) {
76
79
  for (const { typename, id } of entitiesToRemove) {
@@ -145,17 +148,19 @@ const hashSHA256 = async (text) => {
145
148
  };
146
149
 
147
150
  const contextSymbol = Symbol('responseCache');
148
- const rawDocumentStringSymbol = Symbol('rawDocumentString');
149
151
  /**
150
152
  * Default function used for building the response cache key.
151
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.
152
154
  */
153
- const defaultBuildResponseCacheKey = params => hashSHA256([
154
- params.documentString,
155
- params.operationName ?? '',
156
- jsonStableStringify(params.variableValues ?? {}),
157
- params.sessionId ?? '',
158
- ].join('|'));
155
+ const defaultBuildResponseCacheKey = params => {
156
+ var _a, _b, _c;
157
+ return hashSHA256([
158
+ params.documentString,
159
+ (_a = params.operationName) !== null && _a !== void 0 ? _a : '',
160
+ jsonStableStringify((_b = params.variableValues) !== null && _b !== void 0 ? _b : {}),
161
+ (_c = params.sessionId) !== null && _c !== void 0 ? _c : '',
162
+ ].join('|'));
163
+ };
159
164
  /**
160
165
  * Default function used to check if the result should be cached.
161
166
  *
@@ -172,8 +177,16 @@ const defaultShouldCacheResult = (params) => {
172
177
  }
173
178
  return true;
174
179
  };
175
- const defaultGetDocumentStringFromContext = context => context[rawDocumentStringSymbol];
176
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext = defaultGetDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
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,
177
190
  // eslint-disable-next-line dot-notation
178
191
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
179
192
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -182,8 +195,9 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
182
195
  ttlPerSchemaCoordinate = { 'Query.__schema': 0, ...ttlPerSchemaCoordinate };
183
196
  return {
184
197
  onSchemaChange({ schema, replaceSchema }) {
198
+ var _a;
185
199
  // @ts-expect-error See https://github.com/graphql/graphql-js/pull/3511 - remove this comments once merged
186
- if (schema.extensions?.[appliedTransform] === true) {
200
+ if (((_a = schema.extensions) === null || _a === void 0 ? void 0 : _a[appliedTransform]) === true) {
187
201
  return;
188
202
  }
189
203
  const patchedSchema = applyResponseCacheLogic(schema, idFields);
@@ -193,18 +207,15 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
193
207
  };
194
208
  replaceSchema(patchedSchema);
195
209
  },
196
- onParse(parseCtx) {
197
- return function onParseEnd(ctx) {
198
- if (ctx.result && 'kind' in ctx.result) {
199
- const source = parseCtx.params.source;
200
- const rawDocumentString = typeof source === 'string' ? source : source.body;
201
- ctx.extendContext({
202
- [rawDocumentStringSymbol]: rawDocumentString,
203
- });
210
+ onParse({ params: { source } }) {
211
+ return function onParseEnd({ result }) {
212
+ if (result != null && !(result instanceof Error)) {
213
+ documentStringByDocument.set(result, source.toString());
204
214
  }
205
215
  };
206
216
  },
207
217
  async onExecute(ctx) {
218
+ var _a;
208
219
  const identifier = new Map();
209
220
  const types = new Set();
210
221
  const context = {
@@ -244,99 +255,97 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
244
255
  },
245
256
  };
246
257
  }
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,
264
- },
258
+ const documentString = getDocumentString(ctx.args);
259
+ const operationId = await buildResponseCacheKey({
260
+ documentString,
261
+ variableValues: ctx.args.variableValues,
262
+ operationName: ctx.args.operationName,
263
+ sessionId: session(ctx.args.contextValue),
264
+ });
265
+ if (((_a = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : true) === true) {
266
+ const cachedResponse = await cache.get(operationId);
267
+ if (cachedResponse != null) {
268
+ if (includeExtensionMetadata) {
269
+ ctx.setResultAndStopExecution({
270
+ ...cachedResponse,
271
+ extensions: {
272
+ responseCache: {
273
+ hit: true,
265
274
  },
266
- });
267
- }
268
- else {
269
- ctx.setResultAndStopExecution(cachedResponse);
270
- }
271
- return;
275
+ },
276
+ });
272
277
  }
278
+ else {
279
+ ctx.setResultAndStopExecution(cachedResponse);
280
+ }
281
+ return;
273
282
  }
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);
284
- }
285
- }
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) {
302
- if (includeExtensionMetadata) {
303
- setResult({
304
- ...result,
305
- extensions: {
306
- responseCache: {
307
- hit: false,
308
- didCache: false,
309
- },
310
- },
311
- });
283
+ }
284
+ if (ttlPerSchemaCoordinate) {
285
+ const typeInfo = new TypeInfo(ctx.args.schema);
286
+ visit(ctx.args.document, 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);
312
294
  }
313
- return;
314
295
  }
315
- cache.set(operationId, result, identifier.values(), finalTtl);
296
+ },
297
+ }));
298
+ }
299
+ return {
300
+ onExecuteDone({ result, setResult }) {
301
+ var _a;
302
+ if (isAsyncIterable(result)) {
303
+ // eslint-disable-next-line no-console
304
+ console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
305
+ return;
306
+ }
307
+ if (context.skip) {
308
+ return;
309
+ }
310
+ if (!shouldCacheResult({ result })) {
311
+ return;
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
316
  if (includeExtensionMetadata) {
317
317
  setResult({
318
318
  ...result,
319
319
  extensions: {
320
320
  responseCache: {
321
321
  hit: false,
322
- didCache: true,
323
- ttl: finalTtl,
322
+ didCache: false,
324
323
  },
325
324
  },
326
325
  });
327
326
  }
328
- },
329
- };
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;
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
+ },
339
+ },
340
+ });
341
+ }
342
+ },
343
+ };
335
344
  },
336
345
  };
337
346
  }
338
347
  function isOperationDefinition(node) {
339
- return node?.kind === 'OperationDefinition';
348
+ return (node === null || node === void 0 ? void 0 : node.kind) === 'OperationDefinition';
340
349
  }
341
350
  function calculateTtl(typeTtl, currentTtl) {
342
351
  if (typeof currentTtl === 'number') {
@@ -362,7 +371,8 @@ function applyResponseCacheLogic(schema, idFieldNames) {
362
371
  return {
363
372
  ...fieldConfig,
364
373
  resolve(src, args, context, info) {
365
- const result = (fieldConfig.resolve ?? defaultFieldResolver)(src, args, context, info);
374
+ var _a;
375
+ const result = ((_a = fieldConfig.resolve) !== null && _a !== void 0 ? _a : defaultFieldResolver)(src, args, context, info);
366
376
  runWith(result, (id) => {
367
377
  const ctx = context[contextSymbol];
368
378
  if (ctx !== undefined) {
@@ -391,4 +401,4 @@ function applyResponseCacheLogic(schema, idFieldNames) {
391
401
  });
392
402
  }
393
403
 
394
- export { createInMemoryCache, defaultBuildEntityId, defaultBuildResponseCacheKey, defaultGetDocumentStringFromContext, defaultShouldCacheResult, useResponseCache };
404
+ 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-d0d0776.0",
3
+ "version": "3.0.0-alpha-2869053.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@envelop/core": "3.0.0-alpha-d0d0776.0",
6
+ "@envelop/core": "^2.3.3",
7
7
  "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
8
8
  },
9
9
  "dependencies": {
@@ -26,24 +26,12 @@
26
26
  },
27
27
  "exports": {
28
28
  ".": {
29
- "require": {
30
- "default": "./index.js",
31
- "types": "./index.d.ts"
32
- },
33
- "import": {
34
- "default": "./index.mjs",
35
- "types": "./index.d.ts"
36
- }
29
+ "require": "./index.js",
30
+ "import": "./index.mjs"
37
31
  },
38
32
  "./*": {
39
- "require": {
40
- "default": "./*.js",
41
- "types": "./*.d.ts"
42
- },
43
- "import": {
44
- "default": "./*.mjs",
45
- "types": "./*.d.ts"
46
- }
33
+ "require": "./*.js",
34
+ "import": "./*.mjs"
47
35
  },
48
36
  "./package.json": "./package.json"
49
37
  }
package/plugin.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Plugin, Maybe, DefaultContext } from '@envelop/core';
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 GetDocumentStringFromContextFunction = (params: DefaultContext) => Maybe<string>;
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 context object.
76
- * By default, the useResponseCache plugin hooks into onParse and writes the original operation string to the context.
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 `defaultGetDocumentStringFromContext`
78
+ * Defaults to `defaultGetDocumentString`
79
+ *
79
80
  */
80
- getDocumentStringFromContext?: GetDocumentStringFromContextFunction;
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 const defaultGetDocumentStringFromContext: GetDocumentStringFromContextFunction;
108
- export declare function useResponseCache({ cache, ttl: globalTtl, session, enabled, ignoredTypes, ttlPerType, ttlPerSchemaCoordinate, idFields, invalidateViaMutation, buildResponseCacheKey, getDocumentStringFromContext, shouldCacheResult, includeExtensionMetadata, }?: UseResponseCacheParameter): Plugin;
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;