@graphql-box/cache-manager 2.1.4 → 2.3.1

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 +24 -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 +495 -488
  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 +12 -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 +492 -486
  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 +11 -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 +15 -22
  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 +17466 -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 +10 -0
  107. package/src/helpers/validTypeIDValue.ts +11 -0
  108. package/src/index.test.ts +179 -3
  109. package/src/main/index.ts +540 -524
@@ -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,25 @@ 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
- static _getResponseCacheMetadata(cacheMetadata, partialQueryResponse) {
170
- if (!partialQueryResponse) return cacheMetadata;
171
- return new Map([...partialQueryResponse.cacheMetadata, ...cacheMetadata]);
172
- }
78
+ static _isNodeEntity(fieldTypeInfo) {
79
+ if (!fieldTypeInfo) {
80
+ return false;
81
+ }
173
82
 
174
- static _isDataEntity(fieldTypeInfo) {
175
- if (!fieldTypeInfo) return false;
176
83
  const {
177
84
  isEntity,
178
85
  possibleTypes
@@ -180,8 +87,8 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
180
87
  return isEntity || possibleTypes.some(type => !!type.isEntity);
181
88
  }
182
89
 
183
- static _isRequestFieldPath(fieldTypeInfo) {
184
- return !!fieldTypeInfo && (this._isDataEntity(fieldTypeInfo) || fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives);
90
+ static _isNodeRequestFieldPath(fieldTypeInfo) {
91
+ return !!fieldTypeInfo && (this._isNodeEntity(fieldTypeInfo) || fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives);
185
92
  }
186
93
 
187
94
  static _isValid(cacheability) {
@@ -190,6 +97,14 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
190
97
  return !noCache && cacheability.checkTTL();
191
98
  }
192
99
 
100
+ static _mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse) {
101
+ if (!partialQueryResponse) {
102
+ return cacheMetadata;
103
+ }
104
+
105
+ return new Map([...partialQueryResponse.cacheMetadata, ...cacheMetadata]);
106
+ }
107
+
193
108
  static _setCachedData(requestData, {
194
109
  data
195
110
  }, propNameOrIndex) {
@@ -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,101 +314,163 @@ 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
+ path
327
+ } = await this._resolveRequest(updatedRequestData, rawResponseData, options, cacheManagerContext);
367
328
  let partialQueryResponse;
368
329
 
369
- if (context.queryFiltered) {
370
- dataCaching.push(this._setQueryResponseCacheEntry(updatedRequestData.hash, {
371
- cacheMetadata,
372
- data
373
- }, options, context));
374
- partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
330
+ if (cacheManagerContext.queryFiltered) {
331
+ if (!(rawResponseData.hasNext || rawResponseData.path)) {
332
+ dataCaching.push(this._setQueryResponseCacheEntry(updatedRequestData.hash, {
333
+ cacheMetadata,
334
+ data
335
+ }, options, cacheManagerContext));
336
+ }
337
+
338
+ if (!rawResponseData.path) {
339
+ partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
340
+ }
375
341
  }
376
342
 
377
- const responseCacheMetadata = CacheManager._getResponseCacheMetadata(cacheMetadata, partialQueryResponse);
343
+ const responseCacheMetadata = CacheManager._mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse);
378
344
 
379
- const responseData = this._getResponseData(data, partialQueryResponse);
345
+ const responseData = this._mergeResponseData(data, partialQueryResponse);
346
+
347
+ if (!(rawResponseData.hasNext || rawResponseData.path)) {
348
+ dataCaching.push(this._setQueryResponseCacheEntry(requestData.hash, {
349
+ cacheMetadata: responseCacheMetadata,
350
+ data: responseData
351
+ }, options, cacheManagerContext));
352
+ }
353
+
354
+ if (options.awaitDataCaching) {
355
+ await Promise.all(dataCaching);
356
+ }
380
357
 
381
- dataCaching.push(this._setQueryResponseCacheEntry(requestData.hash, {
382
- cacheMetadata: responseCacheMetadata,
383
- data: responseData
384
- }, options, context));
385
- if (options.awaitDataCaching) await Promise.all(dataCaching);
386
358
  return {
387
359
  cacheMetadata: responseCacheMetadata,
388
- data: responseData
360
+ data: responseData,
361
+ hasNext,
362
+ path
389
363
  };
390
364
  }
391
365
 
392
366
  async resolveRequest(requestData, rawResponseData, options, context) {
393
- return this._resolveRequest(requestData, rawResponseData, options, context);
367
+ const cacheManagerContext = { ...context,
368
+ fragmentDefinitions: getFragmentDefinitions(requestData.ast),
369
+ typeIDKey: this._typeIDKey
370
+ };
371
+ return this._resolveRequest(requestData, rawResponseData, options, cacheManagerContext);
394
372
  }
395
373
 
396
- async _analyzeField(field, cachedAncestorFieldData, cachedResponseData, options, context) {
397
- if (hasChildFields(field)) {
398
- await this._analyzeParentField(field, cachedAncestorFieldData, cachedResponseData, options, context);
374
+ async _analyzeFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
375
+ if (hasChildFields(fieldNode)) {
376
+ await this._analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
399
377
  } else {
400
- await CacheManager._analyzeLeafField(field, cachedAncestorFieldData, cachedResponseData, options, context);
378
+ await this._analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
401
379
  }
402
380
  }
403
381
 
404
- async _analyzeParentField(field, cachedAncestorFieldData, cachedResponseData, options, context) {
405
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, cachedAncestorFieldData);
406
-
382
+ async _analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
383
+ const keysAndPaths = buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
407
384
  const {
408
385
  hashedRequestFieldCacheKey,
409
386
  propNameOrIndex,
410
- requestFieldCacheKey,
411
387
  requestFieldPath
412
388
  } = keysAndPaths;
413
389
  const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
414
390
  const {
415
- dataEntityData: ancestorDataEntityData,
416
- requestFieldPathData: ancestorRequestFieldPathData,
391
+ entityData,
392
+ fragmentKind,
393
+ fragmentName,
394
+ requestFieldPathData,
417
395
  typeName
418
396
  } = cachedAncestorFieldData;
419
- const cachedFieldData = {
420
- dataEntityData: CacheManager._getFieldDataFromAncestor(ancestorDataEntityData, propNameOrIndex),
421
- requestFieldPathData: CacheManager._getFieldDataFromAncestor(ancestorRequestFieldPathData, propNameOrIndex)
397
+ const typeNamesAndKind = {
398
+ dataTypeName: (entityData === null || entityData === void 0 ? void 0 : entityData.__typename) || (requestFieldPathData === null || requestFieldPathData === void 0 ? void 0 : requestFieldPathData.__typename),
399
+ fieldTypeName: typeName,
400
+ fragmentKind,
401
+ fragmentName
422
402
  };
423
403
 
424
- if (CacheManager._isRequestFieldPath(fieldTypeInfo)) {
425
- await this._setRequestFieldPathData(cachedFieldData, hashedRequestFieldCacheKey, options, context);
426
- }
404
+ if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
405
+ const {
406
+ cacheability,
407
+ entry
408
+ } = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, options, context);
427
409
 
428
- if (CacheManager._isDataEntity(fieldTypeInfo)) {
429
- await this._setDataEntityData(cachedFieldData, fieldTypeInfo, options, context);
410
+ CacheManager._setCachedResponseData({
411
+ cacheability,
412
+ data: entry
413
+ }, cachedResponseData, keysAndPaths, typeNamesAndKind, options, context);
414
+ } else {
415
+ const cachedFieldData = CacheManager._getFieldDataFromAncestor(entityData, propNameOrIndex) || CacheManager._getFieldDataFromAncestor(requestFieldPathData, propNameOrIndex);
416
+
417
+ CacheManager._setFieldPathChecklist(cachedResponseData.fieldPathChecklist, {
418
+ data: cachedFieldData
419
+ }, requestFieldPath, typeNamesAndKind);
420
+
421
+ CacheManager._setCachedData(cachedResponseData.data, {
422
+ data: cachedFieldData
423
+ }, propNameOrIndex);
430
424
  }
425
+ }
431
426
 
427
+ async _analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
428
+ const keysAndPaths = buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
429
+ const {
430
+ propNameOrIndex,
431
+ requestFieldCacheKey,
432
+ requestFieldPath
433
+ } = keysAndPaths;
434
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
432
435
  const {
433
436
  cacheability,
434
- dataEntityData,
437
+ data,
438
+ entityData,
435
439
  requestFieldPathData
436
- } = cachedFieldData;
437
- const data = !_isUndefined(requestFieldPathData) || !_isUndefined(dataEntityData) ? this._mergeObjects(requestFieldPathData, dataEntityData) : undefined;
440
+ } = await this._retrieveCachedParentNodeData(cachedAncestorFieldData, keysAndPaths, fieldTypeInfo, options, context);
441
+ const {
442
+ fragmentKind,
443
+ fragmentName,
444
+ typeName
445
+ } = cachedAncestorFieldData;
438
446
 
439
447
  CacheManager._setCachedResponseData({
440
448
  cacheability,
441
449
  data
442
450
  }, cachedResponseData, keysAndPaths, {
443
451
  dataTypeName: _get(data, TYPE_NAME_KEY),
444
- fieldTypeName: typeName
452
+ fieldTypeName: typeName,
453
+ fragmentKind,
454
+ fragmentName
445
455
  }, options, context);
446
456
 
447
- if (!_isObjectLike(data)) return;
457
+ if (!_isObjectLike(data)) {
458
+ return;
459
+ }
460
+
448
461
  const objectLikeData = data;
449
462
  const promises = [];
450
- iterateChildFields(field, objectLikeData, (childField, childTypeName, childIndex) => {
451
- promises.push(this._analyzeField(childField, {
463
+ iterateChildFields(fieldNode, objectLikeData, context.fragmentDefinitions, (childField, childTypeName, childFragmentKind, childFragmentName, childIndex) => {
464
+ promises.push(this._analyzeFieldNode(childField, {
465
+ cacheability,
466
+ entityData,
467
+ fragmentKind: childFragmentKind,
468
+ fragmentName: childFragmentName,
452
469
  index: childIndex,
453
470
  requestFieldCacheKey,
454
471
  requestFieldPath,
455
- typeName: childTypeName,
456
- ...cachedFieldData
472
+ requestFieldPathData,
473
+ typeName: childTypeName
457
474
  }, { ...cachedResponseData,
458
475
  data: cachedResponseData.data[propNameOrIndex]
459
476
  }, options, context));
@@ -474,7 +491,11 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
474
491
 
475
492
  const queryNode = getOperationDefinitions(ast, context.operation)[0];
476
493
  const fieldsAndTypeNames = getChildFields(queryNode);
477
- if (!fieldsAndTypeNames) return cacheMetadata;
494
+
495
+ if (!fieldsAndTypeNames) {
496
+ return cacheMetadata;
497
+ }
498
+
478
499
  fieldsAndTypeNames.forEach(({
479
500
  fieldNode
480
501
  }) => this._setFieldCacheability(fieldNode, {
@@ -489,9 +510,17 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
489
510
  async _checkCacheEntry(cacheType, hash, options, context) {
490
511
  try {
491
512
  const cacheability = await this._hasCacheEntry(cacheType, hash);
492
- if (!cacheability || !CacheManager._isValid(cacheability)) return false;
513
+
514
+ if (!cacheability || !CacheManager._isValid(cacheability)) {
515
+ return false;
516
+ }
517
+
493
518
  const entry = await this._getCacheEntry(cacheType, hash, options, context);
494
- if (!entry) return false;
519
+
520
+ if (_isUndefined(entry)) {
521
+ return false;
522
+ }
523
+
495
524
  return {
496
525
  cacheability,
497
526
  entry
@@ -522,148 +551,6 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
522
551
  return cacheMetadata;
523
552
  }
524
553
 
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
554
  async _getCacheEntry(cacheType, hash, _options, _context) {
668
555
  try {
669
556
  return await this._cache.get(`${cacheType}::${hash}`);
@@ -680,11 +567,6 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
680
567
  return partialQueryResponse;
681
568
  }
682
569
 
683
- _getResponseData(responseData, partialQueryResponse) {
684
- if (!partialQueryResponse) return responseData;
685
- return this._mergeObjects(partialQueryResponse.data, responseData);
686
- }
687
-
688
570
  async _hasCacheEntry(cacheType, hash) {
689
571
  try {
690
572
  return await this._cache.has(`${cacheType}::${hash}`);
@@ -697,9 +579,18 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
697
579
  isEntity,
698
580
  possibleTypes
699
581
  }) {
700
- if (!_get(fieldData, this._typeIDKey, null)) return false;
701
- if (isEntity) return true;
702
- if (!possibleTypes.length) return false;
582
+ if (!_get(fieldData, this._typeIDKey, null)) {
583
+ return false;
584
+ }
585
+
586
+ if (isEntity) {
587
+ return true;
588
+ }
589
+
590
+ if (!possibleTypes.length) {
591
+ return false;
592
+ }
593
+
703
594
  return possibleTypes.some(type => type.typeName === fieldData.__typename);
704
595
  }
705
596
 
@@ -709,159 +600,298 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
709
600
  });
710
601
  }
711
602
 
712
- async _parseFieldDataEntityAndRequestFieldPathCacheEntryData(field, ancestorKeysAndPaths, {
603
+ _mergeResponseData(responseData, partialQueryResponse) {
604
+ if (!partialQueryResponse) {
605
+ return responseData;
606
+ }
607
+
608
+ return this._mergeObjects(partialQueryResponse.data, responseData);
609
+ }
610
+
611
+ async _parseEntityAndRequestFieldPathCacheEntryData(field, ancestorKeysAndPaths, {
713
612
  cacheMetadata,
714
- dataEntityData,
613
+ entityData,
715
614
  requestFieldPathData
716
615
  }, options, context) {
717
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, ancestorKeysAndPaths);
718
-
616
+ const keysAndPaths = buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
719
617
  const {
720
618
  requestFieldCacheKey,
721
619
  requestFieldPath,
722
620
  responseDataPath
723
621
  } = keysAndPaths;
724
622
 
725
- const fieldData = _get(requestFieldPathData, responseDataPath, null);
623
+ const fieldData = _get(requestFieldPathData, responseDataPath);
726
624
 
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, {
625
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
626
+
627
+ if (!_isObjectLike(fieldData) && !(fieldTypeInfo !== null && fieldTypeInfo !== void 0 && fieldTypeInfo.hasDirectives)) {
628
+ return;
629
+ }
630
+
631
+ if (_isObjectLike(fieldData)) {
632
+ const promises = [];
633
+ iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
634
+ promises.push(this._parseEntityAndRequestFieldPathCacheEntryData(childField, {
635
+ index: childIndex,
636
+ requestFieldCacheKey,
637
+ requestFieldPath,
638
+ responseDataPath
639
+ }, {
640
+ cacheMetadata,
641
+ entityData,
642
+ requestFieldPathData
643
+ }, options, context));
644
+ });
645
+ await Promise.all(promises);
646
+ }
647
+
648
+ await this._setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
744
649
  cacheMetadata,
745
- dataEntityData,
650
+ entityData,
746
651
  requestFieldPathData
747
652
  }, options, context);
748
653
  }
749
654
 
750
655
  async _resolveRequest(requestData, rawResponseData, options, context) {
656
+ const normalizedResponseData = rawResponseData.path ? normalizeResponseData(rawResponseData) : rawResponseData;
751
657
  const dataCaching = [];
752
658
 
753
- const cacheMetadata = this._buildCacheMetadata(requestData, rawResponseData, options, context);
659
+ const cacheMetadata = this._buildCacheMetadata(requestData, normalizedResponseData, options, context);
754
660
 
755
661
  const {
756
- data
757
- } = rawResponseData;
758
- dataCaching.push(this._setDataEntityAndRequestFieldPathCacheEntries(requestData, {
662
+ data,
663
+ hasNext,
664
+ path
665
+ } = normalizedResponseData;
666
+ dataCaching.push(this._setEntityAndRequestFieldPathCacheEntries(requestData, {
759
667
  cacheMetadata,
760
- dataEntityData: _cloneDeep(data),
668
+ entityData: _cloneDeep(data),
761
669
  requestFieldPathData: _cloneDeep(data)
762
670
  }, options, context));
763
- if (options.awaitDataCaching) await Promise.all(dataCaching);
671
+
672
+ if (options.awaitDataCaching) {
673
+ await Promise.all(dataCaching);
674
+ }
675
+
764
676
  return {
765
677
  cacheMetadata,
766
- data
678
+ data,
679
+ hasNext,
680
+ path
767
681
  };
768
682
  }
769
683
 
684
+ async _retrieveCachedEntityData(validTypeIDValue, {
685
+ possibleTypes,
686
+ typeName
687
+ }, options, context) {
688
+ const typeNames = [...possibleTypes.map(type => type.typeName), typeName];
689
+ const checkResults = await Promise.all(typeNames.map(name => this._checkCacheEntry(DATA_ENTITIES, `${name}::${validTypeIDValue}`, options, context)));
690
+ const validResults = checkResults.filter(result => !!result);
691
+ let validResult;
692
+
693
+ if (validResults.length === 1) {
694
+ validResult = validResults[0];
695
+ } else if (validResults.length > 1) {
696
+ validResults.sort(({
697
+ cacheability: a
698
+ }, {
699
+ cacheability: b
700
+ }) => a.metadata.ttl - b.metadata.ttl);
701
+ validResult = {
702
+ cacheability: validResults[0].cacheability,
703
+ entry: validResults.reduce((obj, {
704
+ entry
705
+ }) => this._mergeObjects(obj, entry), {})
706
+ };
707
+ }
708
+
709
+ return validResult || {};
710
+ }
711
+
712
+ async _retrieveCachedParentNodeData({
713
+ entityData: ancestorEntityData,
714
+ requestFieldPathData: ancestorRequestFieldPathData
715
+ }, {
716
+ hashedRequestFieldCacheKey,
717
+ propNameOrIndex
718
+ }, fieldTypeInfo, options, context) {
719
+ var _entityData;
720
+
721
+ let entityData = CacheManager._getFieldDataFromAncestor(ancestorEntityData, propNameOrIndex);
722
+
723
+ let requestFieldPathData = CacheManager._getFieldDataFromAncestor(ancestorRequestFieldPathData, propNameOrIndex);
724
+
725
+ let cacheability;
726
+
727
+ if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
728
+ const {
729
+ cacheability: entryCacheability,
730
+ entry
731
+ } = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, options, context);
732
+
733
+ if (entry) {
734
+ requestFieldPathData = this._mergeObjects(requestFieldPathData, entry);
735
+ }
736
+
737
+ if (entryCacheability) {
738
+ cacheability = entryCacheability;
739
+ }
740
+ }
741
+
742
+ const validTypeIDValue = getValidTypeIDValue(requestFieldPathData, fieldTypeInfo, this._typeIDKey);
743
+
744
+ if (CacheManager._isNodeEntity(fieldTypeInfo) && validTypeIDValue) {
745
+ var _cacheability;
746
+
747
+ const {
748
+ cacheability: entryCacheability,
749
+ entry
750
+ } = await this._retrieveCachedEntityData(validTypeIDValue, fieldTypeInfo, options, context);
751
+
752
+ if (entry) {
753
+ entityData = this._mergeObjects(entityData, entry);
754
+ }
755
+
756
+ if (entryCacheability && (!cacheability || entryCacheability.metadata.ttl > ((_cacheability = cacheability) === null || _cacheability === void 0 ? void 0 : _cacheability.metadata.ttl))) {
757
+ cacheability = entryCacheability;
758
+ }
759
+ }
760
+
761
+ const data = !_isUndefined(requestFieldPathData) || !_isUndefined(entityData) ? this._mergeObjects(requestFieldPathData, entityData) : (_entityData = entityData) !== null && _entityData !== void 0 ? _entityData : requestFieldPathData;
762
+ return {
763
+ cacheability,
764
+ data,
765
+ entityData,
766
+ requestFieldPathData
767
+ };
768
+ }
769
+
770
+ async _retrieveCachedRequestFieldPathData(hash, options, context) {
771
+ return this._checkCacheEntry(REQUEST_FIELD_PATHS, hash, options, context) || {};
772
+ }
773
+
774
+ async _retrieveCachedResponseData({
775
+ ast
776
+ }, options, context) {
777
+ const cachedResponseData = {
778
+ cacheMetadata: new Map(),
779
+ data: {},
780
+ fieldCount: {
781
+ missing: 0,
782
+ total: 0
783
+ },
784
+ fieldPathChecklist: new Map()
785
+ };
786
+ const queryNode = getOperationDefinitions(ast, context.operation)[0];
787
+ const fieldsAndTypeNames = getChildFields(queryNode);
788
+
789
+ if (!fieldsAndTypeNames) {
790
+ return cachedResponseData;
791
+ }
792
+
793
+ await Promise.all(fieldsAndTypeNames.map(({
794
+ fieldNode
795
+ }) => this._analyzeFieldNode(fieldNode, {
796
+ requestFieldPath: context.operation
797
+ }, cachedResponseData, options, context)));
798
+ cachedResponseData.fieldCount = CacheManager._countFieldPathChecklist(cachedResponseData.fieldPathChecklist);
799
+ return cachedResponseData;
800
+ }
801
+
770
802
  async _setCacheEntry(cacheType, hash, value, cachemapOptions, _options, _context) {
771
803
  try {
772
804
  await this._cache.set(`${cacheType}::${hash}`, _cloneDeep(value), cachemapOptions);
773
805
  } catch (error) {}
774
806
  }
775
807
 
776
- async _setDataEntityAndRequestFieldPathCacheEntries(requestData, responseData, options, context) {
808
+ async _setEntityAndRequestFieldPathCacheEntries(requestData, responseData, options, context) {
777
809
  const operationNode = getOperationDefinitions(requestData.ast, context.operation)[0];
778
810
  const fieldsAndTypeNames = getChildFields(operationNode);
779
- if (!fieldsAndTypeNames) return;
811
+
812
+ if (!fieldsAndTypeNames) {
813
+ return;
814
+ }
815
+
780
816
  await Promise.all(fieldsAndTypeNames.map(({
781
817
  fieldNode
782
818
  }) => {
783
- return this._parseFieldDataEntityAndRequestFieldPathCacheEntryData(fieldNode, {
819
+ return this._parseEntityAndRequestFieldPathCacheEntryData(fieldNode, {
784
820
  requestFieldPath: context.operation
785
821
  }, responseData, options, context);
786
822
  }));
787
823
  }
788
824
 
789
- async _setDataEntityCacheEntry({
790
- responseDataPath
791
- }, {
792
- cacheability,
793
- data,
794
- fieldTypeInfo
825
+ async _setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
826
+ cacheMetadata,
827
+ entityData,
828
+ requestFieldPathData
795
829
  }, options, context) {
796
- const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
830
+ const {
831
+ requestFieldPath,
832
+ responseDataPath
833
+ } = keysAndPaths;
797
834
 
798
- let fieldData = _get(data, responseDataPath, null);
835
+ const fieldData = _get(entityData, responseDataPath);
799
836
 
800
- const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
837
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
838
+ const cacheability = cacheMetadata.get(requestFieldPath);
801
839
 
802
- if (!isEntity && hasArgsOrDirectives) {
803
- _unset(data, responseDataPath);
840
+ if (_isUndefined(fieldData) || !fieldTypeInfo || !cacheability) {
841
+ return;
804
842
  }
805
843
 
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);
844
+ const promises = [];
845
+ promises.push(this._setRequestFieldPathCacheEntry(field, keysAndPaths, {
846
+ cacheability,
847
+ data: requestFieldPathData,
848
+ fieldTypeInfo
849
+ }, options, context));
810
850
 
811
- if (result) {
812
- fieldData = this._mergeObjects(result.entry, fieldData);
813
- }
851
+ const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
814
852
 
815
- await this._setCacheEntry(DATA_ENTITIES, entityDataKey, fieldData, {
816
- cacheHeaders: {
817
- cacheControl: cacheability.printCacheControl()
818
- },
819
- tag: options.tag
820
- }, options, context);
853
+ if (!isEntity && fieldTypeInfo.hasArguments) {
854
+ _unset(entityData, responseDataPath);
855
+ }
821
856
 
822
- _set(data, responseDataPath, {
823
- __cacheKey: `${DATA_ENTITIES}::${entityDataKey}`
824
- });
857
+ if (isEntity) {
858
+ promises.push(this._setEntityCacheEntry(keysAndPaths, {
859
+ cacheability,
860
+ data: entityData,
861
+ fieldTypeInfo
862
+ }, options, context));
825
863
  }
864
+
865
+ await Promise.all(promises);
826
866
  }
827
867
 
828
- async _setDataEntityData(cachedFieldData, {
829
- possibleTypes,
830
- typeIDValue,
831
- typeName
868
+ async _setEntityCacheEntry({
869
+ responseDataPath
870
+ }, {
871
+ cacheability,
872
+ data,
873
+ fieldTypeInfo
832
874
  }, 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;
875
+ let fieldData = _get(data, responseDataPath);
840
876
 
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
- }
877
+ const fieldTypeName = fieldTypeInfo.isEntity ? fieldTypeInfo.typeName : fieldData.__typename;
878
+ const entityDataKey = `${fieldTypeName}::${fieldData[this._typeIDKey]}`;
879
+ const result = await this._checkCacheEntry(DATA_ENTITIES, entityDataKey, options, context);
856
880
 
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;
881
+ if (result) {
882
+ fieldData = this._mergeObjects(result.entry, fieldData);
864
883
  }
884
+
885
+ await this._setCacheEntry(DATA_ENTITIES, entityDataKey, fieldData, {
886
+ cacheHeaders: {
887
+ cacheControl: cacheability.printCacheControl()
888
+ },
889
+ tag: options.tag
890
+ }, options, context);
891
+
892
+ _set(data, responseDataPath, {
893
+ __cacheKey: `${DATA_ENTITIES}::${entityDataKey}`
894
+ });
865
895
  }
866
896
 
867
897
  _setFieldCacheability(field, ancestorKeysAndPaths, {
@@ -871,59 +901,37 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
871
901
  const {
872
902
  requestFieldPath: ancestorRequestFieldPath
873
903
  } = ancestorKeysAndPaths;
874
-
875
- const keysAndPaths = CacheManager._getFieldKeysAndPaths(field, ancestorKeysAndPaths);
876
-
904
+ const keysAndPaths = buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
877
905
  const {
878
906
  requestFieldPath,
879
907
  responseDataPath
880
908
  } = keysAndPaths;
881
909
 
882
- const fieldData = _get(data, responseDataPath, null);
910
+ const fieldData = _get(data, responseDataPath);
911
+
912
+ const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
883
913
 
884
- if (!_isObjectLike(fieldData)) return;
885
- const objectLikeFieldData = fieldData;
914
+ if (!_isObjectLike(fieldData) && !(fieldTypeInfo !== null && fieldTypeInfo !== void 0 && fieldTypeInfo.hasDirectives)) {
915
+ return;
916
+ }
886
917
 
887
918
  this._setFieldTypeCacheDirective(cacheMetadata, {
888
919
  ancestorRequestFieldPath,
889
920
  requestFieldPath
890
921
  }, context);
891
922
 
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);
923
+ if (_isObjectLike(fieldData)) {
924
+ iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
925
+ this._setFieldCacheability(childField, {
926
+ index: childIndex,
927
+ requestFieldPath,
928
+ responseDataPath
929
+ }, {
930
+ cacheMetadata,
931
+ data
932
+ }, options, context);
933
+ });
934
+ }
927
935
  }
928
936
 
929
937
  _setFieldTypeCacheDirective(cacheMetadata, {
@@ -933,7 +941,10 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
933
941
  fieldTypeMap,
934
942
  operation
935
943
  }) {
936
- if (cacheMetadata.has(requestFieldPath)) return;
944
+ if (cacheMetadata.has(requestFieldPath)) {
945
+ return;
946
+ }
947
+
937
948
  const fieldTypeInfo = fieldTypeMap.get(requestFieldPath);
938
949
 
939
950
  if (fieldTypeInfo && this._typeCacheDirectives[fieldTypeInfo.typeName]) {
@@ -970,24 +981,32 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
970
981
  }, options, context);
971
982
  }
972
983
 
973
- async _setRequestFieldPathCacheEntry(field, {
974
- hashedRequestFieldCacheKey,
975
- responseDataPath
976
- }, {
984
+ async _setRequestFieldPathCacheEntry(field, keysAndPaths, {
977
985
  cacheability,
978
986
  data,
979
987
  fieldTypeInfo
980
988
  }, options, context) {
981
- const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
989
+ const {
990
+ hashedRequestFieldCacheKey,
991
+ responseDataPath
992
+ } = keysAndPaths;
982
993
 
983
- let fieldData = _get(data, responseDataPath, null);
994
+ let fieldData = _get(data, responseDataPath);
984
995
 
985
996
  const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
986
997
 
998
+ const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
999
+
987
1000
  if (context.operation === QUERY && (isEntity || hasArgsOrDirectives)) {
1001
+ var _field$selectionSet;
1002
+
1003
+ if (_isPlainObject(fieldData) && (_field$selectionSet = field.selectionSet) !== null && _field$selectionSet !== void 0 && _field$selectionSet.selections) {
1004
+ fieldData = filterOutPropsWithArgsOrDirectives(fieldData, field.selectionSet.selections, keysAndPaths, context);
1005
+ }
1006
+
988
1007
  const result = await this._checkCacheEntry(REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, options, context);
989
1008
 
990
- if (result) {
1009
+ if (result && _isObjectLike(fieldData)) {
991
1010
  fieldData = this._mergeObjects(result.entry, fieldData);
992
1011
  }
993
1012
 
@@ -1010,19 +1029,6 @@ export let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec
1010
1029
  }
1011
1030
  }
1012
1031
 
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
1032
  }, (_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
1033
  export default function init(userOptions) {
1028
1034
  if (!_isPlainObject(userOptions)) {