react-native-onyx 2.0.41 → 2.0.43
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/Onyx.js +61 -26
- package/dist/OnyxCache.d.ts +24 -18
- package/dist/OnyxCache.js +53 -31
- package/dist/OnyxUtils.d.ts +7 -7
- package/dist/OnyxUtils.js +43 -37
- package/dist/index.d.ts +6 -5
- package/dist/index.js +1 -1
- package/dist/storage/providers/IDBKeyValProvider.js +24 -3
- package/dist/types.d.ts +6 -15
- package/dist/utils.d.ts +20 -2
- package/dist/utils.js +52 -2
- package/dist/withOnyx/index.d.ts +15 -0
- package/dist/{withOnyx.js → withOnyx/index.js} +64 -67
- package/dist/{withOnyx.d.ts → withOnyx/types.d.ts} +45 -45
- package/dist/withOnyx/types.js +2 -0
- package/package.json +2 -2
package/dist/Onyx.js
CHANGED
|
@@ -47,7 +47,7 @@ function init({ keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCach
|
|
|
47
47
|
storage_1.default.init();
|
|
48
48
|
if (shouldSyncMultipleInstances) {
|
|
49
49
|
(_a = storage_1.default.keepInstancesSync) === null || _a === void 0 ? void 0 : _a.call(storage_1.default, (key, value) => {
|
|
50
|
-
const prevValue = OnyxCache_1.default.
|
|
50
|
+
const prevValue = OnyxCache_1.default.get(key, false);
|
|
51
51
|
OnyxCache_1.default.set(key, value);
|
|
52
52
|
OnyxUtils_1.default.keyChanged(key, value, prevValue);
|
|
53
53
|
});
|
|
@@ -106,7 +106,7 @@ function connect(connectOptions) {
|
|
|
106
106
|
// Performance improvement
|
|
107
107
|
// If the mapping is connected to an onyx key that is not a collection
|
|
108
108
|
// we can skip the call to getAllKeys() and return an array with a single item
|
|
109
|
-
if (Boolean(mapping.key) && typeof mapping.key === 'string' && !mapping.key.endsWith('_') && OnyxCache_1.default.
|
|
109
|
+
if (Boolean(mapping.key) && typeof mapping.key === 'string' && !mapping.key.endsWith('_') && OnyxCache_1.default.getAllKeys().has(mapping.key)) {
|
|
110
110
|
return new Set([mapping.key]);
|
|
111
111
|
}
|
|
112
112
|
return OnyxUtils_1.default.getAllKeys();
|
|
@@ -122,9 +122,9 @@ function connect(connectOptions) {
|
|
|
122
122
|
// component. This null value will be filtered out so that the connected component can utilize defaultProps.
|
|
123
123
|
if (matchingKeys.length === 0) {
|
|
124
124
|
if (mapping.key && !OnyxUtils_1.default.isCollectionKey(mapping.key)) {
|
|
125
|
-
OnyxCache_1.default.
|
|
125
|
+
OnyxCache_1.default.addNullishStorageKey(mapping.key);
|
|
126
126
|
}
|
|
127
|
-
// Here we cannot use batching because the
|
|
127
|
+
// Here we cannot use batching because the nullish value is expected to be set immediately for default props
|
|
128
128
|
// or they will be undefined.
|
|
129
129
|
OnyxUtils_1.default.sendDataToConnection(mapping, null, undefined, false);
|
|
130
130
|
return;
|
|
@@ -192,8 +192,17 @@ function disconnect(connectionID, keyToRemoveFromEvictionBlocklist) {
|
|
|
192
192
|
* @param value value to store
|
|
193
193
|
*/
|
|
194
194
|
function set(key, value) {
|
|
195
|
-
//
|
|
196
|
-
|
|
195
|
+
// When we use Onyx.set to set a key we want to clear the current delta changes from Onyx.merge that were queued
|
|
196
|
+
// before the value was set. If Onyx.merge is currently reading the old value from storage, it will then not apply the changes.
|
|
197
|
+
if (OnyxUtils_1.default.hasPendingMergeForKey(key)) {
|
|
198
|
+
delete OnyxUtils_1.default.getMergeQueue()[key];
|
|
199
|
+
}
|
|
200
|
+
const existingValue = OnyxCache_1.default.get(key, false);
|
|
201
|
+
// If the existing value as well as the new value are null, we can return early.
|
|
202
|
+
if (value === null && existingValue === null) {
|
|
203
|
+
return Promise.resolve();
|
|
204
|
+
}
|
|
205
|
+
// Check if the value is compatible with the existing value in the storage
|
|
197
206
|
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(value, existingValue);
|
|
198
207
|
if (!isCompatible) {
|
|
199
208
|
Logger.logAlert(logMessages_1.default.incompatibleUpdateAlert(key, 'set', existingValueType, newValueType));
|
|
@@ -201,17 +210,23 @@ function set(key, value) {
|
|
|
201
210
|
}
|
|
202
211
|
// If the value is null, we remove the key from storage
|
|
203
212
|
const { value: valueAfterRemoving, wasRemoved } = OnyxUtils_1.default.removeNullValues(key, value);
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
const logSetCall = (hasChanged = true) => {
|
|
214
|
+
// Logging properties only since values could be sensitive things we don't want to log
|
|
215
|
+
Logger.logInfo(`set called for key: ${key}${underscore_1.default.isObject(value) ? ` properties: ${underscore_1.default.keys(value).join(',')}` : ''} hasChanged: ${hasChanged}`);
|
|
216
|
+
};
|
|
217
|
+
// Calling "OnyxUtils.removeNullValues" removes the key from storage and cache and updates the subscriber.
|
|
218
|
+
// Therefore, we don't need to further broadcast and update the value so we can return early.
|
|
219
|
+
if (wasRemoved) {
|
|
220
|
+
logSetCall();
|
|
221
|
+
return Promise.resolve();
|
|
207
222
|
}
|
|
223
|
+
const valueWithoutNullValues = valueAfterRemoving;
|
|
208
224
|
const hasChanged = OnyxCache_1.default.hasValueChanged(key, valueWithoutNullValues);
|
|
209
|
-
|
|
210
|
-
Logger.logInfo(`set called for key: ${key}${underscore_1.default.isObject(value) ? ` properties: ${underscore_1.default.keys(value).join(',')}` : ''} hasChanged: ${hasChanged}`);
|
|
225
|
+
logSetCall(hasChanged);
|
|
211
226
|
// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
|
|
212
|
-
const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNullValues, hasChanged
|
|
227
|
+
const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, valueWithoutNullValues, hasChanged);
|
|
213
228
|
// If the value has not changed or the key got removed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
214
|
-
if (!hasChanged
|
|
229
|
+
if (!hasChanged) {
|
|
215
230
|
return updatePromise;
|
|
216
231
|
}
|
|
217
232
|
return storage_1.default.setItem(key, valueWithoutNullValues)
|
|
@@ -229,18 +244,28 @@ function set(key, value) {
|
|
|
229
244
|
* @param data object keyed by ONYXKEYS and the values to set
|
|
230
245
|
*/
|
|
231
246
|
function multiSet(data) {
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
247
|
+
const allKeyValuePairs = OnyxUtils_1.default.prepareKeyValuePairsForStorage(data, true);
|
|
248
|
+
// When a key is set to null, we need to remove the remove the key from storage using "OnyxUtils.remove".
|
|
249
|
+
// Therefore, we filter the key value pairs to exclude null values and remove those keys explicitly.
|
|
250
|
+
const removePromises = [];
|
|
251
|
+
const keyValuePairsToUpdate = allKeyValuePairs.filter(([key, value]) => {
|
|
252
|
+
if (value === null) {
|
|
253
|
+
removePromises.push(OnyxUtils_1.default.remove(key));
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
return true;
|
|
257
|
+
});
|
|
258
|
+
const updatePromises = keyValuePairsToUpdate.map(([key, value]) => {
|
|
259
|
+
const prevValue = OnyxCache_1.default.get(key, false);
|
|
235
260
|
// Update cache and optimistically inform subscribers on the next tick
|
|
236
261
|
OnyxCache_1.default.set(key, value);
|
|
237
262
|
return OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, prevValue);
|
|
238
263
|
});
|
|
239
|
-
return storage_1.default.multiSet(
|
|
264
|
+
return storage_1.default.multiSet(allKeyValuePairs)
|
|
240
265
|
.catch((error) => OnyxUtils_1.default.evictStorageAndRetry(error, multiSet, data))
|
|
241
266
|
.then(() => {
|
|
242
267
|
OnyxUtils_1.default.sendActionToDevTools(OnyxUtils_1.default.METHOD.MULTI_SET, undefined, data);
|
|
243
|
-
return Promise.all(updatePromises);
|
|
268
|
+
return Promise.all([removePromises, updatePromises]);
|
|
244
269
|
})
|
|
245
270
|
.then(() => undefined);
|
|
246
271
|
}
|
|
@@ -278,7 +303,7 @@ function merge(key, changes) {
|
|
|
278
303
|
mergeQueuePromise[key] = OnyxUtils_1.default.get(key).then((existingValue) => {
|
|
279
304
|
// Calls to Onyx.set after a merge will terminate the current merge process and clear the merge queue
|
|
280
305
|
if (mergeQueue[key] == null) {
|
|
281
|
-
return
|
|
306
|
+
return Promise.resolve();
|
|
282
307
|
}
|
|
283
308
|
try {
|
|
284
309
|
// We first only merge the changes, so we can provide these to the native implementation (SQLite uses only delta changes in "JSON_PATCH" to merge)
|
|
@@ -291,7 +316,7 @@ function merge(key, changes) {
|
|
|
291
316
|
return isCompatible;
|
|
292
317
|
});
|
|
293
318
|
if (!validChanges.length) {
|
|
294
|
-
return
|
|
319
|
+
return Promise.resolve();
|
|
295
320
|
}
|
|
296
321
|
const batchedDeltaChanges = OnyxUtils_1.default.applyMerge(undefined, validChanges, false);
|
|
297
322
|
// Case (1): When there is no existing value in storage, we want to set the value instead of merge it.
|
|
@@ -301,8 +326,18 @@ function merge(key, changes) {
|
|
|
301
326
|
// Clean up the write queue, so we don't apply these changes again
|
|
302
327
|
delete mergeQueue[key];
|
|
303
328
|
delete mergeQueuePromise[key];
|
|
329
|
+
const logMergeCall = (hasChanged = true) => {
|
|
330
|
+
// Logging properties only since values could be sensitive things we don't want to log
|
|
331
|
+
Logger.logInfo(`merge called for key: ${key}${underscore_1.default.isObject(batchedDeltaChanges) ? ` properties: ${underscore_1.default.keys(batchedDeltaChanges).join(',')}` : ''} hasChanged: ${hasChanged}`);
|
|
332
|
+
};
|
|
304
333
|
// If the batched changes equal null, we want to remove the key from storage, to reduce storage size
|
|
305
334
|
const { wasRemoved } = OnyxUtils_1.default.removeNullValues(key, batchedDeltaChanges);
|
|
335
|
+
// Calling "OnyxUtils.removeNullValues" removes the key from storage and cache and updates the subscriber.
|
|
336
|
+
// Therefore, we don't need to further broadcast and update the value so we can return early.
|
|
337
|
+
if (wasRemoved) {
|
|
338
|
+
logMergeCall();
|
|
339
|
+
return Promise.resolve();
|
|
340
|
+
}
|
|
306
341
|
// For providers that can't handle delta changes, we need to merge the batched changes with the existing value beforehand.
|
|
307
342
|
// The "preMergedValue" will be directly "set" in storage instead of being merged
|
|
308
343
|
// Therefore we merge the batched changes with the existing value to get the final merged value that will be stored.
|
|
@@ -310,12 +345,11 @@ function merge(key, changes) {
|
|
|
310
345
|
const preMergedValue = OnyxUtils_1.default.applyMerge(shouldSetValue ? undefined : existingValue, [batchedDeltaChanges], true);
|
|
311
346
|
// In cache, we don't want to remove the key if it's null to improve performance and speed up the next merge.
|
|
312
347
|
const hasChanged = OnyxCache_1.default.hasValueChanged(key, preMergedValue);
|
|
313
|
-
|
|
314
|
-
Logger.logInfo(`merge called for key: ${key}${underscore_1.default.isObject(batchedDeltaChanges) ? ` properties: ${underscore_1.default.keys(batchedDeltaChanges).join(',')}` : ''} hasChanged: ${hasChanged}`);
|
|
348
|
+
logMergeCall(hasChanged);
|
|
315
349
|
// This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
|
|
316
|
-
const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, preMergedValue, hasChanged
|
|
350
|
+
const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, preMergedValue, hasChanged);
|
|
317
351
|
// If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
|
|
318
|
-
if (!hasChanged
|
|
352
|
+
if (!hasChanged) {
|
|
319
353
|
return updatePromise;
|
|
320
354
|
}
|
|
321
355
|
return storage_1.default.mergeItem(key, batchedDeltaChanges, preMergedValue, shouldSetValue).then(() => {
|
|
@@ -453,6 +487,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
453
487
|
function clear(keysToPreserve = []) {
|
|
454
488
|
return OnyxUtils_1.default.getAllKeys()
|
|
455
489
|
.then((keys) => {
|
|
490
|
+
OnyxCache_1.default.clearNullishStorageKeys();
|
|
456
491
|
const keysToBeClearedFromStorage = [];
|
|
457
492
|
const keyValuesToResetAsCollection = {};
|
|
458
493
|
const keyValuesToResetIndividually = {};
|
|
@@ -471,7 +506,7 @@ function clear(keysToPreserve = []) {
|
|
|
471
506
|
// 2. Figure out whether it is a collection key or not,
|
|
472
507
|
// since collection key subscribers need to be updated differently
|
|
473
508
|
if (!isKeyToPreserve) {
|
|
474
|
-
const oldValue = OnyxCache_1.default.
|
|
509
|
+
const oldValue = OnyxCache_1.default.get(key);
|
|
475
510
|
const newValue = (_a = defaultKeyStates[key]) !== null && _a !== void 0 ? _a : null;
|
|
476
511
|
if (newValue !== oldValue) {
|
|
477
512
|
OnyxCache_1.default.set(key, newValue);
|
|
@@ -496,7 +531,7 @@ function clear(keysToPreserve = []) {
|
|
|
496
531
|
const updatePromises = [];
|
|
497
532
|
// Notify the subscribers for each key/value group so they can receive the new values
|
|
498
533
|
Object.entries(keyValuesToResetIndividually).forEach(([key, value]) => {
|
|
499
|
-
updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.
|
|
534
|
+
updatePromises.push(OnyxUtils_1.default.scheduleSubscriberUpdate(key, value, OnyxCache_1.default.get(key, false)));
|
|
500
535
|
});
|
|
501
536
|
Object.entries(keyValuesToResetAsCollection).forEach(([key, value]) => {
|
|
502
537
|
updatePromises.push(OnyxUtils_1.default.scheduleNotifyCollectionSubscribers(key, value));
|
package/dist/OnyxCache.d.ts
CHANGED
|
@@ -5,7 +5,9 @@ import type { OnyxKey, OnyxValue } from './types';
|
|
|
5
5
|
*/
|
|
6
6
|
declare class OnyxCache {
|
|
7
7
|
/** Cache of all the storage keys available in persistent storage */
|
|
8
|
-
storageKeys
|
|
8
|
+
private storageKeys;
|
|
9
|
+
/** A list of keys where a nullish value has been fetched from storage before, but the key still exists in cache */
|
|
10
|
+
private nullishStorageKeys;
|
|
9
11
|
/** Unique list of keys maintained in access order (most recent at the end) */
|
|
10
12
|
private recentKeys;
|
|
11
13
|
/** A map of cached values */
|
|
@@ -21,16 +23,32 @@ declare class OnyxCache {
|
|
|
21
23
|
/** Get all the storage keys */
|
|
22
24
|
getAllKeys(): Set<OnyxKey>;
|
|
23
25
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
+
* Allows to set all the keys at once.
|
|
27
|
+
* This is useful when we are getting
|
|
28
|
+
* all the keys from the storage provider
|
|
29
|
+
* and we want to keep the cache in sync.
|
|
30
|
+
*
|
|
31
|
+
* Previously, we had to call `addKey` in a loop
|
|
32
|
+
* to achieve the same result.
|
|
33
|
+
*
|
|
34
|
+
* @param keys - an array of keys
|
|
26
35
|
*/
|
|
27
|
-
|
|
28
|
-
/** Check whether cache has data for the given key */
|
|
29
|
-
hasCacheForKey(key: OnyxKey): boolean;
|
|
36
|
+
setAllKeys(keys: OnyxKey[]): void;
|
|
30
37
|
/** Saves a key in the storage keys list
|
|
31
38
|
* Serves to keep the result of `getAllKeys` up to date
|
|
32
39
|
*/
|
|
33
40
|
addKey(key: OnyxKey): void;
|
|
41
|
+
/** Used to set keys that are null/undefined in storage without adding null to the storage map */
|
|
42
|
+
addNullishStorageKey(key: OnyxKey): void;
|
|
43
|
+
/** Used to clear keys that are null/undefined in cache */
|
|
44
|
+
clearNullishStorageKeys(): void;
|
|
45
|
+
/** Check whether cache has data for the given key */
|
|
46
|
+
hasCacheForKey(key: OnyxKey): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Get a cached value from storage
|
|
49
|
+
* @param [shouldReindexCache] – This is an LRU cache, and by default accessing a value will make it become last in line to be evicted. This flag can be used to skip that and just access the value directly without side-effects.
|
|
50
|
+
*/
|
|
51
|
+
get(key: OnyxKey, shouldReindexCache?: boolean): OnyxValue<OnyxKey>;
|
|
34
52
|
/**
|
|
35
53
|
* Set's a key value in cache
|
|
36
54
|
* Adds the key to the storage keys list as well
|
|
@@ -43,18 +61,6 @@ declare class OnyxCache {
|
|
|
43
61
|
* @param data - a map of (cache) key - values
|
|
44
62
|
*/
|
|
45
63
|
merge(data: Record<OnyxKey, OnyxValue<OnyxKey>>): void;
|
|
46
|
-
/**
|
|
47
|
-
* Allows to set all the keys at once.
|
|
48
|
-
* This is useful when we are getting
|
|
49
|
-
* all the keys from the storage provider
|
|
50
|
-
* and we want to keep the cache in sync.
|
|
51
|
-
*
|
|
52
|
-
* Previously, we had to call `addKey` in a loop
|
|
53
|
-
* to achieve the same result.
|
|
54
|
-
*
|
|
55
|
-
* @param keys - an array of keys
|
|
56
|
-
*/
|
|
57
|
-
setAllKeys(keys: OnyxKey[]): void;
|
|
58
64
|
/**
|
|
59
65
|
* Check whether the given task is already running
|
|
60
66
|
* @param taskName - unique name given for the task
|
package/dist/OnyxCache.js
CHANGED
|
@@ -15,29 +15,30 @@ class OnyxCache {
|
|
|
15
15
|
/** Maximum size of the keys store din cache */
|
|
16
16
|
this.maxRecentKeysSize = 0;
|
|
17
17
|
this.storageKeys = new Set();
|
|
18
|
+
this.nullishStorageKeys = new Set();
|
|
18
19
|
this.recentKeys = new Set();
|
|
19
20
|
this.storageMap = {};
|
|
20
21
|
this.pendingPromises = new Map();
|
|
21
22
|
// bind all public methods to prevent problems with `this`
|
|
22
|
-
(0, bindAll_1.default)(this, 'getAllKeys', '
|
|
23
|
+
(0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys');
|
|
23
24
|
}
|
|
24
25
|
/** Get all the storage keys */
|
|
25
26
|
getAllKeys() {
|
|
26
27
|
return this.storageKeys;
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* Allows to set all the keys at once.
|
|
31
|
+
* This is useful when we are getting
|
|
32
|
+
* all the keys from the storage provider
|
|
33
|
+
* and we want to keep the cache in sync.
|
|
34
|
+
*
|
|
35
|
+
* Previously, we had to call `addKey` in a loop
|
|
36
|
+
* to achieve the same result.
|
|
37
|
+
*
|
|
38
|
+
* @param keys - an array of keys
|
|
31
39
|
*/
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
this.addToAccessedKeys(key);
|
|
35
|
-
}
|
|
36
|
-
return this.storageMap[key];
|
|
37
|
-
}
|
|
38
|
-
/** Check whether cache has data for the given key */
|
|
39
|
-
hasCacheForKey(key) {
|
|
40
|
-
return this.storageMap[key] !== undefined;
|
|
40
|
+
setAllKeys(keys) {
|
|
41
|
+
this.storageKeys = new Set(keys);
|
|
41
42
|
}
|
|
42
43
|
/** Saves a key in the storage keys list
|
|
43
44
|
* Serves to keep the result of `getAllKeys` up to date
|
|
@@ -45,6 +46,28 @@ class OnyxCache {
|
|
|
45
46
|
addKey(key) {
|
|
46
47
|
this.storageKeys.add(key);
|
|
47
48
|
}
|
|
49
|
+
/** Used to set keys that are null/undefined in storage without adding null to the storage map */
|
|
50
|
+
addNullishStorageKey(key) {
|
|
51
|
+
this.nullishStorageKeys.add(key);
|
|
52
|
+
}
|
|
53
|
+
/** Used to clear keys that are null/undefined in cache */
|
|
54
|
+
clearNullishStorageKeys() {
|
|
55
|
+
this.nullishStorageKeys = new Set();
|
|
56
|
+
}
|
|
57
|
+
/** Check whether cache has data for the given key */
|
|
58
|
+
hasCacheForKey(key) {
|
|
59
|
+
return this.storageMap[key] !== undefined || this.nullishStorageKeys.has(key);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get a cached value from storage
|
|
63
|
+
* @param [shouldReindexCache] – This is an LRU cache, and by default accessing a value will make it become last in line to be evicted. This flag can be used to skip that and just access the value directly without side-effects.
|
|
64
|
+
*/
|
|
65
|
+
get(key, shouldReindexCache = true) {
|
|
66
|
+
if (shouldReindexCache) {
|
|
67
|
+
this.addToAccessedKeys(key);
|
|
68
|
+
}
|
|
69
|
+
return this.storageMap[key];
|
|
70
|
+
}
|
|
48
71
|
/**
|
|
49
72
|
* Set's a key value in cache
|
|
50
73
|
* Adds the key to the storage keys list as well
|
|
@@ -52,6 +75,13 @@ class OnyxCache {
|
|
|
52
75
|
set(key, value) {
|
|
53
76
|
this.addKey(key);
|
|
54
77
|
this.addToAccessedKeys(key);
|
|
78
|
+
// When a key is explicitly set in cache, we can remove it from the list of nullish keys,
|
|
79
|
+
// since it will either be set to a non nullish value or removed from the cache completely.
|
|
80
|
+
this.nullishStorageKeys.delete(key);
|
|
81
|
+
if (value === null || value === undefined) {
|
|
82
|
+
delete this.storageMap[key];
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
55
85
|
this.storageMap[key] = value;
|
|
56
86
|
return value;
|
|
57
87
|
}
|
|
@@ -69,25 +99,17 @@ class OnyxCache {
|
|
|
69
99
|
if (typeof data !== 'object' || Array.isArray(data)) {
|
|
70
100
|
throw new Error('data passed to cache.merge() must be an Object of onyx key/value pairs');
|
|
71
101
|
}
|
|
72
|
-
this.storageMap = Object.assign({}, utils_1.default.fastMerge(this.storageMap, data
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
*
|
|
84
|
-
* Previously, we had to call `addKey` in a loop
|
|
85
|
-
* to achieve the same result.
|
|
86
|
-
*
|
|
87
|
-
* @param keys - an array of keys
|
|
88
|
-
*/
|
|
89
|
-
setAllKeys(keys) {
|
|
90
|
-
this.storageKeys = new Set(keys);
|
|
102
|
+
this.storageMap = Object.assign({}, utils_1.default.fastMerge(this.storageMap, data));
|
|
103
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
104
|
+
this.addKey(key);
|
|
105
|
+
this.addToAccessedKeys(key);
|
|
106
|
+
if (value === null || value === undefined) {
|
|
107
|
+
this.addNullishStorageKey(key);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
this.nullishStorageKeys.delete(key);
|
|
111
|
+
}
|
|
112
|
+
});
|
|
91
113
|
}
|
|
92
114
|
/**
|
|
93
115
|
* Check whether the given task is already running
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ValueOf } from 'type-fest';
|
|
2
|
-
import type { DeepRecord, Mapping, CollectionKey, CollectionKeyBase, NullableKeyValueMapping, OnyxKey, OnyxValue, OnyxCollection, WithOnyxConnectOptions, OnyxEntry, KeyValueMapping } from './types';
|
|
3
2
|
import type Onyx from './Onyx';
|
|
3
|
+
import type { CollectionKey, CollectionKeyBase, DeepRecord, KeyValueMapping, Mapping, NullableKeyValueMapping, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue, WithOnyxConnectOptions } from './types';
|
|
4
4
|
declare const METHOD: {
|
|
5
5
|
readonly SET: "set";
|
|
6
6
|
readonly MERGE: "merge";
|
|
@@ -107,7 +107,7 @@ declare function getCachedCollection<TKey extends CollectionKeyBase>(collectionK
|
|
|
107
107
|
/**
|
|
108
108
|
* When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
|
|
109
109
|
*/
|
|
110
|
-
declare function keysChanged<TKey extends CollectionKeyBase>(collectionKey: TKey, partialCollection: OnyxCollection<KeyValueMapping[TKey]>,
|
|
110
|
+
declare function keysChanged<TKey extends CollectionKeyBase>(collectionKey: TKey, partialCollection: OnyxCollection<KeyValueMapping[TKey]>, partialPreviousCollection: OnyxCollection<KeyValueMapping[TKey]> | undefined, notifyRegularSubscibers?: boolean, notifyWithOnyxSubscibers?: boolean): void;
|
|
111
111
|
/**
|
|
112
112
|
* When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
|
|
113
113
|
*
|
|
@@ -120,7 +120,7 @@ declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TK
|
|
|
120
120
|
* - sets state on the withOnyxInstances
|
|
121
121
|
* - triggers the callback function
|
|
122
122
|
*/
|
|
123
|
-
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: Mapping<TKey>,
|
|
123
|
+
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: Mapping<TKey>, value: OnyxValue<TKey> | null, matchedKey: TKey | undefined, isBatched: boolean): void;
|
|
124
124
|
/**
|
|
125
125
|
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
126
126
|
* run out of storage the least recently accessed key can be removed.
|
|
@@ -157,10 +157,10 @@ declare function evictStorageAndRetry<TMethod extends typeof Onyx.set | typeof O
|
|
|
157
157
|
/**
|
|
158
158
|
* Notifies subscribers and writes current value to cache
|
|
159
159
|
*/
|
|
160
|
-
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean
|
|
160
|
+
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean): Promise<void>;
|
|
161
161
|
declare function hasPendingMergeForKey(key: OnyxKey): boolean;
|
|
162
|
-
type RemoveNullValuesOutput = {
|
|
163
|
-
value:
|
|
162
|
+
type RemoveNullValuesOutput<Value extends OnyxValue<OnyxKey> | null> = {
|
|
163
|
+
value: Value | null;
|
|
164
164
|
wasRemoved: boolean;
|
|
165
165
|
};
|
|
166
166
|
/**
|
|
@@ -170,7 +170,7 @@ type RemoveNullValuesOutput = {
|
|
|
170
170
|
*
|
|
171
171
|
* @returns The value without null values and a boolean "wasRemoved", which indicates if the key got removed completely
|
|
172
172
|
*/
|
|
173
|
-
declare function removeNullValues(key: OnyxKey, value:
|
|
173
|
+
declare function removeNullValues<Value extends OnyxValue<OnyxKey>>(key: OnyxKey, value: Value | null, shouldRemoveNestedNulls?: boolean): RemoveNullValuesOutput<Value>;
|
|
174
174
|
/**
|
|
175
175
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
176
176
|
* This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
|