@graphql-box/cache-manager 2.1.4 → 2.2.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 (109) hide show
  1. package/lib/browser/index.js +1 -1
  2. package/lib/browser/index.js.map +1 -1
  3. package/lib/browser/production.analysis.txt +129 -17
  4. package/lib/main/debug/log-cache-entry/index.js.map +1 -1
  5. package/lib/main/debug/log-partial-compiled/index.js.map +1 -1
  6. package/lib/main/helpers/buildKeysAndPaths.js +73 -0
  7. package/lib/main/helpers/buildKeysAndPaths.js.map +1 -0
  8. package/lib/main/helpers/checkFieldPathChecklist.js +40 -0
  9. package/lib/main/helpers/checkFieldPathChecklist.js.map +1 -0
  10. package/lib/main/helpers/createFragmentSpreadChecklist.js +28 -0
  11. package/lib/main/helpers/createFragmentSpreadChecklist.js.map +1 -0
  12. package/lib/main/helpers/filterField.js +97 -0
  13. package/lib/main/helpers/filterField.js.map +1 -0
  14. package/lib/main/helpers/filterFragmentDefinitions.js +50 -0
  15. package/lib/main/helpers/filterFragmentDefinitions.js.map +1 -0
  16. package/lib/main/helpers/filterFragmentSpreads.js +37 -0
  17. package/lib/main/helpers/filterFragmentSpreads.js.map +1 -0
  18. package/lib/main/helpers/filterIDsAndTypeNames.js +47 -0
  19. package/lib/main/helpers/filterIDsAndTypeNames.js.map +1 -0
  20. package/lib/main/helpers/filterInlineFragments.js +42 -0
  21. package/lib/main/helpers/filterInlineFragments.js.map +1 -0
  22. package/lib/main/helpers/filterOutPropsWithArgsOrDirectives.js +39 -0
  23. package/lib/main/helpers/filterOutPropsWithArgsOrDirectives.js.map +1 -0
  24. package/lib/main/helpers/filterQuery.js +59 -0
  25. package/lib/main/helpers/filterQuery.js.map +1 -0
  26. package/lib/main/helpers/normalizeResponseData.js +23 -0
  27. package/lib/main/helpers/normalizeResponseData.js.map +1 -0
  28. package/lib/main/helpers/validTypeIDValue.js +20 -0
  29. package/lib/main/helpers/validTypeIDValue.js.map +1 -0
  30. package/lib/main/main/index.js +468 -472
  31. package/lib/main/main/index.js.map +1 -1
  32. package/lib/module/debug/log-cache-entry/index.js.map +1 -1
  33. package/lib/module/debug/log-partial-compiled/index.js.map +1 -1
  34. package/lib/module/helpers/buildKeysAndPaths.js +54 -0
  35. package/lib/module/helpers/buildKeysAndPaths.js.map +1 -0
  36. package/lib/module/helpers/checkFieldPathChecklist.js +31 -0
  37. package/lib/module/helpers/checkFieldPathChecklist.js.map +1 -0
  38. package/lib/module/helpers/createFragmentSpreadChecklist.js +15 -0
  39. package/lib/module/helpers/createFragmentSpreadChecklist.js.map +1 -0
  40. package/lib/module/helpers/filterField.js +81 -0
  41. package/lib/module/helpers/filterField.js.map +1 -0
  42. package/lib/module/helpers/filterFragmentDefinitions.js +39 -0
  43. package/lib/module/helpers/filterFragmentDefinitions.js.map +1 -0
  44. package/lib/module/helpers/filterFragmentSpreads.js +23 -0
  45. package/lib/module/helpers/filterFragmentSpreads.js.map +1 -0
  46. package/lib/module/helpers/filterIDsAndTypeNames.js +36 -0
  47. package/lib/module/helpers/filterIDsAndTypeNames.js.map +1 -0
  48. package/lib/module/helpers/filterInlineFragments.js +32 -0
  49. package/lib/module/helpers/filterInlineFragments.js.map +1 -0
  50. package/lib/module/helpers/filterOutPropsWithArgsOrDirectives.js +25 -0
  51. package/lib/module/helpers/filterOutPropsWithArgsOrDirectives.js.map +1 -0
  52. package/lib/module/helpers/filterQuery.js +43 -0
  53. package/lib/module/helpers/filterQuery.js.map +1 -0
  54. package/lib/module/helpers/normalizeResponseData.js +11 -0
  55. package/lib/module/helpers/normalizeResponseData.js.map +1 -0
  56. package/lib/module/helpers/validTypeIDValue.js +8 -0
  57. package/lib/module/helpers/validTypeIDValue.js.map +1 -0
  58. package/lib/module/main/index.js +465 -470
  59. package/lib/module/main/index.js.map +1 -1
  60. package/lib/types/debug/log-cache-entry/index.d.ts.map +1 -1
  61. package/lib/types/debug/log-cache-query/index.d.ts.map +1 -1
  62. package/lib/types/debug/log-partial-compiled/index.d.ts.map +1 -1
  63. package/lib/types/defs/index.d.ts +19 -9
  64. package/lib/types/defs/index.d.ts.map +1 -1
  65. package/lib/types/helpers/buildKeysAndPaths.d.ts +10 -0
  66. package/lib/types/helpers/buildKeysAndPaths.d.ts.map +1 -0
  67. package/lib/types/helpers/checkFieldPathChecklist.d.ts +4 -0
  68. package/lib/types/helpers/checkFieldPathChecklist.d.ts.map +1 -0
  69. package/lib/types/helpers/createFragmentSpreadChecklist.d.ts +11 -0
  70. package/lib/types/helpers/createFragmentSpreadChecklist.d.ts.map +1 -0
  71. package/lib/types/helpers/filterField.d.ts +6 -0
  72. package/lib/types/helpers/filterField.d.ts.map +1 -0
  73. package/lib/types/helpers/filterFragmentDefinitions.d.ts +10 -0
  74. package/lib/types/helpers/filterFragmentDefinitions.d.ts.map +1 -0
  75. package/lib/types/helpers/filterFragmentSpreads.d.ts +6 -0
  76. package/lib/types/helpers/filterFragmentSpreads.d.ts.map +1 -0
  77. package/lib/types/helpers/filterIDsAndTypeNames.d.ts +5 -0
  78. package/lib/types/helpers/filterIDsAndTypeNames.d.ts.map +1 -0
  79. package/lib/types/helpers/filterInlineFragments.d.ts +5 -0
  80. package/lib/types/helpers/filterInlineFragments.d.ts.map +1 -0
  81. package/lib/types/helpers/filterOutPropsWithArgsOrDirectives.d.ts +6 -0
  82. package/lib/types/helpers/filterOutPropsWithArgsOrDirectives.d.ts.map +1 -0
  83. package/lib/types/helpers/filterQuery.d.ts +5 -0
  84. package/lib/types/helpers/filterQuery.d.ts.map +1 -0
  85. package/lib/types/helpers/normalizeResponseData.d.ts +10 -0
  86. package/lib/types/helpers/normalizeResponseData.d.ts.map +1 -0
  87. package/lib/types/helpers/validTypeIDValue.d.ts +3 -0
  88. package/lib/types/helpers/validTypeIDValue.d.ts.map +1 -0
  89. package/lib/types/main/index.d.ts +13 -20
  90. package/lib/types/main/index.d.ts.map +1 -1
  91. package/package.json +2 -2
  92. package/src/__snapshots__/index.test.ts.snap +17449 -7185
  93. package/src/debug/log-cache-entry/index.ts +1 -1
  94. package/src/debug/log-partial-compiled/index.ts +1 -1
  95. package/src/defs/index.ts +18 -10
  96. package/src/helpers/buildKeysAndPaths.ts +71 -0
  97. package/src/helpers/checkFieldPathChecklist.ts +21 -0
  98. package/src/helpers/createFragmentSpreadChecklist.ts +17 -0
  99. package/src/helpers/filterField.ts +73 -0
  100. package/src/helpers/filterFragmentDefinitions.ts +40 -0
  101. package/src/helpers/filterFragmentSpreads.ts +28 -0
  102. package/src/helpers/filterIDsAndTypeNames.ts +31 -0
  103. package/src/helpers/filterInlineFragments.ts +29 -0
  104. package/src/helpers/filterOutPropsWithArgsOrDirectives.ts +30 -0
  105. package/src/helpers/filterQuery.ts +38 -0
  106. package/src/helpers/normalizeResponseData.ts +9 -0
  107. package/src/helpers/validTypeIDValue.ts +11 -0
  108. package/src/index.test.ts +179 -3
  109. package/src/main/index.ts +506 -499
@@ -5,21 +5,26 @@ import _set from "lodash/set";
5
5
  import _isUndefined from "lodash/isUndefined";
6
6
  import _isPlainObject from "lodash/isPlainObject";
7
7
  import _isObjectLike from "lodash/isObjectLike";
8
- import _isNumber from "lodash/isNumber";
9
8
  import _isArray from "lodash/isArray";
10
9
  import _get from "lodash/get";
11
10
  import _cloneDeep from "lodash/cloneDeep";
11
+ import _assign from "lodash/assign";
12
12
 
13
13
  var _dec, _dec2, _dec3, _class;
14
14
 
15
15
  import "core-js/modules/es.promise.js";
16
16
  import { DATA_ENTITIES, QUERY, QUERY_RESPONSES, REQUEST_FIELD_PATHS, TYPE_NAME_KEY } from "@graphql-box/core";
17
- import { dehydrateCacheMetadata, deleteChildFields, deleteInlineFragments, getAlias, getArguments, getChildFields, getDirectives, getInlineFragments, getName, getOperationDefinitions, hasChildFields, hashRequest, iterateChildFields, mergeObjects, rehydrateCacheMetadata } from "@graphql-box/helpers";
17
+ import { FRAGMENT_SPREAD, dehydrateCacheMetadata, getChildFields, getFragmentDefinitions, getOperationDefinitions, hasChildFields, hashRequest, iterateChildFields, mergeObjects, rehydrateCacheMetadata } from "@graphql-box/helpers";
18
18
  import Cacheability from "cacheability";
19
19
  import { print } from "graphql";
20
20
  import { CACHE_CONTROL, HEADER_NO_CACHE, METADATA, NO_CACHE } from "../consts";
21
21
  import { logCacheEntry, logCacheQuery, logPartialCompiled } from "../debug";
22
+ import { buildFieldKeysAndPaths } from "../helpers/buildKeysAndPaths";
22
23
  import deriveOpCacheability from "../helpers/deriveOpCacheability";
24
+ import filterOutPropsWithArgsOrDirectives from "../helpers/filterOutPropsWithArgsOrDirectives";
25
+ import filterQuery from "../helpers/filterQuery";
26
+ import normalizeResponseData from "../helpers/normalizeResponseData";
27
+ import { getValidTypeIDValue } from "../helpers/validTypeIDValue";
23
28
  export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec3 = logPartialCompiled(), (_class = class CacheManager {
24
29
  static async init(options) {
25
30
  const errors = [];
@@ -33,85 +38,11 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
33
38
  errors.push(new TypeError(message));
34
39
  }
35
40
 
36
- if (errors.length) return Promise.reject(errors);
37
- return new CacheManager(options);
38
- }
39
-
40
- static _analyzeLeafField(field, cachedAncestorFieldData, {
41
- data,
42
- fieldPathChecklist
43
- }, _options, _context) {
44
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, cachedAncestorFieldData);
45
-
46
- const {
47
- propNameOrIndex,
48
- requestFieldPath
49
- } = keysAndPaths;
50
- const {
51
- dataEntityData,
52
- requestFieldPathData,
53
- typeName
54
- } = cachedAncestorFieldData;
55
-
56
- const cachedFieldData = CacheManager._getFieldDataFromAncestor(dataEntityData, propNameOrIndex) || CacheManager._getFieldDataFromAncestor(requestFieldPathData, propNameOrIndex);
57
-
58
- const typeNames = {
59
- dataTypeName: (dataEntityData === null || dataEntityData === void 0 ? void 0 : dataEntityData.__typename) || (requestFieldPathData === null || requestFieldPathData === void 0 ? void 0 : requestFieldPathData.__typename),
60
- fieldTypeName: typeName
61
- };
62
-
63
- CacheManager._setFieldPathChecklist(fieldPathChecklist, {
64
- data: cachedFieldData
65
- }, requestFieldPath, typeNames);
66
-
67
- CacheManager._setCachedData(data, {
68
- data: cachedFieldData
69
- }, propNameOrIndex);
70
- }
71
-
72
- static _buildKey(key, path) {
73
- const paths = [];
74
- if (path.length) paths.push(path);
75
- paths.push(key);
76
- return paths.join(".");
77
- }
78
-
79
- static _buildRequestFieldCacheKey(name, requestFieldCacheKey, args, directives, index) {
80
- let key = `${_isNumber(index) ? index : name}`;
81
- if (args) key = `${key}(${JSON.stringify(args)})`;
82
- if (directives) key = `${key}(${JSON.stringify(directives)})`;
83
- return CacheManager._buildKey(key, requestFieldCacheKey);
84
- }
85
-
86
- static _checkFieldPathChecklist(fieldPathChecklistValues, fieldTypeName) {
87
- if (!fieldPathChecklistValues || !fieldPathChecklistValues.length) {
88
- return {
89
- hasData: false,
90
- typeUnused: !!fieldTypeName
91
- };
92
- }
93
-
94
- if (fieldPathChecklistValues.length === 1) {
95
- const {
96
- hasData,
97
- typeName
98
- } = fieldPathChecklistValues[0];
99
- const typeUnused = !typeName ? undefined : typeName !== fieldTypeName;
100
- return {
101
- hasData,
102
- typeUnused
103
- };
41
+ if (errors.length) {
42
+ return Promise.reject(errors);
104
43
  }
105
44
 
106
- return {
107
- hasData: fieldPathChecklistValues.some(({
108
- hasData,
109
- typeName
110
- }) => typeName === fieldTypeName && hasData),
111
- typeUnused: !fieldPathChecklistValues.every(({
112
- typeName
113
- }) => typeName === fieldTypeName)
114
- };
45
+ return new CacheManager(options);
115
46
  }
116
47
 
117
48
  static _countFieldPathChecklist(fieldPathChecklist) {
@@ -130,49 +61,33 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
130
61
  }
131
62
 
132
63
  static _getFieldDataFromAncestor(ancestorFieldData, propNameOrIndex) {
133
- return _isObjectLike(ancestorFieldData) ? ancestorFieldData[propNameOrIndex] : undefined;
134
- }
135
-
136
- static _getFieldKeysAndPaths(field, options) {
137
- const {
138
- index,
139
- requestFieldCacheKey = "",
140
- requestFieldPath = "",
141
- responseDataPath = ""
142
- } = options;
143
- const name = getName(field);
144
-
145
- const updatedRequestFieldCacheKey = CacheManager._buildRequestFieldCacheKey(name, requestFieldCacheKey, getArguments(field), getDirectives(field), index);
146
-
147
- const fieldAliasOrName = getAlias(field) || name;
148
- const updatedRequestFieldPath = _isNumber(index) ? requestFieldPath : CacheManager._buildKey(fieldAliasOrName, requestFieldPath);
149
- const propNameOrIndex = _isNumber(index) ? index : fieldAliasOrName;
150
-
151
- const updatedResponseDataPath = CacheManager._buildKey(propNameOrIndex, responseDataPath);
152
-
153
- return {
154
- hashedRequestFieldCacheKey: hashRequest(updatedRequestFieldCacheKey),
155
- propNameOrIndex,
156
- requestFieldCacheKey: updatedRequestFieldCacheKey,
157
- requestFieldPath: updatedRequestFieldPath,
158
- responseDataPath: updatedResponseDataPath
159
- };
64
+ return _isObjectLike(ancestorFieldData) ? _cloneDeep(ancestorFieldData[propNameOrIndex]) : undefined;
160
65
  }
161
66
 
162
67
  static _getOperationCacheControl(cacheMetadata, operation) {
163
68
  const defaultCacheControl = HEADER_NO_CACHE;
164
- if (!cacheMetadata) return defaultCacheControl;
69
+
70
+ if (!cacheMetadata) {
71
+ return defaultCacheControl;
72
+ }
73
+
165
74
  const cacheability = cacheMetadata.get(operation);
166
75
  return cacheability ? cacheability.printCacheControl() : defaultCacheControl;
167
76
  }
168
77
 
169
78
  static _getResponseCacheMetadata(cacheMetadata, partialQueryResponse) {
170
- if (!partialQueryResponse) return cacheMetadata;
79
+ if (!partialQueryResponse) {
80
+ return cacheMetadata;
81
+ }
82
+
171
83
  return new Map([...partialQueryResponse.cacheMetadata, ...cacheMetadata]);
172
84
  }
173
85
 
174
- static _isDataEntity(fieldTypeInfo) {
175
- if (!fieldTypeInfo) return false;
86
+ static _isNodeEntity(fieldTypeInfo) {
87
+ if (!fieldTypeInfo) {
88
+ return false;
89
+ }
90
+
176
91
  const {
177
92
  isEntity,
178
93
  possibleTypes
@@ -180,8 +95,8 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
180
95
  return isEntity || possibleTypes.some(type => !!type.isEntity);
181
96
  }
182
97
 
183
- static _isRequestFieldPath(fieldTypeInfo) {
184
- return !!fieldTypeInfo && (this._isDataEntity(fieldTypeInfo) || fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives);
98
+ static _isNodeRequestFieldPath(fieldTypeInfo) {
99
+ return !!fieldTypeInfo && (this._isNodeEntity(fieldTypeInfo) || fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives);
185
100
  }
186
101
 
187
102
  static _isValid(cacheability) {
@@ -208,18 +123,21 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
208
123
  }, {
209
124
  propNameOrIndex,
210
125
  requestFieldPath
211
- }, typeNames, _options, {
126
+ }, typeNamesAndKind, _options, {
212
127
  operation
213
128
  }) {
214
129
  CacheManager._setCacheMetadata(cacheMetadata, cachedFieldData.cacheability, requestFieldPath, operation);
215
130
 
216
- CacheManager._setFieldPathChecklist(fieldPathChecklist, cachedFieldData, requestFieldPath, typeNames);
131
+ CacheManager._setFieldPathChecklist(fieldPathChecklist, cachedFieldData, requestFieldPath, typeNamesAndKind);
217
132
 
218
133
  CacheManager._setCachedData(data, cachedFieldData, propNameOrIndex);
219
134
  }
220
135
 
221
136
  static _setCacheMetadata(cacheMetadata, cacheability, requestFieldPath, operation) {
222
- if (!cacheability) return;
137
+ if (!cacheability) {
138
+ return;
139
+ }
140
+
223
141
  cacheMetadata.set(requestFieldPath, cacheability);
224
142
  const operationCacheability = cacheMetadata.get(operation);
225
143
 
@@ -232,23 +150,39 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
232
150
  data
233
151
  }, requestFieldPath, {
234
152
  dataTypeName,
235
- fieldTypeName
153
+ fieldTypeName,
154
+ fragmentKind,
155
+ fragmentName
236
156
  }) {
237
- if (_isUndefined(fieldTypeName)) {
238
- if (fieldPathChecklist.has(requestFieldPath)) return;
157
+ if (_isUndefined(fieldTypeName) || fragmentKind === FRAGMENT_SPREAD) {
158
+ if (fieldPathChecklist.has(requestFieldPath)) {
159
+ return;
160
+ }
161
+
239
162
  fieldPathChecklist.set(requestFieldPath, [{
163
+ fragmentKind,
164
+ fragmentName,
240
165
  hasData: !_isUndefined(data)
241
166
  }]);
242
167
  return;
243
168
  }
244
169
 
245
- if (dataTypeName !== fieldTypeName) return;
170
+ if (dataTypeName !== fieldTypeName) {
171
+ return;
172
+ }
173
+
246
174
  const entry = fieldPathChecklist.get(requestFieldPath);
247
175
  const checklistValues = entry ? entry : [];
176
+
248
177
  if (checklistValues.some(({
249
178
  typeName
250
- }) => typeName === dataTypeName)) return;
179
+ }) => typeName === dataTypeName)) {
180
+ return;
181
+ }
182
+
251
183
  fieldPathChecklist.set(requestFieldPath, [...checklistValues, {
184
+ fragmentKind,
185
+ fragmentName,
252
186
  hasData: !_isUndefined(data),
253
187
  typeName: dataTypeName
254
188
  }]);
@@ -295,23 +229,33 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
295
229
  return Promise.reject(new TypeError("@graphql-box/cache-manager expected an AST."));
296
230
  }
297
231
 
298
- const cachedResponseData = await this._getCachedResponseData(requestData, options, context);
232
+ const cacheManagerContext = { ...context,
233
+ fragmentDefinitions: getFragmentDefinitions(ast),
234
+ typeIDKey: this._typeIDKey
235
+ };
236
+ const cachedResponseData = await this._retrieveCachedResponseData(requestData, options, cacheManagerContext);
299
237
  const {
300
238
  cacheMetadata,
301
239
  data,
302
240
  fieldCount
303
241
  } = cachedResponseData;
304
- if (fieldCount.missing === fieldCount.total) return {
305
- updated: requestData
306
- };
242
+
243
+ if (fieldCount.missing === fieldCount.total) {
244
+ return {
245
+ updated: requestData
246
+ };
247
+ }
307
248
 
308
249
  if (!fieldCount.missing) {
309
250
  const dataCaching = this._setQueryResponseCacheEntry(hash, {
310
251
  cacheMetadata,
311
252
  data
312
- }, options, context);
253
+ }, options, cacheManagerContext);
254
+
255
+ if (options.awaitDataCaching) {
256
+ await dataCaching;
257
+ }
313
258
 
314
- if (options.awaitDataCaching) await dataCaching;
315
259
  return {
316
260
  response: {
317
261
  cacheMetadata,
@@ -323,14 +267,21 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
323
267
  this._setPartialQueryResponse(hash, {
324
268
  cacheMetadata,
325
269
  data
326
- }, options, context);
270
+ }, options, cacheManagerContext);
271
+
272
+ const filteredAST = filterQuery(requestData, cachedResponseData, cacheManagerContext);
273
+ const {
274
+ fragmentDefinitions,
275
+ typeIDKey,
276
+ ...rest
277
+ } = cacheManagerContext;
327
278
 
328
- this._filterQuery(requestData, cachedResponseData, context);
279
+ _assign(context, rest);
329
280
 
330
- const request = print(ast);
281
+ const request = print(filteredAST);
331
282
  return {
332
283
  updated: {
333
- ast,
284
+ ast: filteredAST,
334
285
  hash: hashRequest(request),
335
286
  request
336
287
  }
@@ -343,7 +294,11 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
343
294
 
344
295
  async checkQueryResponseCacheEntry(hash, options, context) {
345
296
  const result = await this._checkCacheEntry(QUERY_RESPONSES, hash, options, context);
346
- if (!result) return false;
297
+
298
+ if (!result) {
299
+ return false;
300
+ }
301
+
347
302
  const {
348
303
  cacheMetadata,
349
304
  data
@@ -359,18 +314,23 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
359
314
  }
360
315
 
361
316
  async resolveQuery(requestData, updatedRequestData, rawResponseData, options, context) {
317
+ const cacheManagerContext = { ...context,
318
+ fragmentDefinitions: getFragmentDefinitions(updatedRequestData.ast),
319
+ typeIDKey: this._typeIDKey
320
+ };
362
321
  const dataCaching = [];
363
322
  const {
364
323
  cacheMetadata,
365
- data
366
- } = await this._resolveRequest(updatedRequestData, rawResponseData, options, context);
324
+ data,
325
+ hasNext
326
+ } = await this._resolveRequest(updatedRequestData, rawResponseData, options, cacheManagerContext);
367
327
  let partialQueryResponse;
368
328
 
369
- if (context.queryFiltered) {
329
+ if (cacheManagerContext.queryFiltered) {
370
330
  dataCaching.push(this._setQueryResponseCacheEntry(updatedRequestData.hash, {
371
331
  cacheMetadata,
372
332
  data
373
- }, options, context));
333
+ }, options, cacheManagerContext));
374
334
  partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
375
335
  }
376
336
 
@@ -381,79 +341,127 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
381
341
  dataCaching.push(this._setQueryResponseCacheEntry(requestData.hash, {
382
342
  cacheMetadata: responseCacheMetadata,
383
343
  data: responseData
384
- }, options, context));
385
- if (options.awaitDataCaching) await Promise.all(dataCaching);
344
+ }, options, cacheManagerContext));
345
+
346
+ if (options.awaitDataCaching) {
347
+ await Promise.all(dataCaching);
348
+ }
349
+
386
350
  return {
387
351
  cacheMetadata: responseCacheMetadata,
388
- data: responseData
352
+ data: responseData,
353
+ hasNext
389
354
  };
390
355
  }
391
356
 
392
357
  async resolveRequest(requestData, rawResponseData, options, context) {
393
- return this._resolveRequest(requestData, rawResponseData, options, context);
358
+ const cacheManagerContext = { ...context,
359
+ fragmentDefinitions: getFragmentDefinitions(requestData.ast),
360
+ typeIDKey: this._typeIDKey
361
+ };
362
+ return this._resolveRequest(requestData, rawResponseData, options, cacheManagerContext);
394
363
  }
395
364
 
396
- async _analyzeField(field, cachedAncestorFieldData, cachedResponseData, options, context) {
397
- if (hasChildFields(field)) {
398
- await this._analyzeParentField(field, cachedAncestorFieldData, cachedResponseData, options, context);
365
+ async _analyzeFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
366
+ if (hasChildFields(fieldNode)) {
367
+ await this._analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
399
368
  } else {
400
- await CacheManager._analyzeLeafField(field, cachedAncestorFieldData, cachedResponseData, options, context);
369
+ await this._analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
401
370
  }
402
371
  }
403
372
 
404
- async _analyzeParentField(field, cachedAncestorFieldData, cachedResponseData, options, context) {
405
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, cachedAncestorFieldData);
406
-
373
+ async _analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
374
+ const keysAndPaths = buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
407
375
  const {
408
376
  hashedRequestFieldCacheKey,
409
377
  propNameOrIndex,
410
- requestFieldCacheKey,
411
378
  requestFieldPath
412
379
  } = keysAndPaths;
413
380
  const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
414
381
  const {
415
- dataEntityData: ancestorDataEntityData,
416
- requestFieldPathData: ancestorRequestFieldPathData,
382
+ entityData,
383
+ fragmentKind,
384
+ fragmentName,
385
+ requestFieldPathData,
417
386
  typeName
418
387
  } = cachedAncestorFieldData;
419
- const cachedFieldData = {
420
- dataEntityData: CacheManager._getFieldDataFromAncestor(ancestorDataEntityData, propNameOrIndex),
421
- requestFieldPathData: CacheManager._getFieldDataFromAncestor(ancestorRequestFieldPathData, propNameOrIndex)
388
+ const typeNamesAndKind = {
389
+ dataTypeName: (entityData === null || entityData === void 0 ? void 0 : entityData.__typename) || (requestFieldPathData === null || requestFieldPathData === void 0 ? void 0 : requestFieldPathData.__typename),
390
+ fieldTypeName: typeName,
391
+ fragmentKind,
392
+ fragmentName
422
393
  };
423
394
 
424
- if (CacheManager._isRequestFieldPath(fieldTypeInfo)) {
425
- await this._setRequestFieldPathData(cachedFieldData, hashedRequestFieldCacheKey, options, context);
426
- }
395
+ if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
396
+ const {
397
+ cacheability,
398
+ entry
399
+ } = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, options, context);
427
400
 
428
- if (CacheManager._isDataEntity(fieldTypeInfo)) {
429
- await this._setDataEntityData(cachedFieldData, fieldTypeInfo, options, context);
401
+ CacheManager._setCachedResponseData({
402
+ cacheability,
403
+ data: entry
404
+ }, cachedResponseData, keysAndPaths, typeNamesAndKind, options, context);
405
+ } else {
406
+ const cachedFieldData = CacheManager._getFieldDataFromAncestor(entityData, propNameOrIndex) || CacheManager._getFieldDataFromAncestor(requestFieldPathData, propNameOrIndex);
407
+
408
+ CacheManager._setFieldPathChecklist(cachedResponseData.fieldPathChecklist, {
409
+ data: cachedFieldData
410
+ }, requestFieldPath, typeNamesAndKind);
411
+
412
+ CacheManager._setCachedData(cachedResponseData.data, {
413
+ data: cachedFieldData
414
+ }, propNameOrIndex);
430
415
  }
416
+ }
431
417
 
418
+ async _analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
419
+ const keysAndPaths = buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
420
+ const {
421
+ propNameOrIndex,
422
+ requestFieldCacheKey,
423
+ requestFieldPath
424
+ } = keysAndPaths;
425
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
432
426
  const {
433
427
  cacheability,
434
- dataEntityData,
428
+ data,
429
+ entityData,
435
430
  requestFieldPathData
436
- } = cachedFieldData;
437
- const data = !_isUndefined(requestFieldPathData) || !_isUndefined(dataEntityData) ? this._mergeObjects(requestFieldPathData, dataEntityData) : undefined;
431
+ } = await this._retrieveCachedParentNodeData(cachedAncestorFieldData, keysAndPaths, fieldTypeInfo, options, context);
432
+ const {
433
+ fragmentKind,
434
+ fragmentName,
435
+ typeName
436
+ } = cachedAncestorFieldData;
438
437
 
439
438
  CacheManager._setCachedResponseData({
440
439
  cacheability,
441
440
  data
442
441
  }, cachedResponseData, keysAndPaths, {
443
442
  dataTypeName: _get(data, TYPE_NAME_KEY),
444
- fieldTypeName: typeName
443
+ fieldTypeName: typeName,
444
+ fragmentKind,
445
+ fragmentName
445
446
  }, options, context);
446
447
 
447
- if (!_isObjectLike(data)) return;
448
+ if (!_isObjectLike(data)) {
449
+ return;
450
+ }
451
+
448
452
  const objectLikeData = data;
449
453
  const promises = [];
450
- iterateChildFields(field, objectLikeData, (childField, childTypeName, childIndex) => {
451
- promises.push(this._analyzeField(childField, {
454
+ iterateChildFields(fieldNode, objectLikeData, context.fragmentDefinitions, (childField, childTypeName, childFragmentKind, childFragmentName, childIndex) => {
455
+ promises.push(this._analyzeFieldNode(childField, {
456
+ cacheability,
457
+ entityData,
458
+ fragmentKind: childFragmentKind,
459
+ fragmentName: childFragmentName,
452
460
  index: childIndex,
453
461
  requestFieldCacheKey,
454
462
  requestFieldPath,
455
- typeName: childTypeName,
456
- ...cachedFieldData
463
+ requestFieldPathData,
464
+ typeName: childTypeName
457
465
  }, { ...cachedResponseData,
458
466
  data: cachedResponseData.data[propNameOrIndex]
459
467
  }, options, context));
@@ -474,7 +482,11 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
474
482
 
475
483
  const queryNode = getOperationDefinitions(ast, context.operation)[0];
476
484
  const fieldsAndTypeNames = getChildFields(queryNode);
477
- if (!fieldsAndTypeNames) return cacheMetadata;
485
+
486
+ if (!fieldsAndTypeNames) {
487
+ return cacheMetadata;
488
+ }
489
+
478
490
  fieldsAndTypeNames.forEach(({
479
491
  fieldNode
480
492
  }) => this._setFieldCacheability(fieldNode, {
@@ -489,9 +501,17 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
489
501
  async _checkCacheEntry(cacheType, hash, options, context) {
490
502
  try {
491
503
  const cacheability = await this._hasCacheEntry(cacheType, hash);
492
- if (!cacheability || !CacheManager._isValid(cacheability)) return false;
504
+
505
+ if (!cacheability || !CacheManager._isValid(cacheability)) {
506
+ return false;
507
+ }
508
+
493
509
  const entry = await this._getCacheEntry(cacheType, hash, options, context);
494
- if (!entry) return false;
510
+
511
+ if (_isUndefined(entry)) {
512
+ return false;
513
+ }
514
+
495
515
  return {
496
516
  cacheability,
497
517
  entry
@@ -522,148 +542,6 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
522
542
  return cacheMetadata;
523
543
  }
524
544
 
525
- _filterField(field, fieldPathChecklist, ancestorRequestFieldPath, context) {
526
- const fieldsAndTypeNames = getChildFields(field);
527
- if (!fieldsAndTypeNames) return false;
528
-
529
- for (let i = fieldsAndTypeNames.length - 1; i >= 0; i -= 1) {
530
- const {
531
- fieldNode: childField,
532
- typeName: childTypeName
533
- } = fieldsAndTypeNames[i];
534
- const childFieldName = getName(childField);
535
- if (childFieldName === this._typeIDKey || childFieldName === TYPE_NAME_KEY) continue;
536
-
537
- const {
538
- requestFieldPath
539
- } = CacheManager._getFieldKeysAndPaths(childField, {
540
- requestFieldPath: ancestorRequestFieldPath
541
- });
542
-
543
- const {
544
- hasData,
545
- typeUnused
546
- } = CacheManager._checkFieldPathChecklist(fieldPathChecklist.get(requestFieldPath), childTypeName);
547
-
548
- if (hasData || typeUnused) {
549
- if (!hasChildFields(childField)) {
550
- deleteChildFields(field, childField);
551
- } else if (this._filterField(childField, fieldPathChecklist, requestFieldPath, context)) {
552
- deleteChildFields(field, childField);
553
- }
554
- }
555
- }
556
-
557
- this._filterInlineFragments(field);
558
-
559
- this._filterIDsAndTypeNames(field);
560
-
561
- return !hasChildFields(field);
562
- }
563
-
564
- _filterIDsAndTypeNames(field) {
565
- const fieldsAndTypeNames = getChildFields(field);
566
- if (!fieldsAndTypeNames || fieldsAndTypeNames.length > 3) return false;
567
- const fieldNames = fieldsAndTypeNames.map(({
568
- fieldNode
569
- }) => getName(fieldNode));
570
-
571
- if (fieldNames.length === 2 && fieldNames.every(name => name === this._typeIDKey || name === TYPE_NAME_KEY)) {
572
- deleteChildFields(field, fieldsAndTypeNames.map(({
573
- fieldNode
574
- }) => fieldNode));
575
- return true;
576
- }
577
-
578
- if (fieldNames.length === 1 && fieldNames[0] === this._typeIDKey || fieldNames[0] === TYPE_NAME_KEY) {
579
- const {
580
- fieldNode
581
- } = fieldsAndTypeNames[0];
582
- deleteChildFields(field, fieldNode);
583
- return true;
584
- }
585
-
586
- return false;
587
- }
588
-
589
- _filterInlineFragments(field) {
590
- const inlineFragments = getInlineFragments(field);
591
- let filtered = false;
592
- inlineFragments.forEach(fragment => {
593
- const fieldsAndTypeNames = getChildFields(fragment);
594
-
595
- if (!fieldsAndTypeNames || !fieldsAndTypeNames.length) {
596
- deleteInlineFragments(field, fragment);
597
- filtered = true;
598
- return;
599
- }
600
-
601
- if (fieldsAndTypeNames.length === 1) {
602
- const {
603
- fieldNode
604
- } = fieldsAndTypeNames[0];
605
-
606
- if (getName(fieldNode) === this._typeIDKey) {
607
- deleteInlineFragments(field, fragment);
608
- filtered = true;
609
- }
610
- }
611
- });
612
- return filtered;
613
- }
614
-
615
- _filterQuery({
616
- ast
617
- }, {
618
- fieldPathChecklist
619
- }, context) {
620
- const queryNode = getOperationDefinitions(ast, context.operation)[0];
621
- const fieldsAndTypeNames = getChildFields(queryNode);
622
- if (!fieldsAndTypeNames) return;
623
-
624
- for (let i = fieldsAndTypeNames.length - 1; i >= 0; i -= 1) {
625
- const {
626
- fieldNode
627
- } = fieldsAndTypeNames[i];
628
-
629
- const {
630
- requestFieldPath
631
- } = CacheManager._getFieldKeysAndPaths(fieldNode, {
632
- requestFieldPath: context.operation
633
- });
634
-
635
- if (this._filterField(fieldNode, fieldPathChecklist, requestFieldPath, context)) {
636
- deleteChildFields(queryNode, fieldNode);
637
- }
638
- }
639
-
640
- context.queryFiltered = true;
641
- }
642
-
643
- async _getCachedResponseData({
644
- ast
645
- }, options, context) {
646
- const cachedResponseData = {
647
- cacheMetadata: new Map(),
648
- data: {},
649
- fieldCount: {
650
- missing: 0,
651
- total: 0
652
- },
653
- fieldPathChecklist: new Map()
654
- };
655
- const queryNode = getOperationDefinitions(ast, context.operation)[0];
656
- const fieldsAndTypeNames = getChildFields(queryNode);
657
- if (!fieldsAndTypeNames) return cachedResponseData;
658
- await Promise.all(fieldsAndTypeNames.map(({
659
- fieldNode
660
- }) => this._analyzeField(fieldNode, {
661
- requestFieldPath: context.operation
662
- }, cachedResponseData, options, context)));
663
- cachedResponseData.fieldCount = CacheManager._countFieldPathChecklist(cachedResponseData.fieldPathChecklist);
664
- return cachedResponseData;
665
- }
666
-
667
545
  async _getCacheEntry(cacheType, hash, _options, _context) {
668
546
  try {
669
547
  return await this._cache.get(`${cacheType}::${hash}`);
@@ -681,7 +559,10 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
681
559
  }
682
560
 
683
561
  _getResponseData(responseData, partialQueryResponse) {
684
- if (!partialQueryResponse) return responseData;
562
+ if (!partialQueryResponse) {
563
+ return responseData;
564
+ }
565
+
685
566
  return this._mergeObjects(partialQueryResponse.data, responseData);
686
567
  }
687
568
 
@@ -697,9 +578,18 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
697
578
  isEntity,
698
579
  possibleTypes
699
580
  }) {
700
- if (!_get(fieldData, this._typeIDKey, null)) return false;
701
- if (isEntity) return true;
702
- if (!possibleTypes.length) return false;
581
+ if (!_get(fieldData, this._typeIDKey, null)) {
582
+ return false;
583
+ }
584
+
585
+ if (isEntity) {
586
+ return true;
587
+ }
588
+
589
+ if (!possibleTypes.length) {
590
+ return false;
591
+ }
592
+
703
593
  return possibleTypes.some(type => type.typeName === fieldData.__typename);
704
594
  }
705
595
 
@@ -709,159 +599,288 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
709
599
  });
710
600
  }
711
601
 
712
- async _parseFieldDataEntityAndRequestFieldPathCacheEntryData(field, ancestorKeysAndPaths, {
602
+ async _parseEntityAndRequestFieldPathCacheEntryData(field, ancestorKeysAndPaths, {
713
603
  cacheMetadata,
714
- dataEntityData,
604
+ entityData,
715
605
  requestFieldPathData
716
606
  }, options, context) {
717
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, ancestorKeysAndPaths);
718
-
607
+ const keysAndPaths = buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
719
608
  const {
720
609
  requestFieldCacheKey,
721
610
  requestFieldPath,
722
611
  responseDataPath
723
612
  } = keysAndPaths;
724
613
 
725
- const fieldData = _get(requestFieldPathData, responseDataPath, null);
614
+ const fieldData = _get(requestFieldPathData, responseDataPath);
726
615
 
727
- if (!_isObjectLike(fieldData)) return;
728
- const objectLikeFieldData = fieldData;
729
- const promises = [];
730
- iterateChildFields(field, objectLikeFieldData, (childField, _typeName, childIndex) => {
731
- promises.push(this._parseFieldDataEntityAndRequestFieldPathCacheEntryData(childField, {
732
- index: childIndex,
733
- requestFieldCacheKey,
734
- requestFieldPath,
735
- responseDataPath
736
- }, {
737
- cacheMetadata,
738
- dataEntityData,
739
- requestFieldPathData
740
- }, options, context));
741
- });
742
- await Promise.all(promises);
743
- await this._setFieldDataEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
616
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
617
+
618
+ if (!_isObjectLike(fieldData) && !(fieldTypeInfo !== null && fieldTypeInfo !== void 0 && fieldTypeInfo.hasDirectives)) {
619
+ return;
620
+ }
621
+
622
+ if (_isObjectLike(fieldData)) {
623
+ const promises = [];
624
+ iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
625
+ promises.push(this._parseEntityAndRequestFieldPathCacheEntryData(childField, {
626
+ index: childIndex,
627
+ requestFieldCacheKey,
628
+ requestFieldPath,
629
+ responseDataPath
630
+ }, {
631
+ cacheMetadata,
632
+ entityData,
633
+ requestFieldPathData
634
+ }, options, context));
635
+ });
636
+ await Promise.all(promises);
637
+ }
638
+
639
+ await this._setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
744
640
  cacheMetadata,
745
- dataEntityData,
641
+ entityData,
746
642
  requestFieldPathData
747
643
  }, options, context);
748
644
  }
749
645
 
750
646
  async _resolveRequest(requestData, rawResponseData, options, context) {
647
+ const normalizedResponseData = rawResponseData.path ? normalizeResponseData(rawResponseData) : rawResponseData;
751
648
  const dataCaching = [];
752
649
 
753
- const cacheMetadata = this._buildCacheMetadata(requestData, rawResponseData, options, context);
650
+ const cacheMetadata = this._buildCacheMetadata(requestData, normalizedResponseData, options, context);
754
651
 
755
652
  const {
756
- data
757
- } = rawResponseData;
758
- dataCaching.push(this._setDataEntityAndRequestFieldPathCacheEntries(requestData, {
653
+ data,
654
+ hasNext
655
+ } = normalizedResponseData;
656
+ dataCaching.push(this._setEntityAndRequestFieldPathCacheEntries(requestData, {
759
657
  cacheMetadata,
760
- dataEntityData: _cloneDeep(data),
658
+ entityData: _cloneDeep(data),
761
659
  requestFieldPathData: _cloneDeep(data)
762
660
  }, options, context));
763
- if (options.awaitDataCaching) await Promise.all(dataCaching);
661
+
662
+ if (options.awaitDataCaching) {
663
+ await Promise.all(dataCaching);
664
+ }
665
+
764
666
  return {
765
667
  cacheMetadata,
766
- data
668
+ data,
669
+ hasNext
670
+ };
671
+ }
672
+
673
+ async _retrieveCachedEntityData(validTypeIDValue, {
674
+ possibleTypes,
675
+ typeName
676
+ }, options, context) {
677
+ const typeNames = [...possibleTypes.map(type => type.typeName), typeName];
678
+ const checkResults = await Promise.all(typeNames.map(name => this._checkCacheEntry(DATA_ENTITIES, `${name}::${validTypeIDValue}`, options, context)));
679
+ const validResults = checkResults.filter(result => !!result);
680
+ let validResult;
681
+
682
+ if (validResults.length === 1) {
683
+ validResult = validResults[0];
684
+ } else if (validResults.length > 1) {
685
+ validResults.sort(({
686
+ cacheability: a
687
+ }, {
688
+ cacheability: b
689
+ }) => a.metadata.ttl - b.metadata.ttl);
690
+ validResult = {
691
+ cacheability: validResults[0].cacheability,
692
+ entry: validResults.reduce((obj, {
693
+ entry
694
+ }) => this._mergeObjects(obj, entry), {})
695
+ };
696
+ }
697
+
698
+ return validResult || {};
699
+ }
700
+
701
+ async _retrieveCachedParentNodeData({
702
+ entityData: ancestorEntityData,
703
+ requestFieldPathData: ancestorRequestFieldPathData
704
+ }, {
705
+ hashedRequestFieldCacheKey,
706
+ propNameOrIndex
707
+ }, fieldTypeInfo, options, context) {
708
+ var _entityData;
709
+
710
+ let entityData = CacheManager._getFieldDataFromAncestor(ancestorEntityData, propNameOrIndex);
711
+
712
+ let requestFieldPathData = CacheManager._getFieldDataFromAncestor(ancestorRequestFieldPathData, propNameOrIndex);
713
+
714
+ let cacheability;
715
+
716
+ if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
717
+ const {
718
+ cacheability: entryCacheability,
719
+ entry
720
+ } = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, options, context);
721
+
722
+ if (entry) {
723
+ requestFieldPathData = this._mergeObjects(requestFieldPathData, entry);
724
+ }
725
+
726
+ if (entryCacheability) {
727
+ cacheability = entryCacheability;
728
+ }
729
+ }
730
+
731
+ const validTypeIDValue = getValidTypeIDValue(requestFieldPathData, fieldTypeInfo, this._typeIDKey);
732
+
733
+ if (CacheManager._isNodeEntity(fieldTypeInfo) && validTypeIDValue) {
734
+ var _cacheability;
735
+
736
+ const {
737
+ cacheability: entryCacheability,
738
+ entry
739
+ } = await this._retrieveCachedEntityData(validTypeIDValue, fieldTypeInfo, options, context);
740
+
741
+ if (entry) {
742
+ entityData = this._mergeObjects(entityData, entry);
743
+ }
744
+
745
+ if (entryCacheability && (!cacheability || entryCacheability.metadata.ttl > ((_cacheability = cacheability) === null || _cacheability === void 0 ? void 0 : _cacheability.metadata.ttl))) {
746
+ cacheability = entryCacheability;
747
+ }
748
+ }
749
+
750
+ const data = !_isUndefined(requestFieldPathData) || !_isUndefined(entityData) ? this._mergeObjects(requestFieldPathData, entityData) : (_entityData = entityData) !== null && _entityData !== void 0 ? _entityData : requestFieldPathData;
751
+ return {
752
+ cacheability,
753
+ data,
754
+ entityData,
755
+ requestFieldPathData
767
756
  };
768
757
  }
769
758
 
759
+ async _retrieveCachedRequestFieldPathData(hash, options, context) {
760
+ return this._checkCacheEntry(REQUEST_FIELD_PATHS, hash, options, context) || {};
761
+ }
762
+
763
+ async _retrieveCachedResponseData({
764
+ ast
765
+ }, options, context) {
766
+ const cachedResponseData = {
767
+ cacheMetadata: new Map(),
768
+ data: {},
769
+ fieldCount: {
770
+ missing: 0,
771
+ total: 0
772
+ },
773
+ fieldPathChecklist: new Map()
774
+ };
775
+ const queryNode = getOperationDefinitions(ast, context.operation)[0];
776
+ const fieldsAndTypeNames = getChildFields(queryNode);
777
+
778
+ if (!fieldsAndTypeNames) {
779
+ return cachedResponseData;
780
+ }
781
+
782
+ await Promise.all(fieldsAndTypeNames.map(({
783
+ fieldNode
784
+ }) => this._analyzeFieldNode(fieldNode, {
785
+ requestFieldPath: context.operation
786
+ }, cachedResponseData, options, context)));
787
+ cachedResponseData.fieldCount = CacheManager._countFieldPathChecklist(cachedResponseData.fieldPathChecklist);
788
+ return cachedResponseData;
789
+ }
790
+
770
791
  async _setCacheEntry(cacheType, hash, value, cachemapOptions, _options, _context) {
771
792
  try {
772
793
  await this._cache.set(`${cacheType}::${hash}`, _cloneDeep(value), cachemapOptions);
773
794
  } catch (error) {}
774
795
  }
775
796
 
776
- async _setDataEntityAndRequestFieldPathCacheEntries(requestData, responseData, options, context) {
797
+ async _setEntityAndRequestFieldPathCacheEntries(requestData, responseData, options, context) {
777
798
  const operationNode = getOperationDefinitions(requestData.ast, context.operation)[0];
778
799
  const fieldsAndTypeNames = getChildFields(operationNode);
779
- if (!fieldsAndTypeNames) return;
800
+
801
+ if (!fieldsAndTypeNames) {
802
+ return;
803
+ }
804
+
780
805
  await Promise.all(fieldsAndTypeNames.map(({
781
806
  fieldNode
782
807
  }) => {
783
- return this._parseFieldDataEntityAndRequestFieldPathCacheEntryData(fieldNode, {
808
+ return this._parseEntityAndRequestFieldPathCacheEntryData(fieldNode, {
784
809
  requestFieldPath: context.operation
785
810
  }, responseData, options, context);
786
811
  }));
787
812
  }
788
813
 
789
- async _setDataEntityCacheEntry({
790
- responseDataPath
791
- }, {
792
- cacheability,
793
- data,
794
- fieldTypeInfo
814
+ async _setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
815
+ cacheMetadata,
816
+ entityData,
817
+ requestFieldPathData
795
818
  }, options, context) {
796
- const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
819
+ const {
820
+ requestFieldPath,
821
+ responseDataPath
822
+ } = keysAndPaths;
797
823
 
798
- let fieldData = _get(data, responseDataPath, null);
824
+ const fieldData = _get(entityData, responseDataPath);
799
825
 
800
- const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
826
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
827
+ const cacheability = cacheMetadata.get(requestFieldPath);
801
828
 
802
- if (!isEntity && hasArgsOrDirectives) {
803
- _unset(data, responseDataPath);
829
+ if (_isUndefined(fieldData) || !fieldTypeInfo || !cacheability) {
830
+ return;
804
831
  }
805
832
 
806
- if (isEntity) {
807
- const fieldTypeName = fieldTypeInfo.isEntity ? fieldTypeInfo.typeName : fieldData.__typename;
808
- const entityDataKey = `${fieldTypeName}::${fieldData[this._typeIDKey]}`;
809
- const result = await this._checkCacheEntry(DATA_ENTITIES, entityDataKey, options, context);
833
+ const promises = [];
834
+ promises.push(this._setRequestFieldPathCacheEntry(field, keysAndPaths, {
835
+ cacheability,
836
+ data: requestFieldPathData,
837
+ fieldTypeInfo
838
+ }, options, context));
810
839
 
811
- if (result) {
812
- fieldData = this._mergeObjects(result.entry, fieldData);
813
- }
840
+ const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
814
841
 
815
- await this._setCacheEntry(DATA_ENTITIES, entityDataKey, fieldData, {
816
- cacheHeaders: {
817
- cacheControl: cacheability.printCacheControl()
818
- },
819
- tag: options.tag
820
- }, options, context);
842
+ if (!isEntity && fieldTypeInfo.hasArguments) {
843
+ _unset(entityData, responseDataPath);
844
+ }
821
845
 
822
- _set(data, responseDataPath, {
823
- __cacheKey: `${DATA_ENTITIES}::${entityDataKey}`
824
- });
846
+ if (isEntity) {
847
+ promises.push(this._setEntityCacheEntry(keysAndPaths, {
848
+ cacheability,
849
+ data: entityData,
850
+ fieldTypeInfo
851
+ }, options, context));
825
852
  }
853
+
854
+ await Promise.all(promises);
826
855
  }
827
856
 
828
- async _setDataEntityData(cachedFieldData, {
829
- possibleTypes,
830
- typeIDValue,
831
- typeName
857
+ async _setEntityCacheEntry({
858
+ responseDataPath
859
+ }, {
860
+ cacheability,
861
+ data,
862
+ fieldTypeInfo
832
863
  }, options, context) {
833
- const requestFieldPathDataIDValue = _isPlainObject(cachedFieldData.requestFieldPathData) ? cachedFieldData.requestFieldPathData[this._typeIDKey] : undefined;
834
- const validTypeIDValue = typeIDValue || requestFieldPathDataIDValue;
835
- if (!validTypeIDValue) return;
836
- const typeNames = [...possibleTypes.map(type => type.typeName), typeName];
837
- const checkResults = await Promise.all(typeNames.map(name => this._checkCacheEntry(DATA_ENTITIES, `${name}::${validTypeIDValue}`, options, context)));
838
- const validResults = checkResults.filter(result => !!result);
839
- let validResult;
864
+ let fieldData = _get(data, responseDataPath);
840
865
 
841
- if (validResults.length === 1) {
842
- validResult = validResults[0];
843
- } else if (validResults.length > 1) {
844
- validResults.sort(({
845
- cacheability: a
846
- }, {
847
- cacheability: b
848
- }) => a.metadata.ttl - b.metadata.ttl);
849
- validResult = {
850
- cacheability: validResults[0].cacheability,
851
- entry: validResults.reduce((obj, {
852
- entry
853
- }) => this._mergeObjects(obj, entry), {})
854
- };
855
- }
866
+ const fieldTypeName = fieldTypeInfo.isEntity ? fieldTypeInfo.typeName : fieldData.__typename;
867
+ const entityDataKey = `${fieldTypeName}::${fieldData[this._typeIDKey]}`;
868
+ const result = await this._checkCacheEntry(DATA_ENTITIES, entityDataKey, options, context);
856
869
 
857
- if (validResult) {
858
- const {
859
- cacheability,
860
- entry
861
- } = validResult;
862
- if (cacheability && !cachedFieldData.cacheability) cachedFieldData.cacheability = cacheability;
863
- if (entry) cachedFieldData.dataEntityData = entry;
870
+ if (result) {
871
+ fieldData = this._mergeObjects(result.entry, fieldData);
864
872
  }
873
+
874
+ await this._setCacheEntry(DATA_ENTITIES, entityDataKey, fieldData, {
875
+ cacheHeaders: {
876
+ cacheControl: cacheability.printCacheControl()
877
+ },
878
+ tag: options.tag
879
+ }, options, context);
880
+
881
+ _set(data, responseDataPath, {
882
+ __cacheKey: `${DATA_ENTITIES}::${entityDataKey}`
883
+ });
865
884
  }
866
885
 
867
886
  _setFieldCacheability(field, ancestorKeysAndPaths, {
@@ -871,59 +890,37 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
871
890
  const {
872
891
  requestFieldPath: ancestorRequestFieldPath
873
892
  } = ancestorKeysAndPaths;
874
-
875
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, ancestorKeysAndPaths);
876
-
893
+ const keysAndPaths = buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
877
894
  const {
878
895
  requestFieldPath,
879
896
  responseDataPath
880
897
  } = keysAndPaths;
881
898
 
882
- const fieldData = _get(data, responseDataPath, null);
899
+ const fieldData = _get(data, responseDataPath);
883
900
 
884
- if (!_isObjectLike(fieldData)) return;
885
- const objectLikeFieldData = fieldData;
901
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
902
+
903
+ if (!_isObjectLike(fieldData) && !(fieldTypeInfo !== null && fieldTypeInfo !== void 0 && fieldTypeInfo.hasDirectives)) {
904
+ return;
905
+ }
886
906
 
887
907
  this._setFieldTypeCacheDirective(cacheMetadata, {
888
908
  ancestorRequestFieldPath,
889
909
  requestFieldPath
890
910
  }, context);
891
911
 
892
- iterateChildFields(field, objectLikeFieldData, (childField, _typeName, childIndex) => {
893
- this._setFieldCacheability(childField, {
894
- index: childIndex,
895
- requestFieldPath,
896
- responseDataPath
897
- }, {
898
- cacheMetadata,
899
- data
900
- }, options, context);
901
- });
902
- }
903
-
904
- async _setFieldDataEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
905
- cacheMetadata,
906
- dataEntityData,
907
- requestFieldPathData
908
- }, options, context) {
909
- const {
910
- requestFieldPath
911
- } = keysAndPaths;
912
- const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
913
- const cacheability = cacheMetadata.get(requestFieldPath);
914
- if (!fieldTypeInfo || !cacheability) return;
915
- const promises = [];
916
- promises.push(this._setRequestFieldPathCacheEntry(field, keysAndPaths, {
917
- cacheability,
918
- data: requestFieldPathData,
919
- fieldTypeInfo
920
- }, options, context));
921
- promises.push(this._setDataEntityCacheEntry(keysAndPaths, {
922
- cacheability,
923
- data: dataEntityData,
924
- fieldTypeInfo
925
- }, options, context));
926
- await Promise.all(promises);
912
+ if (_isObjectLike(fieldData)) {
913
+ iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
914
+ this._setFieldCacheability(childField, {
915
+ index: childIndex,
916
+ requestFieldPath,
917
+ responseDataPath
918
+ }, {
919
+ cacheMetadata,
920
+ data
921
+ }, options, context);
922
+ });
923
+ }
927
924
  }
928
925
 
929
926
  _setFieldTypeCacheDirective(cacheMetadata, {
@@ -933,7 +930,10 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
933
930
  fieldTypeMap,
934
931
  operation
935
932
  }) {
936
- if (cacheMetadata.has(requestFieldPath)) return;
933
+ if (cacheMetadata.has(requestFieldPath)) {
934
+ return;
935
+ }
936
+
937
937
  const fieldTypeInfo = fieldTypeMap.get(requestFieldPath);
938
938
 
939
939
  if (fieldTypeInfo && this._typeCacheDirectives[fieldTypeInfo.typeName]) {
@@ -970,24 +970,32 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
970
970
  }, options, context);
971
971
  }
972
972
 
973
- async _setRequestFieldPathCacheEntry(field, {
974
- hashedRequestFieldCacheKey,
975
- responseDataPath
976
- }, {
973
+ async _setRequestFieldPathCacheEntry(field, keysAndPaths, {
977
974
  cacheability,
978
975
  data,
979
976
  fieldTypeInfo
980
977
  }, options, context) {
981
- const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
978
+ const {
979
+ hashedRequestFieldCacheKey,
980
+ responseDataPath
981
+ } = keysAndPaths;
982
982
 
983
- let fieldData = _get(data, responseDataPath, null);
983
+ let fieldData = _get(data, responseDataPath);
984
984
 
985
985
  const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
986
986
 
987
+ const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
988
+
987
989
  if (context.operation === QUERY && (isEntity || hasArgsOrDirectives)) {
990
+ var _field$selectionSet;
991
+
992
+ if (_isPlainObject(fieldData) && (_field$selectionSet = field.selectionSet) !== null && _field$selectionSet !== void 0 && _field$selectionSet.selections) {
993
+ fieldData = filterOutPropsWithArgsOrDirectives(fieldData, field.selectionSet.selections, keysAndPaths, context);
994
+ }
995
+
988
996
  const result = await this._checkCacheEntry(REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, options, context);
989
997
 
990
- if (result) {
998
+ if (result && _isObjectLike(fieldData)) {
991
999
  fieldData = this._mergeObjects(result.entry, fieldData);
992
1000
  }
993
1001
 
@@ -1010,19 +1018,6 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
1010
1018
  }
1011
1019
  }
1012
1020
 
1013
- async _setRequestFieldPathData(cachedFieldData, hash, options, context) {
1014
- const checkResult = await this._checkCacheEntry(REQUEST_FIELD_PATHS, hash, options, context);
1015
-
1016
- if (checkResult) {
1017
- const {
1018
- cacheability,
1019
- entry
1020
- } = checkResult;
1021
- if (cacheability) cachedFieldData.cacheability = cacheability;
1022
- if (entry) cachedFieldData.requestFieldPathData = entry;
1023
- }
1024
- }
1025
-
1026
1021
  }, (_applyDecoratedDescriptor(_class.prototype, "_getCacheEntry", [_dec], Object.getOwnPropertyDescriptor(_class.prototype, "_getCacheEntry"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_setCacheEntry", [_dec2], Object.getOwnPropertyDescriptor(_class.prototype, "_setCacheEntry"), _class.prototype), _applyDecoratedDescriptor(_class.prototype, "_setPartialQueryResponse", [_dec3], Object.getOwnPropertyDescriptor(_class.prototype, "_setPartialQueryResponse"), _class.prototype)), _class));
1027
1022
  export default function init(userOptions) {
1028
1023
  if (!_isPlainObject(userOptions)) {