react-native-onyx 3.0.115 → 3.0.116
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 +7 -3
- package/dist/OnyxUtils.d.ts +7 -0
- package/dist/OnyxUtils.js +62 -0
- package/package.json +1 -1
package/dist/Onyx.js
CHANGED
|
@@ -239,16 +239,18 @@ function merge(key, changes) {
|
|
|
239
239
|
mergeQueue[key].push(changes);
|
|
240
240
|
return mergeQueuePromise[key];
|
|
241
241
|
}
|
|
242
|
-
|
|
242
|
+
const queuedChanges = [changes];
|
|
243
|
+
mergeQueue[key] = queuedChanges;
|
|
243
244
|
mergeQueuePromise[key] = OnyxUtils_1.default.get(key).then((valueFromGet) => {
|
|
244
245
|
// Calls to Onyx.set after a merge will terminate the current merge process and clear the merge queue
|
|
245
|
-
if (mergeQueue[key]
|
|
246
|
+
if (mergeQueue[key] !== queuedChanges) {
|
|
246
247
|
return Promise.resolve();
|
|
247
248
|
}
|
|
248
249
|
// Other writers (notably Onyx.update's mergeCollection path, which doesn't participate in mergeQueue)
|
|
249
250
|
// can land between get() resolving and this callback running. Applying the delta on top of the value
|
|
250
251
|
// captured back then and broadcasting it would overwrite those writes wholesale, so re-read the cache.
|
|
251
|
-
const
|
|
252
|
+
const baseValue = OnyxUtils_1.default.hasStaleMergeRead(queuedChanges) ? undefined : valueFromGet;
|
|
253
|
+
const existingValue = OnyxCache_1.default.hasCacheForKey(key) ? OnyxCache_1.default.get(key) : baseValue;
|
|
252
254
|
try {
|
|
253
255
|
const validChanges = mergeQueue[key].filter((change) => {
|
|
254
256
|
const { isCompatible, existingValueType, newValueType, isEmptyArrayCoercion } = utils_1.default.checkCompatibilityWithExistingValue(change, existingValue);
|
|
@@ -327,6 +329,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
327
329
|
*/
|
|
328
330
|
function clear(keysToPreserve = []) {
|
|
329
331
|
return OnyxUtils_1.default.afterInit(() => {
|
|
332
|
+
const pendingMergeEntries = OnyxUtils_1.default.getPendingMergeEntries(keysToPreserve);
|
|
330
333
|
const defaultKeyStates = OnyxUtils_1.default.getDefaultKeyStates();
|
|
331
334
|
const initialKeys = Object.keys(defaultKeyStates);
|
|
332
335
|
const promise = OnyxUtils_1.default.getAllKeys()
|
|
@@ -339,6 +342,7 @@ function clear(keysToPreserve = []) {
|
|
|
339
342
|
// because the notification process needs the old values in cache but at that point they will be already removed from it.
|
|
340
343
|
const keyValuesToResetAsCollection = {};
|
|
341
344
|
const allKeys = new Set([...cachedKeys, ...initialKeys]);
|
|
345
|
+
OnyxUtils_1.default.cancelPendingMerges(pendingMergeEntries);
|
|
342
346
|
// The only keys that should not be cleared are:
|
|
343
347
|
// 1. Anything specifically passed in keysToPreserve (because some keys like language preferences, offline
|
|
344
348
|
// status, or activeClients need to remain in Onyx even when signed out)
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -164,6 +164,10 @@ declare function retryOperation<TMethod extends RetriableOnyxOperation>(error: E
|
|
|
164
164
|
*/
|
|
165
165
|
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean): void;
|
|
166
166
|
declare function hasPendingMergeForKey(key: OnyxKey): boolean;
|
|
167
|
+
type PendingMergeEntry = [OnyxKey, Array<OnyxValue<OnyxKey>>, number];
|
|
168
|
+
declare function getPendingMergeEntries(keysToPreserve: OnyxKey[]): PendingMergeEntry[];
|
|
169
|
+
declare function cancelPendingMerges(entries: PendingMergeEntry[]): void;
|
|
170
|
+
declare function hasStaleMergeRead(queuedChanges: Array<OnyxValue<OnyxKey>>): boolean;
|
|
167
171
|
/**
|
|
168
172
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
169
173
|
* This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
|
|
@@ -305,6 +309,9 @@ declare const OnyxUtils: {
|
|
|
305
309
|
retryOperation: typeof retryOperation;
|
|
306
310
|
broadcastUpdate: typeof broadcastUpdate;
|
|
307
311
|
hasPendingMergeForKey: typeof hasPendingMergeForKey;
|
|
312
|
+
getPendingMergeEntries: typeof getPendingMergeEntries;
|
|
313
|
+
cancelPendingMerges: typeof cancelPendingMerges;
|
|
314
|
+
hasStaleMergeRead: typeof hasStaleMergeRead;
|
|
308
315
|
prepareKeyValuePairsForStorage: typeof prepareKeyValuePairsForStorage;
|
|
309
316
|
mergeChanges: typeof mergeChanges;
|
|
310
317
|
mergeAndMarkChanges: typeof mergeAndMarkChanges;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -74,6 +74,7 @@ function formatCaughtError(error) {
|
|
|
74
74
|
// Key/value store of Onyx key and arrays of values to merge
|
|
75
75
|
let mergeQueue = {};
|
|
76
76
|
let mergeQueuePromise = {};
|
|
77
|
+
const mergeQueuesWithStaleRead = new WeakSet();
|
|
77
78
|
// Holds a mapping of all the React components that want their state subscribed to a store key
|
|
78
79
|
let callbackToStateMapping = {};
|
|
79
80
|
// Holds a mapping of the connected key to the subscriptionID for faster lookups
|
|
@@ -773,6 +774,52 @@ function broadcastUpdate(key, value, hasChanged) {
|
|
|
773
774
|
function hasPendingMergeForKey(key) {
|
|
774
775
|
return !!mergeQueue[key];
|
|
775
776
|
}
|
|
777
|
+
function cancelPendingMergesForKey(key) {
|
|
778
|
+
delete mergeQueue[key];
|
|
779
|
+
delete mergeQueuePromise[key];
|
|
780
|
+
}
|
|
781
|
+
function cancelPendingMergesForCollection(collectionKey) {
|
|
782
|
+
for (const key of Object.keys(mergeQueue)) {
|
|
783
|
+
if (!OnyxKeys_1.default.isCollectionMemberKey(collectionKey, key)) {
|
|
784
|
+
continue;
|
|
785
|
+
}
|
|
786
|
+
cancelPendingMergesForKey(key);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
function getPendingMergeEntries(keysToPreserve) {
|
|
790
|
+
return Object.entries(mergeQueue)
|
|
791
|
+
.filter(([key]) => !keysToPreserve.some((preserveKey) => OnyxKeys_1.default.isKeyMatch(preserveKey, key)))
|
|
792
|
+
.map(([key, queuedChanges]) => [key, queuedChanges, queuedChanges.length]);
|
|
793
|
+
}
|
|
794
|
+
function cancelPendingMerges(entries) {
|
|
795
|
+
for (const [key, queuedChanges, capturedLength] of entries) {
|
|
796
|
+
if (mergeQueue[key] !== queuedChanges) {
|
|
797
|
+
continue;
|
|
798
|
+
}
|
|
799
|
+
if (queuedChanges.length === capturedLength) {
|
|
800
|
+
cancelPendingMergesForKey(key);
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
queuedChanges.splice(0, capturedLength);
|
|
804
|
+
mergeQueuesWithStaleRead.add(queuedChanges);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
function hasStaleMergeRead(queuedChanges) {
|
|
808
|
+
return mergeQueuesWithStaleRead.has(queuedChanges);
|
|
809
|
+
}
|
|
810
|
+
function cancelPendingMergesForKeys(keys) {
|
|
811
|
+
for (const key of keys) {
|
|
812
|
+
cancelPendingMergesForKey(key);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
function cancelPendingMergesForNullMembers(collection) {
|
|
816
|
+
for (const [key, value] of Object.entries(collection)) {
|
|
817
|
+
if (value !== null) {
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
cancelPendingMergesForKey(key);
|
|
821
|
+
}
|
|
822
|
+
}
|
|
776
823
|
/**
|
|
777
824
|
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
|
|
778
825
|
* This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
|
|
@@ -1197,6 +1244,9 @@ function multiSetWithRetry(data, retryAttempt) {
|
|
|
1197
1244
|
}, {});
|
|
1198
1245
|
}
|
|
1199
1246
|
const { pairs: keyValuePairsToSet, keysToRemove: removalCandidates } = OnyxUtils.prepareKeyValuePairsForStorage(newData, true);
|
|
1247
|
+
if (!retryAttempt) {
|
|
1248
|
+
cancelPendingMergesForKeys(removalCandidates);
|
|
1249
|
+
}
|
|
1200
1250
|
// Removals of keys that are neither cached nor persisted are no-ops and skipped. When the key
|
|
1201
1251
|
// index has not been loaded yet (empty set), keep the removal to be safe.
|
|
1202
1252
|
const persistedKeys = OnyxCache_1.default.getAllKeys();
|
|
@@ -1321,6 +1371,9 @@ function setCollectionWithRetry({ collectionKey, collection }, retryAttempt) {
|
|
|
1321
1371
|
}, {});
|
|
1322
1372
|
}
|
|
1323
1373
|
resultCollectionKeys = Object.keys(resultCollection);
|
|
1374
|
+
if (!retryAttempt) {
|
|
1375
|
+
cancelPendingMergesForCollection(collectionKey);
|
|
1376
|
+
}
|
|
1324
1377
|
return OnyxUtils.getAllKeys().then((persistedKeys) => {
|
|
1325
1378
|
const mutableCollection = Object.assign({}, resultCollection);
|
|
1326
1379
|
for (const key of persistedKeys) {
|
|
@@ -1408,6 +1461,9 @@ function mergeCollectionWithPatches({ collectionKey, collection, mergeReplaceNul
|
|
|
1408
1461
|
}, {});
|
|
1409
1462
|
}
|
|
1410
1463
|
resultCollectionKeys = Object.keys(resultCollection);
|
|
1464
|
+
if (!retryAttempt) {
|
|
1465
|
+
cancelPendingMergesForNullMembers(resultCollection);
|
|
1466
|
+
}
|
|
1411
1467
|
return getAllKeys()
|
|
1412
1468
|
.then((persistedKeys) => {
|
|
1413
1469
|
// Split to keys that exist in storage and keys that don't. Null members are collected
|
|
@@ -1561,6 +1617,9 @@ function partialSetCollection({ collectionKey, collection }, retryAttempt) {
|
|
|
1561
1617
|
}, {});
|
|
1562
1618
|
}
|
|
1563
1619
|
resultCollectionKeys = Object.keys(resultCollection);
|
|
1620
|
+
if (!retryAttempt) {
|
|
1621
|
+
cancelPendingMergesForKeys(resultCollectionKeys);
|
|
1622
|
+
}
|
|
1564
1623
|
return getAllKeys().then((persistedKeys) => {
|
|
1565
1624
|
const mutableCollection = Object.assign({}, resultCollection);
|
|
1566
1625
|
const existingKeys = resultCollectionKeys.filter((key) => persistedKeys.has(key));
|
|
@@ -1638,6 +1697,9 @@ const OnyxUtils = {
|
|
|
1638
1697
|
retryOperation,
|
|
1639
1698
|
broadcastUpdate,
|
|
1640
1699
|
hasPendingMergeForKey,
|
|
1700
|
+
getPendingMergeEntries,
|
|
1701
|
+
cancelPendingMerges,
|
|
1702
|
+
hasStaleMergeRead,
|
|
1641
1703
|
prepareKeyValuePairsForStorage,
|
|
1642
1704
|
mergeChanges,
|
|
1643
1705
|
mergeAndMarkChanges,
|