@graphql-box/cache-manager 2.4.2 → 2.5.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/lib/browser/index.js +1 -1
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/production.analysis.txt +62 -26
- package/lib/main/helpers/isFirstResponseChunk.js +11 -0
- package/lib/main/helpers/isFirstResponseChunk.js.map +1 -0
- package/lib/main/helpers/isLastResponseChunk.js +11 -0
- package/lib/main/helpers/isLastResponseChunk.js.map +1 -0
- package/lib/main/helpers/isNotLastResponseChunk.js +11 -0
- package/lib/main/helpers/isNotLastResponseChunk.js.map +1 -0
- package/lib/main/helpers/isNotResponseChunk.js +11 -0
- package/lib/main/helpers/isNotResponseChunk.js.map +1 -0
- package/lib/main/helpers/mergeResponseDataSets.js +53 -0
- package/lib/main/helpers/mergeResponseDataSets.js.map +1 -0
- package/lib/main/helpers/normalizePatchResponseData.js +10 -5
- package/lib/main/helpers/normalizePatchResponseData.js.map +1 -1
- package/lib/main/main/index.js +124 -89
- package/lib/main/main/index.js.map +1 -1
- package/lib/module/helpers/isFirstResponseChunk.js +2 -0
- package/lib/module/helpers/isFirstResponseChunk.js.map +1 -0
- package/lib/module/helpers/isLastResponseChunk.js +2 -0
- package/lib/module/helpers/isLastResponseChunk.js.map +1 -0
- package/lib/module/helpers/isNotLastResponseChunk.js +2 -0
- package/lib/module/helpers/isNotLastResponseChunk.js.map +1 -0
- package/lib/module/helpers/isNotResponseChunk.js +2 -0
- package/lib/module/helpers/isNotResponseChunk.js.map +1 -0
- package/lib/module/helpers/mergeResponseDataSets.js +41 -0
- package/lib/module/helpers/mergeResponseDataSets.js.map +1 -0
- package/lib/module/helpers/normalizePatchResponseData.js +10 -5
- package/lib/module/helpers/normalizePatchResponseData.js.map +1 -1
- package/lib/module/main/index.js +121 -89
- package/lib/module/main/index.js.map +1 -1
- package/lib/types/defs/index.d.ts +2 -2
- package/lib/types/defs/index.d.ts.map +1 -1
- package/lib/types/helpers/isFirstResponseChunk.d.ts +5 -0
- package/lib/types/helpers/isFirstResponseChunk.d.ts.map +1 -0
- package/lib/types/helpers/isLastResponseChunk.d.ts +5 -0
- package/lib/types/helpers/isLastResponseChunk.d.ts.map +1 -0
- package/lib/types/helpers/isNotLastResponseChunk.d.ts +5 -0
- package/lib/types/helpers/isNotLastResponseChunk.d.ts.map +1 -0
- package/lib/types/helpers/isNotResponseChunk.d.ts +5 -0
- package/lib/types/helpers/isNotResponseChunk.d.ts.map +1 -0
- package/lib/types/helpers/mergeResponseDataSets.d.ts +4 -0
- package/lib/types/helpers/mergeResponseDataSets.d.ts.map +1 -0
- package/lib/types/helpers/normalizePatchResponseData.d.ts +2 -8
- package/lib/types/helpers/normalizePatchResponseData.d.ts.map +1 -1
- package/lib/types/main/index.d.ts +6 -3
- package/lib/types/main/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__snapshots__/index.test.ts.snap +12481 -11881
- package/src/defs/index.ts +13 -13
- package/src/helpers/isFirstResponseChunk.ts +5 -0
- package/src/helpers/isLastResponseChunk.ts +5 -0
- package/src/helpers/isNotLastResponseChunk.ts +5 -0
- package/src/helpers/isNotResponseChunk.ts +5 -0
- package/src/helpers/mergeResponseDataSets.ts +35 -0
- package/src/helpers/normalizePatchResponseData.ts +8 -1
- package/src/index.test.ts +162 -86
- package/src/main/index.ts +150 -110
package/src/main/index.ts
CHANGED
|
@@ -63,6 +63,10 @@ import { buildFieldKeysAndPaths } from "../helpers/buildKeysAndPaths";
|
|
|
63
63
|
import deriveOpCacheability from "../helpers/deriveOpCacheability";
|
|
64
64
|
import filterOutPropsWithArgsOrDirectives from "../helpers/filterOutPropsWithArgsOrDirectives";
|
|
65
65
|
import filterQuery from "../helpers/filterQuery";
|
|
66
|
+
import isLastResponseChunk from "../helpers/isLastResponseChunk";
|
|
67
|
+
import isNotLastResponseChunk from "../helpers/isNotLastResponseChunk";
|
|
68
|
+
import isNotResponseChunk from "../helpers/isNotResponseChunk";
|
|
69
|
+
import mergeResponseDataSets from "../helpers/mergeResponseDataSets";
|
|
66
70
|
import normalizePatchResponseData from "../helpers/normalizePatchResponseData";
|
|
67
71
|
import { getValidTypeIDValue } from "../helpers/validTypeIDValue";
|
|
68
72
|
|
|
@@ -225,6 +229,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
225
229
|
private _cascadeCacheControl: boolean;
|
|
226
230
|
private _fallbackOperationCacheability: string;
|
|
227
231
|
private _partialQueryResponses: PartialQueryResponses = new Map();
|
|
232
|
+
private _responseChunksAwaitingCaching: Map<string, RawResponseDataWithMaybeCacheMetadata[]> = new Map();
|
|
228
233
|
private _typeCacheDirectives: PlainObjectStringMap;
|
|
229
234
|
private _typeIDKey: string;
|
|
230
235
|
|
|
@@ -283,6 +288,37 @@ export class CacheManager implements CacheManagerDef {
|
|
|
283
288
|
return { updated: { ast: filteredAST, hash: hashRequest(request), request } };
|
|
284
289
|
}
|
|
285
290
|
|
|
291
|
+
public async cacheQuery(
|
|
292
|
+
requestData: RequestData,
|
|
293
|
+
updatedRequestData: RequestData,
|
|
294
|
+
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
295
|
+
options: RequestOptions,
|
|
296
|
+
context: RequestContext,
|
|
297
|
+
): Promise<ResponseData> {
|
|
298
|
+
const cacheManagerContext: CacheManagerContext = {
|
|
299
|
+
...context,
|
|
300
|
+
fragmentDefinitions: getFragmentDefinitions(updatedRequestData.ast),
|
|
301
|
+
typeIDKey: this._typeIDKey,
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
return this._cacheResponse(requestData, updatedRequestData, rawResponseData, options, cacheManagerContext);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
public async cacheResponse(
|
|
308
|
+
requestData: RequestData,
|
|
309
|
+
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
310
|
+
options: RequestOptions,
|
|
311
|
+
context: RequestContext,
|
|
312
|
+
): Promise<ResponseData> {
|
|
313
|
+
const cacheManagerContext: CacheManagerContext = {
|
|
314
|
+
...context,
|
|
315
|
+
fragmentDefinitions: getFragmentDefinitions(requestData.ast),
|
|
316
|
+
typeIDKey: this._typeIDKey,
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
return this._cacheResponse(requestData, undefined, rawResponseData, options, cacheManagerContext);
|
|
320
|
+
}
|
|
321
|
+
|
|
286
322
|
public async checkCacheEntry(
|
|
287
323
|
cacheType: CacheTypes,
|
|
288
324
|
hash: string,
|
|
@@ -315,83 +351,6 @@ export class CacheManager implements CacheManagerDef {
|
|
|
315
351
|
this._partialQueryResponses.delete(hash);
|
|
316
352
|
}
|
|
317
353
|
|
|
318
|
-
public async resolveQuery(
|
|
319
|
-
requestData: RequestData,
|
|
320
|
-
updatedRequestData: RequestData,
|
|
321
|
-
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
322
|
-
options: RequestOptions,
|
|
323
|
-
context: RequestContext,
|
|
324
|
-
): Promise<ResponseData> {
|
|
325
|
-
const cacheManagerContext: CacheManagerContext = {
|
|
326
|
-
...context,
|
|
327
|
-
fragmentDefinitions: getFragmentDefinitions(updatedRequestData.ast),
|
|
328
|
-
typeIDKey: this._typeIDKey,
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
const dataCaching: Promise<void>[] = [];
|
|
332
|
-
|
|
333
|
-
const { cacheMetadata, data, hasNext, paths } = await this._resolveRequest(
|
|
334
|
-
updatedRequestData,
|
|
335
|
-
rawResponseData,
|
|
336
|
-
options,
|
|
337
|
-
cacheManagerContext,
|
|
338
|
-
);
|
|
339
|
-
|
|
340
|
-
let partialQueryResponse: PartialQueryResponse | undefined;
|
|
341
|
-
|
|
342
|
-
if (cacheManagerContext.queryFiltered) {
|
|
343
|
-
if (!(rawResponseData.hasNext || rawResponseData.paths)) {
|
|
344
|
-
dataCaching.push(
|
|
345
|
-
this._setQueryResponseCacheEntry(
|
|
346
|
-
updatedRequestData.hash,
|
|
347
|
-
{ cacheMetadata, data },
|
|
348
|
-
options,
|
|
349
|
-
cacheManagerContext,
|
|
350
|
-
),
|
|
351
|
-
);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
if (!rawResponseData.paths) {
|
|
355
|
-
partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const responseCacheMetadata = CacheManager._mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse);
|
|
360
|
-
const responseData = this._mergeResponseData(data, partialQueryResponse);
|
|
361
|
-
|
|
362
|
-
if (!(rawResponseData.hasNext || rawResponseData.paths)) {
|
|
363
|
-
dataCaching.push(
|
|
364
|
-
this._setQueryResponseCacheEntry(
|
|
365
|
-
requestData.hash,
|
|
366
|
-
{ cacheMetadata: responseCacheMetadata, data: responseData },
|
|
367
|
-
options,
|
|
368
|
-
cacheManagerContext,
|
|
369
|
-
),
|
|
370
|
-
);
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (options.awaitDataCaching) {
|
|
374
|
-
await Promise.all(dataCaching);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return { cacheMetadata: responseCacheMetadata, data: responseData, hasNext, paths };
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
public async resolveRequest(
|
|
381
|
-
requestData: RequestData,
|
|
382
|
-
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
383
|
-
options: RequestOptions,
|
|
384
|
-
context: RequestContext,
|
|
385
|
-
): Promise<ResponseData> {
|
|
386
|
-
const cacheManagerContext: CacheManagerContext = {
|
|
387
|
-
...context,
|
|
388
|
-
fragmentDefinitions: getFragmentDefinitions(requestData.ast),
|
|
389
|
-
typeIDKey: this._typeIDKey,
|
|
390
|
-
};
|
|
391
|
-
|
|
392
|
-
return this._resolveRequest(requestData, rawResponseData, options, cacheManagerContext);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
354
|
private async _analyzeFieldNode(
|
|
396
355
|
fieldNode: FieldNode,
|
|
397
356
|
cachedAncestorFieldData: CachedAncestorFieldData,
|
|
@@ -399,7 +358,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
399
358
|
options: RequestOptions,
|
|
400
359
|
context: CacheManagerContext,
|
|
401
360
|
): Promise<void> {
|
|
402
|
-
if (hasChildFields(fieldNode)) {
|
|
361
|
+
if (hasChildFields(fieldNode, { fragmentDefinitions: context.fragmentDefinitions })) {
|
|
403
362
|
await this._analyzeParentFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
|
|
404
363
|
} else {
|
|
405
364
|
await this._analyzeLeafFieldNode(fieldNode, cachedAncestorFieldData, cachedResponseData, options, context);
|
|
@@ -556,6 +515,93 @@ export class CacheManager implements CacheManagerDef {
|
|
|
556
515
|
return cacheMetadata;
|
|
557
516
|
}
|
|
558
517
|
|
|
518
|
+
private async _cacheResponse(
|
|
519
|
+
requestData: RequestData,
|
|
520
|
+
updatedRequestData: RequestData | undefined,
|
|
521
|
+
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
522
|
+
options: RequestOptions,
|
|
523
|
+
context: CacheManagerContext,
|
|
524
|
+
): Promise<ResponseData> {
|
|
525
|
+
const normalizedResponseData = normalizePatchResponseData(rawResponseData, context);
|
|
526
|
+
let responseDataForCaching: RawResponseDataWithMaybeCacheMetadata | undefined = normalizedResponseData;
|
|
527
|
+
|
|
528
|
+
if (isNotLastResponseChunk(rawResponseData, context)) {
|
|
529
|
+
this._setResponseChunksAwaitingCaching(normalizedResponseData, context);
|
|
530
|
+
responseDataForCaching = undefined;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
if (isLastResponseChunk(rawResponseData, context)) {
|
|
534
|
+
responseDataForCaching = this._retrieveResponseDataForCaching(normalizedResponseData, context);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
const dataCaching: Promise<void>[] = [];
|
|
538
|
+
|
|
539
|
+
if (responseDataForCaching) {
|
|
540
|
+
const { data } = responseDataForCaching;
|
|
541
|
+
const cacheMetadata = this._buildCacheMetadata(requestData, responseDataForCaching, options, context);
|
|
542
|
+
|
|
543
|
+
dataCaching.push(
|
|
544
|
+
this._setEntityAndRequestFieldPathCacheEntries(
|
|
545
|
+
requestData,
|
|
546
|
+
{
|
|
547
|
+
cacheMetadata,
|
|
548
|
+
entityData: cloneDeep(data),
|
|
549
|
+
requestFieldPathData: cloneDeep(data),
|
|
550
|
+
},
|
|
551
|
+
options,
|
|
552
|
+
context,
|
|
553
|
+
),
|
|
554
|
+
);
|
|
555
|
+
|
|
556
|
+
let queryCacheMetadata: CacheMetadata | undefined;
|
|
557
|
+
let queryData: PlainObjectMap | undefined;
|
|
558
|
+
|
|
559
|
+
if (context.operation === QUERY) {
|
|
560
|
+
let partialQueryResponse: PartialQueryResponse | undefined;
|
|
561
|
+
|
|
562
|
+
if (context.queryFiltered && updatedRequestData) {
|
|
563
|
+
dataCaching.push(
|
|
564
|
+
this._setQueryResponseCacheEntry(updatedRequestData.hash, { cacheMetadata, data }, options, context),
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
partialQueryResponse = this._getPartialQueryResponse(requestData.hash);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
queryCacheMetadata = CacheManager._mergeResponseCacheMetadata(cacheMetadata, partialQueryResponse);
|
|
571
|
+
queryData = this._mergeResponseData(data, partialQueryResponse);
|
|
572
|
+
|
|
573
|
+
dataCaching.push(
|
|
574
|
+
this._setQueryResponseCacheEntry(
|
|
575
|
+
requestData.hash,
|
|
576
|
+
{ cacheMetadata: queryCacheMetadata, data: queryData },
|
|
577
|
+
options,
|
|
578
|
+
context,
|
|
579
|
+
),
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (options.awaitDataCaching) {
|
|
584
|
+
await Promise.all(dataCaching);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (isNotResponseChunk(normalizedResponseData, context) && queryCacheMetadata && queryData) {
|
|
588
|
+
return {
|
|
589
|
+
cacheMetadata: queryCacheMetadata,
|
|
590
|
+
data: queryData,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const { data, hasNext, paths } = normalizedResponseData;
|
|
596
|
+
|
|
597
|
+
return {
|
|
598
|
+
cacheMetadata: this._buildCacheMetadata(requestData, normalizedResponseData, options, context),
|
|
599
|
+
data,
|
|
600
|
+
hasNext,
|
|
601
|
+
paths,
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
559
605
|
private async _checkCacheEntry(
|
|
560
606
|
cacheType: CacheTypes,
|
|
561
607
|
hash: string,
|
|
@@ -717,37 +763,6 @@ export class CacheManager implements CacheManagerDef {
|
|
|
717
763
|
);
|
|
718
764
|
}
|
|
719
765
|
|
|
720
|
-
private async _resolveRequest(
|
|
721
|
-
requestData: RequestData,
|
|
722
|
-
rawResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
723
|
-
options: RequestOptions,
|
|
724
|
-
context: CacheManagerContext,
|
|
725
|
-
): Promise<ResponseData> {
|
|
726
|
-
const normalizedResponseData =
|
|
727
|
-
rawResponseData.paths && context.normalizePatchResponseData
|
|
728
|
-
? normalizePatchResponseData(rawResponseData)
|
|
729
|
-
: rawResponseData;
|
|
730
|
-
|
|
731
|
-
const dataCaching: Promise<void>[] = [];
|
|
732
|
-
const cacheMetadata = this._buildCacheMetadata(requestData, normalizedResponseData, options, context);
|
|
733
|
-
const { data, hasNext, paths } = normalizedResponseData;
|
|
734
|
-
|
|
735
|
-
dataCaching.push(
|
|
736
|
-
this._setEntityAndRequestFieldPathCacheEntries(
|
|
737
|
-
requestData,
|
|
738
|
-
{ cacheMetadata, entityData: cloneDeep(data), requestFieldPathData: cloneDeep(data) },
|
|
739
|
-
options,
|
|
740
|
-
context,
|
|
741
|
-
),
|
|
742
|
-
);
|
|
743
|
-
|
|
744
|
-
if (options.awaitDataCaching) {
|
|
745
|
-
await Promise.all(dataCaching);
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
return { cacheMetadata, data, hasNext, paths };
|
|
749
|
-
}
|
|
750
|
-
|
|
751
766
|
private async _retrieveCachedEntityData(
|
|
752
767
|
validTypeIDValue: string | number,
|
|
753
768
|
{ possibleTypes, typeName }: FieldTypeInfo,
|
|
@@ -879,6 +894,18 @@ export class CacheManager implements CacheManagerDef {
|
|
|
879
894
|
return cachedResponseData;
|
|
880
895
|
}
|
|
881
896
|
|
|
897
|
+
private _retrieveResponseDataForCaching(
|
|
898
|
+
normalizedResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
899
|
+
context: CacheManagerContext,
|
|
900
|
+
) {
|
|
901
|
+
const responseChunks = this._responseChunksAwaitingCaching.get(
|
|
902
|
+
context.boxID,
|
|
903
|
+
) as RawResponseDataWithMaybeCacheMetadata[];
|
|
904
|
+
|
|
905
|
+
this._responseChunksAwaitingCaching.delete(context.boxID);
|
|
906
|
+
return mergeResponseDataSets([...responseChunks, normalizedResponseData]);
|
|
907
|
+
}
|
|
908
|
+
|
|
882
909
|
@logCacheEntry()
|
|
883
910
|
private async _setCacheEntry(
|
|
884
911
|
cacheType: CacheTypes,
|
|
@@ -1119,7 +1146,7 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1119
1146
|
context,
|
|
1120
1147
|
);
|
|
1121
1148
|
|
|
1122
|
-
if (hasChildFields(field)) {
|
|
1149
|
+
if (hasChildFields(field, { fragmentDefinitions: context.fragmentDefinitions })) {
|
|
1123
1150
|
if (isEntity) {
|
|
1124
1151
|
set(data, responseDataPath, { __cacheKey: `${REQUEST_FIELD_PATHS}::${hashedRequestFieldCacheKey}` });
|
|
1125
1152
|
} else {
|
|
@@ -1128,6 +1155,19 @@ export class CacheManager implements CacheManagerDef {
|
|
|
1128
1155
|
}
|
|
1129
1156
|
}
|
|
1130
1157
|
}
|
|
1158
|
+
|
|
1159
|
+
private _setResponseChunksAwaitingCaching(
|
|
1160
|
+
normalizedResponseData: RawResponseDataWithMaybeCacheMetadata,
|
|
1161
|
+
context: CacheManagerContext,
|
|
1162
|
+
) {
|
|
1163
|
+
const responseChunks = this._responseChunksAwaitingCaching.get(context.boxID);
|
|
1164
|
+
|
|
1165
|
+
if (responseChunks) {
|
|
1166
|
+
this._responseChunksAwaitingCaching.set(context.boxID, [...responseChunks, normalizedResponseData]);
|
|
1167
|
+
} else {
|
|
1168
|
+
this._responseChunksAwaitingCaching.set(context.boxID, [normalizedResponseData]);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1131
1171
|
}
|
|
1132
1172
|
|
|
1133
1173
|
export default function init(userOptions: UserOptions): CacheManagerInit {
|