@graphql-box/cache-manager 5.0.0 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -1476
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1 -1474
- package/dist/esm/index.mjs.map +1 -1
- package/dist/production.analysis.txt +250 -0
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +17 -15
- package/tsconfig.build.json +2 -2
- package/tsconfig.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,1477 +1,2 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
4
|
-
var _applyDecoratedDescriptor = require('@babel/runtime/helpers/applyDecoratedDescriptor');
|
|
5
|
-
require('core-js/modules/es.array.push.js');
|
|
6
|
-
var core = require('@graphql-box/core');
|
|
7
|
-
var helpers = require('@graphql-box/helpers');
|
|
8
|
-
var cacheability = require('cacheability');
|
|
9
|
-
var graphql = require('graphql');
|
|
10
|
-
var lodashEs = require('lodash-es');
|
|
11
|
-
|
|
12
|
-
const METADATA = 'metadata';
|
|
13
|
-
const CACHE_CONTROL = 'cacheControl';
|
|
14
|
-
const NO_CACHE = 'noCache';
|
|
15
|
-
const HEADER_CACHE_CONTROL = 'cache-control';
|
|
16
|
-
const HEADER_NO_CACHE = 'no-cache';
|
|
17
|
-
|
|
18
|
-
const logCacheEntry = () => {
|
|
19
|
-
return (_target, _propertyName, descriptor) => {
|
|
20
|
-
const method = descriptor.value;
|
|
21
|
-
if (!method) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
descriptor.value = async function descriptorValue(...args) {
|
|
25
|
-
return new Promise(resolve => {
|
|
26
|
-
void (async () => {
|
|
27
|
-
const {
|
|
28
|
-
debugManager,
|
|
29
|
-
requestFieldCacheKey,
|
|
30
|
-
...otherContext
|
|
31
|
-
} = args[5];
|
|
32
|
-
if (!debugManager) {
|
|
33
|
-
await method.apply(this, args);
|
|
34
|
-
resolve();
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
const startTime = debugManager.now();
|
|
38
|
-
await method.apply(this, args);
|
|
39
|
-
const endTime = debugManager.now();
|
|
40
|
-
const duration = endTime - startTime;
|
|
41
|
-
resolve();
|
|
42
|
-
const payload = {
|
|
43
|
-
cacheType: args[0],
|
|
44
|
-
cachemapOptions: args[3],
|
|
45
|
-
context: otherContext,
|
|
46
|
-
options: args[4],
|
|
47
|
-
requestHash: args[1],
|
|
48
|
-
stats: {
|
|
49
|
-
duration,
|
|
50
|
-
endTime,
|
|
51
|
-
startTime
|
|
52
|
-
},
|
|
53
|
-
value: args[2],
|
|
54
|
-
...(requestFieldCacheKey ? {
|
|
55
|
-
decryptedCacheKey: requestFieldCacheKey
|
|
56
|
-
} : {})
|
|
57
|
-
};
|
|
58
|
-
debugManager.log(core.CACHE_ENTRY_ADDED, payload);
|
|
59
|
-
})();
|
|
60
|
-
});
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
const logCacheQuery = () => {
|
|
66
|
-
return (_target, _propertyName, descriptor) => {
|
|
67
|
-
const method = descriptor.value;
|
|
68
|
-
if (!method) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
descriptor.value = async function descriptorValue(...args) {
|
|
72
|
-
return new Promise(resolve => {
|
|
73
|
-
void (async () => {
|
|
74
|
-
const {
|
|
75
|
-
debugManager,
|
|
76
|
-
requestFieldCacheKey,
|
|
77
|
-
...otherContext
|
|
78
|
-
} = args[3];
|
|
79
|
-
if (!debugManager) {
|
|
80
|
-
resolve(await method.apply(this, args));
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
const startTime = debugManager.now();
|
|
84
|
-
const result = await method.apply(this, args);
|
|
85
|
-
const endTime = debugManager.now();
|
|
86
|
-
const duration = endTime - startTime;
|
|
87
|
-
resolve(result);
|
|
88
|
-
const payload = {
|
|
89
|
-
cacheType: args[0],
|
|
90
|
-
context: otherContext,
|
|
91
|
-
options: args[2],
|
|
92
|
-
requestHash: args[1],
|
|
93
|
-
result,
|
|
94
|
-
stats: {
|
|
95
|
-
duration,
|
|
96
|
-
endTime,
|
|
97
|
-
startTime
|
|
98
|
-
},
|
|
99
|
-
...(requestFieldCacheKey ? {
|
|
100
|
-
decryptedCacheKey: requestFieldCacheKey
|
|
101
|
-
} : {})
|
|
102
|
-
};
|
|
103
|
-
debugManager.log(core.CACHE_ENTRY_QUERIED, payload);
|
|
104
|
-
})();
|
|
105
|
-
});
|
|
106
|
-
};
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
const logPartialCompiled = () => {
|
|
111
|
-
return (_target, _propertyName, descriptor) => {
|
|
112
|
-
const method = descriptor.value;
|
|
113
|
-
if (!method) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
descriptor.value = function descriptorValue(...args) {
|
|
117
|
-
const {
|
|
118
|
-
debugManager,
|
|
119
|
-
...otherContext
|
|
120
|
-
} = args[3];
|
|
121
|
-
if (!debugManager) {
|
|
122
|
-
method.apply(this, args);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const startTime = debugManager.now();
|
|
126
|
-
method.apply(this, args);
|
|
127
|
-
const endTime = debugManager.now();
|
|
128
|
-
const duration = endTime - startTime;
|
|
129
|
-
debugManager.log(core.PARTIAL_QUERY_COMPILED, {
|
|
130
|
-
context: otherContext,
|
|
131
|
-
options: args[2],
|
|
132
|
-
requestHash: args[0],
|
|
133
|
-
result: args[1],
|
|
134
|
-
stats: {
|
|
135
|
-
duration,
|
|
136
|
-
endTime,
|
|
137
|
-
startTime
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
};
|
|
141
|
-
};
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
const checkValue = (value, typeIDKey) => {
|
|
145
|
-
if (helpers.isArray(value)) {
|
|
146
|
-
return value.reduce((acc, entry) => {
|
|
147
|
-
if (!acc) {
|
|
148
|
-
return false;
|
|
149
|
-
}
|
|
150
|
-
return checkValue(entry, typeIDKey);
|
|
151
|
-
}, true);
|
|
152
|
-
}
|
|
153
|
-
if (helpers.isPlainObject(value)) {
|
|
154
|
-
return recursivelyCheckProps(value, typeIDKey);
|
|
155
|
-
}
|
|
156
|
-
return false;
|
|
157
|
-
};
|
|
158
|
-
const recursivelyCheckProps = (data, typeIDKey) => {
|
|
159
|
-
const keys = helpers.isPlainObject(data) ? Object.keys(data) : [...data.keys()];
|
|
160
|
-
if (keys.length === 1 && helpers.isPlainObject(data) && !!data[typeIDKey]) {
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
|
-
return keys.reduce((acc, key) => {
|
|
164
|
-
if (!acc) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
if (lodashEs.isNumber(key) && helpers.isArray(data)) {
|
|
168
|
-
return checkValue(data[key], typeIDKey);
|
|
169
|
-
} else if (lodashEs.isString(key) && helpers.isPlainObject(data)) {
|
|
170
|
-
return checkValue(data[key], typeIDKey);
|
|
171
|
-
}
|
|
172
|
-
return acc;
|
|
173
|
-
}, true);
|
|
174
|
-
};
|
|
175
|
-
const areOnlyPopulatedFieldsTypeIdKeys = (data, typeIDKey) => {
|
|
176
|
-
return recursivelyCheckProps(data, typeIDKey);
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const mergeDataSets = (obj, source, typeIDKey) => {
|
|
180
|
-
return helpers.mergeObjects(obj, source, (_key, value) => {
|
|
181
|
-
return helpers.isPlainObject(value) && value[typeIDKey] ? value[typeIDKey] : undefined;
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
const combineDataSets = (dataSetA, dataSetB, typeIDKey) => {
|
|
186
|
-
if (!dataSetA && dataSetB) {
|
|
187
|
-
return dataSetB;
|
|
188
|
-
}
|
|
189
|
-
if (helpers.isObjectLike(dataSetA) && helpers.isObjectLike(dataSetB)) {
|
|
190
|
-
return mergeDataSets(dataSetA, dataSetB, typeIDKey);
|
|
191
|
-
}
|
|
192
|
-
return dataSetA;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
const deriveOpCacheability = ({
|
|
196
|
-
_cacheMetadata,
|
|
197
|
-
fallback,
|
|
198
|
-
headers
|
|
199
|
-
}) => {
|
|
200
|
-
if (_cacheMetadata && !lodashEs.isEmpty(_cacheMetadata)) {
|
|
201
|
-
const [first, ...rest] = Object.values(_cacheMetadata);
|
|
202
|
-
return new cacheability.Cacheability({
|
|
203
|
-
metadata: rest.reduce((acc, metadata) => {
|
|
204
|
-
if (!acc) {
|
|
205
|
-
return metadata;
|
|
206
|
-
}
|
|
207
|
-
if (metadata.ttl < acc.ttl) {
|
|
208
|
-
return metadata;
|
|
209
|
-
}
|
|
210
|
-
return acc;
|
|
211
|
-
}, first)
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
if (headers?.has(HEADER_CACHE_CONTROL)) {
|
|
215
|
-
return new cacheability.Cacheability({
|
|
216
|
-
headers
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
return new cacheability.Cacheability({
|
|
220
|
-
cacheControl: fallback
|
|
221
|
-
});
|
|
222
|
-
};
|
|
223
|
-
|
|
224
|
-
const filterOutPropsWithArgsOrDirectives = (fieldData, selectionNodes, ancestorKeysAndPaths, context) => {
|
|
225
|
-
const fieldAndTypeName = helpers.resolveFragments(selectionNodes, context.fragmentDefinitions);
|
|
226
|
-
return lodashEs.keys(fieldData).reduce((acc, key) => {
|
|
227
|
-
const match = fieldAndTypeName.find(({
|
|
228
|
-
fieldNode
|
|
229
|
-
}) => helpers.getName(fieldNode) === key);
|
|
230
|
-
if (match) {
|
|
231
|
-
const {
|
|
232
|
-
requestFieldPath
|
|
233
|
-
} = helpers.buildFieldKeysAndPaths(match.fieldNode, ancestorKeysAndPaths, context);
|
|
234
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
235
|
-
if (!fieldTypeInfo?.hasArguments && !fieldTypeInfo?.hasDirectives) {
|
|
236
|
-
acc[key] = fieldData[key];
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return acc;
|
|
240
|
-
}, {});
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
const createFragmentSpreadChecklist = ({
|
|
244
|
-
request
|
|
245
|
-
}, {
|
|
246
|
-
fragmentDefinitions
|
|
247
|
-
}) => lodashEs.keys(fragmentDefinitions ?? {}).reduce((acc, name) => {
|
|
248
|
-
acc[name] = {
|
|
249
|
-
deleted: 0,
|
|
250
|
-
paths: [],
|
|
251
|
-
total: (request.match(new RegExp(`\\.\\.\\.${name}`, 'g')) ?? []).length
|
|
252
|
-
};
|
|
253
|
-
return acc;
|
|
254
|
-
}, {});
|
|
255
|
-
|
|
256
|
-
const checkFieldPathChecklist = (fieldPathChecklistValues, fieldTypeName) => {
|
|
257
|
-
if (!fieldPathChecklistValues || fieldPathChecklistValues.length === 0) {
|
|
258
|
-
return {
|
|
259
|
-
hasData: false,
|
|
260
|
-
typeUnused: !!fieldTypeName
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
const [fieldPathChecklistValue] = fieldPathChecklistValues;
|
|
264
|
-
if (fieldPathChecklistValue) {
|
|
265
|
-
const {
|
|
266
|
-
hasData,
|
|
267
|
-
typeName
|
|
268
|
-
} = fieldPathChecklistValue;
|
|
269
|
-
const typeUnused = typeName ? typeName !== fieldTypeName : undefined;
|
|
270
|
-
return {
|
|
271
|
-
hasData,
|
|
272
|
-
typeUnused
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
return {
|
|
276
|
-
hasData: fieldPathChecklistValues.some(({
|
|
277
|
-
hasData,
|
|
278
|
-
typeName
|
|
279
|
-
}) => typeName === fieldTypeName && hasData),
|
|
280
|
-
typeUnused: !fieldPathChecklistValues.every(({
|
|
281
|
-
typeName
|
|
282
|
-
}) => typeName === fieldTypeName)
|
|
283
|
-
};
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const filterFragmentSpreads = (field, fragmentSpreadFieldCounter, fragmentSpreadChecklist, ancestorRequestFieldPath) => {
|
|
287
|
-
if (lodashEs.isEmpty(fragmentSpreadFieldCounter)) {
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
for (const key of Object.keys(fragmentSpreadFieldCounter)) {
|
|
291
|
-
const checklist = fragmentSpreadChecklist[key];
|
|
292
|
-
if (!checklist) {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
checklist.paths.push(ancestorRequestFieldPath);
|
|
296
|
-
const {
|
|
297
|
-
hasData,
|
|
298
|
-
total
|
|
299
|
-
} = fragmentSpreadFieldCounter[key];
|
|
300
|
-
if (hasData === total) {
|
|
301
|
-
helpers.deleteFragmentSpreads(field, key);
|
|
302
|
-
checklist.deleted += 1;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
|
|
307
|
-
const filterIDsAndTypeNames = (field, {
|
|
308
|
-
fragmentDefinitions,
|
|
309
|
-
typeIDKey
|
|
310
|
-
}) => {
|
|
311
|
-
const fieldsAndTypeNames = helpers.getChildFields(field, {
|
|
312
|
-
fragmentDefinitions
|
|
313
|
-
});
|
|
314
|
-
if (!fieldsAndTypeNames || fieldsAndTypeNames.length > 3) {
|
|
315
|
-
return false;
|
|
316
|
-
}
|
|
317
|
-
const fieldNames = fieldsAndTypeNames.map(({
|
|
318
|
-
fieldNode
|
|
319
|
-
}) => helpers.getName(fieldNode));
|
|
320
|
-
if (fieldNames.length === 2 && fieldNames.every(name => name === typeIDKey || name === core.TYPE_NAME_KEY)) {
|
|
321
|
-
helpers.deleteChildFields(field, fieldsAndTypeNames.map(({
|
|
322
|
-
fieldNode
|
|
323
|
-
}) => fieldNode));
|
|
324
|
-
return true;
|
|
325
|
-
}
|
|
326
|
-
if (fieldNames.length === 1 && fieldNames[0] === typeIDKey || fieldNames[0] === core.TYPE_NAME_KEY) {
|
|
327
|
-
const [fieldAndTypeName] = fieldsAndTypeNames;
|
|
328
|
-
if (fieldAndTypeName) {
|
|
329
|
-
const {
|
|
330
|
-
fieldNode
|
|
331
|
-
} = fieldAndTypeName;
|
|
332
|
-
helpers.deleteChildFields(field, fieldNode);
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return false;
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
const filterInlineFragments = (field, {
|
|
340
|
-
fragmentDefinitions,
|
|
341
|
-
typeIDKey
|
|
342
|
-
}) => {
|
|
343
|
-
const inlineFragments = helpers.getInlineFragments(field);
|
|
344
|
-
let filtered = false;
|
|
345
|
-
for (const fragment of inlineFragments) {
|
|
346
|
-
const fieldsAndTypeNames = helpers.getChildFields(fragment, {
|
|
347
|
-
fragmentDefinitions
|
|
348
|
-
});
|
|
349
|
-
if (!fieldsAndTypeNames || fieldsAndTypeNames.length === 0) {
|
|
350
|
-
helpers.deleteInlineFragments(field, fragment);
|
|
351
|
-
filtered = true;
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
const [fieldAndTypeName] = fieldsAndTypeNames;
|
|
355
|
-
if (fieldAndTypeName) {
|
|
356
|
-
const {
|
|
357
|
-
fieldNode
|
|
358
|
-
} = fieldAndTypeName;
|
|
359
|
-
if (helpers.getName(fieldNode) === typeIDKey) {
|
|
360
|
-
helpers.deleteInlineFragments(field, fragment);
|
|
361
|
-
filtered = true;
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
return filtered;
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
const filterField = (field, fieldPathChecklist, fragmentSpreadChecklist, ancestorRequestFieldPath, context) => {
|
|
369
|
-
const {
|
|
370
|
-
fragmentDefinitions,
|
|
371
|
-
typeIDKey
|
|
372
|
-
} = context;
|
|
373
|
-
const fieldsAndTypeNames = helpers.getChildFields(field, {
|
|
374
|
-
fragmentDefinitions
|
|
375
|
-
});
|
|
376
|
-
if (!fieldsAndTypeNames) {
|
|
377
|
-
return false;
|
|
378
|
-
}
|
|
379
|
-
const fragmentSpreadFieldCounter = {};
|
|
380
|
-
for (let index = fieldsAndTypeNames.length - 1; index >= 0; index -= 1) {
|
|
381
|
-
const fieldAndTypeName = fieldsAndTypeNames[index];
|
|
382
|
-
if (!fieldAndTypeName) {
|
|
383
|
-
continue;
|
|
384
|
-
}
|
|
385
|
-
const {
|
|
386
|
-
fieldNode: childField,
|
|
387
|
-
fragmentKind,
|
|
388
|
-
fragmentName,
|
|
389
|
-
typeName: childTypeName
|
|
390
|
-
} = fieldAndTypeName;
|
|
391
|
-
if (fragmentKind === graphql.Kind.FRAGMENT_SPREAD && fragmentName && !fragmentSpreadFieldCounter[fragmentName]) {
|
|
392
|
-
fragmentSpreadFieldCounter[fragmentName] = {
|
|
393
|
-
hasData: 0,
|
|
394
|
-
total: fragmentDefinitions?.[fragmentName] ? helpers.getChildFields(fragmentDefinitions[fragmentName], {
|
|
395
|
-
fragmentDefinitions
|
|
396
|
-
})?.length ?? 0 : 0
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
const childFieldName = helpers.getName(childField);
|
|
400
|
-
if (childFieldName === typeIDKey || childFieldName === core.TYPE_NAME_KEY) {
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const {
|
|
404
|
-
requestFieldPath
|
|
405
|
-
} = helpers.buildFieldKeysAndPaths(childField, {
|
|
406
|
-
requestFieldPath: ancestorRequestFieldPath
|
|
407
|
-
}, context);
|
|
408
|
-
const {
|
|
409
|
-
hasData,
|
|
410
|
-
typeUnused
|
|
411
|
-
} = checkFieldPathChecklist(fieldPathChecklist.get(requestFieldPath), childTypeName);
|
|
412
|
-
if (hasData || typeUnused) {
|
|
413
|
-
if (fragmentKind === graphql.Kind.FRAGMENT_SPREAD && fragmentName) {
|
|
414
|
-
const counter = fragmentSpreadFieldCounter[fragmentName];
|
|
415
|
-
if (counter) {
|
|
416
|
-
counter.hasData += 1;
|
|
417
|
-
}
|
|
418
|
-
} else if (!helpers.hasChildFields(childField, {
|
|
419
|
-
fragmentDefinitions
|
|
420
|
-
})) {
|
|
421
|
-
helpers.deleteChildFields(field, childField);
|
|
422
|
-
} else if (filterField(childField, fieldPathChecklist, fragmentSpreadChecklist, requestFieldPath, context)) {
|
|
423
|
-
helpers.deleteChildFields(field, childField);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
filterFragmentSpreads(field, fragmentSpreadFieldCounter, fragmentSpreadChecklist, ancestorRequestFieldPath);
|
|
428
|
-
filterInlineFragments(field, context);
|
|
429
|
-
filterIDsAndTypeNames(field, context);
|
|
430
|
-
return !helpers.hasChildFields(field, {
|
|
431
|
-
fragmentDefinitions
|
|
432
|
-
});
|
|
433
|
-
};
|
|
434
|
-
|
|
435
|
-
const filterFragmentDefinitions = (ast, fieldPathChecklist, fragmentSpreadChecklist, context) => {
|
|
436
|
-
const definitionsToFilter = lodashEs.keys(fragmentSpreadChecklist).reduce((namesAndPaths, key) => {
|
|
437
|
-
const checklist = fragmentSpreadChecklist[key];
|
|
438
|
-
if (!checklist) {
|
|
439
|
-
return namesAndPaths;
|
|
440
|
-
}
|
|
441
|
-
const {
|
|
442
|
-
deleted,
|
|
443
|
-
paths,
|
|
444
|
-
total
|
|
445
|
-
} = checklist;
|
|
446
|
-
return deleted === 0 && total === 1 ? [...namesAndPaths, {
|
|
447
|
-
name: key,
|
|
448
|
-
path: paths[0]
|
|
449
|
-
}] : namesAndPaths;
|
|
450
|
-
}, []);
|
|
451
|
-
const {
|
|
452
|
-
fragmentDefinitions = {}
|
|
453
|
-
} = context;
|
|
454
|
-
for (const {
|
|
455
|
-
name,
|
|
456
|
-
path
|
|
457
|
-
} of definitionsToFilter) {
|
|
458
|
-
const fragmentDefinition = fragmentDefinitions[name];
|
|
459
|
-
if (!fragmentDefinition) {
|
|
460
|
-
continue;
|
|
461
|
-
}
|
|
462
|
-
filterField(fragmentDefinition, fieldPathChecklist, fragmentSpreadChecklist, path, context);
|
|
463
|
-
}
|
|
464
|
-
const definitionsToDelete = lodashEs.keys(fragmentSpreadChecklist).reduce((names, key) => {
|
|
465
|
-
const checklist = fragmentSpreadChecklist[key];
|
|
466
|
-
if (!checklist) {
|
|
467
|
-
return names;
|
|
468
|
-
}
|
|
469
|
-
const {
|
|
470
|
-
deleted,
|
|
471
|
-
total
|
|
472
|
-
} = checklist;
|
|
473
|
-
return deleted > 0 && deleted === total ? [...names, key] : names;
|
|
474
|
-
}, []);
|
|
475
|
-
if (definitionsToDelete.length === 0) {
|
|
476
|
-
return ast;
|
|
477
|
-
}
|
|
478
|
-
return helpers.deleteFragmentDefinitions(ast, {
|
|
479
|
-
include: definitionsToDelete
|
|
480
|
-
});
|
|
481
|
-
};
|
|
482
|
-
|
|
483
|
-
const filterQuery = (requestData, {
|
|
484
|
-
fieldPathChecklist
|
|
485
|
-
}, context) => {
|
|
486
|
-
const {
|
|
487
|
-
ast
|
|
488
|
-
} = requestData;
|
|
489
|
-
const queryNode = helpers.getOperationDefinitions(ast, context.operation)[0];
|
|
490
|
-
if (!queryNode) {
|
|
491
|
-
return ast;
|
|
492
|
-
}
|
|
493
|
-
const {
|
|
494
|
-
fragmentDefinitions,
|
|
495
|
-
operation
|
|
496
|
-
} = context;
|
|
497
|
-
const fieldsAndTypeNames = helpers.getChildFields(queryNode, {
|
|
498
|
-
fragmentDefinitions
|
|
499
|
-
});
|
|
500
|
-
if (!fieldsAndTypeNames) {
|
|
501
|
-
return ast;
|
|
502
|
-
}
|
|
503
|
-
const fragmentSpreadChecklist = createFragmentSpreadChecklist(requestData, context);
|
|
504
|
-
for (let index = fieldsAndTypeNames.length - 1; index >= 0; index -= 1) {
|
|
505
|
-
const {
|
|
506
|
-
fieldNode
|
|
507
|
-
} = fieldsAndTypeNames[index];
|
|
508
|
-
const {
|
|
509
|
-
requestFieldPath
|
|
510
|
-
} = helpers.buildFieldKeysAndPaths(fieldNode, {
|
|
511
|
-
requestFieldPath: operation
|
|
512
|
-
}, context);
|
|
513
|
-
if (filterField(fieldNode, fieldPathChecklist, fragmentSpreadChecklist, requestFieldPath, context)) {
|
|
514
|
-
helpers.deleteChildFields(queryNode, fieldNode);
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
context.queryFiltered = true;
|
|
518
|
-
return filterFragmentDefinitions(ast, fieldPathChecklist, fragmentSpreadChecklist, context);
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
const getDataValue = (value, key) => {
|
|
522
|
-
if (helpers.isArray(value) && lodashEs.isNumber(key)) {
|
|
523
|
-
return value[key];
|
|
524
|
-
}
|
|
525
|
-
if (helpers.isPlainObject(value) && lodashEs.isString(key)) {
|
|
526
|
-
return value[key];
|
|
527
|
-
}
|
|
528
|
-
return;
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
const hasTypename = value => {
|
|
532
|
-
if (!helpers.isObjectLike(value)) {
|
|
533
|
-
return false;
|
|
534
|
-
}
|
|
535
|
-
return core.TYPE_NAME_KEY in value && lodashEs.isString(value[core.TYPE_NAME_KEY]);
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
const isLastResponseChunk = (rawResponseData, context) => context.hasDeferOrStream && !rawResponseData.hasNext && rawResponseData.paths;
|
|
539
|
-
|
|
540
|
-
const isNotLastResponseChunk = (rawResponseData, context) => context.hasDeferOrStream && rawResponseData.hasNext;
|
|
541
|
-
|
|
542
|
-
const isNotResponseChunk = (rawResponseData, context) => !context.hasDeferOrStream && !rawResponseData.hasNext && !rawResponseData.paths;
|
|
543
|
-
|
|
544
|
-
const mergeResponseDataSets = responseDataSets => {
|
|
545
|
-
return responseDataSets.reduce((acc, dataSet, index) => {
|
|
546
|
-
const {
|
|
547
|
-
_cacheMetadata,
|
|
548
|
-
data,
|
|
549
|
-
hasNext,
|
|
550
|
-
headers,
|
|
551
|
-
paths
|
|
552
|
-
} = dataSet;
|
|
553
|
-
if (_cacheMetadata) {
|
|
554
|
-
acc._cacheMetadata = acc._cacheMetadata ? {
|
|
555
|
-
...acc._cacheMetadata,
|
|
556
|
-
..._cacheMetadata
|
|
557
|
-
} : _cacheMetadata;
|
|
558
|
-
}
|
|
559
|
-
acc.data = lodashEs.merge(acc.data, data);
|
|
560
|
-
if (index === 0) {
|
|
561
|
-
acc.headers = headers;
|
|
562
|
-
}
|
|
563
|
-
if (index === responseDataSets.length - 1) {
|
|
564
|
-
acc.hasNext = hasNext;
|
|
565
|
-
}
|
|
566
|
-
if (paths) {
|
|
567
|
-
if (!acc.paths) {
|
|
568
|
-
acc.paths = [];
|
|
569
|
-
}
|
|
570
|
-
acc.paths.push(...paths);
|
|
571
|
-
}
|
|
572
|
-
return acc;
|
|
573
|
-
}, {
|
|
574
|
-
data: {}
|
|
575
|
-
});
|
|
576
|
-
};
|
|
577
|
-
|
|
578
|
-
const normalizePatchResponseData = (rawResponseData, context) => {
|
|
579
|
-
if (!context.normalizePatchResponseData) {
|
|
580
|
-
return rawResponseData;
|
|
581
|
-
}
|
|
582
|
-
const {
|
|
583
|
-
data,
|
|
584
|
-
paths,
|
|
585
|
-
...rest
|
|
586
|
-
} = rawResponseData;
|
|
587
|
-
if (!paths?.length || !lodashEs.isString(paths[0])) {
|
|
588
|
-
return rawResponseData;
|
|
589
|
-
}
|
|
590
|
-
return {
|
|
591
|
-
...rest,
|
|
592
|
-
data: lodashEs.set({}, paths[0], data),
|
|
593
|
-
paths
|
|
594
|
-
};
|
|
595
|
-
};
|
|
596
|
-
|
|
597
|
-
const getValidTypeIdValue = (requestFieldPathData, {
|
|
598
|
-
typeIDValue
|
|
599
|
-
}, typeIDKey) => {
|
|
600
|
-
if (typeIDValue) {
|
|
601
|
-
return typeIDValue;
|
|
602
|
-
}
|
|
603
|
-
if (helpers.isPlainObject(requestFieldPathData)) {
|
|
604
|
-
return requestFieldPathData[typeIDKey];
|
|
605
|
-
}
|
|
606
|
-
return;
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
var _dec, _dec2, _dec3, _class;
|
|
610
|
-
let CacheManager = (_dec = logCacheQuery(), _dec2 = logCacheEntry(), _dec3 = logPartialCompiled(), (_class = class CacheManager {
|
|
611
|
-
static _countFieldPathChecklist(fieldPathChecklist) {
|
|
612
|
-
const fieldCount = {
|
|
613
|
-
missing: 0,
|
|
614
|
-
total: 0
|
|
615
|
-
};
|
|
616
|
-
for (const [, checklistValues] of fieldPathChecklist) {
|
|
617
|
-
fieldCount.total += checklistValues.length;
|
|
618
|
-
const missing = checklistValues.filter(({
|
|
619
|
-
hasData
|
|
620
|
-
}) => !hasData);
|
|
621
|
-
fieldCount.missing += missing.length;
|
|
622
|
-
}
|
|
623
|
-
return fieldCount;
|
|
624
|
-
}
|
|
625
|
-
static _getFieldDataFromAncestor(ancestorFieldData, propNameOrIndex) {
|
|
626
|
-
const dataValue = getDataValue(ancestorFieldData, propNameOrIndex);
|
|
627
|
-
return helpers.isObjectLike(dataValue) ? lodashEs.cloneDeep(dataValue) : dataValue;
|
|
628
|
-
}
|
|
629
|
-
static _getOperationCacheControl(cacheMetadata, operation) {
|
|
630
|
-
const defaultCacheControl = HEADER_NO_CACHE;
|
|
631
|
-
if (!cacheMetadata) {
|
|
632
|
-
return defaultCacheControl;
|
|
633
|
-
}
|
|
634
|
-
const cacheability = cacheMetadata.get(operation);
|
|
635
|
-
return cacheability ? cacheability.printCacheControl() : defaultCacheControl;
|
|
636
|
-
}
|
|
637
|
-
static _isNodeEntity(fieldTypeInfo) {
|
|
638
|
-
if (!fieldTypeInfo) {
|
|
639
|
-
return false;
|
|
640
|
-
}
|
|
641
|
-
const {
|
|
642
|
-
isEntity,
|
|
643
|
-
possibleTypes
|
|
644
|
-
} = fieldTypeInfo;
|
|
645
|
-
return isEntity || possibleTypes.some(type => !!type.isEntity);
|
|
646
|
-
}
|
|
647
|
-
static _isNodeRequestFieldPath(fieldTypeInfo) {
|
|
648
|
-
return !!fieldTypeInfo && (this._isNodeEntity(fieldTypeInfo) || fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives);
|
|
649
|
-
}
|
|
650
|
-
static _isValid(cacheability) {
|
|
651
|
-
const noCache = lodashEs.get(cacheability, [METADATA, CACHE_CONTROL, NO_CACHE], false);
|
|
652
|
-
return !noCache && cacheability.checkTTL();
|
|
653
|
-
}
|
|
654
|
-
static _mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse) {
|
|
655
|
-
if (!partialQueryResponse) {
|
|
656
|
-
return cacheMetadata;
|
|
657
|
-
}
|
|
658
|
-
return new Map([...partialQueryResponse.cacheMetadata, ...cacheMetadata]);
|
|
659
|
-
}
|
|
660
|
-
static _setCachedData(responseData, {
|
|
661
|
-
data
|
|
662
|
-
}, propNameOrIndex) {
|
|
663
|
-
const setData = value => {
|
|
664
|
-
if (helpers.isArray(responseData) && lodashEs.isNumber(propNameOrIndex)) {
|
|
665
|
-
responseData[propNameOrIndex] = value;
|
|
666
|
-
} else if (helpers.isPlainObject(responseData)) {
|
|
667
|
-
responseData[propNameOrIndex] = value;
|
|
668
|
-
}
|
|
669
|
-
};
|
|
670
|
-
if (!helpers.isObjectLike(data) && !lodashEs.isUndefined(data)) {
|
|
671
|
-
setData(data);
|
|
672
|
-
} else if (helpers.isArray(data)) {
|
|
673
|
-
setData([]);
|
|
674
|
-
} else if (helpers.isPlainObject(data)) {
|
|
675
|
-
setData({});
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
static _setCachedResponseData(cachedFieldData, {
|
|
679
|
-
cacheMetadata,
|
|
680
|
-
data,
|
|
681
|
-
fieldPathChecklist
|
|
682
|
-
}, {
|
|
683
|
-
propNameOrIndex,
|
|
684
|
-
requestFieldPath
|
|
685
|
-
}, typeNamesAndKind, _options, {
|
|
686
|
-
operation
|
|
687
|
-
}) {
|
|
688
|
-
CacheManager._setCacheMetadata(cacheMetadata, cachedFieldData.cacheability, requestFieldPath, operation);
|
|
689
|
-
CacheManager._setFieldPathChecklist(fieldPathChecklist, cachedFieldData, requestFieldPath, typeNamesAndKind);
|
|
690
|
-
CacheManager._setCachedData(data, cachedFieldData, propNameOrIndex);
|
|
691
|
-
}
|
|
692
|
-
static _setCacheMetadata(cacheMetadata, cacheability, requestFieldPath, operation) {
|
|
693
|
-
if (!cacheability) {
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
|
-
cacheMetadata.set(requestFieldPath, cacheability);
|
|
697
|
-
const operationCacheability = cacheMetadata.get(operation);
|
|
698
|
-
if (!operationCacheability || operationCacheability.metadata.ttl > cacheability.metadata.ttl) {
|
|
699
|
-
cacheMetadata.set(operation, cacheability);
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
static _setFieldPathChecklist(fieldPathChecklist, {
|
|
703
|
-
data
|
|
704
|
-
}, requestFieldPath, {
|
|
705
|
-
dataTypename: dataTypeName,
|
|
706
|
-
fieldTypename: fieldTypeName,
|
|
707
|
-
fragmentKind,
|
|
708
|
-
fragmentName
|
|
709
|
-
}) {
|
|
710
|
-
if (lodashEs.isUndefined(fieldTypeName) || fragmentKind === graphql.Kind.FRAGMENT_SPREAD) {
|
|
711
|
-
if (fieldPathChecklist.has(requestFieldPath)) {
|
|
712
|
-
return;
|
|
713
|
-
}
|
|
714
|
-
fieldPathChecklist.set(requestFieldPath, [{
|
|
715
|
-
fragmentKind,
|
|
716
|
-
fragmentName,
|
|
717
|
-
hasData: !lodashEs.isUndefined(data)
|
|
718
|
-
}]);
|
|
719
|
-
return;
|
|
720
|
-
}
|
|
721
|
-
if (dataTypeName !== fieldTypeName) {
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
const entry = fieldPathChecklist.get(requestFieldPath);
|
|
725
|
-
const checklistValues = entry ?? [];
|
|
726
|
-
if (checklistValues.some(({
|
|
727
|
-
typeName
|
|
728
|
-
}) => typeName === dataTypeName)) {
|
|
729
|
-
return;
|
|
730
|
-
}
|
|
731
|
-
fieldPathChecklist.set(requestFieldPath, [...checklistValues, {
|
|
732
|
-
fragmentKind,
|
|
733
|
-
fragmentName,
|
|
734
|
-
hasData: !lodashEs.isUndefined(data),
|
|
735
|
-
typeName: dataTypeName
|
|
736
|
-
}]);
|
|
737
|
-
}
|
|
738
|
-
constructor(options) {
|
|
739
|
-
_defineProperty(this, "_cache", void 0);
|
|
740
|
-
_defineProperty(this, "_cascadeCacheControl", void 0);
|
|
741
|
-
_defineProperty(this, "_fallbackOperationCacheability", void 0);
|
|
742
|
-
_defineProperty(this, "_partialQueryResponses", new Map());
|
|
743
|
-
_defineProperty(this, "_responseChunksAwaitingCaching", new Map());
|
|
744
|
-
_defineProperty(this, "_typeCacheDirectives", void 0);
|
|
745
|
-
_defineProperty(this, "_typeIDKey", void 0);
|
|
746
|
-
const errors = [];
|
|
747
|
-
if (!('cache' in options)) {
|
|
748
|
-
errors.push(new helpers.ArgsError('@graphql-box/cache-manager expected cache to be in options.'));
|
|
749
|
-
}
|
|
750
|
-
if (!!options.typeCacheDirectives && !helpers.isPlainObject(options.typeCacheDirectives)) {
|
|
751
|
-
const message = '@graphql-box/cache-manager expected options.typeCacheDirectives to be a plain object.';
|
|
752
|
-
errors.push(new helpers.ArgsError(message));
|
|
753
|
-
}
|
|
754
|
-
if (errors.length > 0) {
|
|
755
|
-
throw new helpers.GroupedError('@graphql-box/cache-manager argument validation errors.', errors);
|
|
756
|
-
}
|
|
757
|
-
this._cache = options.cache;
|
|
758
|
-
this._cascadeCacheControl = options.cascadeCacheControl ?? false;
|
|
759
|
-
this._fallbackOperationCacheability = options.fallbackOperationCacheability ?? NO_CACHE;
|
|
760
|
-
this._typeCacheDirectives = options.typeCacheDirectives ?? {};
|
|
761
|
-
this._typeIDKey = options.typeIDKey ?? core.DEFAULT_TYPE_ID_KEY;
|
|
762
|
-
}
|
|
763
|
-
async analyzeQuery(requestData, options, context) {
|
|
764
|
-
const {
|
|
765
|
-
ast,
|
|
766
|
-
hash
|
|
767
|
-
} = requestData;
|
|
768
|
-
const cacheManagerContext = {
|
|
769
|
-
...context,
|
|
770
|
-
fragmentDefinitions: helpers.getFragmentDefinitions(ast),
|
|
771
|
-
typeIDKey: this._typeIDKey
|
|
772
|
-
};
|
|
773
|
-
const cachedResponseData = await this._retrieveCachedResponseData(requestData, options, cacheManagerContext);
|
|
774
|
-
const {
|
|
775
|
-
cacheMetadata,
|
|
776
|
-
data,
|
|
777
|
-
fieldCount
|
|
778
|
-
} = cachedResponseData;
|
|
779
|
-
if (fieldCount.missing === fieldCount.total || areOnlyPopulatedFieldsTypeIdKeys(data, this._typeIDKey)) {
|
|
780
|
-
return {
|
|
781
|
-
updated: requestData
|
|
782
|
-
};
|
|
783
|
-
}
|
|
784
|
-
if (!fieldCount.missing) {
|
|
785
|
-
const dataCaching = this._setQueryResponseCacheEntry(hash, {
|
|
786
|
-
cacheMetadata,
|
|
787
|
-
data
|
|
788
|
-
}, options, cacheManagerContext);
|
|
789
|
-
if (options.awaitDataCaching) {
|
|
790
|
-
await dataCaching;
|
|
791
|
-
}
|
|
792
|
-
return {
|
|
793
|
-
response: {
|
|
794
|
-
cacheMetadata,
|
|
795
|
-
data
|
|
796
|
-
}
|
|
797
|
-
};
|
|
798
|
-
}
|
|
799
|
-
const filteredAST = filterQuery(requestData, cachedResponseData, cacheManagerContext);
|
|
800
|
-
const filteredRequest = graphql.print(filteredAST);
|
|
801
|
-
const {
|
|
802
|
-
fragmentDefinitions,
|
|
803
|
-
typeIDKey,
|
|
804
|
-
...rest
|
|
805
|
-
} = cacheManagerContext;
|
|
806
|
-
lodashEs.assign(context, {
|
|
807
|
-
...rest,
|
|
808
|
-
filteredRequest
|
|
809
|
-
});
|
|
810
|
-
this._setPartialQueryResponse(hash, {
|
|
811
|
-
cacheMetadata,
|
|
812
|
-
data
|
|
813
|
-
}, options, context);
|
|
814
|
-
return {
|
|
815
|
-
updated: {
|
|
816
|
-
ast: filteredAST,
|
|
817
|
-
hash: helpers.hashRequest(filteredRequest),
|
|
818
|
-
request: filteredRequest
|
|
819
|
-
}
|
|
820
|
-
};
|
|
821
|
-
}
|
|
822
|
-
get cache() {
|
|
823
|
-
return this._cache;
|
|
824
|
-
}
|
|
825
|
-
async cacheQuery(requestData, updatedRequestData, rawResponseData, options, context) {
|
|
826
|
-
const cacheManagerContext = {
|
|
827
|
-
...context,
|
|
828
|
-
fragmentDefinitions: helpers.getFragmentDefinitions((updatedRequestData ?? requestData).ast),
|
|
829
|
-
typeIDKey: this._typeIDKey
|
|
830
|
-
};
|
|
831
|
-
return this._cacheResponse(requestData, updatedRequestData, rawResponseData, options, cacheManagerContext);
|
|
832
|
-
}
|
|
833
|
-
async cacheResponse(requestData, rawResponseData, options, context) {
|
|
834
|
-
const cacheManagerContext = {
|
|
835
|
-
...context,
|
|
836
|
-
fragmentDefinitions: helpers.getFragmentDefinitions(requestData.ast),
|
|
837
|
-
typeIDKey: this._typeIDKey
|
|
838
|
-
};
|
|
839
|
-
return this._cacheResponse(requestData, undefined, rawResponseData, options, cacheManagerContext);
|
|
840
|
-
}
|
|
841
|
-
async checkCacheEntry(cacheType, hash, options, context) {
|
|
842
|
-
return this._checkCacheEntry(cacheType, hash, options, context);
|
|
843
|
-
}
|
|
844
|
-
async checkQueryResponseCacheEntry(hash, options, context) {
|
|
845
|
-
const result = await this._checkCacheEntry(core.QUERY_RESPONSES, hash, options, context);
|
|
846
|
-
if (!result) {
|
|
847
|
-
return false;
|
|
848
|
-
}
|
|
849
|
-
const {
|
|
850
|
-
cacheMetadata,
|
|
851
|
-
data
|
|
852
|
-
} = result.entry;
|
|
853
|
-
return {
|
|
854
|
-
cacheMetadata: helpers.rehydrateCacheMetadata(cacheMetadata),
|
|
855
|
-
data
|
|
856
|
-
};
|
|
857
|
-
}
|
|
858
|
-
deletePartialQueryResponse(hash) {
|
|
859
|
-
this._partialQueryResponses.delete(hash);
|
|
860
|
-
}
|
|
861
|
-
async setQueryResponseCacheEntry(requestData, responseData, options, context) {
|
|
862
|
-
return this._setQueryResponseCacheEntry(requestData.hash, responseData, options, context);
|
|
863
|
-
}
|
|
864
|
-
async _analyzeFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
|
|
865
|
-
await (helpers.hasChildFields(fieldNode, {
|
|
866
|
-
fragmentDefinitions: context.fragmentDefinitions
|
|
867
|
-
}) ? this._analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) : this._analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context));
|
|
868
|
-
}
|
|
869
|
-
async _analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
|
|
870
|
-
const keysAndPaths = helpers.buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
|
|
871
|
-
const {
|
|
872
|
-
hashedRequestFieldCacheKey,
|
|
873
|
-
propNameOrIndex,
|
|
874
|
-
requestFieldCacheKey,
|
|
875
|
-
requestFieldPath
|
|
876
|
-
} = keysAndPaths;
|
|
877
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
878
|
-
const {
|
|
879
|
-
entityData,
|
|
880
|
-
fragmentKind,
|
|
881
|
-
fragmentName,
|
|
882
|
-
requestFieldPathData,
|
|
883
|
-
typeName
|
|
884
|
-
} = cachedAncestorFieldData;
|
|
885
|
-
const dataTypename = hasTypename(entityData) ? entityData.__typename : hasTypename(requestFieldPathData) ? requestFieldPathData.__typename : undefined;
|
|
886
|
-
const typenamesAndKind = {
|
|
887
|
-
dataTypename,
|
|
888
|
-
fieldTypename: typeName,
|
|
889
|
-
fragmentKind,
|
|
890
|
-
fragmentName
|
|
891
|
-
};
|
|
892
|
-
if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
|
|
893
|
-
const {
|
|
894
|
-
cacheability,
|
|
895
|
-
entry
|
|
896
|
-
} = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, requestFieldCacheKey, options, context);
|
|
897
|
-
CacheManager._setCachedResponseData({
|
|
898
|
-
cacheability,
|
|
899
|
-
data: entry
|
|
900
|
-
}, cachedResponseData, keysAndPaths, typenamesAndKind, options, context);
|
|
901
|
-
} else {
|
|
902
|
-
const cachedFieldData = CacheManager._getFieldDataFromAncestor(entityData, propNameOrIndex) ?? CacheManager._getFieldDataFromAncestor(requestFieldPathData, propNameOrIndex);
|
|
903
|
-
CacheManager._setFieldPathChecklist(cachedResponseData.fieldPathChecklist, {
|
|
904
|
-
data: cachedFieldData
|
|
905
|
-
}, requestFieldPath, typenamesAndKind);
|
|
906
|
-
CacheManager._setCachedData(cachedResponseData.data, {
|
|
907
|
-
data: cachedFieldData
|
|
908
|
-
}, propNameOrIndex);
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
async _analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context) {
|
|
912
|
-
const keysAndPaths = helpers.buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
|
|
913
|
-
const {
|
|
914
|
-
propNameOrIndex,
|
|
915
|
-
requestFieldCacheKey,
|
|
916
|
-
requestFieldPath
|
|
917
|
-
} = keysAndPaths;
|
|
918
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
919
|
-
const {
|
|
920
|
-
cacheability,
|
|
921
|
-
data,
|
|
922
|
-
entityData,
|
|
923
|
-
requestFieldPathData
|
|
924
|
-
} = await this._retrieveCachedParentNodeData(cachedAncestorFieldData, keysAndPaths, fieldTypeInfo, options, context);
|
|
925
|
-
const {
|
|
926
|
-
fragmentKind,
|
|
927
|
-
fragmentName,
|
|
928
|
-
typeName
|
|
929
|
-
} = cachedAncestorFieldData;
|
|
930
|
-
CacheManager._setCachedResponseData({
|
|
931
|
-
cacheability,
|
|
932
|
-
data
|
|
933
|
-
}, cachedResponseData, keysAndPaths, {
|
|
934
|
-
dataTypename: lodashEs.get(data, core.TYPE_NAME_KEY),
|
|
935
|
-
fieldTypename: typeName,
|
|
936
|
-
fragmentKind,
|
|
937
|
-
fragmentName
|
|
938
|
-
}, options, context);
|
|
939
|
-
if (!helpers.isObjectLike(data)) {
|
|
940
|
-
return;
|
|
941
|
-
}
|
|
942
|
-
const promises = [];
|
|
943
|
-
helpers.iterateChildFields(fieldNode, data, context.fragmentDefinitions, (childField, childTypeName, childFragmentKind, childFragmentName, childIndex) => {
|
|
944
|
-
promises.push(this._analyzeFieldNode(childField, {
|
|
945
|
-
cacheability,
|
|
946
|
-
entityData,
|
|
947
|
-
fragmentKind: childFragmentKind,
|
|
948
|
-
fragmentName: childFragmentName,
|
|
949
|
-
index: childIndex,
|
|
950
|
-
requestFieldCacheKey,
|
|
951
|
-
requestFieldPath,
|
|
952
|
-
requestFieldPathData,
|
|
953
|
-
typeName: childTypeName
|
|
954
|
-
}, {
|
|
955
|
-
...cachedResponseData,
|
|
956
|
-
data: getDataValue(cachedResponseData.data, propNameOrIndex)
|
|
957
|
-
}, options, context));
|
|
958
|
-
});
|
|
959
|
-
await Promise.all(promises);
|
|
960
|
-
}
|
|
961
|
-
_buildCacheMetadata({
|
|
962
|
-
ast
|
|
963
|
-
}, {
|
|
964
|
-
data,
|
|
965
|
-
...otherProps
|
|
966
|
-
}, options, context) {
|
|
967
|
-
const cacheMetadata = this._createCacheMetadata({
|
|
968
|
-
data,
|
|
969
|
-
...otherProps
|
|
970
|
-
}, context);
|
|
971
|
-
const queryNode = helpers.getOperationDefinitions(ast, context.operation)[0];
|
|
972
|
-
if (!queryNode) {
|
|
973
|
-
return cacheMetadata;
|
|
974
|
-
}
|
|
975
|
-
const fieldsAndTypeNames = helpers.getChildFields(queryNode);
|
|
976
|
-
if (!fieldsAndTypeNames) {
|
|
977
|
-
return cacheMetadata;
|
|
978
|
-
}
|
|
979
|
-
for (const {
|
|
980
|
-
fieldNode
|
|
981
|
-
} of fieldsAndTypeNames) this._setFieldCacheability(fieldNode, {
|
|
982
|
-
requestFieldPath: context.operation
|
|
983
|
-
}, {
|
|
984
|
-
cacheMetadata,
|
|
985
|
-
data
|
|
986
|
-
}, options, context);
|
|
987
|
-
return cacheMetadata;
|
|
988
|
-
}
|
|
989
|
-
async _cacheResponse(requestData, updatedRequestData, rawResponseData, options, context) {
|
|
990
|
-
const normalizedResponseData = normalizePatchResponseData(rawResponseData, context);
|
|
991
|
-
let responseDataForCaching = normalizedResponseData;
|
|
992
|
-
if (isNotLastResponseChunk(rawResponseData, context)) {
|
|
993
|
-
this._setResponseChunksAwaitingCaching(normalizedResponseData, context);
|
|
994
|
-
responseDataForCaching = undefined;
|
|
995
|
-
}
|
|
996
|
-
if (isLastResponseChunk(rawResponseData, context)) {
|
|
997
|
-
responseDataForCaching = this._retrieveResponseDataForCaching(normalizedResponseData, context);
|
|
998
|
-
}
|
|
999
|
-
const dataCaching = [];
|
|
1000
|
-
if (responseDataForCaching) {
|
|
1001
|
-
const {
|
|
1002
|
-
data
|
|
1003
|
-
} = responseDataForCaching;
|
|
1004
|
-
const cacheMetadata = this._buildCacheMetadata(requestData, responseDataForCaching, options, context);
|
|
1005
|
-
dataCaching.push(this._setEntityAndRequestFieldPathCacheEntries(requestData, {
|
|
1006
|
-
cacheMetadata,
|
|
1007
|
-
entityData: lodashEs.cloneDeep(data),
|
|
1008
|
-
requestFieldPathData: lodashEs.cloneDeep(data)
|
|
1009
|
-
}, options, context));
|
|
1010
|
-
let queryCacheMetadata;
|
|
1011
|
-
let queryData;
|
|
1012
|
-
if (context.operation === graphql.OperationTypeNode.QUERY) {
|
|
1013
|
-
let partialQueryResponse;
|
|
1014
|
-
if (context.queryFiltered && updatedRequestData) {
|
|
1015
|
-
dataCaching.push(this._setQueryResponseCacheEntry(updatedRequestData.hash, {
|
|
1016
|
-
cacheMetadata,
|
|
1017
|
-
data
|
|
1018
|
-
}, options, context));
|
|
1019
|
-
partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
|
|
1020
|
-
}
|
|
1021
|
-
queryCacheMetadata = CacheManager._mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse);
|
|
1022
|
-
queryData = this._mergeResponseData(data, partialQueryResponse);
|
|
1023
|
-
dataCaching.push(this._setQueryResponseCacheEntry(requestData.hash, {
|
|
1024
|
-
cacheMetadata: queryCacheMetadata,
|
|
1025
|
-
data: queryData
|
|
1026
|
-
}, options, context));
|
|
1027
|
-
}
|
|
1028
|
-
if (options.awaitDataCaching) {
|
|
1029
|
-
await Promise.all(dataCaching);
|
|
1030
|
-
}
|
|
1031
|
-
if (isNotResponseChunk(normalizedResponseData, context) && queryCacheMetadata && queryData) {
|
|
1032
|
-
return {
|
|
1033
|
-
cacheMetadata: queryCacheMetadata,
|
|
1034
|
-
data: queryData
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
const {
|
|
1039
|
-
data,
|
|
1040
|
-
hasNext,
|
|
1041
|
-
paths
|
|
1042
|
-
} = normalizedResponseData;
|
|
1043
|
-
return {
|
|
1044
|
-
cacheMetadata: this._buildCacheMetadata(requestData, normalizedResponseData, options, context),
|
|
1045
|
-
data,
|
|
1046
|
-
hasNext,
|
|
1047
|
-
paths
|
|
1048
|
-
};
|
|
1049
|
-
}
|
|
1050
|
-
async _checkCacheEntry(cacheType, hash, options, context) {
|
|
1051
|
-
try {
|
|
1052
|
-
const cacheability = await this._hasCacheEntry(cacheType, hash);
|
|
1053
|
-
if (!cacheability || !CacheManager._isValid(cacheability)) {
|
|
1054
|
-
return false;
|
|
1055
|
-
}
|
|
1056
|
-
const entry = await this._getCacheEntry(cacheType, hash, options, context);
|
|
1057
|
-
if (lodashEs.isUndefined(entry)) {
|
|
1058
|
-
return false;
|
|
1059
|
-
}
|
|
1060
|
-
return {
|
|
1061
|
-
cacheability,
|
|
1062
|
-
entry
|
|
1063
|
-
};
|
|
1064
|
-
} catch {
|
|
1065
|
-
return false;
|
|
1066
|
-
}
|
|
1067
|
-
}
|
|
1068
|
-
_createCacheMetadata({
|
|
1069
|
-
_cacheMetadata,
|
|
1070
|
-
headers
|
|
1071
|
-
}, {
|
|
1072
|
-
operation
|
|
1073
|
-
}) {
|
|
1074
|
-
const cacheMetadata = new Map();
|
|
1075
|
-
const cacheability = deriveOpCacheability({
|
|
1076
|
-
_cacheMetadata,
|
|
1077
|
-
fallback: this._fallbackOperationCacheability,
|
|
1078
|
-
headers
|
|
1079
|
-
});
|
|
1080
|
-
cacheMetadata.set(operation, cacheability);
|
|
1081
|
-
if (_cacheMetadata) {
|
|
1082
|
-
helpers.rehydrateCacheMetadata(_cacheMetadata, cacheMetadata);
|
|
1083
|
-
}
|
|
1084
|
-
return cacheMetadata;
|
|
1085
|
-
}
|
|
1086
|
-
async _getCacheEntry(cacheType, hash, _options, _context) {
|
|
1087
|
-
return this._cache.get(`${cacheType}::${hash}`);
|
|
1088
|
-
}
|
|
1089
|
-
_getPartialQueryResponse(hash) {
|
|
1090
|
-
const partialQueryResponse = this._partialQueryResponses.get(hash);
|
|
1091
|
-
this._partialQueryResponses.delete(hash);
|
|
1092
|
-
return partialQueryResponse;
|
|
1093
|
-
}
|
|
1094
|
-
async _hasCacheEntry(cacheType, hash) {
|
|
1095
|
-
try {
|
|
1096
|
-
return await this._cache.has(`${cacheType}::${hash}`);
|
|
1097
|
-
} catch {
|
|
1098
|
-
return false;
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
_isFieldEntity(fieldData, {
|
|
1102
|
-
isEntity,
|
|
1103
|
-
possibleTypes
|
|
1104
|
-
}) {
|
|
1105
|
-
if (!helpers.isPlainObject(fieldData) || !(this._typeIDKey in fieldData)) {
|
|
1106
|
-
return false;
|
|
1107
|
-
}
|
|
1108
|
-
if (isEntity) {
|
|
1109
|
-
return true;
|
|
1110
|
-
}
|
|
1111
|
-
if (possibleTypes.length === 0) {
|
|
1112
|
-
return false;
|
|
1113
|
-
}
|
|
1114
|
-
return possibleTypes.some(type => type.typeName === fieldData.__typename);
|
|
1115
|
-
}
|
|
1116
|
-
_mergeResponseData(responseData, partialQueryResponse) {
|
|
1117
|
-
if (!partialQueryResponse) {
|
|
1118
|
-
return responseData;
|
|
1119
|
-
}
|
|
1120
|
-
return mergeDataSets(partialQueryResponse.data, responseData, this._typeIDKey);
|
|
1121
|
-
}
|
|
1122
|
-
async _parseEntityAndRequestFieldPathCacheEntryData(field, ancestorKeysAndPaths, {
|
|
1123
|
-
cacheMetadata,
|
|
1124
|
-
entityData,
|
|
1125
|
-
requestFieldPathData
|
|
1126
|
-
}, options, context) {
|
|
1127
|
-
const keysAndPaths = helpers.buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
|
|
1128
|
-
const {
|
|
1129
|
-
requestFieldCacheKey,
|
|
1130
|
-
requestFieldPath,
|
|
1131
|
-
responseDataPath
|
|
1132
|
-
} = keysAndPaths;
|
|
1133
|
-
const fieldData = lodashEs.get(requestFieldPathData, responseDataPath);
|
|
1134
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
1135
|
-
if (!helpers.isObjectLike(fieldData) && !fieldTypeInfo?.hasDirectives) {
|
|
1136
|
-
return;
|
|
1137
|
-
}
|
|
1138
|
-
if (helpers.isObjectLike(fieldData)) {
|
|
1139
|
-
const promises = [];
|
|
1140
|
-
helpers.iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
|
|
1141
|
-
promises.push(this._parseEntityAndRequestFieldPathCacheEntryData(childField, {
|
|
1142
|
-
index: childIndex,
|
|
1143
|
-
requestFieldCacheKey,
|
|
1144
|
-
requestFieldPath,
|
|
1145
|
-
responseDataPath
|
|
1146
|
-
}, {
|
|
1147
|
-
cacheMetadata,
|
|
1148
|
-
entityData,
|
|
1149
|
-
requestFieldPathData
|
|
1150
|
-
}, options, context));
|
|
1151
|
-
});
|
|
1152
|
-
await Promise.all(promises);
|
|
1153
|
-
}
|
|
1154
|
-
await this._setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
|
|
1155
|
-
cacheMetadata,
|
|
1156
|
-
entityData,
|
|
1157
|
-
requestFieldPathData
|
|
1158
|
-
}, options, context);
|
|
1159
|
-
}
|
|
1160
|
-
async _retrieveCachedEntityData(validTypeIDValue, {
|
|
1161
|
-
possibleTypes,
|
|
1162
|
-
typeName
|
|
1163
|
-
}, options, context) {
|
|
1164
|
-
const typeNames = [...possibleTypes.map(type => type.typeName), typeName];
|
|
1165
|
-
const checkResults = await Promise.all(typeNames.map(name => this._checkCacheEntry(core.DATA_ENTITIES, `${name}::${validTypeIDValue}`, options, context)));
|
|
1166
|
-
const validResults = checkResults.filter(result => !!result);
|
|
1167
|
-
let validResult;
|
|
1168
|
-
if (validResults.length === 1) {
|
|
1169
|
-
validResult = validResults[0];
|
|
1170
|
-
} else if (validResults.length > 1) {
|
|
1171
|
-
validResults.sort(({
|
|
1172
|
-
cacheability: a
|
|
1173
|
-
}, {
|
|
1174
|
-
cacheability: b
|
|
1175
|
-
}) => a.metadata.ttl - b.metadata.ttl);
|
|
1176
|
-
validResult = {
|
|
1177
|
-
cacheability: validResults[0].cacheability,
|
|
1178
|
-
entry: validResults.reduce((obj, {
|
|
1179
|
-
entry
|
|
1180
|
-
}) => mergeDataSets(obj, entry, this._typeIDKey), {})
|
|
1181
|
-
};
|
|
1182
|
-
}
|
|
1183
|
-
return validResult ?? {};
|
|
1184
|
-
}
|
|
1185
|
-
async _retrieveCachedParentNodeData({
|
|
1186
|
-
entityData: ancestorEntityData,
|
|
1187
|
-
requestFieldPathData: ancestorRequestFieldPathData
|
|
1188
|
-
}, {
|
|
1189
|
-
hashedRequestFieldCacheKey,
|
|
1190
|
-
propNameOrIndex,
|
|
1191
|
-
requestFieldCacheKey
|
|
1192
|
-
}, fieldTypeInfo, options, context) {
|
|
1193
|
-
let entityData = CacheManager._getFieldDataFromAncestor(ancestorEntityData, propNameOrIndex);
|
|
1194
|
-
let requestFieldPathData = CacheManager._getFieldDataFromAncestor(ancestorRequestFieldPathData, propNameOrIndex);
|
|
1195
|
-
let cacheability;
|
|
1196
|
-
if (CacheManager._isNodeRequestFieldPath(fieldTypeInfo)) {
|
|
1197
|
-
const {
|
|
1198
|
-
cacheability: entryCacheability,
|
|
1199
|
-
entry
|
|
1200
|
-
} = await this._retrieveCachedRequestFieldPathData(hashedRequestFieldCacheKey, requestFieldCacheKey, options, context);
|
|
1201
|
-
requestFieldPathData = combineDataSets(requestFieldPathData, entry, this._typeIDKey);
|
|
1202
|
-
if (entryCacheability) {
|
|
1203
|
-
cacheability = entryCacheability;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
const validTypeIDValue = getValidTypeIdValue(requestFieldPathData, fieldTypeInfo, this._typeIDKey);
|
|
1207
|
-
if (CacheManager._isNodeEntity(fieldTypeInfo) && validTypeIDValue) {
|
|
1208
|
-
const {
|
|
1209
|
-
cacheability: entryCacheability,
|
|
1210
|
-
entry
|
|
1211
|
-
} = await this._retrieveCachedEntityData(validTypeIDValue, fieldTypeInfo, options, context);
|
|
1212
|
-
entityData = combineDataSets(entityData, entry, this._typeIDKey);
|
|
1213
|
-
if (entryCacheability && (!cacheability || entryCacheability.metadata.ttl > cacheability.metadata.ttl)) {
|
|
1214
|
-
cacheability = entryCacheability;
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
const data = lodashEs.isEqual(entityData, requestFieldPathData) ? entityData : combineDataSets(entityData, requestFieldPathData, this._typeIDKey);
|
|
1218
|
-
return {
|
|
1219
|
-
cacheability,
|
|
1220
|
-
data,
|
|
1221
|
-
entityData,
|
|
1222
|
-
requestFieldPathData
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
async _retrieveCachedRequestFieldPathData(hash, requestFieldCacheKey, options, context) {
|
|
1226
|
-
return (await this._checkCacheEntry(core.REQUEST_FIELD_PATHS, hash, options, {
|
|
1227
|
-
...context,
|
|
1228
|
-
requestFieldCacheKey
|
|
1229
|
-
})) || {};
|
|
1230
|
-
}
|
|
1231
|
-
async _retrieveCachedResponseData({
|
|
1232
|
-
ast
|
|
1233
|
-
}, options, context) {
|
|
1234
|
-
const cachedResponseData = {
|
|
1235
|
-
cacheMetadata: new Map(),
|
|
1236
|
-
data: {},
|
|
1237
|
-
fieldCount: {
|
|
1238
|
-
missing: 0,
|
|
1239
|
-
total: 0
|
|
1240
|
-
},
|
|
1241
|
-
fieldPathChecklist: new Map()
|
|
1242
|
-
};
|
|
1243
|
-
const queryNode = helpers.getOperationDefinitions(ast, context.operation)[0];
|
|
1244
|
-
if (!queryNode) {
|
|
1245
|
-
return cachedResponseData;
|
|
1246
|
-
}
|
|
1247
|
-
const fieldsAndTypeNames = helpers.getChildFields(queryNode);
|
|
1248
|
-
if (!fieldsAndTypeNames) {
|
|
1249
|
-
return cachedResponseData;
|
|
1250
|
-
}
|
|
1251
|
-
await Promise.all(fieldsAndTypeNames.map(({
|
|
1252
|
-
fieldNode
|
|
1253
|
-
}) => this._analyzeFieldNode(fieldNode, {
|
|
1254
|
-
requestFieldPath: context.operation
|
|
1255
|
-
}, cachedResponseData, options, context)));
|
|
1256
|
-
cachedResponseData.fieldCount = CacheManager._countFieldPathChecklist(cachedResponseData.fieldPathChecklist);
|
|
1257
|
-
return cachedResponseData;
|
|
1258
|
-
}
|
|
1259
|
-
_retrieveResponseDataForCaching(normalizedResponseData, context) {
|
|
1260
|
-
const responseChunks = this._responseChunksAwaitingCaching.get(context.requestID);
|
|
1261
|
-
this._responseChunksAwaitingCaching.delete(context.requestID);
|
|
1262
|
-
return mergeResponseDataSets([...responseChunks, normalizedResponseData]);
|
|
1263
|
-
}
|
|
1264
|
-
async _setCacheEntry(cacheType, hash, value, cachemapOptions, _options, _context) {
|
|
1265
|
-
try {
|
|
1266
|
-
await this._cache.set(`${cacheType}::${hash}`, lodashEs.cloneDeep(value), cachemapOptions);
|
|
1267
|
-
} catch {}
|
|
1268
|
-
}
|
|
1269
|
-
async _setEntityAndRequestFieldPathCacheEntries(requestData, responseData, options, context) {
|
|
1270
|
-
const operationNode = helpers.getOperationDefinitions(requestData.ast, context.operation)[0];
|
|
1271
|
-
if (!operationNode) {
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1274
|
-
const fieldsAndTypeNames = helpers.getChildFields(operationNode);
|
|
1275
|
-
if (!fieldsAndTypeNames) {
|
|
1276
|
-
return;
|
|
1277
|
-
}
|
|
1278
|
-
await Promise.all(fieldsAndTypeNames.map(({
|
|
1279
|
-
fieldNode
|
|
1280
|
-
}) => {
|
|
1281
|
-
return this._parseEntityAndRequestFieldPathCacheEntryData(fieldNode, {
|
|
1282
|
-
requestFieldPath: context.operation
|
|
1283
|
-
}, responseData, options, context);
|
|
1284
|
-
}));
|
|
1285
|
-
}
|
|
1286
|
-
async _setEntityAndRequestFieldPathCacheEntry(field, keysAndPaths, {
|
|
1287
|
-
cacheMetadata,
|
|
1288
|
-
entityData,
|
|
1289
|
-
requestFieldPathData
|
|
1290
|
-
}, options, context) {
|
|
1291
|
-
const {
|
|
1292
|
-
requestFieldPath,
|
|
1293
|
-
responseDataPath
|
|
1294
|
-
} = keysAndPaths;
|
|
1295
|
-
const fieldData = lodashEs.get(entityData, responseDataPath);
|
|
1296
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
1297
|
-
const cacheability = cacheMetadata.get(requestFieldPath);
|
|
1298
|
-
if (lodashEs.isUndefined(fieldData) || !fieldTypeInfo || !cacheability) {
|
|
1299
|
-
return;
|
|
1300
|
-
}
|
|
1301
|
-
const promises = [];
|
|
1302
|
-
promises.push(this._setRequestFieldPathCacheEntry(field, keysAndPaths, {
|
|
1303
|
-
cacheability,
|
|
1304
|
-
data: requestFieldPathData,
|
|
1305
|
-
fieldTypeInfo
|
|
1306
|
-
}, options, context));
|
|
1307
|
-
const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
|
|
1308
|
-
if (!isEntity && fieldTypeInfo.hasArguments) {
|
|
1309
|
-
lodashEs.unset(entityData, responseDataPath);
|
|
1310
|
-
}
|
|
1311
|
-
if (isEntity) {
|
|
1312
|
-
promises.push(this._setEntityCacheEntry(keysAndPaths, {
|
|
1313
|
-
cacheability,
|
|
1314
|
-
data: entityData,
|
|
1315
|
-
fieldTypeInfo
|
|
1316
|
-
}, options, context));
|
|
1317
|
-
}
|
|
1318
|
-
await Promise.all(promises);
|
|
1319
|
-
}
|
|
1320
|
-
async _setEntityCacheEntry({
|
|
1321
|
-
responseDataPath
|
|
1322
|
-
}, {
|
|
1323
|
-
cacheability,
|
|
1324
|
-
data,
|
|
1325
|
-
fieldTypeInfo
|
|
1326
|
-
}, options, context) {
|
|
1327
|
-
let fieldData = lodashEs.get(data, responseDataPath);
|
|
1328
|
-
const fieldTypeName = fieldTypeInfo.isEntity ? fieldTypeInfo.typeName : fieldData.__typename;
|
|
1329
|
-
const entityDataKey = `${fieldTypeName}::${String(fieldData[this._typeIDKey])}`;
|
|
1330
|
-
const result = await this._checkCacheEntry(core.DATA_ENTITIES, entityDataKey, options, context);
|
|
1331
|
-
if (result) {
|
|
1332
|
-
fieldData = mergeDataSets(result.entry, fieldData, this._typeIDKey);
|
|
1333
|
-
}
|
|
1334
|
-
await this._setCacheEntry(core.DATA_ENTITIES, entityDataKey, fieldData, {
|
|
1335
|
-
cacheHeaders: {
|
|
1336
|
-
cacheControl: cacheability.printCacheControl()
|
|
1337
|
-
},
|
|
1338
|
-
tag: options.tag
|
|
1339
|
-
}, options, context);
|
|
1340
|
-
lodashEs.set(data, responseDataPath, {
|
|
1341
|
-
__cacheKey: `${core.DATA_ENTITIES}::${entityDataKey}`
|
|
1342
|
-
});
|
|
1343
|
-
}
|
|
1344
|
-
_setFieldCacheability(field, ancestorKeysAndPaths, {
|
|
1345
|
-
cacheMetadata,
|
|
1346
|
-
data
|
|
1347
|
-
}, options, context) {
|
|
1348
|
-
const {
|
|
1349
|
-
requestFieldPath: ancestorRequestFieldPath
|
|
1350
|
-
} = ancestorKeysAndPaths;
|
|
1351
|
-
const keysAndPaths = helpers.buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
|
|
1352
|
-
const {
|
|
1353
|
-
requestFieldPath,
|
|
1354
|
-
responseDataPath
|
|
1355
|
-
} = keysAndPaths;
|
|
1356
|
-
if (!helpers.isObjectLike(data)) {
|
|
1357
|
-
return;
|
|
1358
|
-
}
|
|
1359
|
-
const fieldData = lodashEs.get(data, responseDataPath);
|
|
1360
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
1361
|
-
if (!helpers.isObjectLike(fieldData) && !fieldTypeInfo?.hasDirectives) {
|
|
1362
|
-
return;
|
|
1363
|
-
}
|
|
1364
|
-
this._setFieldTypeCacheDirective(cacheMetadata, {
|
|
1365
|
-
ancestorRequestFieldPath,
|
|
1366
|
-
requestFieldPath
|
|
1367
|
-
}, context);
|
|
1368
|
-
if (helpers.isObjectLike(fieldData)) {
|
|
1369
|
-
helpers.iterateChildFields(field, fieldData, context.fragmentDefinitions, (childField, _typeName, _fragmentKind, _fragmentName, childIndex) => {
|
|
1370
|
-
this._setFieldCacheability(childField, {
|
|
1371
|
-
index: childIndex,
|
|
1372
|
-
requestFieldPath,
|
|
1373
|
-
responseDataPath
|
|
1374
|
-
}, {
|
|
1375
|
-
cacheMetadata,
|
|
1376
|
-
data
|
|
1377
|
-
}, options, context);
|
|
1378
|
-
});
|
|
1379
|
-
}
|
|
1380
|
-
}
|
|
1381
|
-
_setFieldTypeCacheDirective(cacheMetadata, {
|
|
1382
|
-
ancestorRequestFieldPath,
|
|
1383
|
-
requestFieldPath
|
|
1384
|
-
}, {
|
|
1385
|
-
fieldTypeMap,
|
|
1386
|
-
operation
|
|
1387
|
-
}) {
|
|
1388
|
-
if (cacheMetadata.has(requestFieldPath)) {
|
|
1389
|
-
return;
|
|
1390
|
-
}
|
|
1391
|
-
const fieldTypeInfo = fieldTypeMap.get(requestFieldPath);
|
|
1392
|
-
if (fieldTypeInfo && this._typeCacheDirectives[fieldTypeInfo.typeName]) {
|
|
1393
|
-
const cacheability$1 = new cacheability.Cacheability({
|
|
1394
|
-
cacheControl: this._typeCacheDirectives[fieldTypeInfo.typeName]
|
|
1395
|
-
});
|
|
1396
|
-
CacheManager._setCacheMetadata(cacheMetadata, cacheability$1, requestFieldPath, operation);
|
|
1397
|
-
} else if (this._cascadeCacheControl && ancestorRequestFieldPath) {
|
|
1398
|
-
CacheManager._setCacheMetadata(cacheMetadata, cacheMetadata.get(ancestorRequestFieldPath), requestFieldPath, operation);
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
_setPartialQueryResponse(hash, partialQueryResponse, _options, _context) {
|
|
1402
|
-
this._partialQueryResponses.set(hash, partialQueryResponse);
|
|
1403
|
-
}
|
|
1404
|
-
async _setQueryResponseCacheEntry(hash, {
|
|
1405
|
-
cacheMetadata,
|
|
1406
|
-
data
|
|
1407
|
-
}, options, context) {
|
|
1408
|
-
const dehydratedCacheMetadata = helpers.dehydrateCacheMetadata(cacheMetadata);
|
|
1409
|
-
const cacheControl = CacheManager._getOperationCacheControl(cacheMetadata, context.operation);
|
|
1410
|
-
await this._setCacheEntry(core.QUERY_RESPONSES, hash, {
|
|
1411
|
-
cacheMetadata: dehydratedCacheMetadata,
|
|
1412
|
-
data
|
|
1413
|
-
}, {
|
|
1414
|
-
cacheHeaders: {
|
|
1415
|
-
cacheControl
|
|
1416
|
-
},
|
|
1417
|
-
tag: options.tag
|
|
1418
|
-
}, options, context);
|
|
1419
|
-
}
|
|
1420
|
-
async _setRequestFieldPathCacheEntry(field, keysAndPaths, {
|
|
1421
|
-
cacheability,
|
|
1422
|
-
data,
|
|
1423
|
-
fieldTypeInfo
|
|
1424
|
-
}, options, context) {
|
|
1425
|
-
const {
|
|
1426
|
-
hashedRequestFieldCacheKey,
|
|
1427
|
-
requestFieldCacheKey,
|
|
1428
|
-
responseDataPath
|
|
1429
|
-
} = keysAndPaths;
|
|
1430
|
-
let fieldData = lodashEs.get(data, responseDataPath);
|
|
1431
|
-
const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
|
|
1432
|
-
const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
|
|
1433
|
-
if (context.operation === graphql.OperationTypeNode.QUERY && (isEntity || hasArgsOrDirectives)) {
|
|
1434
|
-
if (helpers.isPlainObject(fieldData) && field.selectionSet?.selections) {
|
|
1435
|
-
fieldData = filterOutPropsWithArgsOrDirectives(fieldData, field.selectionSet.selections, keysAndPaths, context);
|
|
1436
|
-
}
|
|
1437
|
-
const result = await this._checkCacheEntry(core.REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, options, {
|
|
1438
|
-
...context,
|
|
1439
|
-
requestFieldCacheKey
|
|
1440
|
-
});
|
|
1441
|
-
if (result && helpers.isObjectLike(result.entry) && helpers.isObjectLike(fieldData)) {
|
|
1442
|
-
fieldData = mergeDataSets(result.entry, fieldData, this._typeIDKey);
|
|
1443
|
-
}
|
|
1444
|
-
await this._setCacheEntry(core.REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, fieldData, {
|
|
1445
|
-
cacheHeaders: {
|
|
1446
|
-
cacheControl: cacheability.printCacheControl()
|
|
1447
|
-
},
|
|
1448
|
-
tag: options.tag
|
|
1449
|
-
}, options, {
|
|
1450
|
-
...context,
|
|
1451
|
-
requestFieldCacheKey
|
|
1452
|
-
});
|
|
1453
|
-
if (helpers.hasChildFields(field, {
|
|
1454
|
-
fragmentDefinitions: context.fragmentDefinitions
|
|
1455
|
-
})) {
|
|
1456
|
-
if (isEntity) {
|
|
1457
|
-
lodashEs.set(data, responseDataPath, {
|
|
1458
|
-
__cacheKey: `${core.REQUEST_FIELD_PATHS}::${hashedRequestFieldCacheKey}`
|
|
1459
|
-
});
|
|
1460
|
-
} else {
|
|
1461
|
-
lodashEs.unset(data, responseDataPath);
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
_setResponseChunksAwaitingCaching(normalizedResponseData, context) {
|
|
1467
|
-
const responseChunks = this._responseChunksAwaitingCaching.get(context.requestID);
|
|
1468
|
-
if (responseChunks) {
|
|
1469
|
-
this._responseChunksAwaitingCaching.set(context.requestID, [...responseChunks, normalizedResponseData]);
|
|
1470
|
-
} else {
|
|
1471
|
-
this._responseChunksAwaitingCaching.set(context.requestID, [normalizedResponseData]);
|
|
1472
|
-
}
|
|
1473
|
-
}
|
|
1474
|
-
}, (_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));
|
|
1475
|
-
|
|
1476
|
-
exports.CacheManager = CacheManager;
|
|
1
|
+
"use strict";var e=require("@babel/runtime/helpers/defineProperty"),t=require("@babel/runtime/helpers/applyDecoratedDescriptor");require("core-js/modules/es.array.push.js");var a=require("@graphql-box/core"),i=require("@graphql-box/helpers"),s=require("cacheability"),n=require("graphql"),r=require("lodash-es");const c="noCache",h=(e,t)=>i.isArray(e)?e.reduce(((e,a)=>!!e&&h(a,t)),!0):!!i.isPlainObject(e)&&o(e,t),o=(e,t)=>{const a=i.isPlainObject(e)?Object.keys(e):[...e.keys()];return!(1!==a.length||!i.isPlainObject(e)||!e[t])||a.reduce(((a,s)=>!!a&&(r.isNumber(s)&&i.isArray(e)||r.isString(s)&&i.isPlainObject(e)?h(e[s],t):a)),!0)},d=(e,t,a)=>i.mergeObjects(e,t,((e,t)=>i.isPlainObject(t)&&t[a]?t[a]:void 0)),l=(e,t,a)=>!e&&t?t:i.isObjectLike(e)&&i.isObjectLike(t)?d(e,t,a):e,y=({_cacheMetadata:e,fallback:t,headers:a})=>{if(e&&!r.isEmpty(e)){const[t,...a]=Object.values(e);return new s.Cacheability({metadata:a.reduce(((e,t)=>e?t.ttl<e.ttl?t:e:t),t)})}return a?.has("cache-control")?new s.Cacheability({headers:a}):new s.Cacheability({cacheControl:t})},p=(e,t)=>{if(!e||0===e.length)return{hasData:!1,typeUnused:!!t};const[a]=e;if(a){const{hasData:e,typeName:i}=a;return{hasData:e,typeUnused:i?i!==t:void 0}}return{hasData:e.some((({hasData:e,typeName:a})=>a===t&&e)),typeUnused:!e.every((({typeName:e})=>e===t))}},u=(e,t,s,c,h)=>{const{fragmentDefinitions:o,typeIDKey:d}=h,l=i.getChildFields(e,{fragmentDefinitions:o});if(!l)return!1;const y={};for(let r=l.length-1;r>=0;r-=1){const _=l[r];if(!_)continue;const{fieldNode:f,fragmentKind:g,fragmentName:C,typeName:D}=_;g===n.Kind.FRAGMENT_SPREAD&&C&&!y[C]&&(y[C]={hasData:0,total:o?.[C]?i.getChildFields(o[C],{fragmentDefinitions:o})?.length??0:0});const m=i.getName(f);if(m===d||m===a.TYPE_NAME_KEY)continue;const{requestFieldPath:F}=i.buildFieldKeysAndPaths(f,{requestFieldPath:c},h),{hasData:E,typeUnused:P}=p(t.get(F),D);if(E||P)if(g===n.Kind.FRAGMENT_SPREAD&&C){const e=y[C];e&&(e.hasData+=1)}else i.hasChildFields(f,{fragmentDefinitions:o})?u(f,t,s,F,h)&&i.deleteChildFields(e,f):i.deleteChildFields(e,f)}return((e,t,a,s)=>{if(!r.isEmpty(t))for(const n of Object.keys(t)){const r=a[n];if(!r)continue;r.paths.push(s);const{hasData:c,total:h}=t[n];c===h&&(i.deleteFragmentSpreads(e,n),r.deleted+=1)}})(e,y,s,c),((e,{fragmentDefinitions:t,typeIDKey:a})=>{const s=i.getInlineFragments(e);let n=!1;for(const r of s){const s=i.getChildFields(r,{fragmentDefinitions:t});if(!s||0===s.length){i.deleteInlineFragments(e,r),n=!0;continue}const[c]=s;if(c){const{fieldNode:t}=c;i.getName(t)===a&&(i.deleteInlineFragments(e,r),n=!0)}}})(e,h),((e,{fragmentDefinitions:t,typeIDKey:s})=>{const n=i.getChildFields(e,{fragmentDefinitions:t});if(!n||n.length>3)return!1;const r=n.map((({fieldNode:e})=>i.getName(e)));if(2===r.length&&r.every((e=>e===s||e===a.TYPE_NAME_KEY)))return i.deleteChildFields(e,n.map((({fieldNode:e})=>e))),!0;if(1===r.length&&r[0]===s||r[0]===a.TYPE_NAME_KEY){const[t]=n;if(t){const{fieldNode:a}=t;return i.deleteChildFields(e,a),!0}}})(e,h),!i.hasChildFields(e,{fragmentDefinitions:o})},_=(e,{fieldPathChecklist:t},a)=>{const{ast:s}=e,n=i.getOperationDefinitions(s,a.operation)[0];if(!n)return s;const{fragmentDefinitions:c,operation:h}=a,o=i.getChildFields(n,{fragmentDefinitions:c});if(!o)return s;const d=(({request:e},{fragmentDefinitions:t})=>r.keys(t??{}).reduce(((t,a)=>(t[a]={deleted:0,paths:[],total:(e.match(new RegExp(`\\.\\.\\.${a}`,"g"))??[]).length},t)),{}))(e,a);for(let e=o.length-1;e>=0;e-=1){const{fieldNode:s}=o[e],{requestFieldPath:r}=i.buildFieldKeysAndPaths(s,{requestFieldPath:h},a);u(s,t,d,r,a)&&i.deleteChildFields(n,s)}return a.queryFiltered=!0,((e,t,a,s)=>{const n=r.keys(a).reduce(((e,t)=>{const i=a[t];if(!i)return e;const{deleted:s,paths:n,total:r}=i;return 0===s&&1===r?[...e,{name:t,path:n[0]}]:e}),[]),{fragmentDefinitions:c={}}=s;for(const{name:e,path:i}of n){const n=c[e];n&&u(n,t,a,i,s)}const h=r.keys(a).reduce(((e,t)=>{const i=a[t];if(!i)return e;const{deleted:s,total:n}=i;return s>0&&s===n?[...e,t]:e}),[]);return 0===h.length?e:i.deleteFragmentDefinitions(e,{include:h})})(s,t,d,a)},f=(e,t)=>i.isArray(e)&&r.isNumber(t)||i.isPlainObject(e)&&r.isString(t)?e[t]:void 0,g=e=>!!i.isObjectLike(e)&&(a.TYPE_NAME_KEY in e&&r.isString(e[a.TYPE_NAME_KEY]));var C,D,m,F;let E=(C=(e,t,i)=>{const s=i.value;s&&(i.value=async function(...e){return new Promise((t=>{(async()=>{const{debugManager:i,requestFieldCacheKey:n,...r}=e[3];if(!i)return void t(await s.apply(this,e));const c=i.now(),h=await s.apply(this,e),o=i.now(),d=o-c;t(h);const l={cacheType:e[0],context:r,options:e[2],requestHash:e[1],result:h,stats:{duration:d,endTime:o,startTime:c},...n?{decryptedCacheKey:n}:{}};i.log(a.CACHE_ENTRY_QUERIED,l)})()}))})},D=(e,t,i)=>{const s=i.value;s&&(i.value=async function(...e){return new Promise((t=>{(async()=>{const{debugManager:i,requestFieldCacheKey:n,...r}=e[5];if(!i)return await s.apply(this,e),void t();const c=i.now();await s.apply(this,e);const h=i.now(),o=h-c;t();const d={cacheType:e[0],cachemapOptions:e[3],context:r,options:e[4],requestHash:e[1],stats:{duration:o,endTime:h,startTime:c},value:e[2],...n?{decryptedCacheKey:n}:{}};i.log(a.CACHE_ENTRY_ADDED,d)})()}))})},m=(e,t,i)=>{const s=i.value;s&&(i.value=function(...e){const{debugManager:t,...i}=e[3];if(!t)return void s.apply(this,e);const n=t.now();s.apply(this,e);const r=t.now(),c=r-n;t.log(a.PARTIAL_QUERY_COMPILED,{context:i,options:e[2],requestHash:e[0],result:e[1],stats:{duration:c,endTime:r,startTime:n}})})},F=class t{static _countFieldPathChecklist(e){const t={missing:0,total:0};for(const[,a]of e){t.total+=a.length;const e=a.filter((({hasData:e})=>!e));t.missing+=e.length}return t}static _getFieldDataFromAncestor(e,t){const a=f(e,t);return i.isObjectLike(a)?r.cloneDeep(a):a}static _getOperationCacheControl(e,t){const a="no-cache";if(!e)return a;const i=e.get(t);return i?i.printCacheControl():a}static _isNodeEntity(e){if(!e)return!1;const{isEntity:t,possibleTypes:a}=e;return t||a.some((e=>!!e.isEntity))}static _isNodeRequestFieldPath(e){return!!e&&(this._isNodeEntity(e)||e.hasArguments||e.hasDirectives)}static _isValid(e){return!r.get(e,["metadata","cacheControl",c],!1)&&e.checkTTL()}static _mergeResponseCacheMetadata(e,t){return t?new Map([...t.cacheMetadata,...e]):e}static _setCachedData(e,{data:t},a){const s=t=>{(i.isArray(e)&&r.isNumber(a)||i.isPlainObject(e))&&(e[a]=t)};i.isObjectLike(t)||r.isUndefined(t)?i.isArray(t)?s([]):i.isPlainObject(t)&&s({}):s(t)}static _setCachedResponseData(e,{cacheMetadata:a,data:i,fieldPathChecklist:s},{propNameOrIndex:n,requestFieldPath:r},c,h,{operation:o}){t._setCacheMetadata(a,e.cacheability,r,o),t._setFieldPathChecklist(s,e,r,c),t._setCachedData(i,e,n)}static _setCacheMetadata(e,t,a,i){if(!t)return;e.set(a,t);const s=e.get(i);(!s||s.metadata.ttl>t.metadata.ttl)&&e.set(i,t)}static _setFieldPathChecklist(e,{data:t},a,{dataTypename:i,fieldTypename:s,fragmentKind:c,fragmentName:h}){if(r.isUndefined(s)||c===n.Kind.FRAGMENT_SPREAD){if(e.has(a))return;return void e.set(a,[{fragmentKind:c,fragmentName:h,hasData:!r.isUndefined(t)}])}if(i!==s)return;const o=e.get(a)??[];o.some((({typeName:e})=>e===i))||e.set(a,[...o,{fragmentKind:c,fragmentName:h,hasData:!r.isUndefined(t),typeName:i}])}constructor(t){e(this,"_cache",void 0),e(this,"_cascadeCacheControl",void 0),e(this,"_fallbackOperationCacheability",void 0),e(this,"_partialQueryResponses",new Map),e(this,"_responseChunksAwaitingCaching",new Map),e(this,"_typeCacheDirectives",void 0),e(this,"_typeIDKey",void 0);const s=[];if("cache"in t||s.push(new i.ArgsError("@graphql-box/cache-manager expected cache to be in options.")),t.typeCacheDirectives&&!i.isPlainObject(t.typeCacheDirectives)){const e="@graphql-box/cache-manager expected options.typeCacheDirectives to be a plain object.";s.push(new i.ArgsError(e))}if(s.length>0)throw new i.GroupedError("@graphql-box/cache-manager argument validation errors.",s);this._cache=t.cache,this._cascadeCacheControl=t.cascadeCacheControl??!1,this._fallbackOperationCacheability=t.fallbackOperationCacheability??c,this._typeCacheDirectives=t.typeCacheDirectives??{},this._typeIDKey=t.typeIDKey??a.DEFAULT_TYPE_ID_KEY}async analyzeQuery(e,t,a){const{ast:s,hash:c}=e,h={...a,fragmentDefinitions:i.getFragmentDefinitions(s),typeIDKey:this._typeIDKey},d=await this._retrieveCachedResponseData(e,t,h),{cacheMetadata:l,data:y,fieldCount:p}=d;if(p.missing===p.total||((e,t)=>o(e,t))(y,this._typeIDKey))return{updated:e};if(!p.missing){const e=this._setQueryResponseCacheEntry(c,{cacheMetadata:l,data:y},t,h);return t.awaitDataCaching&&await e,{response:{cacheMetadata:l,data:y}}}const u=_(e,d,h),f=n.print(u),{fragmentDefinitions:g,typeIDKey:C,...D}=h;return r.assign(a,{...D,filteredRequest:f}),this._setPartialQueryResponse(c,{cacheMetadata:l,data:y},t,a),{updated:{ast:u,hash:i.hashRequest(f),request:f}}}get cache(){return this._cache}async cacheQuery(e,t,a,s,n){const r={...n,fragmentDefinitions:i.getFragmentDefinitions((t??e).ast),typeIDKey:this._typeIDKey};return this._cacheResponse(e,t,a,s,r)}async cacheResponse(e,t,a,s){const n={...s,fragmentDefinitions:i.getFragmentDefinitions(e.ast),typeIDKey:this._typeIDKey};return this._cacheResponse(e,void 0,t,a,n)}async checkCacheEntry(e,t,a,i){return this._checkCacheEntry(e,t,a,i)}async checkQueryResponseCacheEntry(e,t,s){const n=await this._checkCacheEntry(a.QUERY_RESPONSES,e,t,s);if(!n)return!1;const{cacheMetadata:r,data:c}=n.entry;return{cacheMetadata:i.rehydrateCacheMetadata(r),data:c}}deletePartialQueryResponse(e){this._partialQueryResponses.delete(e)}async setQueryResponseCacheEntry(e,t,a,i){return this._setQueryResponseCacheEntry(e.hash,t,a,i)}async _analyzeFieldNode(e,t,a,s,n){await(i.hasChildFields(e,{fragmentDefinitions:n.fragmentDefinitions})?this._analyzeParentFieldNode(e,t,a,s,n):this._analyzeLeafFieldNode(e,t,a,s,n))}async _analyzeLeafFieldNode(e,a,s,n,r){const c=i.buildFieldKeysAndPaths(e,a,r),{hashedRequestFieldCacheKey:h,propNameOrIndex:o,requestFieldCacheKey:d,requestFieldPath:l}=c,y=r.fieldTypeMap.get(l),{entityData:p,fragmentKind:u,fragmentName:_,requestFieldPathData:f,typeName:C}=a,D={dataTypename:g(p)?p.__typename:g(f)?f.__typename:void 0,fieldTypename:C,fragmentKind:u,fragmentName:_};if(t._isNodeRequestFieldPath(y)){const{cacheability:e,entry:a}=await this._retrieveCachedRequestFieldPathData(h,d,n,r);t._setCachedResponseData({cacheability:e,data:a},s,c,D,n,r)}else{const e=t._getFieldDataFromAncestor(p,o)??t._getFieldDataFromAncestor(f,o);t._setFieldPathChecklist(s.fieldPathChecklist,{data:e},l,D),t._setCachedData(s.data,{data:e},o)}}async _analyzeParentFieldNode(e,s,n,c,h){const o=i.buildFieldKeysAndPaths(e,s,h),{propNameOrIndex:d,requestFieldCacheKey:l,requestFieldPath:y}=o,p=h.fieldTypeMap.get(y),{cacheability:u,data:_,entityData:g,requestFieldPathData:C}=await this._retrieveCachedParentNodeData(s,o,p,c,h),{fragmentKind:D,fragmentName:m,typeName:F}=s;if(t._setCachedResponseData({cacheability:u,data:_},n,o,{dataTypename:r.get(_,a.TYPE_NAME_KEY),fieldTypename:F,fragmentKind:D,fragmentName:m},c,h),!i.isObjectLike(_))return;const E=[];i.iterateChildFields(e,_,h.fragmentDefinitions,((e,t,a,i,s)=>{E.push(this._analyzeFieldNode(e,{cacheability:u,entityData:g,fragmentKind:a,fragmentName:i,index:s,requestFieldCacheKey:l,requestFieldPath:y,requestFieldPathData:C,typeName:t},{...n,data:f(n.data,d)},c,h))})),await Promise.all(E)}_buildCacheMetadata({ast:e},{data:t,...a},s,n){const r=this._createCacheMetadata({data:t,...a},n),c=i.getOperationDefinitions(e,n.operation)[0];if(!c)return r;const h=i.getChildFields(c);if(!h)return r;for(const{fieldNode:e}of h)this._setFieldCacheability(e,{requestFieldPath:n.operation},{cacheMetadata:r,data:t},s,n);return r}async _cacheResponse(e,a,i,s,c){const h=((e,t)=>{if(!t.normalizePatchResponseData)return e;const{data:a,paths:i,...s}=e;return i?.length&&r.isString(i[0])?{...s,data:r.set({},i[0],a),paths:i}:e})(i,c);let o=h;((e,t)=>t.hasDeferOrStream&&e.hasNext)(i,c)&&(this._setResponseChunksAwaitingCaching(h,c),o=void 0),((e,t)=>t.hasDeferOrStream&&!e.hasNext&&e.paths)(i,c)&&(o=this._retrieveResponseDataForCaching(h,c));const d=[];if(o){const{data:i}=o,l=this._buildCacheMetadata(e,o,s,c);let y,p;if(d.push(this._setEntityAndRequestFieldPathCacheEntries(e,{cacheMetadata:l,entityData:r.cloneDeep(i),requestFieldPathData:r.cloneDeep(i)},s,c)),c.operation===n.OperationTypeNode.QUERY){let n;c.queryFiltered&&a&&(d.push(this._setQueryResponseCacheEntry(a.hash,{cacheMetadata:l,data:i},s,c)),n=this._getPartialQueryResponse(e.hash)),y=t._mergeResponseCacheMetadata(l,n),p=this._mergeResponseData(i,n),d.push(this._setQueryResponseCacheEntry(e.hash,{cacheMetadata:y,data:p},s,c))}if(s.awaitDataCaching&&await Promise.all(d),((e,t)=>!t.hasDeferOrStream&&!e.hasNext&&!e.paths)(h,c)&&y&&p)return{cacheMetadata:y,data:p}}const{data:l,hasNext:y,paths:p}=h;return{cacheMetadata:this._buildCacheMetadata(e,h,s,c),data:l,hasNext:y,paths:p}}async _checkCacheEntry(e,a,i,s){try{const n=await this._hasCacheEntry(e,a);if(!n||!t._isValid(n))return!1;const c=await this._getCacheEntry(e,a,i,s);return!r.isUndefined(c)&&{cacheability:n,entry:c}}catch{return!1}}_createCacheMetadata({_cacheMetadata:e,headers:t},{operation:a}){const s=new Map,n=y({_cacheMetadata:e,fallback:this._fallbackOperationCacheability,headers:t});return s.set(a,n),e&&i.rehydrateCacheMetadata(e,s),s}async _getCacheEntry(e,t,a,i){return this._cache.get(`${e}::${t}`)}_getPartialQueryResponse(e){const t=this._partialQueryResponses.get(e);return this._partialQueryResponses.delete(e),t}async _hasCacheEntry(e,t){try{return await this._cache.has(`${e}::${t}`)}catch{return!1}}_isFieldEntity(e,{isEntity:t,possibleTypes:a}){return!(!i.isPlainObject(e)||!(this._typeIDKey in e))&&(!!t||0!==a.length&&a.some((t=>t.typeName===e.__typename)))}_mergeResponseData(e,t){return t?d(t.data,e,this._typeIDKey):e}async _parseEntityAndRequestFieldPathCacheEntryData(e,t,{cacheMetadata:a,entityData:s,requestFieldPathData:n},c,h){const o=i.buildFieldKeysAndPaths(e,t,h),{requestFieldCacheKey:d,requestFieldPath:l,responseDataPath:y}=o,p=r.get(n,y),u=h.fieldTypeMap.get(l);if(i.isObjectLike(p)||u?.hasDirectives){if(i.isObjectLike(p)){const t=[];i.iterateChildFields(e,p,h.fragmentDefinitions,((e,i,r,o,p)=>{t.push(this._parseEntityAndRequestFieldPathCacheEntryData(e,{index:p,requestFieldCacheKey:d,requestFieldPath:l,responseDataPath:y},{cacheMetadata:a,entityData:s,requestFieldPathData:n},c,h))})),await Promise.all(t)}await this._setEntityAndRequestFieldPathCacheEntry(e,o,{cacheMetadata:a,entityData:s,requestFieldPathData:n},c,h)}}async _retrieveCachedEntityData(e,{possibleTypes:t,typeName:i},s,n){const r=[...t.map((e=>e.typeName)),i],c=(await Promise.all(r.map((t=>this._checkCacheEntry(a.DATA_ENTITIES,`${t}::${e}`,s,n))))).filter((e=>!!e));let h;return 1===c.length?h=c[0]:c.length>1&&(c.sort((({cacheability:e},{cacheability:t})=>e.metadata.ttl-t.metadata.ttl)),h={cacheability:c[0].cacheability,entry:c.reduce(((e,{entry:t})=>d(e,t,this._typeIDKey)),{})}),h??{}}async _retrieveCachedParentNodeData({entityData:e,requestFieldPathData:a},{hashedRequestFieldCacheKey:s,propNameOrIndex:n,requestFieldCacheKey:c},h,o,d){let y,p=t._getFieldDataFromAncestor(e,n),u=t._getFieldDataFromAncestor(a,n);if(t._isNodeRequestFieldPath(h)){const{cacheability:e,entry:t}=await this._retrieveCachedRequestFieldPathData(s,c,o,d);u=l(u,t,this._typeIDKey),e&&(y=e)}const _=((e,{typeIDValue:t},a)=>t||(i.isPlainObject(e)?e[a]:void 0))(u,h,this._typeIDKey);if(t._isNodeEntity(h)&&_){const{cacheability:e,entry:t}=await this._retrieveCachedEntityData(_,h,o,d);p=l(p,t,this._typeIDKey),e&&(!y||e.metadata.ttl>y.metadata.ttl)&&(y=e)}return{cacheability:y,data:r.isEqual(p,u)?p:l(p,u,this._typeIDKey),entityData:p,requestFieldPathData:u}}async _retrieveCachedRequestFieldPathData(e,t,i,s){return await this._checkCacheEntry(a.REQUEST_FIELD_PATHS,e,i,{...s,requestFieldCacheKey:t})||{}}async _retrieveCachedResponseData({ast:e},a,s){const n={cacheMetadata:new Map,data:{},fieldCount:{missing:0,total:0},fieldPathChecklist:new Map},r=i.getOperationDefinitions(e,s.operation)[0];if(!r)return n;const c=i.getChildFields(r);return c?(await Promise.all(c.map((({fieldNode:e})=>this._analyzeFieldNode(e,{requestFieldPath:s.operation},n,a,s)))),n.fieldCount=t._countFieldPathChecklist(n.fieldPathChecklist),n):n}_retrieveResponseDataForCaching(e,t){const a=this._responseChunksAwaitingCaching.get(t.requestID);return this._responseChunksAwaitingCaching.delete(t.requestID),(i=[...a,e]).reduce(((e,t,a)=>{const{_cacheMetadata:s,data:n,hasNext:c,headers:h,paths:o}=t;return s&&(e._cacheMetadata=e._cacheMetadata?{...e._cacheMetadata,...s}:s),e.data=r.merge(e.data,n),0===a&&(e.headers=h),a===i.length-1&&(e.hasNext=c),o&&(e.paths||(e.paths=[]),e.paths.push(...o)),e}),{data:{}});var i}async _setCacheEntry(e,t,a,i,s,n){try{await this._cache.set(`${e}::${t}`,r.cloneDeep(a),i)}catch{}}async _setEntityAndRequestFieldPathCacheEntries(e,t,a,s){const n=i.getOperationDefinitions(e.ast,s.operation)[0];if(!n)return;const r=i.getChildFields(n);r&&await Promise.all(r.map((({fieldNode:e})=>this._parseEntityAndRequestFieldPathCacheEntryData(e,{requestFieldPath:s.operation},t,a,s))))}async _setEntityAndRequestFieldPathCacheEntry(e,t,{cacheMetadata:a,entityData:i,requestFieldPathData:s},n,c){const{requestFieldPath:h,responseDataPath:o}=t,d=r.get(i,o),l=c.fieldTypeMap.get(h),y=a.get(h);if(r.isUndefined(d)||!l||!y)return;const p=[];p.push(this._setRequestFieldPathCacheEntry(e,t,{cacheability:y,data:s,fieldTypeInfo:l},n,c));const u=this._isFieldEntity(d,l);!u&&l.hasArguments&&r.unset(i,o),u&&p.push(this._setEntityCacheEntry(t,{cacheability:y,data:i,fieldTypeInfo:l},n,c)),await Promise.all(p)}async _setEntityCacheEntry({responseDataPath:e},{cacheability:t,data:i,fieldTypeInfo:s},n,c){let h=r.get(i,e);const o=`${s.isEntity?s.typeName:h.__typename}::${String(h[this._typeIDKey])}`,l=await this._checkCacheEntry(a.DATA_ENTITIES,o,n,c);l&&(h=d(l.entry,h,this._typeIDKey)),await this._setCacheEntry(a.DATA_ENTITIES,o,h,{cacheHeaders:{cacheControl:t.printCacheControl()},tag:n.tag},n,c),r.set(i,e,{__cacheKey:`${a.DATA_ENTITIES}::${o}`})}_setFieldCacheability(e,t,{cacheMetadata:a,data:s},n,c){const{requestFieldPath:h}=t,o=i.buildFieldKeysAndPaths(e,t,c),{requestFieldPath:d,responseDataPath:l}=o;if(!i.isObjectLike(s))return;const y=r.get(s,l),p=c.fieldTypeMap.get(d);(i.isObjectLike(y)||p?.hasDirectives)&&(this._setFieldTypeCacheDirective(a,{ancestorRequestFieldPath:h,requestFieldPath:d},c),i.isObjectLike(y)&&i.iterateChildFields(e,y,c.fragmentDefinitions,((e,t,i,r,h)=>{this._setFieldCacheability(e,{index:h,requestFieldPath:d,responseDataPath:l},{cacheMetadata:a,data:s},n,c)})))}_setFieldTypeCacheDirective(e,{ancestorRequestFieldPath:a,requestFieldPath:i},{fieldTypeMap:n,operation:r}){if(e.has(i))return;const c=n.get(i);if(c&&this._typeCacheDirectives[c.typeName]){const a=new s.Cacheability({cacheControl:this._typeCacheDirectives[c.typeName]});t._setCacheMetadata(e,a,i,r)}else this._cascadeCacheControl&&a&&t._setCacheMetadata(e,e.get(a),i,r)}_setPartialQueryResponse(e,t,a,i){this._partialQueryResponses.set(e,t)}async _setQueryResponseCacheEntry(e,{cacheMetadata:s,data:n},r,c){const h=i.dehydrateCacheMetadata(s),o=t._getOperationCacheControl(s,c.operation);await this._setCacheEntry(a.QUERY_RESPONSES,e,{cacheMetadata:h,data:n},{cacheHeaders:{cacheControl:o},tag:r.tag},r,c)}async _setRequestFieldPathCacheEntry(e,t,{cacheability:s,data:c,fieldTypeInfo:h},o,l){const{hashedRequestFieldCacheKey:y,requestFieldCacheKey:p,responseDataPath:u}=t;let _=r.get(c,u);const f=this._isFieldEntity(_,h),g=h.hasArguments||h.hasDirectives;if(l.operation===n.OperationTypeNode.QUERY&&(f||g)){i.isPlainObject(_)&&e.selectionSet?.selections&&(_=((e,t,a,s)=>{const n=i.resolveFragments(t,s.fragmentDefinitions);return r.keys(e).reduce(((t,r)=>{const c=n.find((({fieldNode:e})=>i.getName(e)===r));if(c){const{requestFieldPath:n}=i.buildFieldKeysAndPaths(c.fieldNode,a,s),h=s.fieldTypeMap.get(n);h?.hasArguments||h?.hasDirectives||(t[r]=e[r])}return t}),{})})(_,e.selectionSet.selections,t,l));const n=await this._checkCacheEntry(a.REQUEST_FIELD_PATHS,y,o,{...l,requestFieldCacheKey:p});n&&i.isObjectLike(n.entry)&&i.isObjectLike(_)&&(_=d(n.entry,_,this._typeIDKey)),await this._setCacheEntry(a.REQUEST_FIELD_PATHS,y,_,{cacheHeaders:{cacheControl:s.printCacheControl()},tag:o.tag},o,{...l,requestFieldCacheKey:p}),i.hasChildFields(e,{fragmentDefinitions:l.fragmentDefinitions})&&(f?r.set(c,u,{__cacheKey:`${a.REQUEST_FIELD_PATHS}::${y}`}):r.unset(c,u))}}_setResponseChunksAwaitingCaching(e,t){const a=this._responseChunksAwaitingCaching.get(t.requestID);a?this._responseChunksAwaitingCaching.set(t.requestID,[...a,e]):this._responseChunksAwaitingCaching.set(t.requestID,[e])}},t(F.prototype,"_getCacheEntry",[C],Object.getOwnPropertyDescriptor(F.prototype,"_getCacheEntry"),F.prototype),t(F.prototype,"_setCacheEntry",[D],Object.getOwnPropertyDescriptor(F.prototype,"_setCacheEntry"),F.prototype),t(F.prototype,"_setPartialQueryResponse",[m],Object.getOwnPropertyDescriptor(F.prototype,"_setPartialQueryResponse"),F.prototype),F);exports.CacheManager=E;
|
|
1477
2
|
//# sourceMappingURL=index.cjs.map
|