-
-
Notifications
You must be signed in to change notification settings - Fork 32
/
cache.ts
82 lines (65 loc) 路 2.21 KB
/
cache.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { OperationResult, ClientPlugin, ClientPluginContext, ClientPluginOperation } from './types';
import { arrayToExistHash } from './utils';
interface ResultCache {
[k: string]: { result: OperationResult; tags?: string[] };
}
export function cache(): ClientPlugin & { clearCache(tags?: string | string[]): void } {
let resultCache: ResultCache = {};
function setCacheResult({ key, tags }: ClientPluginOperation & { type: 'query' }, result: OperationResult) {
resultCache[key] = { result, tags };
}
function getCachedResult({ key }: ClientPluginOperation): OperationResult | undefined {
return resultCache[key]?.result;
}
function clearCache(tags?: string | string[]) {
if (!tags) {
resultCache = {};
return;
}
const tagArray = Array.isArray(tags) ? tags : [tags];
if (!tagArray.length) {
return;
}
const tagsLookup = arrayToExistHash(tagArray);
// clears cache keys one by one
Object.keys(resultCache).forEach(key => {
const cacheItem = resultCache[key];
if (!cacheItem.tags) {
return;
}
const tagExists = cacheItem.tags.some(t => tagsLookup[t]);
if (tagExists) {
delete resultCache[key];
}
});
}
function cachePlugin({ afterQuery, useResult, operation }: ClientPluginContext) {
if (operation.type === 'mutation' && operation.clearCacheTags?.length) {
afterQuery(result => {
// only after successful operation
if (result.data) {
clearCache(operation.clearCacheTags);
}
});
return;
}
if (operation.type !== 'query' || operation.cachePolicy === 'network-only') {
return;
}
// Set the cache result after query is resolved
afterQuery(result => {
setCacheResult(operation, result);
});
// Get cached item
const cachedResult = getCachedResult(operation);
if (operation.cachePolicy === 'cache-only') {
return useResult(cachedResult || { data: null, error: null }, true);
}
// if exists in cache, terminate with result
if (cachedResult) {
return useResult(cachedResult, operation.cachePolicy === 'cache-first');
}
}
cachePlugin.clearCache = clearCache;
return cachePlugin;
}