react-native-onyx 2.0.52 → 2.0.54
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 +15 -12
- package/dist/OnyxUtils.d.ts +2 -0
- package/dist/OnyxUtils.js +66 -62
- package/dist/useOnyx.d.ts +3 -2
- package/dist/utils.js +5 -7
- package/package.json +1 -1
package/dist/Onyx.js
CHANGED
|
@@ -146,10 +146,11 @@ function connect(connectOptions) {
|
|
|
146
146
|
return;
|
|
147
147
|
}
|
|
148
148
|
// We did not opt into using waitForCollectionCallback mode so the callback is called for every matching key.
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
149
|
+
OnyxUtils_1.default.multiGet(matchingKeys).then((values) => {
|
|
150
|
+
values.forEach((val, key) => {
|
|
151
|
+
OnyxUtils_1.default.sendDataToConnection(mapping, val, key, true);
|
|
152
|
+
});
|
|
153
|
+
});
|
|
153
154
|
return;
|
|
154
155
|
}
|
|
155
156
|
// If we are not subscribed to a collection key then there's only a single key to send an update for.
|
|
@@ -386,7 +387,8 @@ function mergeCollection(collectionKey, collection) {
|
|
|
386
387
|
const mergedCollection = collection;
|
|
387
388
|
// Confirm all the collection keys belong to the same parent
|
|
388
389
|
let hasCollectionKeyCheckFailed = false;
|
|
389
|
-
Object.keys(mergedCollection)
|
|
390
|
+
const mergedCollectionKeys = Object.keys(mergedCollection);
|
|
391
|
+
mergedCollectionKeys.forEach((dataKey) => {
|
|
390
392
|
if (OnyxUtils_1.default.isKeyMatch(collectionKey, dataKey)) {
|
|
391
393
|
return;
|
|
392
394
|
}
|
|
@@ -403,7 +405,7 @@ function mergeCollection(collectionKey, collection) {
|
|
|
403
405
|
return OnyxUtils_1.default.getAllKeys()
|
|
404
406
|
.then((persistedKeys) => {
|
|
405
407
|
// Split to keys that exist in storage and keys that don't
|
|
406
|
-
const keys =
|
|
408
|
+
const keys = mergedCollectionKeys.filter((key) => {
|
|
407
409
|
if (mergedCollection[key] === null) {
|
|
408
410
|
OnyxUtils_1.default.remove(key);
|
|
409
411
|
return false;
|
|
@@ -412,7 +414,6 @@ function mergeCollection(collectionKey, collection) {
|
|
|
412
414
|
});
|
|
413
415
|
const existingKeys = keys.filter((key) => persistedKeys.has(key));
|
|
414
416
|
const cachedCollectionForExistingKeys = OnyxUtils_1.default.getCachedCollection(collectionKey, existingKeys);
|
|
415
|
-
const newKeys = keys.filter((key) => !persistedKeys.has(key));
|
|
416
417
|
const existingKeyCollection = existingKeys.reduce((obj, key) => {
|
|
417
418
|
const { isCompatible, existingValueType, newValueType } = utils_1.default.checkCompatibilityWithExistingValue(mergedCollection[key], cachedCollectionForExistingKeys[key]);
|
|
418
419
|
if (!isCompatible) {
|
|
@@ -423,11 +424,13 @@ function mergeCollection(collectionKey, collection) {
|
|
|
423
424
|
obj[key] = mergedCollection[key];
|
|
424
425
|
return obj;
|
|
425
426
|
}, {});
|
|
426
|
-
const newCollection =
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
427
|
+
const newCollection = {};
|
|
428
|
+
keys.forEach((key) => {
|
|
429
|
+
if (persistedKeys.has(key)) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
newCollection[key] = mergedCollection[key];
|
|
433
|
+
});
|
|
431
434
|
// When (multi-)merging the values with the existing values in storage,
|
|
432
435
|
// we don't want to remove nested null values from the data that we pass to the storage layer,
|
|
433
436
|
// because the storage layer uses them to remove nested keys from storage natively.
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ declare function maybeFlushBatchUpdates(): Promise<void>;
|
|
|
54
54
|
declare function batchUpdates(updates: () => void): Promise<void>;
|
|
55
55
|
/** Get some data from the store */
|
|
56
56
|
declare function get<TKey extends OnyxKey, TValue extends OnyxValue<TKey>>(key: TKey): Promise<TValue>;
|
|
57
|
+
declare function multiGet<TKey extends OnyxKey>(keys: CollectionKeyBase[]): Promise<Map<OnyxKey, OnyxValue<TKey>>>;
|
|
57
58
|
/** Returns current key names stored in persisted storage */
|
|
58
59
|
declare function getAllKeys(): Promise<Set<OnyxKey>>;
|
|
59
60
|
/**
|
|
@@ -237,5 +238,6 @@ declare const OnyxUtils: {
|
|
|
237
238
|
applyMerge: typeof applyMerge;
|
|
238
239
|
initializeWithDefaultKeyStates: typeof initializeWithDefaultKeyStates;
|
|
239
240
|
getSnapshotKey: typeof getSnapshotKey;
|
|
241
|
+
multiGet: typeof multiGet;
|
|
240
242
|
};
|
|
241
243
|
export default OnyxUtils;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -190,6 +190,69 @@ function get(key) {
|
|
|
190
190
|
.catch((err) => Logger.logInfo(`Unable to get item from persistent storage. Key: ${key} Error: ${err}`));
|
|
191
191
|
return OnyxCache_1.default.captureTask(taskName, promise);
|
|
192
192
|
}
|
|
193
|
+
// multiGet the data first from the cache and then from the storage for the missing keys.
|
|
194
|
+
function multiGet(keys) {
|
|
195
|
+
// Keys that are not in the cache
|
|
196
|
+
const missingKeys = [];
|
|
197
|
+
// Tasks that are pending
|
|
198
|
+
const pendingTasks = [];
|
|
199
|
+
// Keys for the tasks that are pending
|
|
200
|
+
const pendingKeys = [];
|
|
201
|
+
// Data to be sent back to the invoker
|
|
202
|
+
const dataMap = new Map();
|
|
203
|
+
/**
|
|
204
|
+
* We are going to iterate over all the matching keys and check if we have the data in the cache.
|
|
205
|
+
* If we do then we add it to the data object. If we do not have them, then we check if there is a pending task
|
|
206
|
+
* for the key. If there is such task, then we add the promise to the pendingTasks array and the key to the pendingKeys
|
|
207
|
+
* array. If there is no pending task then we add the key to the missingKeys array.
|
|
208
|
+
*
|
|
209
|
+
* These missingKeys will be later used to multiGet the data from the storage.
|
|
210
|
+
*/
|
|
211
|
+
keys.forEach((key) => {
|
|
212
|
+
const cacheValue = OnyxCache_1.default.get(key);
|
|
213
|
+
if (cacheValue) {
|
|
214
|
+
dataMap.set(key, cacheValue);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
const pendingKey = `get:${key}`;
|
|
218
|
+
if (OnyxCache_1.default.hasPendingTask(pendingKey)) {
|
|
219
|
+
pendingTasks.push(OnyxCache_1.default.getTaskPromise(pendingKey));
|
|
220
|
+
pendingKeys.push(key);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
missingKeys.push(key);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
return (Promise.all(pendingTasks)
|
|
227
|
+
// Wait for all the pending tasks to resolve and then add the data to the data map.
|
|
228
|
+
.then((values) => {
|
|
229
|
+
values.forEach((value, index) => {
|
|
230
|
+
dataMap.set(pendingKeys[index], value);
|
|
231
|
+
});
|
|
232
|
+
return Promise.resolve();
|
|
233
|
+
})
|
|
234
|
+
// Get the missing keys using multiGet from the storage.
|
|
235
|
+
.then(() => {
|
|
236
|
+
if (missingKeys.length === 0) {
|
|
237
|
+
return Promise.resolve(undefined);
|
|
238
|
+
}
|
|
239
|
+
return storage_1.default.multiGet(missingKeys);
|
|
240
|
+
})
|
|
241
|
+
// Add the data from the missing keys to the data map and also merge it to the cache.
|
|
242
|
+
.then((values) => {
|
|
243
|
+
if (!values || values.length === 0) {
|
|
244
|
+
return dataMap;
|
|
245
|
+
}
|
|
246
|
+
// temp object is used to merge the missing data into the cache
|
|
247
|
+
const temp = {};
|
|
248
|
+
values.forEach(([key, value]) => {
|
|
249
|
+
dataMap.set(key, value);
|
|
250
|
+
temp[key] = value;
|
|
251
|
+
});
|
|
252
|
+
OnyxCache_1.default.merge(temp);
|
|
253
|
+
return dataMap;
|
|
254
|
+
}));
|
|
255
|
+
}
|
|
193
256
|
/** Returns current key names stored in persisted storage */
|
|
194
257
|
function getAllKeys() {
|
|
195
258
|
// When we've already read stored keys, resolve right away
|
|
@@ -682,68 +745,8 @@ function addKeyToRecentlyAccessedIfNeeded(mapping) {
|
|
|
682
745
|
* Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
|
|
683
746
|
*/
|
|
684
747
|
function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
// Tasks that are pending
|
|
688
|
-
const pendingTasks = [];
|
|
689
|
-
// Keys for the tasks that are pending
|
|
690
|
-
const pendingKeys = [];
|
|
691
|
-
// We are going to combine all the data from the matching keys into a single object
|
|
692
|
-
const data = {};
|
|
693
|
-
/**
|
|
694
|
-
* We are going to iterate over all the matching keys and check if we have the data in the cache.
|
|
695
|
-
* If we do then we add it to the data object. If we do not then we check if there is a pending task
|
|
696
|
-
* for the key. If there is then we add the promise to the pendingTasks array and the key to the pendingKeys
|
|
697
|
-
* array. If there is no pending task then we add the key to the missingKeys array.
|
|
698
|
-
*
|
|
699
|
-
* These missingKeys will be later to use to multiGet the data from the storage.
|
|
700
|
-
*/
|
|
701
|
-
matchingKeys.forEach((key) => {
|
|
702
|
-
const cacheValue = OnyxCache_1.default.get(key);
|
|
703
|
-
if (cacheValue) {
|
|
704
|
-
data[key] = cacheValue;
|
|
705
|
-
return;
|
|
706
|
-
}
|
|
707
|
-
const pendingKey = `get:${key}`;
|
|
708
|
-
if (OnyxCache_1.default.hasPendingTask(pendingKey)) {
|
|
709
|
-
pendingTasks.push(OnyxCache_1.default.getTaskPromise(pendingKey));
|
|
710
|
-
pendingKeys.push(key);
|
|
711
|
-
}
|
|
712
|
-
else {
|
|
713
|
-
missingKeys.push(key);
|
|
714
|
-
}
|
|
715
|
-
});
|
|
716
|
-
Promise.all(pendingTasks)
|
|
717
|
-
// We are going to wait for all the pending tasks to resolve and then add the data to the data object.
|
|
718
|
-
.then((values) => {
|
|
719
|
-
values.forEach((value, index) => {
|
|
720
|
-
data[pendingKeys[index]] = value;
|
|
721
|
-
});
|
|
722
|
-
return Promise.resolve();
|
|
723
|
-
})
|
|
724
|
-
// We are going to get the missing keys using multiGet from the storage.
|
|
725
|
-
.then(() => {
|
|
726
|
-
if (missingKeys.length === 0) {
|
|
727
|
-
return Promise.resolve(undefined);
|
|
728
|
-
}
|
|
729
|
-
return storage_1.default.multiGet(missingKeys);
|
|
730
|
-
})
|
|
731
|
-
// We are going to add the data from the missing keys to the data object and also merge it to the cache.
|
|
732
|
-
.then((values) => {
|
|
733
|
-
if (!values || values.length === 0) {
|
|
734
|
-
return Promise.resolve();
|
|
735
|
-
}
|
|
736
|
-
// temp object is used to merge the missing data into the cache
|
|
737
|
-
const temp = {};
|
|
738
|
-
values.forEach(([key, value]) => {
|
|
739
|
-
data[key] = value;
|
|
740
|
-
temp[key] = value;
|
|
741
|
-
});
|
|
742
|
-
OnyxCache_1.default.merge(temp);
|
|
743
|
-
return Promise.resolve();
|
|
744
|
-
})
|
|
745
|
-
// We are going to send the data to the subscriber.
|
|
746
|
-
.finally(() => {
|
|
748
|
+
multiGet(matchingKeys).then((dataMap) => {
|
|
749
|
+
const data = Object.fromEntries(dataMap.entries());
|
|
747
750
|
sendDataToConnection(mapping, data, undefined, true);
|
|
748
751
|
});
|
|
749
752
|
}
|
|
@@ -936,5 +939,6 @@ const OnyxUtils = {
|
|
|
936
939
|
applyMerge,
|
|
937
940
|
initializeWithDefaultKeyStates,
|
|
938
941
|
getSnapshotKey,
|
|
942
|
+
multiGet,
|
|
939
943
|
};
|
|
940
944
|
exports.default = OnyxUtils;
|
package/dist/useOnyx.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IsEqual } from 'type-fest';
|
|
2
|
-
import type { CollectionKeyBase, OnyxCollection, OnyxKey, OnyxValue, Selector } from './types';
|
|
2
|
+
import type { CollectionKeyBase, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue, Selector } from './types';
|
|
3
3
|
type BaseUseOnyxOptions = {
|
|
4
4
|
/**
|
|
5
5
|
* Determines if this key in this subscription is safe to be evicted.
|
|
@@ -30,7 +30,8 @@ type UseOnyxSelectorOption<TKey extends OnyxKey, TReturnValue> = {
|
|
|
30
30
|
selector?: Selector<TKey, unknown, TReturnValue>;
|
|
31
31
|
};
|
|
32
32
|
type FetchStatus = 'loading' | 'loaded';
|
|
33
|
-
type
|
|
33
|
+
type SelectedValue<TKey, TValue> = TKey extends CollectionKeyBase ? OnyxCollection<TValue> : OnyxEntry<TValue>;
|
|
34
|
+
type CachedValue<TKey extends OnyxKey, TValue> = IsEqual<TValue, OnyxValue<TKey>> extends true ? TValue : SelectedValue<TKey, TValue>;
|
|
34
35
|
type ResultMetadata = {
|
|
35
36
|
status: FetchStatus;
|
|
36
37
|
};
|
package/dist/utils.js
CHANGED
|
@@ -11,7 +11,7 @@ function isEmptyObject(obj) {
|
|
|
11
11
|
*/
|
|
12
12
|
function isMergeableObject(value) {
|
|
13
13
|
const isNonNullObject = value != null ? typeof value === 'object' : false;
|
|
14
|
-
return isNonNullObject &&
|
|
14
|
+
return isNonNullObject && !(value instanceof RegExp) && !(value instanceof Date) && !Array.isArray(value);
|
|
15
15
|
}
|
|
16
16
|
/**
|
|
17
17
|
* Merges the source object into the target object.
|
|
@@ -28,9 +28,8 @@ function mergeObject(target, source, shouldRemoveNestedNulls = true) {
|
|
|
28
28
|
// If "shouldRemoveNestedNulls" is true, we want to remove null values from the merged object
|
|
29
29
|
// and therefore we need to omit keys where either the source or target value is null.
|
|
30
30
|
if (targetObject) {
|
|
31
|
-
|
|
32
|
-
for (
|
|
33
|
-
const key = targetKeys[i];
|
|
31
|
+
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
32
|
+
for (const key in targetObject) {
|
|
34
33
|
const sourceValue = source === null || source === void 0 ? void 0 : source[key];
|
|
35
34
|
const targetValue = targetObject === null || targetObject === void 0 ? void 0 : targetObject[key];
|
|
36
35
|
// If "shouldRemoveNestedNulls" is true, we want to remove null values from the merged object.
|
|
@@ -46,9 +45,8 @@ function mergeObject(target, source, shouldRemoveNestedNulls = true) {
|
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
// After copying over all keys from the target object, we want to merge the source object into the destination object.
|
|
49
|
-
|
|
50
|
-
for (
|
|
51
|
-
const key = sourceKeys[i];
|
|
48
|
+
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
49
|
+
for (const key in source) {
|
|
52
50
|
const sourceValue = source === null || source === void 0 ? void 0 : source[key];
|
|
53
51
|
const targetValue = targetObject === null || targetObject === void 0 ? void 0 : targetObject[key];
|
|
54
52
|
// If undefined is passed as the source value for a key, we want to generally ignore it.
|