@graphql-box/cache-manager 5.0.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/production.analysis.txt +125 -96
- package/dist/types/cjs/helpers/createEntityDataKey.d.cts +4 -0
- package/dist/types/cjs/helpers/createEntityDataKey.d.cts.map +1 -0
- package/dist/types/cjs/helpers/filterOutPropsWithEntityArgsOrDirectives.d.cts +5 -0
- package/dist/types/cjs/helpers/filterOutPropsWithEntityArgsOrDirectives.d.cts.map +1 -0
- package/dist/types/cjs/helpers/filterOutPropsWithEntityOrArgs.d.cts +6 -0
- package/dist/types/cjs/helpers/filterOutPropsWithEntityOrArgs.d.cts.map +1 -0
- package/dist/types/cjs/helpers/isFieldEntity.d.cts +3 -0
- package/dist/types/cjs/helpers/isFieldEntity.d.cts.map +1 -0
- package/dist/types/cjs/helpers/validTypeIdValue.d.cts +1 -1
- package/dist/types/cjs/helpers/validTypeIdValue.d.cts.map +1 -1
- package/dist/types/cjs/main.d.cts +3 -5
- package/dist/types/cjs/main.d.cts.map +1 -1
- package/dist/types/cjs/types.d.cts +5 -5
- package/dist/types/cjs/types.d.cts.map +1 -1
- package/dist/types/esm/helpers/createEntityDataKey.d.ts +4 -0
- package/dist/types/esm/helpers/createEntityDataKey.d.ts.map +1 -0
- package/dist/types/esm/helpers/filterOutPropsWithEntityArgsOrDirectives.d.ts +5 -0
- package/dist/types/esm/helpers/filterOutPropsWithEntityArgsOrDirectives.d.ts.map +1 -0
- package/dist/types/esm/helpers/filterOutPropsWithEntityOrArgs.d.ts +6 -0
- package/dist/types/esm/helpers/filterOutPropsWithEntityOrArgs.d.ts.map +1 -0
- package/dist/types/esm/helpers/isFieldEntity.d.ts +3 -0
- package/dist/types/esm/helpers/isFieldEntity.d.ts.map +1 -0
- package/dist/types/esm/helpers/validTypeIdValue.d.ts +1 -1
- package/dist/types/esm/helpers/validTypeIdValue.d.ts.map +1 -1
- package/dist/types/esm/main.d.ts +3 -5
- package/dist/types/esm/main.d.ts.map +1 -1
- package/dist/types/esm/types.d.ts +5 -5
- package/dist/types/esm/types.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/__snapshots__/index.test.ts.snap +19450 -19450
- package/src/helpers/createEntityDataKey.ts +11 -0
- package/src/helpers/filterOutPropsWithEntityArgsOrDirectives.ts +45 -0
- package/src/helpers/filterOutPropsWithEntityOrArgs.ts +31 -0
- package/src/helpers/isFieldEntity.ts +24 -0
- package/src/helpers/validTypeIdValue.ts +3 -3
- package/src/index.test.ts +153 -127
- package/src/main.ts +122 -179
- package/src/types.ts +5 -5
- package/dist/types/cjs/helpers/filterOutPropsWithArgsOrDirectives.d.cts +0 -6
- package/dist/types/cjs/helpers/filterOutPropsWithArgsOrDirectives.d.cts.map +0 -1
- package/dist/types/esm/helpers/filterOutPropsWithArgsOrDirectives.d.ts +0 -6
- package/dist/types/esm/helpers/filterOutPropsWithArgsOrDirectives.d.ts.map +0 -1
- package/src/helpers/filterOutPropsWithArgsOrDirectives.ts +0 -29
package/src/main.ts
CHANGED
|
@@ -36,16 +36,19 @@ import {
|
|
|
36
36
|
} from '@graphql-box/helpers';
|
|
37
37
|
import { Cacheability } from 'cacheability';
|
|
38
38
|
import { type FieldNode, Kind, OperationTypeNode, print } from 'graphql';
|
|
39
|
-
import { assign,
|
|
39
|
+
import { assign, get, isEqual, isNumber, isUndefined, set, unset } from 'lodash-es';
|
|
40
40
|
import { CACHE_CONTROL, HEADER_NO_CACHE, METADATA, NO_CACHE } from './constants.ts';
|
|
41
41
|
import { logCacheEntry, logCacheQuery, logPartialCompiled } from './debug/index.ts';
|
|
42
42
|
import { areOnlyPopulatedFieldsTypeIdKeys } from './helpers/areOnlyPopulatedFieldsTypeIdKeys.ts';
|
|
43
43
|
import { combineDataSets } from './helpers/combineData.ts';
|
|
44
|
+
import { createEntityDataKey } from './helpers/createEntityDataKey.ts';
|
|
44
45
|
import { deriveOpCacheability } from './helpers/deriveOpCacheability.ts';
|
|
45
|
-
import {
|
|
46
|
+
import { filterOutPropsWithEntityArgsOrDirectives } from './helpers/filterOutPropsWithEntityArgsOrDirectives.ts';
|
|
47
|
+
import { filterOutPropsWithEntityOrArgs } from './helpers/filterOutPropsWithEntityOrArgs.ts';
|
|
46
48
|
import { filterQuery } from './helpers/filterQuery.ts';
|
|
47
49
|
import { getDataValue } from './helpers/getDataValue.ts';
|
|
48
50
|
import { hasTypename } from './helpers/hasTypename.ts';
|
|
51
|
+
import { isFieldEntity } from './helpers/isFieldEntity.ts';
|
|
49
52
|
import { isLastResponseChunk } from './helpers/isLastResponseChunk.ts';
|
|
50
53
|
import { isNotLastResponseChunk } from './helpers/isNotLastResponseChunk.ts';
|
|
51
54
|
import { isNotResponseChunk } from './helpers/isNotResponseChunk.ts';
|
|
@@ -88,7 +91,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
88
91
|
|
|
89
92
|
private static _getFieldDataFromAncestor<T>(ancestorFieldData: unknown, propNameOrIndex: string | number) {
|
|
90
93
|
const dataValue = getDataValue<T>(ancestorFieldData, propNameOrIndex);
|
|
91
|
-
return isObjectLike(dataValue) ?
|
|
94
|
+
return isObjectLike(dataValue) ? structuredClone(dataValue) : dataValue;
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
private static _getOperationCacheControl(cacheMetadata: CacheMetadata | undefined, operation: string): string {
|
|
@@ -276,12 +279,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
276
279
|
}
|
|
277
280
|
|
|
278
281
|
if (!fieldCount.missing) {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (options.awaitDataCaching) {
|
|
282
|
-
await dataCaching;
|
|
283
|
-
}
|
|
284
|
-
|
|
282
|
+
this._setQueryResponseCacheEntry(hash, { cacheMetadata, data }, options, cacheManagerContext);
|
|
285
283
|
return { response: { cacheMetadata, data } };
|
|
286
284
|
}
|
|
287
285
|
|
|
@@ -300,13 +298,13 @@ export class CacheManager implements CacheManagerDef {
|
|
|
300
298
|
return this._cache;
|
|
301
299
|
}
|
|
302
300
|
|
|
303
|
-
public
|
|
301
|
+
public cacheQuery(
|
|
304
302
|
requestData: RequestData,
|
|
305
303
|
updatedRequestData: RequestData | undefined,
|
|
306
304
|
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
307
305
|
options: RequestOptions,
|
|
308
306
|
context: RequestContext
|
|
309
|
-
):
|
|
307
|
+
): ResponseData {
|
|
310
308
|
const cacheManagerContext: CacheManagerContext = {
|
|
311
309
|
...context,
|
|
312
310
|
fragmentDefinitions: getFragmentDefinitions((updatedRequestData ?? requestData).ast),
|
|
@@ -316,12 +314,12 @@ export class CacheManager implements CacheManagerDef {
|
|
|
316
314
|
return this._cacheResponse(requestData, updatedRequestData, rawResponseData, options, cacheManagerContext);
|
|
317
315
|
}
|
|
318
316
|
|
|
319
|
-
public
|
|
317
|
+
public cacheResponse(
|
|
320
318
|
requestData: RequestData,
|
|
321
319
|
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
322
320
|
options: RequestOptions,
|
|
323
321
|
context: RequestContext
|
|
324
|
-
):
|
|
322
|
+
): ResponseData {
|
|
325
323
|
const cacheManagerContext: CacheManagerContext = {
|
|
326
324
|
...context,
|
|
327
325
|
fragmentDefinitions: getFragmentDefinitions(requestData.ast),
|
|
@@ -363,13 +361,13 @@ export class CacheManager implements CacheManagerDef {
|
|
|
363
361
|
this._partialQueryResponses.delete(hash);
|
|
364
362
|
}
|
|
365
363
|
|
|
366
|
-
public
|
|
364
|
+
public setQueryResponseCacheEntry(
|
|
367
365
|
requestData: RequestData,
|
|
368
366
|
responseData: ResponseData,
|
|
369
367
|
options: RequestOptions,
|
|
370
368
|
context: CacheManagerContext
|
|
371
|
-
):
|
|
372
|
-
|
|
369
|
+
): void {
|
|
370
|
+
this._setQueryResponseCacheEntry(requestData.hash, responseData, options, context);
|
|
373
371
|
}
|
|
374
372
|
|
|
375
373
|
private async _analyzeFieldNode(
|
|
@@ -450,7 +448,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
450
448
|
): Promise<void> {
|
|
451
449
|
const keysAndPaths = buildFieldKeysAndPaths(fieldNode, cachedAncestorFieldData, context);
|
|
452
450
|
const { propNameOrIndex, requestFieldCacheKey, requestFieldPath } = keysAndPaths;
|
|
453
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath)
|
|
451
|
+
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
454
452
|
|
|
455
453
|
const { cacheability, data, entityData, requestFieldPathData } = await this._retrieveCachedParentNodeData(
|
|
456
454
|
cachedAncestorFieldData,
|
|
@@ -553,13 +551,13 @@ export class CacheManager implements CacheManagerDef {
|
|
|
553
551
|
return cacheMetadata;
|
|
554
552
|
}
|
|
555
553
|
|
|
556
|
-
private
|
|
554
|
+
private _cacheResponse(
|
|
557
555
|
requestData: RequestData,
|
|
558
556
|
updatedRequestData: RequestData | undefined,
|
|
559
557
|
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
560
558
|
options: RequestOptions,
|
|
561
559
|
context: CacheManagerContext
|
|
562
|
-
):
|
|
560
|
+
): ResponseData {
|
|
563
561
|
const normalizedResponseData = normalizePatchResponseData(rawResponseData, context);
|
|
564
562
|
let responseDataForCaching: RawResponseDataWithMaybeCacheMetadata | undefined = normalizedResponseData;
|
|
565
563
|
|
|
@@ -572,24 +570,22 @@ export class CacheManager implements CacheManagerDef {
|
|
|
572
570
|
responseDataForCaching = this._retrieveResponseDataForCaching(normalizedResponseData, context);
|
|
573
571
|
}
|
|
574
572
|
|
|
575
|
-
const dataCaching: Promise<void>[] = [];
|
|
576
|
-
|
|
577
573
|
if (responseDataForCaching) {
|
|
578
574
|
const { data } = responseDataForCaching;
|
|
579
575
|
const cacheMetadata = this._buildCacheMetadata(requestData, responseDataForCaching, options, context);
|
|
580
576
|
|
|
581
|
-
|
|
577
|
+
void new Promise(() => {
|
|
582
578
|
this._setEntityAndRequestFieldPathCacheEntries(
|
|
583
579
|
requestData,
|
|
584
580
|
{
|
|
585
581
|
cacheMetadata,
|
|
586
|
-
entityData:
|
|
587
|
-
requestFieldPathData:
|
|
582
|
+
entityData: structuredClone(data),
|
|
583
|
+
requestFieldPathData: structuredClone(data),
|
|
588
584
|
},
|
|
589
585
|
options,
|
|
590
586
|
context
|
|
591
|
-
)
|
|
592
|
-
);
|
|
587
|
+
);
|
|
588
|
+
});
|
|
593
589
|
|
|
594
590
|
let queryCacheMetadata: CacheMetadata | undefined;
|
|
595
591
|
let queryData: PlainData | undefined;
|
|
@@ -598,30 +594,21 @@ export class CacheManager implements CacheManagerDef {
|
|
|
598
594
|
let partialQueryResponse: PartialQueryResponse | undefined;
|
|
599
595
|
|
|
600
596
|
if (context.queryFiltered && updatedRequestData) {
|
|
601
|
-
|
|
602
|
-
this._setQueryResponseCacheEntry(updatedRequestData.hash, { cacheMetadata, data }, options, context)
|
|
603
|
-
);
|
|
604
|
-
|
|
597
|
+
this._setQueryResponseCacheEntry(updatedRequestData.hash, { cacheMetadata, data }, options, context);
|
|
605
598
|
partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
|
|
606
599
|
}
|
|
607
600
|
|
|
608
601
|
queryCacheMetadata = CacheManager._mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse);
|
|
609
602
|
queryData = this._mergeResponseData(data, partialQueryResponse);
|
|
610
603
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
context
|
|
617
|
-
)
|
|
604
|
+
this._setQueryResponseCacheEntry(
|
|
605
|
+
requestData.hash,
|
|
606
|
+
{ cacheMetadata: queryCacheMetadata, data: queryData },
|
|
607
|
+
options,
|
|
608
|
+
context
|
|
618
609
|
);
|
|
619
610
|
}
|
|
620
611
|
|
|
621
|
-
if (options.awaitDataCaching) {
|
|
622
|
-
await Promise.all(dataCaching);
|
|
623
|
-
}
|
|
624
|
-
|
|
625
612
|
if (isNotResponseChunk(normalizedResponseData, context) && queryCacheMetadata && queryData) {
|
|
626
613
|
return {
|
|
627
614
|
cacheMetadata: queryCacheMetadata,
|
|
@@ -710,22 +697,6 @@ export class CacheManager implements CacheManagerDef {
|
|
|
710
697
|
}
|
|
711
698
|
}
|
|
712
699
|
|
|
713
|
-
private _isFieldEntity(fieldData: unknown, { isEntity, possibleTypes }: FieldTypeInfo): boolean {
|
|
714
|
-
if (!isPlainObject(fieldData) || !(this._typeIDKey in fieldData)) {
|
|
715
|
-
return false;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
if (isEntity) {
|
|
719
|
-
return true;
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
if (possibleTypes.length === 0) {
|
|
723
|
-
return false;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
return possibleTypes.some(type => type.typeName === fieldData.__typename);
|
|
727
|
-
}
|
|
728
|
-
|
|
729
700
|
private _mergeResponseData(responseData: PlainData, partialQueryResponse?: PartialQueryResponse): PlainData {
|
|
730
701
|
if (!partialQueryResponse) {
|
|
731
702
|
return responseData;
|
|
@@ -734,25 +705,24 @@ export class CacheManager implements CacheManagerDef {
|
|
|
734
705
|
return mergeDataSets(partialQueryResponse.data, responseData, this._typeIDKey);
|
|
735
706
|
}
|
|
736
707
|
|
|
737
|
-
private
|
|
708
|
+
private _parseEntityAndRequestFieldPathCacheEntryData(
|
|
738
709
|
field: FieldNode,
|
|
739
710
|
ancestorKeysAndPaths: AncestorKeysAndPaths,
|
|
740
711
|
{ cacheMetadata, entityData, requestFieldPathData }: ResponseDataForCaching,
|
|
741
712
|
options: RequestOptions,
|
|
742
713
|
context: CacheManagerContext
|
|
743
|
-
):
|
|
714
|
+
): void {
|
|
744
715
|
const keysAndPaths = buildFieldKeysAndPaths(field, ancestorKeysAndPaths, context);
|
|
745
|
-
const { requestFieldCacheKey, requestFieldPath, responseDataPath } = keysAndPaths;
|
|
716
|
+
const { hashedRequestFieldCacheKey, requestFieldCacheKey, requestFieldPath, responseDataPath } = keysAndPaths;
|
|
746
717
|
const fieldData = get(requestFieldPathData, responseDataPath) as unknown;
|
|
747
718
|
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
719
|
+
const cacheability = cacheMetadata.get(requestFieldPath);
|
|
748
720
|
|
|
749
721
|
if (!isObjectLike(fieldData) && !fieldTypeInfo?.hasDirectives) {
|
|
750
722
|
return;
|
|
751
723
|
}
|
|
752
724
|
|
|
753
725
|
if (isObjectLike(fieldData)) {
|
|
754
|
-
const promises: Promise<void>[] = [];
|
|
755
|
-
|
|
756
726
|
iterateChildFields(
|
|
757
727
|
field,
|
|
758
728
|
fieldData,
|
|
@@ -764,41 +734,81 @@ export class CacheManager implements CacheManagerDef {
|
|
|
764
734
|
_fragmentName: string | undefined,
|
|
765
735
|
childIndex?: number
|
|
766
736
|
) => {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
context
|
|
774
|
-
)
|
|
737
|
+
this._parseEntityAndRequestFieldPathCacheEntryData(
|
|
738
|
+
childField,
|
|
739
|
+
{ index: childIndex, requestFieldCacheKey, requestFieldPath, responseDataPath },
|
|
740
|
+
{ cacheMetadata, entityData, requestFieldPathData },
|
|
741
|
+
options,
|
|
742
|
+
context
|
|
775
743
|
);
|
|
776
744
|
}
|
|
777
745
|
);
|
|
746
|
+
}
|
|
778
747
|
|
|
779
|
-
|
|
748
|
+
if (isUndefined(fieldData) || !fieldTypeInfo || !cacheability) {
|
|
749
|
+
return;
|
|
780
750
|
}
|
|
781
751
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
752
|
+
const isEntity = isFieldEntity(fieldData, fieldTypeInfo, this._typeIDKey);
|
|
753
|
+
const hasArgsOrDirectives = !!fieldTypeInfo.hasArguments || !!fieldTypeInfo.hasDirectives;
|
|
754
|
+
|
|
755
|
+
if (context.operation === OperationTypeNode.QUERY && (isEntity || hasArgsOrDirectives)) {
|
|
756
|
+
void this._setRequestFieldPathCacheEntry(
|
|
757
|
+
keysAndPaths,
|
|
758
|
+
{
|
|
759
|
+
cacheability,
|
|
760
|
+
fieldData: filterOutPropsWithEntityArgsOrDirectives(structuredClone(fieldData), field, keysAndPaths, context),
|
|
761
|
+
fieldTypeInfo,
|
|
762
|
+
},
|
|
763
|
+
options,
|
|
764
|
+
context
|
|
765
|
+
);
|
|
766
|
+
|
|
767
|
+
if (hasChildFields(field, { fragmentDefinitions: context.fragmentDefinitions })) {
|
|
768
|
+
if (isEntity) {
|
|
769
|
+
set(requestFieldPathData, responseDataPath, {
|
|
770
|
+
__cacheKey: `${REQUEST_FIELD_PATHS}::${hashedRequestFieldCacheKey}`,
|
|
771
|
+
});
|
|
772
|
+
} else {
|
|
773
|
+
unset(requestFieldPathData, responseDataPath);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
if (isEntity) {
|
|
779
|
+
void this._setEntityCacheEntry(
|
|
780
|
+
{
|
|
781
|
+
cacheability,
|
|
782
|
+
fieldData: filterOutPropsWithEntityOrArgs(
|
|
783
|
+
structuredClone(get(entityData, responseDataPath)) as EntityData,
|
|
784
|
+
field,
|
|
785
|
+
keysAndPaths,
|
|
786
|
+
context
|
|
787
|
+
),
|
|
788
|
+
fieldTypeInfo,
|
|
789
|
+
},
|
|
790
|
+
options,
|
|
791
|
+
context
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
set(entityData, responseDataPath, {
|
|
795
|
+
__cacheKey: `${DATA_ENTITIES}::${createEntityDataKey(fieldData, fieldTypeInfo, context)}`,
|
|
796
|
+
});
|
|
797
|
+
}
|
|
789
798
|
}
|
|
790
799
|
|
|
791
800
|
private async _retrieveCachedEntityData(
|
|
792
801
|
validTypeIDValue: string | number,
|
|
793
|
-
|
|
802
|
+
fieldTypeInfo: FieldTypeInfo | undefined,
|
|
794
803
|
options: RequestOptions,
|
|
795
804
|
context: CacheManagerContext
|
|
796
805
|
): Promise<Partial<CheckCacheEntryResult<EntityData>>> {
|
|
806
|
+
const { possibleTypes = [], typeName } = fieldTypeInfo ?? {};
|
|
797
807
|
const typeNames = [...possibleTypes.map(type => type.typeName), typeName];
|
|
798
808
|
|
|
799
809
|
const checkResults = await Promise.all(
|
|
800
810
|
typeNames.map(name =>
|
|
801
|
-
this._checkCacheEntry<EntityData>(DATA_ENTITIES, `${name}::${validTypeIDValue}`, options, context)
|
|
811
|
+
this._checkCacheEntry<EntityData>(DATA_ENTITIES, `${String(name)}::${validTypeIDValue}`, options, context)
|
|
802
812
|
)
|
|
803
813
|
);
|
|
804
814
|
|
|
@@ -825,7 +835,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
825
835
|
private async _retrieveCachedParentNodeData(
|
|
826
836
|
{ entityData: ancestorEntityData, requestFieldPathData: ancestorRequestFieldPathData }: CachedAncestorFieldData,
|
|
827
837
|
{ hashedRequestFieldCacheKey, propNameOrIndex, requestFieldCacheKey }: KeysAndPaths,
|
|
828
|
-
fieldTypeInfo: FieldTypeInfo,
|
|
838
|
+
fieldTypeInfo: FieldTypeInfo | undefined,
|
|
829
839
|
options: RequestOptions,
|
|
830
840
|
context: CacheManagerContext
|
|
831
841
|
) {
|
|
@@ -942,18 +952,18 @@ export class CacheManager implements CacheManagerDef {
|
|
|
942
952
|
_context: CacheManagerContext & { requestFieldCacheKey?: string }
|
|
943
953
|
): Promise<void> {
|
|
944
954
|
try {
|
|
945
|
-
await this._cache.set(`${cacheType}::${hash}`,
|
|
955
|
+
await this._cache.set(`${cacheType}::${hash}`, value, cachemapOptions);
|
|
946
956
|
} catch {
|
|
947
957
|
// no catch
|
|
948
958
|
}
|
|
949
959
|
}
|
|
950
960
|
|
|
951
|
-
private
|
|
961
|
+
private _setEntityAndRequestFieldPathCacheEntries(
|
|
952
962
|
requestData: RequestData,
|
|
953
963
|
responseData: ResponseDataForCaching,
|
|
954
964
|
options: RequestOptions,
|
|
955
965
|
context: CacheManagerContext
|
|
956
|
-
):
|
|
966
|
+
): void {
|
|
957
967
|
const operationNode = getOperationDefinitions(requestData.ast, context.operation)[0];
|
|
958
968
|
|
|
959
969
|
if (!operationNode) {
|
|
@@ -966,69 +976,22 @@ export class CacheManager implements CacheManagerDef {
|
|
|
966
976
|
return;
|
|
967
977
|
}
|
|
968
978
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
responseData,
|
|
975
|
-
options,
|
|
976
|
-
context
|
|
977
|
-
);
|
|
978
|
-
})
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
private async _setEntityAndRequestFieldPathCacheEntry(
|
|
983
|
-
field: FieldNode,
|
|
984
|
-
keysAndPaths: KeysAndPaths,
|
|
985
|
-
{ cacheMetadata, entityData, requestFieldPathData }: ResponseDataForCaching,
|
|
986
|
-
options: RequestOptions,
|
|
987
|
-
context: CacheManagerContext
|
|
988
|
-
) {
|
|
989
|
-
const { requestFieldPath, responseDataPath } = keysAndPaths;
|
|
990
|
-
const fieldData = get(entityData, responseDataPath) as unknown;
|
|
991
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
992
|
-
const cacheability = cacheMetadata.get(requestFieldPath);
|
|
993
|
-
|
|
994
|
-
if (isUndefined(fieldData) || !fieldTypeInfo || !cacheability) {
|
|
995
|
-
return;
|
|
996
|
-
}
|
|
997
|
-
|
|
998
|
-
const promises: Promise<void>[] = [];
|
|
999
|
-
|
|
1000
|
-
promises.push(
|
|
1001
|
-
this._setRequestFieldPathCacheEntry(
|
|
1002
|
-
field,
|
|
1003
|
-
keysAndPaths,
|
|
1004
|
-
{ cacheability, data: requestFieldPathData, fieldTypeInfo },
|
|
979
|
+
fieldsAndTypeNames.map(({ fieldNode }) => {
|
|
980
|
+
this._parseEntityAndRequestFieldPathCacheEntryData(
|
|
981
|
+
fieldNode,
|
|
982
|
+
{ requestFieldPath: context.operation },
|
|
983
|
+
responseData,
|
|
1005
984
|
options,
|
|
1006
985
|
context
|
|
1007
|
-
)
|
|
1008
|
-
);
|
|
1009
|
-
|
|
1010
|
-
const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
|
|
1011
|
-
|
|
1012
|
-
if (!isEntity && fieldTypeInfo.hasArguments) {
|
|
1013
|
-
unset(entityData, responseDataPath);
|
|
1014
|
-
}
|
|
1015
|
-
|
|
1016
|
-
if (isEntity) {
|
|
1017
|
-
promises.push(
|
|
1018
|
-
this._setEntityCacheEntry(keysAndPaths, { cacheability, data: entityData, fieldTypeInfo }, options, context)
|
|
1019
986
|
);
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
await Promise.all(promises);
|
|
987
|
+
});
|
|
1023
988
|
}
|
|
1024
989
|
|
|
1025
990
|
private async _setEntityCacheEntry(
|
|
1026
|
-
{
|
|
1027
|
-
{ cacheability, data, fieldTypeInfo }: DataForCachingEntry,
|
|
991
|
+
{ cacheability, fieldData, fieldTypeInfo }: DataForCachingEntry<EntityData>,
|
|
1028
992
|
options: RequestOptions,
|
|
1029
993
|
context: CacheManagerContext
|
|
1030
994
|
) {
|
|
1031
|
-
let fieldData = get(data, responseDataPath) as EntityData;
|
|
1032
995
|
const fieldTypeName = fieldTypeInfo.isEntity ? fieldTypeInfo.typeName : fieldData.__typename;
|
|
1033
996
|
const entityDataKey = `${fieldTypeName}::${String(fieldData[this._typeIDKey])}`;
|
|
1034
997
|
const result = await this._checkCacheEntry<EntityData>(DATA_ENTITIES, entityDataKey, options, context);
|
|
@@ -1037,7 +1000,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1037
1000
|
fieldData = mergeDataSets(result.entry, fieldData, this._typeIDKey);
|
|
1038
1001
|
}
|
|
1039
1002
|
|
|
1040
|
-
|
|
1003
|
+
void this._setCacheEntry(
|
|
1041
1004
|
DATA_ENTITIES,
|
|
1042
1005
|
entityDataKey,
|
|
1043
1006
|
fieldData,
|
|
@@ -1045,8 +1008,6 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1045
1008
|
options,
|
|
1046
1009
|
context
|
|
1047
1010
|
);
|
|
1048
|
-
|
|
1049
|
-
set(data, responseDataPath, { __cacheKey: `${DATA_ENTITIES}::${entityDataKey}` });
|
|
1050
1011
|
}
|
|
1051
1012
|
|
|
1052
1013
|
private _setFieldCacheability(
|
|
@@ -1131,16 +1092,16 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1131
1092
|
this._partialQueryResponses.set(hash, partialQueryResponse);
|
|
1132
1093
|
}
|
|
1133
1094
|
|
|
1134
|
-
private
|
|
1095
|
+
private _setQueryResponseCacheEntry(
|
|
1135
1096
|
hash: string,
|
|
1136
1097
|
{ cacheMetadata, data }: ResponseData,
|
|
1137
1098
|
options: RequestOptions,
|
|
1138
1099
|
context: CacheManagerContext
|
|
1139
|
-
):
|
|
1100
|
+
): void {
|
|
1140
1101
|
const dehydratedCacheMetadata = dehydrateCacheMetadata(cacheMetadata);
|
|
1141
1102
|
const cacheControl = CacheManager._getOperationCacheControl(cacheMetadata, context.operation);
|
|
1142
1103
|
|
|
1143
|
-
|
|
1104
|
+
void this._setCacheEntry(
|
|
1144
1105
|
QUERY_RESPONSES,
|
|
1145
1106
|
hash,
|
|
1146
1107
|
{ cacheMetadata: dehydratedCacheMetadata, data },
|
|
@@ -1151,48 +1112,30 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1151
1112
|
}
|
|
1152
1113
|
|
|
1153
1114
|
private async _setRequestFieldPathCacheEntry(
|
|
1154
|
-
field: FieldNode,
|
|
1155
1115
|
keysAndPaths: KeysAndPaths,
|
|
1156
|
-
{ cacheability,
|
|
1116
|
+
{ cacheability, fieldData }: DataForCachingEntry,
|
|
1157
1117
|
options: RequestOptions,
|
|
1158
1118
|
context: CacheManagerContext
|
|
1159
1119
|
): Promise<void> {
|
|
1160
|
-
const { hashedRequestFieldCacheKey, requestFieldCacheKey
|
|
1161
|
-
let fieldData = get(data, responseDataPath) as unknown;
|
|
1162
|
-
const isEntity = this._isFieldEntity(fieldData, fieldTypeInfo);
|
|
1163
|
-
const hasArgsOrDirectives = fieldTypeInfo.hasArguments || fieldTypeInfo.hasDirectives;
|
|
1120
|
+
const { hashedRequestFieldCacheKey, requestFieldCacheKey } = keysAndPaths;
|
|
1164
1121
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
const result = await this._checkCacheEntry(REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, options, {
|
|
1171
|
-
...context,
|
|
1172
|
-
requestFieldCacheKey,
|
|
1173
|
-
});
|
|
1174
|
-
|
|
1175
|
-
if (result && isObjectLike(result.entry) && isObjectLike(fieldData)) {
|
|
1176
|
-
fieldData = mergeDataSets(result.entry, fieldData, this._typeIDKey);
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
await this._setCacheEntry(
|
|
1180
|
-
REQUEST_FIELD_PATHS,
|
|
1181
|
-
hashedRequestFieldCacheKey,
|
|
1182
|
-
fieldData,
|
|
1183
|
-
{ cacheHeaders: { cacheControl: cacheability.printCacheControl() }, tag: options.tag },
|
|
1184
|
-
options,
|
|
1185
|
-
{ ...context, requestFieldCacheKey }
|
|
1186
|
-
);
|
|
1122
|
+
const result = await this._checkCacheEntry(REQUEST_FIELD_PATHS, hashedRequestFieldCacheKey, options, {
|
|
1123
|
+
...context,
|
|
1124
|
+
requestFieldCacheKey,
|
|
1125
|
+
});
|
|
1187
1126
|
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
set(data, responseDataPath, { __cacheKey: `${REQUEST_FIELD_PATHS}::${hashedRequestFieldCacheKey}` });
|
|
1191
|
-
} else {
|
|
1192
|
-
unset(data, responseDataPath);
|
|
1193
|
-
}
|
|
1194
|
-
}
|
|
1127
|
+
if (result && isObjectLike(result.entry) && isObjectLike(fieldData)) {
|
|
1128
|
+
fieldData = mergeDataSets(result.entry, fieldData, this._typeIDKey);
|
|
1195
1129
|
}
|
|
1130
|
+
|
|
1131
|
+
void this._setCacheEntry(
|
|
1132
|
+
REQUEST_FIELD_PATHS,
|
|
1133
|
+
hashedRequestFieldCacheKey,
|
|
1134
|
+
fieldData,
|
|
1135
|
+
{ cacheHeaders: { cacheControl: cacheability.printCacheControl() }, tag: options.tag },
|
|
1136
|
+
options,
|
|
1137
|
+
{ ...context, requestFieldCacheKey }
|
|
1138
|
+
);
|
|
1196
1139
|
}
|
|
1197
1140
|
|
|
1198
1141
|
private _setResponseChunksAwaitingCaching(
|
package/src/types.ts
CHANGED
|
@@ -122,9 +122,9 @@ export interface ResponseDataForCaching {
|
|
|
122
122
|
requestFieldPathData: PlainData;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
export interface DataForCachingEntry {
|
|
125
|
+
export interface DataForCachingEntry<Data = unknown> {
|
|
126
126
|
cacheability: Cacheability;
|
|
127
|
-
|
|
127
|
+
fieldData: Data;
|
|
128
128
|
fieldTypeInfo: FieldTypeInfo;
|
|
129
129
|
}
|
|
130
130
|
|
|
@@ -157,13 +157,13 @@ export interface CacheManagerDef {
|
|
|
157
157
|
responseData: RawResponseDataWithMaybeCacheMetadata,
|
|
158
158
|
options: RequestOptions,
|
|
159
159
|
context: RequestContext
|
|
160
|
-
):
|
|
160
|
+
): ResponseData;
|
|
161
161
|
cacheResponse(
|
|
162
162
|
requestData: RequestData,
|
|
163
163
|
responseData: RawResponseDataWithMaybeCacheMetadata,
|
|
164
164
|
options: RequestOptions,
|
|
165
165
|
context: RequestContext
|
|
166
|
-
):
|
|
166
|
+
): ResponseData;
|
|
167
167
|
checkCacheEntry(
|
|
168
168
|
cacheType: CacheTypes,
|
|
169
169
|
hash: string,
|
|
@@ -181,5 +181,5 @@ export interface CacheManagerDef {
|
|
|
181
181
|
responseData: ResponseData,
|
|
182
182
|
options: RequestOptions,
|
|
183
183
|
context: CacheManagerContext
|
|
184
|
-
):
|
|
184
|
+
): void;
|
|
185
185
|
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type PlainObject } from '@graphql-box/core';
|
|
2
|
-
import { type KeysAndPaths } from '@graphql-box/helpers';
|
|
3
|
-
import { type SelectionNode } from 'graphql';
|
|
4
|
-
import { type CacheManagerContext } from '../types.cts';
|
|
5
|
-
export declare const filterOutPropsWithArgsOrDirectives: (fieldData: PlainObject, selectionNodes: readonly SelectionNode[], ancestorKeysAndPaths: KeysAndPaths, context: CacheManagerContext) => PlainObject;
|
|
6
|
-
//# sourceMappingURL=filterOutPropsWithArgsOrDirectives.d.cts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"filterOutPropsWithArgsOrDirectives.d.cts","sourceRoot":"","sources":["../../../../src/helpers/filterOutPropsWithArgsOrDirectives.cts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,YAAY,EAAqD,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,kCAAkC,cAClC,WAAW,kBACN,SAAS,aAAa,EAAE,wBAClB,YAAY,WACzB,mBAAmB,gBAkB7B,CAAC"}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { type PlainObject } from '@graphql-box/core';
|
|
2
|
-
import { type KeysAndPaths } from '@graphql-box/helpers';
|
|
3
|
-
import { type SelectionNode } from 'graphql';
|
|
4
|
-
import { type CacheManagerContext } from '../types.ts';
|
|
5
|
-
export declare const filterOutPropsWithArgsOrDirectives: (fieldData: PlainObject, selectionNodes: readonly SelectionNode[], ancestorKeysAndPaths: KeysAndPaths, context: CacheManagerContext) => PlainObject;
|
|
6
|
-
//# sourceMappingURL=filterOutPropsWithArgsOrDirectives.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"filterOutPropsWithArgsOrDirectives.d.ts","sourceRoot":"","sources":["../../../../src/helpers/filterOutPropsWithArgsOrDirectives.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,YAAY,EAAqD,MAAM,sBAAsB,CAAC;AAC5G,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,eAAO,MAAM,kCAAkC,cAClC,WAAW,kBACN,SAAS,aAAa,EAAE,wBAClB,YAAY,WACzB,mBAAmB,gBAkB7B,CAAC"}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type PlainObject } from '@graphql-box/core';
|
|
2
|
-
import { type KeysAndPaths, buildFieldKeysAndPaths, getName, resolveFragments } from '@graphql-box/helpers';
|
|
3
|
-
import { type SelectionNode } from 'graphql';
|
|
4
|
-
import { keys } from 'lodash-es';
|
|
5
|
-
import { type CacheManagerContext } from '../types.ts';
|
|
6
|
-
|
|
7
|
-
export const filterOutPropsWithArgsOrDirectives = (
|
|
8
|
-
fieldData: PlainObject,
|
|
9
|
-
selectionNodes: readonly SelectionNode[],
|
|
10
|
-
ancestorKeysAndPaths: KeysAndPaths,
|
|
11
|
-
context: CacheManagerContext
|
|
12
|
-
) => {
|
|
13
|
-
const fieldAndTypeName = resolveFragments(selectionNodes, context.fragmentDefinitions);
|
|
14
|
-
|
|
15
|
-
return keys(fieldData).reduce<PlainObject>((acc, key) => {
|
|
16
|
-
const match = fieldAndTypeName.find(({ fieldNode }) => getName(fieldNode) === key);
|
|
17
|
-
|
|
18
|
-
if (match) {
|
|
19
|
-
const { requestFieldPath } = buildFieldKeysAndPaths(match.fieldNode, ancestorKeysAndPaths, context);
|
|
20
|
-
const fieldTypeInfo = context.fieldTypeMap.get(requestFieldPath);
|
|
21
|
-
|
|
22
|
-
if (!fieldTypeInfo?.hasArguments && !fieldTypeInfo?.hasDirectives) {
|
|
23
|
-
acc[key] = fieldData[key];
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return acc;
|
|
28
|
-
}, {});
|
|
29
|
-
};
|