@khanacademy/wonder-blocks-data 3.2.0 → 4.0.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/CHANGELOG.md +23 -0
- package/dist/es/index.js +356 -332
- package/dist/index.js +507 -456
- package/docs.md +17 -35
- package/package.json +1 -1
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +7 -46
- package/src/__tests__/generated-snapshot.test.js +56 -122
- package/src/components/__tests__/data.test.js +372 -297
- package/src/components/__tests__/intercept-data.test.js +6 -30
- package/src/components/data.js +153 -21
- package/src/components/data.md +38 -69
- package/src/components/intercept-context.js +6 -2
- package/src/components/intercept-data.js +40 -51
- package/src/components/intercept-data.md +13 -27
- package/src/components/track-data.md +9 -23
- package/src/hooks/__tests__/__snapshots__/use-shared-cache.test.js.snap +17 -0
- package/src/hooks/__tests__/use-server-effect.test.js +217 -0
- package/src/hooks/__tests__/use-shared-cache.test.js +307 -0
- package/src/hooks/use-server-effect.js +45 -0
- package/src/hooks/use-shared-cache.js +106 -0
- package/src/index.js +15 -19
- package/src/util/__tests__/__snapshots__/scoped-in-memory-cache.test.js.snap +19 -0
- package/src/util/__tests__/request-fulfillment.test.js +42 -85
- package/src/util/__tests__/request-tracking.test.js +72 -191
- package/src/util/__tests__/{result-from-cache-entry.test.js → result-from-cache-response.test.js} +9 -10
- package/src/util/__tests__/scoped-in-memory-cache.test.js +396 -0
- package/src/util/__tests__/ssr-cache.test.js +639 -0
- package/src/util/request-fulfillment.js +36 -44
- package/src/util/request-tracking.js +62 -75
- package/src/util/{result-from-cache-entry.js → result-from-cache-response.js} +10 -13
- package/src/util/scoped-in-memory-cache.js +149 -0
- package/src/util/ssr-cache.js +206 -0
- package/src/util/types.js +43 -108
- package/src/hooks/__tests__/use-data.test.js +0 -826
- package/src/hooks/use-data.js +0 -143
- package/src/util/__tests__/memory-cache.test.js +0 -446
- package/src/util/__tests__/request-handler.test.js +0 -121
- package/src/util/__tests__/response-cache.test.js +0 -879
- package/src/util/memory-cache.js +0 -187
- package/src/util/request-handler.js +0 -42
- package/src/util/request-handler.md +0 -51
- package/src/util/response-cache.js +0 -213
package/src/util/memory-cache.js
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import type {
|
|
3
|
-
ValidData,
|
|
4
|
-
ICache,
|
|
5
|
-
CacheEntry,
|
|
6
|
-
Cache,
|
|
7
|
-
IRequestHandler,
|
|
8
|
-
} from "./types.js";
|
|
9
|
-
|
|
10
|
-
function deepClone<T: {...}>(source: T | $ReadOnly<T>): $ReadOnly<T> {
|
|
11
|
-
/**
|
|
12
|
-
* We want to deep clone the source cache to dodge mutations by external
|
|
13
|
-
* references. So we serialize the source cache to JSON and parse it
|
|
14
|
-
* back into a new object.
|
|
15
|
-
*
|
|
16
|
-
* NOTE: This doesn't work for get/set property accessors.
|
|
17
|
-
*/
|
|
18
|
-
const serializedInitCache = JSON.stringify(source);
|
|
19
|
-
const cloneInitCache = JSON.parse(serializedInitCache);
|
|
20
|
-
return Object.freeze(cloneInitCache);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* INTERNAL USE ONLY
|
|
25
|
-
*
|
|
26
|
-
* Special case cache implementation for the memory cache.
|
|
27
|
-
*
|
|
28
|
-
* This is only used within our framework for SSR (see ./response-cache.js).
|
|
29
|
-
*/
|
|
30
|
-
export default class MemoryCache<TOptions, TData: ValidData>
|
|
31
|
-
implements ICache<TOptions, TData>
|
|
32
|
-
{
|
|
33
|
-
_cache: Cache;
|
|
34
|
-
|
|
35
|
-
constructor(source: ?$ReadOnly<Cache> = null) {
|
|
36
|
-
this._cache = {};
|
|
37
|
-
if (source != null) {
|
|
38
|
-
try {
|
|
39
|
-
/**
|
|
40
|
-
* Object.assign only performs a shallow clone.
|
|
41
|
-
* So we deep clone it and then assign the clone values to our
|
|
42
|
-
* internal cache.
|
|
43
|
-
*/
|
|
44
|
-
const cloneInitCache = deepClone(source);
|
|
45
|
-
Object.assign(this._cache, cloneInitCache);
|
|
46
|
-
} catch (e) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`An error occurred trying to initialize from a response cache snapshot: ${e}`,
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Indicate if this cache is being used or now.
|
|
56
|
-
*
|
|
57
|
-
* When the cache has entries, returns `true`; otherwise, returns `false`.
|
|
58
|
-
*/
|
|
59
|
-
get inUse(): boolean {
|
|
60
|
-
return Object.keys(this._cache).length > 0;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
store: <TOptions, TData: ValidData>(
|
|
64
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
65
|
-
options: TOptions,
|
|
66
|
-
entry: CacheEntry<TData>,
|
|
67
|
-
) => void = <TOptions, TData: ValidData>(
|
|
68
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
69
|
-
options: TOptions,
|
|
70
|
-
entry: CacheEntry<TData>,
|
|
71
|
-
): void => {
|
|
72
|
-
const requestType = handler.type;
|
|
73
|
-
|
|
74
|
-
const frozenEntry = Object.freeze(entry);
|
|
75
|
-
|
|
76
|
-
// Ensure we have a cache location for this handler type.
|
|
77
|
-
this._cache[requestType] = this._cache[requestType] || {};
|
|
78
|
-
|
|
79
|
-
// Cache the data.
|
|
80
|
-
const key = handler.getKey(options);
|
|
81
|
-
this._cache[requestType][key] = frozenEntry;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
retrieve: <TOptions, TData: ValidData>(
|
|
85
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
86
|
-
options: TOptions,
|
|
87
|
-
) => ?CacheEntry<TData> = <TOptions, TData: ValidData>(
|
|
88
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
89
|
-
options: TOptions,
|
|
90
|
-
): ?CacheEntry<TData> => {
|
|
91
|
-
const requestType = handler.type;
|
|
92
|
-
|
|
93
|
-
// Get the internal subcache for the handler.
|
|
94
|
-
const handlerCache = this._cache[requestType];
|
|
95
|
-
if (!handlerCache) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Get the response.
|
|
100
|
-
const key = handler.getKey(options);
|
|
101
|
-
const internalEntry = handlerCache[key];
|
|
102
|
-
if (internalEntry == null) {
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return internalEntry;
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
remove: <TOptions, TData: ValidData>(
|
|
110
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
111
|
-
options: TOptions,
|
|
112
|
-
) => boolean = <TOptions, TData: ValidData>(
|
|
113
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
114
|
-
options: TOptions,
|
|
115
|
-
): boolean => {
|
|
116
|
-
const requestType = handler.type;
|
|
117
|
-
|
|
118
|
-
// NOTE(somewhatabstract): We could invoke removeAll with a predicate
|
|
119
|
-
// to match the key of the entry we're removing, but that's an
|
|
120
|
-
// inefficient way to remove a single item, so let's not do that.
|
|
121
|
-
|
|
122
|
-
// Get the internal subcache for the handler.
|
|
123
|
-
const handlerCache = this._cache[requestType];
|
|
124
|
-
if (!handlerCache) {
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Get the entry.
|
|
129
|
-
const key = handler.getKey(options);
|
|
130
|
-
const internalEntry = handlerCache[key];
|
|
131
|
-
if (internalEntry == null) {
|
|
132
|
-
return false;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Delete the entry.
|
|
136
|
-
delete handlerCache[key];
|
|
137
|
-
return true;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
removeAll: <TOptions, TData: ValidData>(
|
|
141
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
142
|
-
predicate?: (
|
|
143
|
-
key: string,
|
|
144
|
-
cachedEntry: $ReadOnly<CacheEntry<TData>>,
|
|
145
|
-
) => boolean,
|
|
146
|
-
) => number = <TOptions, TData: ValidData>(
|
|
147
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
148
|
-
predicate?: (
|
|
149
|
-
key: string,
|
|
150
|
-
cachedEntry: $ReadOnly<CacheEntry<TData>>,
|
|
151
|
-
) => boolean,
|
|
152
|
-
): number => {
|
|
153
|
-
const requestType = handler.type;
|
|
154
|
-
|
|
155
|
-
// Get the internal subcache for the handler.
|
|
156
|
-
const handlerCache = this._cache[requestType];
|
|
157
|
-
if (!handlerCache) {
|
|
158
|
-
return 0;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
let removedCount = 0;
|
|
162
|
-
if (typeof predicate === "function") {
|
|
163
|
-
// Apply the predicate to what we have cached.
|
|
164
|
-
for (const [key, entry] of Object.entries(handlerCache)) {
|
|
165
|
-
if (predicate(key, (entry: any))) {
|
|
166
|
-
removedCount++;
|
|
167
|
-
delete handlerCache[key];
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
// We're removing everything so delete the entire subcache.
|
|
172
|
-
removedCount = Object.keys(handlerCache).length;
|
|
173
|
-
delete this._cache[requestType];
|
|
174
|
-
}
|
|
175
|
-
return removedCount;
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
cloneData: () => $ReadOnly<Cache> = (): $ReadOnly<Cache> => {
|
|
179
|
-
try {
|
|
180
|
-
return deepClone(this._cache);
|
|
181
|
-
} catch (e) {
|
|
182
|
-
throw new Error(
|
|
183
|
-
`An error occurred while trying to clone the cache: ${e}`,
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import type {ValidData, IRequestHandler} from "./types.js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Base implementation for creating a request handler.
|
|
6
|
-
*
|
|
7
|
-
* Provides a base implementation of the `IRequestHandler` base class for
|
|
8
|
-
* use with the Wonder Blocks Data framework.
|
|
9
|
-
*/
|
|
10
|
-
export default class RequestHandler<TOptions, TData: ValidData>
|
|
11
|
-
implements IRequestHandler<TOptions, TData>
|
|
12
|
-
{
|
|
13
|
-
_type: string;
|
|
14
|
-
_hydrate: boolean;
|
|
15
|
-
|
|
16
|
-
constructor(type: string, hydrate?: boolean = true) {
|
|
17
|
-
this._type = type;
|
|
18
|
-
this._hydrate = !!hydrate;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get type(): string {
|
|
22
|
-
return this._type;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get hydrate(): boolean {
|
|
26
|
-
return this._hydrate;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
getKey(options: TOptions): string {
|
|
30
|
-
try {
|
|
31
|
-
return options === undefined
|
|
32
|
-
? "undefined"
|
|
33
|
-
: (JSON.stringify(options): any);
|
|
34
|
-
} catch (e) {
|
|
35
|
-
throw new Error(`Failed to auto-generate key: ${e}`);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
fulfillRequest(options: TOptions): Promise<TData> {
|
|
40
|
-
throw new Error("Not implemented");
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
This class implements the `IRequestHandler` interface. It is to be used as a
|
|
2
|
-
base class to implement your own request handler.
|
|
3
|
-
|
|
4
|
-
```js static
|
|
5
|
-
interface IRequestHandler<TOptions, TData> {
|
|
6
|
-
/**
|
|
7
|
-
* Fulfill a given request.
|
|
8
|
-
*/
|
|
9
|
-
fulfillRequest(options: TOptions): Promise<TData>;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* The handler type; this is used to uniquely identify this handler from
|
|
13
|
-
* any other handler.
|
|
14
|
-
*/
|
|
15
|
-
get type(): string;
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* When true, server-side results are cached and hydrated in the client.
|
|
19
|
-
* When false, the server-side cache is not used and results are not
|
|
20
|
-
* hydrated.
|
|
21
|
-
* This should only be set to false if something is ensuring that the
|
|
22
|
-
* hydrated client result will match the server result.
|
|
23
|
-
*/
|
|
24
|
-
get hydrate(): boolean;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get the key to use for a given request. This should be idempotent for a
|
|
28
|
-
* given options set if you want caching to work across requests.
|
|
29
|
-
*/
|
|
30
|
-
getKey(options: TOptions): string;
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
The constructor requires a `type` to identify your handler. This should be unique
|
|
35
|
-
among the handlers that are used across your application, otherwise, requests
|
|
36
|
-
may be fulfilled by the wrong handler.
|
|
37
|
-
|
|
38
|
-
The `fulfillRequest` method of this class is not implemented and will throw if
|
|
39
|
-
called. Subclasses will need to implement this method.
|
|
40
|
-
|
|
41
|
-
A default implementation of `getKey` is provided that serializes the options of
|
|
42
|
-
a request to a string and uses that as the cache key. You may want to override
|
|
43
|
-
this behavior to simplify the key or to omit some values from the key.
|
|
44
|
-
|
|
45
|
-
The `hydrate` property indicates if the data that is fulfilled for the handler
|
|
46
|
-
during SSR should be provided for hydration. This should be `true` in most
|
|
47
|
-
cases. When `false`, React hydration will fail unless some other aspect of your
|
|
48
|
-
SSR process is tracking the data for hydration. An example of setting this to
|
|
49
|
-
false might be when you are using Apollo Client. In that scenario, you may use
|
|
50
|
-
Apollo Cache to store and hydrate the data, while using Wonder Blocks Data to
|
|
51
|
-
track and fulfill any query requests made via Apollo Client.
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
// @flow
|
|
2
|
-
import {Server} from "@khanacademy/wonder-blocks-core";
|
|
3
|
-
import MemoryCache from "./memory-cache.js";
|
|
4
|
-
|
|
5
|
-
import type {
|
|
6
|
-
ValidData,
|
|
7
|
-
CacheEntry,
|
|
8
|
-
Cache,
|
|
9
|
-
IRequestHandler,
|
|
10
|
-
ResponseCache as ResCache,
|
|
11
|
-
} from "./types.js";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* The default instance is stored here.
|
|
15
|
-
* It's created below in the Default() static property.
|
|
16
|
-
*/
|
|
17
|
-
let _default: ResponseCache;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Implements the response cache.
|
|
21
|
-
*
|
|
22
|
-
* INTERNAL USE ONLY
|
|
23
|
-
*/
|
|
24
|
-
export class ResponseCache {
|
|
25
|
-
static get Default(): ResponseCache {
|
|
26
|
-
if (!_default) {
|
|
27
|
-
_default = new ResponseCache();
|
|
28
|
-
}
|
|
29
|
-
return _default;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
_hydrationCache: MemoryCache<any, any>;
|
|
33
|
-
_ssrOnlyCache: ?MemoryCache<any, any>;
|
|
34
|
-
|
|
35
|
-
constructor(
|
|
36
|
-
hydrationCache: ?MemoryCache<any, any> = null,
|
|
37
|
-
ssrOnlyCache: ?MemoryCache<any, any> = null,
|
|
38
|
-
) {
|
|
39
|
-
this._ssrOnlyCache = Server.isServerSide()
|
|
40
|
-
? ssrOnlyCache || new MemoryCache()
|
|
41
|
-
: undefined;
|
|
42
|
-
this._hydrationCache = hydrationCache || new MemoryCache();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
_setCacheEntry<TOptions, TData: ValidData>(
|
|
46
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
47
|
-
options: TOptions,
|
|
48
|
-
entry: CacheEntry<TData>,
|
|
49
|
-
): CacheEntry<TData> {
|
|
50
|
-
const frozenEntry = Object.freeze(entry);
|
|
51
|
-
if (this._ssrOnlyCache != null) {
|
|
52
|
-
// We are server-side.
|
|
53
|
-
// We need to store this value.
|
|
54
|
-
if (handler.hydrate) {
|
|
55
|
-
this._hydrationCache.store(handler, options, frozenEntry);
|
|
56
|
-
} else {
|
|
57
|
-
this._ssrOnlyCache.store(handler, options, frozenEntry);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return frozenEntry;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Initialize the cache from a given cache state.
|
|
65
|
-
*
|
|
66
|
-
* This can only be called if the cache is not already in use.
|
|
67
|
-
*/
|
|
68
|
-
initialize: (source: ResCache) => void = (source) => {
|
|
69
|
-
if (this._hydrationCache.inUse) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
"Cannot initialize data response cache more than once",
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
this._hydrationCache = new MemoryCache(source);
|
|
77
|
-
} catch (e) {
|
|
78
|
-
throw new Error(
|
|
79
|
-
`An error occurred trying to initialize the data response cache: ${e}`,
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Cache data for a specific response.
|
|
86
|
-
*
|
|
87
|
-
* This is a noop when client-side.
|
|
88
|
-
*/
|
|
89
|
-
cacheData: <TOptions, TData: ValidData>(
|
|
90
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
91
|
-
options: TOptions,
|
|
92
|
-
data: TData,
|
|
93
|
-
) => CacheEntry<TData> = <TOptions, TData: ValidData>(
|
|
94
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
95
|
-
options: TOptions,
|
|
96
|
-
data: TData,
|
|
97
|
-
): CacheEntry<TData> => this._setCacheEntry(handler, options, {data});
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Cache an error for a specific response.
|
|
101
|
-
*
|
|
102
|
-
* This is a noop when client-side.
|
|
103
|
-
*/
|
|
104
|
-
cacheError: <TOptions, TData: ValidData>(
|
|
105
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
106
|
-
options: TOptions,
|
|
107
|
-
error: Error | string,
|
|
108
|
-
) => CacheEntry<TData> = <TOptions, TData: ValidData>(
|
|
109
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
110
|
-
options: TOptions,
|
|
111
|
-
error: Error | string,
|
|
112
|
-
): CacheEntry<TData> => {
|
|
113
|
-
const errorMessage = typeof error === "string" ? error : error.message;
|
|
114
|
-
return this._setCacheEntry(handler, options, {error: errorMessage});
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Retrieve data from our cache.
|
|
119
|
-
*/
|
|
120
|
-
getEntry: <TOptions, TData: ValidData>(
|
|
121
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
122
|
-
options: TOptions,
|
|
123
|
-
) => ?$ReadOnly<CacheEntry<TData>> = <TOptions, TData: ValidData>(
|
|
124
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
125
|
-
options: TOptions,
|
|
126
|
-
): ?$ReadOnly<CacheEntry<TData>> => {
|
|
127
|
-
// Get the cached entry for this value.
|
|
128
|
-
// If the handler wants WB Data to hydrate (i.e. handler.hydrate is
|
|
129
|
-
// true), we use our hydration cache. Otherwise, if we're server-side
|
|
130
|
-
// we use our SSR-only cache. Otherwise, there's no entry to return.
|
|
131
|
-
const cache = handler.hydrate
|
|
132
|
-
? this._hydrationCache
|
|
133
|
-
: Server.isServerSide()
|
|
134
|
-
? this._ssrOnlyCache
|
|
135
|
-
: undefined;
|
|
136
|
-
const internalEntry = cache?.retrieve(handler, options);
|
|
137
|
-
|
|
138
|
-
// If we are not server-side and we hydrated something, let's clear
|
|
139
|
-
// that from the hydration cache to save memory.
|
|
140
|
-
if (this._ssrOnlyCache == null && internalEntry != null) {
|
|
141
|
-
// We now delete this from our hydration cache as we don't need it.
|
|
142
|
-
// This does mean that if another handler of the same type but
|
|
143
|
-
// without some sort of linked cache won't get the value, but
|
|
144
|
-
// that's not an expected use-case. If two different places use the
|
|
145
|
-
// same handler and options (i.e. the same request), then the
|
|
146
|
-
// handler should cater to that to ensure they share the result.
|
|
147
|
-
this._hydrationCache.remove(handler, options);
|
|
148
|
-
}
|
|
149
|
-
return internalEntry;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Remove from cache, the entry matching the given handler and options.
|
|
154
|
-
*
|
|
155
|
-
* This will, if present therein, remove the value from the custom cache
|
|
156
|
-
* associated with the handler and the framework in-memory cache.
|
|
157
|
-
*
|
|
158
|
-
* Returns true if something was removed from any cache; otherwise, false.
|
|
159
|
-
*/
|
|
160
|
-
remove: <TOptions, TData: ValidData>(
|
|
161
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
162
|
-
options: TOptions,
|
|
163
|
-
) => boolean = <TOptions, TData: ValidData>(
|
|
164
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
165
|
-
options: TOptions,
|
|
166
|
-
): boolean => {
|
|
167
|
-
// NOTE(somewhatabstract): We could invoke removeAll with a predicate
|
|
168
|
-
// to match the key of the entry we're removing, but that's an
|
|
169
|
-
// inefficient way to remove a single item, so let's not do that.
|
|
170
|
-
|
|
171
|
-
// Delete the entry from the appropriate cache.
|
|
172
|
-
return handler.hydrate
|
|
173
|
-
? this._hydrationCache.remove(handler, options)
|
|
174
|
-
: this._ssrOnlyCache?.remove(handler, options) ?? false;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Remove from cache, any entries matching the given handler and predicate.
|
|
179
|
-
*
|
|
180
|
-
* This will, if present therein, remove matching values from the framework
|
|
181
|
-
* in-memory cache.
|
|
182
|
-
*
|
|
183
|
-
* It returns a count of all records removed.
|
|
184
|
-
*/
|
|
185
|
-
removeAll: <TOptions, TData: ValidData>(
|
|
186
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
187
|
-
predicate?: (
|
|
188
|
-
key: string,
|
|
189
|
-
cachedEntry: $ReadOnly<CacheEntry<TData>>,
|
|
190
|
-
) => boolean,
|
|
191
|
-
) => number = <TOptions, TData: ValidData>(
|
|
192
|
-
handler: IRequestHandler<TOptions, TData>,
|
|
193
|
-
predicate?: (
|
|
194
|
-
key: string,
|
|
195
|
-
cachedEntry: $ReadOnly<CacheEntry<TData>>,
|
|
196
|
-
) => boolean,
|
|
197
|
-
): number => {
|
|
198
|
-
// Apply the predicate to what we have in the appropriate cache.
|
|
199
|
-
return handler.hydrate
|
|
200
|
-
? this._hydrationCache.removeAll(handler, predicate)
|
|
201
|
-
: this._ssrOnlyCache?.removeAll(handler, predicate) ?? 0;
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Deep clone the hydration cache.
|
|
206
|
-
*
|
|
207
|
-
* By design, this only clones the data that is to be used for hydration.
|
|
208
|
-
*/
|
|
209
|
-
cloneHydratableData: () => $ReadOnly<Cache> = (): $ReadOnly<Cache> => {
|
|
210
|
-
// We return our hydration cache only.
|
|
211
|
-
return this._hydrationCache.cloneData();
|
|
212
|
-
};
|
|
213
|
-
}
|