@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.
@@ -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