@envelop/response-cache 2.3.3-alpha-a584bed.0 → 2.3.4-alpha-fae0892.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 +98 -102
  2. package/index.mjs +99 -103
  3. package/package.json +3 -3
  4. package/plugin.d.ts +2 -0
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
- else if (webCrypto) {
127
+ if (webCrypto) {
128
128
  let buf;
129
129
  if (typeof TextEncoder !== 'undefined') {
130
130
  buf = new TextEncoder().encode(text);
@@ -184,8 +184,18 @@ const defaultShouldCacheResult = (params) => {
184
184
  }
185
185
  return true;
186
186
  };
187
+ // @deprecated This will be removed in the next major
187
188
  const defaultGetDocumentStringFromContext = context => context[rawDocumentStringSymbol];
188
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext = defaultGetDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
189
+ const documentStringByDocument = new WeakMap();
190
+ function getDocumentStringFromDocument(documentNode) {
191
+ let documentString = documentStringByDocument.get(documentNode);
192
+ if (!documentString) {
193
+ documentString = graphql.print(documentNode);
194
+ documentStringByDocument.set(documentNode, documentString);
195
+ }
196
+ return documentString;
197
+ }
198
+ function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
189
199
  // eslint-disable-next-line dot-notation
190
200
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
191
201
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -206,19 +216,15 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
206
216
  };
207
217
  replaceSchema(patchedSchema);
208
218
  },
209
- onParse(parseCtx) {
210
- return function onParseEnd(ctx) {
211
- if (ctx.result && 'kind' in ctx.result) {
212
- const source = parseCtx.params.source;
213
- const rawDocumentString = typeof source === 'string' ? source : source.body;
214
- ctx.extendContext({
215
- [rawDocumentStringSymbol]: rawDocumentString,
216
- });
219
+ onParse({ params: { source } }) {
220
+ return function onParseEnd({ result }) {
221
+ if (result != null && !(result instanceof Error)) {
222
+ documentStringByDocument.set(result, source.toString());
217
223
  }
218
224
  };
219
225
  },
220
226
  async onExecute(ctx) {
221
- var _a;
227
+ var _a, _b;
222
228
  const identifier = new Map();
223
229
  const types = new Set();
224
230
  const context = {
@@ -258,102 +264,92 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
258
264
  },
259
265
  };
260
266
  }
261
- else {
262
- const documentString = getDocumentStringFromContext(ctx.args.contextValue);
263
- if (documentString != null) {
264
- const operationId = await buildResponseCacheKey({
265
- documentString,
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);
267
+ const documentString = (_a = getDocumentStringFromContext === null || getDocumentStringFromContext === void 0 ? void 0 : getDocumentStringFromContext(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : getDocumentStringFromDocument(ctx.args.document);
268
+ const operationId = await buildResponseCacheKey({
269
+ documentString,
270
+ variableValues: ctx.args.variableValues,
271
+ operationName: ctx.args.operationName,
272
+ sessionId: session(ctx.args.contextValue),
273
+ });
274
+ if (((_b = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _b !== void 0 ? _b : true) === true) {
275
+ const cachedResponse = await cache.get(operationId);
276
+ if (cachedResponse != null) {
277
+ if (includeExtensionMetadata) {
278
+ ctx.setResultAndStopExecution({
279
+ ...cachedResponse,
280
+ extensions: {
281
+ responseCache: {
282
+ hit: true,
283
+ },
284
+ },
285
+ });
286
+ }
287
+ else {
288
+ ctx.setResultAndStopExecution(cachedResponse);
289
+ }
290
+ return;
291
+ }
292
+ }
293
+ if (ttlPerSchemaCoordinate) {
294
+ const typeInfo = new graphql.TypeInfo(ctx.args.schema);
295
+ graphql.visit(ctx.args.document, graphql.visitWithTypeInfo(typeInfo, {
296
+ Field(fieldNode) {
297
+ const parentType = typeInfo.getParentType();
298
+ if (parentType) {
299
+ const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
300
+ const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
301
+ if (maybeTtl !== undefined) {
302
+ context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
285
303
  }
286
- return;
287
304
  }
305
+ },
306
+ }));
307
+ }
308
+ return {
309
+ onExecuteDone({ result, setResult }) {
310
+ var _a;
311
+ if (core.isAsyncIterable(result)) {
312
+ // eslint-disable-next-line no-console
313
+ console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
314
+ return;
288
315
  }
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);
299
- }
300
- }
301
- },
302
- }));
316
+ if (context.skip) {
317
+ return;
303
318
  }
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
- });
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
- },
319
+ if (!shouldCacheResult({ result })) {
320
+ return;
321
+ }
322
+ // we only use the global ttl if no currentTtl has been determined.
323
+ const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
324
+ if (finalTtl === 0) {
325
+ if (includeExtensionMetadata) {
326
+ setResult({
327
+ ...result,
328
+ extensions: {
329
+ responseCache: {
330
+ hit: false,
331
+ didCache: false,
344
332
  },
345
- });
346
- }
347
- },
348
- };
349
- }
350
- else {
351
- // eslint-disable-next-line no-console
352
- console.warn(`[useResponseCache] Failed extracting document string from the context. The response will not be cached or served from the cache. ` +
353
- `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.`);
354
- return undefined;
355
- }
356
- }
333
+ },
334
+ });
335
+ }
336
+ return;
337
+ }
338
+ cache.set(operationId, result, identifier.values(), finalTtl);
339
+ if (includeExtensionMetadata) {
340
+ setResult({
341
+ ...result,
342
+ extensions: {
343
+ responseCache: {
344
+ hit: false,
345
+ didCache: true,
346
+ ttl: finalTtl,
347
+ },
348
+ },
349
+ });
350
+ }
351
+ },
352
+ };
357
353
  },
358
354
  };
359
355
  }
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 { defaultFieldResolver, TypeInfo, visit, visitWithTypeInfo, print } 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
- else if (webCrypto) {
121
+ if (webCrypto) {
122
122
  let buf;
123
123
  if (typeof TextEncoder !== 'undefined') {
124
124
  buf = new TextEncoder().encode(text);
@@ -178,8 +178,18 @@ const defaultShouldCacheResult = (params) => {
178
178
  }
179
179
  return true;
180
180
  };
181
+ // @deprecated This will be removed in the next major
181
182
  const defaultGetDocumentStringFromContext = context => context[rawDocumentStringSymbol];
182
- function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext = defaultGetDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
183
+ const documentStringByDocument = new WeakMap();
184
+ function getDocumentStringFromDocument(documentNode) {
185
+ let documentString = documentStringByDocument.get(documentNode);
186
+ if (!documentString) {
187
+ documentString = print(documentNode);
188
+ documentStringByDocument.set(documentNode, documentString);
189
+ }
190
+ return documentString;
191
+ }
192
+ function useResponseCache({ cache = createInMemoryCache(), ttl: globalTtl = Infinity, session = () => null, enabled, ignoredTypes = [], ttlPerType = {}, ttlPerSchemaCoordinate = {}, idFields = ['id'], invalidateViaMutation = true, buildResponseCacheKey = defaultBuildResponseCacheKey, getDocumentStringFromContext, shouldCacheResult = defaultShouldCacheResult,
183
193
  // eslint-disable-next-line dot-notation
184
194
  includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_ENV'] === 'development' : false, } = {}) {
185
195
  const appliedTransform = Symbol('responseCache.appliedTransform');
@@ -200,19 +210,15 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
200
210
  };
201
211
  replaceSchema(patchedSchema);
202
212
  },
203
- onParse(parseCtx) {
204
- return function onParseEnd(ctx) {
205
- if (ctx.result && 'kind' in ctx.result) {
206
- const source = parseCtx.params.source;
207
- const rawDocumentString = typeof source === 'string' ? source : source.body;
208
- ctx.extendContext({
209
- [rawDocumentStringSymbol]: rawDocumentString,
210
- });
213
+ onParse({ params: { source } }) {
214
+ return function onParseEnd({ result }) {
215
+ if (result != null && !(result instanceof Error)) {
216
+ documentStringByDocument.set(result, source.toString());
211
217
  }
212
218
  };
213
219
  },
214
220
  async onExecute(ctx) {
215
- var _a;
221
+ var _a, _b;
216
222
  const identifier = new Map();
217
223
  const types = new Set();
218
224
  const context = {
@@ -252,102 +258,92 @@ includeExtensionMetadata = typeof process !== 'undefined' ? process.env['NODE_EN
252
258
  },
253
259
  };
254
260
  }
255
- else {
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 (((_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);
261
+ const documentString = (_a = getDocumentStringFromContext === null || getDocumentStringFromContext === void 0 ? void 0 : getDocumentStringFromContext(ctx.args.contextValue)) !== null && _a !== void 0 ? _a : getDocumentStringFromDocument(ctx.args.document);
262
+ const operationId = await buildResponseCacheKey({
263
+ documentString,
264
+ variableValues: ctx.args.variableValues,
265
+ operationName: ctx.args.operationName,
266
+ sessionId: session(ctx.args.contextValue),
267
+ });
268
+ if (((_b = enabled === null || enabled === void 0 ? void 0 : enabled(ctx.args.contextValue)) !== null && _b !== void 0 ? _b : true) === true) {
269
+ const cachedResponse = await cache.get(operationId);
270
+ if (cachedResponse != null) {
271
+ if (includeExtensionMetadata) {
272
+ ctx.setResultAndStopExecution({
273
+ ...cachedResponse,
274
+ extensions: {
275
+ responseCache: {
276
+ hit: true,
277
+ },
278
+ },
279
+ });
280
+ }
281
+ else {
282
+ ctx.setResultAndStopExecution(cachedResponse);
283
+ }
284
+ return;
285
+ }
286
+ }
287
+ if (ttlPerSchemaCoordinate) {
288
+ const typeInfo = new TypeInfo(ctx.args.schema);
289
+ visit(ctx.args.document, visitWithTypeInfo(typeInfo, {
290
+ Field(fieldNode) {
291
+ const parentType = typeInfo.getParentType();
292
+ if (parentType) {
293
+ const schemaCoordinate = `${parentType.name}.${fieldNode.name.value}`;
294
+ const maybeTtl = ttlPerSchemaCoordinate[schemaCoordinate];
295
+ if (maybeTtl !== undefined) {
296
+ context.currentTtl = calculateTtl(maybeTtl, context.currentTtl);
279
297
  }
280
- return;
281
298
  }
299
+ },
300
+ }));
301
+ }
302
+ return {
303
+ onExecuteDone({ result, setResult }) {
304
+ var _a;
305
+ if (isAsyncIterable(result)) {
306
+ // eslint-disable-next-line no-console
307
+ console.warn('[useResponseCache] AsyncIterable returned from execute is currently unsupported.');
308
+ return;
282
309
  }
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);
293
- }
294
- }
295
- },
296
- }));
310
+ if (context.skip) {
311
+ return;
297
312
  }
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
- });
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
- },
313
+ if (!shouldCacheResult({ result })) {
314
+ return;
315
+ }
316
+ // we only use the global ttl if no currentTtl has been determined.
317
+ const finalTtl = (_a = context.currentTtl) !== null && _a !== void 0 ? _a : globalTtl;
318
+ if (finalTtl === 0) {
319
+ if (includeExtensionMetadata) {
320
+ setResult({
321
+ ...result,
322
+ extensions: {
323
+ responseCache: {
324
+ hit: false,
325
+ didCache: false,
338
326
  },
339
- });
340
- }
341
- },
342
- };
343
- }
344
- else {
345
- // eslint-disable-next-line no-console
346
- console.warn(`[useResponseCache] Failed extracting document string from the context. The response will not be cached or served from the cache. ` +
347
- `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.`);
348
- return undefined;
349
- }
350
- }
327
+ },
328
+ });
329
+ }
330
+ return;
331
+ }
332
+ cache.set(operationId, result, identifier.values(), finalTtl);
333
+ if (includeExtensionMetadata) {
334
+ setResult({
335
+ ...result,
336
+ extensions: {
337
+ responseCache: {
338
+ hit: false,
339
+ didCache: true,
340
+ ttl: finalTtl,
341
+ },
342
+ },
343
+ });
344
+ }
345
+ },
346
+ };
351
347
  },
352
348
  };
353
349
  }
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@envelop/response-cache",
3
- "version": "2.3.3-alpha-a584bed.0",
3
+ "version": "2.3.4-alpha-fae0892.0",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
- "@envelop/core": "2.3.3-alpha-a584bed.0",
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/dotansimha/envelop.git",
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
@@ -76,6 +76,8 @@ export declare type UseResponseCacheParameter<C = any> = {
76
76
  * By default, the useResponseCache plugin hooks into onParse and writes the original operation string to the context.
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
78
  * Defaults to `defaultGetDocumentStringFromContext`
79
+ *
80
+ * @deprecated No longer being used in the next major version.
79
81
  */
80
82
  getDocumentStringFromContext?: GetDocumentStringFromContextFunction;
81
83
  /**