react-native-onyx 2.0.111 → 2.0.113
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.d.ts +1 -1
- package/dist/Onyx.js +2 -2
- package/dist/OnyxUtils.d.ts +3 -2
- package/dist/OnyxUtils.js +36 -16
- package/dist/types.d.ts +7 -0
- package/dist/useOnyx.js +1 -3
- package/package.json +1 -1
package/dist/Onyx.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as Logger from './Logger';
|
|
|
2
2
|
import type { CollectionKeyBase, ConnectOptions, InitOptions, Mapping, OnyxKey, OnyxMergeCollectionInput, OnyxMergeInput, OnyxMultiSetInput, OnyxSetInput, OnyxUpdate } from './types';
|
|
3
3
|
import type { Connection } from './OnyxConnectionManager';
|
|
4
4
|
/** Initialize the store with actions and listening for storage events */
|
|
5
|
-
declare function init({ keys, initialKeyStates, evictableKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, skippableCollectionMemberIDs, }: InitOptions): void;
|
|
5
|
+
declare function init({ keys, initialKeyStates, evictableKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, skippableCollectionMemberIDs, fullyMergedSnapshotKeys, }: InitOptions): void;
|
|
6
6
|
/**
|
|
7
7
|
* Connects to an Onyx key given the options passed and listens to its changes.
|
|
8
8
|
*
|
package/dist/Onyx.js
CHANGED
|
@@ -40,7 +40,7 @@ const OnyxConnectionManager_1 = __importDefault(require("./OnyxConnectionManager
|
|
|
40
40
|
const GlobalSettings = __importStar(require("./GlobalSettings"));
|
|
41
41
|
const metrics_1 = __importDefault(require("./metrics"));
|
|
42
42
|
/** Initialize the store with actions and listening for storage events */
|
|
43
|
-
function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = !!global.localStorage, debugSetState = false, enablePerformanceMetrics = false, skippableCollectionMemberIDs = [], }) {
|
|
43
|
+
function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = !!global.localStorage, debugSetState = false, enablePerformanceMetrics = false, skippableCollectionMemberIDs = [], fullyMergedSnapshotKeys = [], }) {
|
|
44
44
|
var _a;
|
|
45
45
|
if (enablePerformanceMetrics) {
|
|
46
46
|
GlobalSettings.setPerformanceMetricsEnabled(true);
|
|
@@ -61,7 +61,7 @@ function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedK
|
|
|
61
61
|
if (maxCachedKeysCount > 0) {
|
|
62
62
|
OnyxCache_1.default.setRecentKeysLimit(maxCachedKeysCount);
|
|
63
63
|
}
|
|
64
|
-
OnyxUtils_1.default.initStoreValues(keys, initialKeyStates, evictableKeys);
|
|
64
|
+
OnyxUtils_1.default.initStoreValues(keys, initialKeyStates, evictableKeys, fullyMergedSnapshotKeys);
|
|
65
65
|
// Initialize all of our keys with data provided then give green light to any pending connections
|
|
66
66
|
Promise.all([OnyxCache_1.default.addEvictableKeysToRecentlyAccessedList(OnyxUtils_1.default.isCollectionKey, OnyxUtils_1.default.getAllKeys), OnyxUtils_1.default.initializeWithDefaultKeyStates()]).then(OnyxUtils_1.default.getDeferredInitTask().resolve);
|
|
67
67
|
}
|
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -43,8 +43,9 @@ declare function setSkippableCollectionMemberIDs(ids: Set<string>): void;
|
|
|
43
43
|
* @param keys - `ONYXKEYS` constants object from Onyx.init()
|
|
44
44
|
* @param initialKeyStates - initial data to set when `init()` and `clear()` are called
|
|
45
45
|
* @param evictableKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
|
|
46
|
+
* @param fullyMergedSnapshotKeys - Array of snapshot collection keys where full merge is supported and data structure can be changed after merge.
|
|
46
47
|
*/
|
|
47
|
-
declare function initStoreValues(keys: DeepRecord<string, OnyxKey>, initialKeyStates: Partial<KeyValueMapping>, evictableKeys: OnyxKey[]): void;
|
|
48
|
+
declare function initStoreValues(keys: DeepRecord<string, OnyxKey>, initialKeyStates: Partial<KeyValueMapping>, evictableKeys: OnyxKey[], fullyMergedSnapshotKeysParam?: string[]): void;
|
|
48
49
|
/**
|
|
49
50
|
* Sends an action to DevTools extension
|
|
50
51
|
*
|
|
@@ -105,7 +106,7 @@ declare function getCollectionKeys(): Set<OnyxKey>;
|
|
|
105
106
|
* is associated with a collection of keys.
|
|
106
107
|
*/
|
|
107
108
|
declare function isCollectionKey(key: OnyxKey): key is CollectionKeyBase;
|
|
108
|
-
declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>(collectionKey: TCollectionKey, key: string
|
|
109
|
+
declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>(collectionKey: TCollectionKey, key: string): key is `${TCollectionKey}${string}`;
|
|
109
110
|
/**
|
|
110
111
|
* Splits a collection member key into the collection key part and the ID part.
|
|
111
112
|
* @param key - The collection member key to split.
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -29,6 +29,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
29
29
|
/* eslint-disable no-continue */
|
|
30
30
|
const fast_equals_1 = require("fast-equals");
|
|
31
31
|
const clone_1 = __importDefault(require("lodash/clone"));
|
|
32
|
+
const pick_1 = __importDefault(require("lodash/pick"));
|
|
32
33
|
const DevTools_1 = __importDefault(require("./DevTools"));
|
|
33
34
|
const Logger = __importStar(require("./Logger"));
|
|
34
35
|
const OnyxCache_1 = __importStar(require("./OnyxCache"));
|
|
@@ -65,6 +66,7 @@ let batchUpdatesQueue = [];
|
|
|
65
66
|
// Used for comparison with a new update to avoid invoking the Onyx.connect callback with the same data.
|
|
66
67
|
const lastConnectionCallbackData = new Map();
|
|
67
68
|
let snapshotKey = null;
|
|
69
|
+
let fullyMergedSnapshotKeys;
|
|
68
70
|
// Keeps track of the last subscriptionID that was used so we can keep incrementing it
|
|
69
71
|
let lastSubscriptionID = 0;
|
|
70
72
|
// Connections can be made before `Onyx.init`. They would wait for this task before resolving
|
|
@@ -116,8 +118,9 @@ function setSkippableCollectionMemberIDs(ids) {
|
|
|
116
118
|
* @param keys - `ONYXKEYS` constants object from Onyx.init()
|
|
117
119
|
* @param initialKeyStates - initial data to set when `init()` and `clear()` are called
|
|
118
120
|
* @param evictableKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
|
|
121
|
+
* @param fullyMergedSnapshotKeys - Array of snapshot collection keys where full merge is supported and data structure can be changed after merge.
|
|
119
122
|
*/
|
|
120
|
-
function initStoreValues(keys, initialKeyStates, evictableKeys) {
|
|
123
|
+
function initStoreValues(keys, initialKeyStates, evictableKeys, fullyMergedSnapshotKeysParam) {
|
|
121
124
|
var _a;
|
|
122
125
|
// We need the value of the collection keys later for checking if a
|
|
123
126
|
// key is a collection. We store it in a map for faster lookup.
|
|
@@ -133,6 +136,7 @@ function initStoreValues(keys, initialKeyStates, evictableKeys) {
|
|
|
133
136
|
OnyxCache_1.default.setEvictionAllowList(evictableKeys);
|
|
134
137
|
if (typeof keys.COLLECTION === 'object' && typeof keys.COLLECTION.SNAPSHOT === 'string') {
|
|
135
138
|
snapshotKey = keys.COLLECTION.SNAPSHOT;
|
|
139
|
+
fullyMergedSnapshotKeys = new Set(fullyMergedSnapshotKeysParam !== null && fullyMergedSnapshotKeysParam !== void 0 ? fullyMergedSnapshotKeysParam : []);
|
|
136
140
|
}
|
|
137
141
|
}
|
|
138
142
|
function sendActionToDevTools(method, key, value, mergedValue = undefined) {
|
|
@@ -361,8 +365,8 @@ function getCollectionKeys() {
|
|
|
361
365
|
function isCollectionKey(key) {
|
|
362
366
|
return onyxCollectionKeySet.has(key);
|
|
363
367
|
}
|
|
364
|
-
function isCollectionMemberKey(collectionKey, key
|
|
365
|
-
return key.startsWith(collectionKey) && key.length >
|
|
368
|
+
function isCollectionMemberKey(collectionKey, key) {
|
|
369
|
+
return key.startsWith(collectionKey) && key.length > collectionKey.length;
|
|
366
370
|
}
|
|
367
371
|
/**
|
|
368
372
|
* Splits a collection member key into the collection key part and the ID part.
|
|
@@ -372,7 +376,7 @@ function isCollectionMemberKey(collectionKey, key, collectionKeyLength) {
|
|
|
372
376
|
* or throws an Error if the key is not a collection one.
|
|
373
377
|
*/
|
|
374
378
|
function splitCollectionMemberKey(key, collectionKey) {
|
|
375
|
-
if (collectionKey && !isCollectionMemberKey(collectionKey, key
|
|
379
|
+
if (collectionKey && !isCollectionMemberKey(collectionKey, key)) {
|
|
376
380
|
throw new Error(`Invalid '${collectionKey}' collection key provided, it isn't compatible with '${key}' key.`);
|
|
377
381
|
}
|
|
378
382
|
if (!collectionKey) {
|
|
@@ -450,13 +454,12 @@ function tryGetCachedValue(key, mapping) {
|
|
|
450
454
|
function getCachedCollection(collectionKey, collectionMemberKeys) {
|
|
451
455
|
const allKeys = collectionMemberKeys || OnyxCache_1.default.getAllKeys();
|
|
452
456
|
const collection = {};
|
|
453
|
-
const collectionKeyLength = collectionKey.length;
|
|
454
457
|
// forEach exists on both Set and Array
|
|
455
458
|
allKeys.forEach((key) => {
|
|
456
459
|
// If we don't have collectionMemberKeys array then we have to check whether a key is a collection member key.
|
|
457
460
|
// Because in that case the keys will be coming from `cache.getAllKeys()` and we need to filter out the keys that
|
|
458
461
|
// are not part of the collection.
|
|
459
|
-
if (!collectionMemberKeys && !isCollectionMemberKey(collectionKey, key
|
|
462
|
+
if (!collectionMemberKeys && !isCollectionMemberKey(collectionKey, key)) {
|
|
460
463
|
return;
|
|
461
464
|
}
|
|
462
465
|
const cachedValue = OnyxCache_1.default.get(key);
|
|
@@ -479,7 +482,6 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
|
|
|
479
482
|
// individual collection key member for the collection that is being updated. It is important to note that the collection parameter cane be a PARTIAL collection
|
|
480
483
|
// and does not represent all of the combined keys and values for a collection key. It is just the "new" data that was merged in via mergeCollection().
|
|
481
484
|
const stateMappingKeys = Object.keys(callbackToStateMapping);
|
|
482
|
-
const collectionKeyLength = collectionKey.length;
|
|
483
485
|
for (const stateMappingKey of stateMappingKeys) {
|
|
484
486
|
const subscriber = callbackToStateMapping[stateMappingKey];
|
|
485
487
|
if (!subscriber) {
|
|
@@ -496,7 +498,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
|
|
|
496
498
|
/**
|
|
497
499
|
* e.g. Onyx.connect({key: `${ONYXKEYS.COLLECTION.REPORT}{reportID}`, callback: ...});
|
|
498
500
|
*/
|
|
499
|
-
const isSubscribedToCollectionMemberKey = isCollectionMemberKey(collectionKey, subscriber.key
|
|
501
|
+
const isSubscribedToCollectionMemberKey = isCollectionMemberKey(collectionKey, subscriber.key);
|
|
500
502
|
// Regular Onyx.connect() subscriber found.
|
|
501
503
|
if (typeof subscriber.callback === 'function') {
|
|
502
504
|
if (!notifyConnectSubscribers) {
|
|
@@ -1046,12 +1048,21 @@ function subscribeToKey(connectOptions) {
|
|
|
1046
1048
|
// can send data back to the subscriber. Note that multiple keys can match as a subscriber could either be
|
|
1047
1049
|
// subscribed to a "collection key" or a single key.
|
|
1048
1050
|
const matchingKeys = [];
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1051
|
+
// Performance optimization: For single key subscriptions, avoid O(n) iteration
|
|
1052
|
+
if (!isCollectionKey(mapping.key)) {
|
|
1053
|
+
if (keys.has(mapping.key)) {
|
|
1054
|
+
matchingKeys.push(mapping.key);
|
|
1052
1055
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1056
|
+
}
|
|
1057
|
+
else {
|
|
1058
|
+
// Collection case - need to iterate through all keys to find matches (O(n))
|
|
1059
|
+
keys.forEach((key) => {
|
|
1060
|
+
if (!isKeyMatch(mapping.key, key)) {
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1063
|
+
matchingKeys.push(key);
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1055
1066
|
// If the key being connected to does not exist we initialize the value with null. For subscribers that connected
|
|
1056
1067
|
// directly via connect() they will simply get a null value sent to them without any information about which key matched
|
|
1057
1068
|
// since there are none matched. In withOnyx() we wait for all connected keys to return a value before rendering the child
|
|
@@ -1121,7 +1132,6 @@ function updateSnapshots(data, mergeFn) {
|
|
|
1121
1132
|
return [];
|
|
1122
1133
|
const promises = [];
|
|
1123
1134
|
const snapshotCollection = OnyxUtils.getCachedCollection(snapshotCollectionKey);
|
|
1124
|
-
const snapshotCollectionKeyLength = snapshotCollectionKey.length;
|
|
1125
1135
|
Object.entries(snapshotCollection).forEach(([snapshotEntryKey, snapshotEntryValue]) => {
|
|
1126
1136
|
// Snapshots may not be present in cache. We don't know how to update them so we skip.
|
|
1127
1137
|
if (!snapshotEntryValue) {
|
|
@@ -1130,7 +1140,7 @@ function updateSnapshots(data, mergeFn) {
|
|
|
1130
1140
|
let updatedData = {};
|
|
1131
1141
|
data.forEach(({ key, value }) => {
|
|
1132
1142
|
// snapshots are normal keys so we want to skip update if they are written to Onyx
|
|
1133
|
-
if (OnyxUtils.isCollectionMemberKey(snapshotCollectionKey, key
|
|
1143
|
+
if (OnyxUtils.isCollectionMemberKey(snapshotCollectionKey, key)) {
|
|
1134
1144
|
return;
|
|
1135
1145
|
}
|
|
1136
1146
|
if (typeof snapshotEntryValue !== 'object' || !('data' in snapshotEntryValue)) {
|
|
@@ -1149,7 +1159,17 @@ function updateSnapshots(data, mergeFn) {
|
|
|
1149
1159
|
return;
|
|
1150
1160
|
}
|
|
1151
1161
|
const oldValue = updatedData[key] || {};
|
|
1152
|
-
|
|
1162
|
+
let collectionKey;
|
|
1163
|
+
try {
|
|
1164
|
+
collectionKey = getCollectionKey(key);
|
|
1165
|
+
}
|
|
1166
|
+
catch (e) {
|
|
1167
|
+
// If getCollectionKey() throws an error it means the key is not a collection key.
|
|
1168
|
+
collectionKey = undefined;
|
|
1169
|
+
}
|
|
1170
|
+
const shouldFullyMerge = fullyMergedSnapshotKeys === null || fullyMergedSnapshotKeys === void 0 ? void 0 : fullyMergedSnapshotKeys.has(collectionKey || key);
|
|
1171
|
+
const newValue = shouldFullyMerge ? value : (0, pick_1.default)(value, Object.keys(snapshotData[key]));
|
|
1172
|
+
updatedData = Object.assign(Object.assign({}, updatedData), { [key]: Object.assign(oldValue, newValue) });
|
|
1153
1173
|
});
|
|
1154
1174
|
// Skip the update if there's no data to be merged
|
|
1155
1175
|
if (utils_1.default.isEmptyObject(updatedData)) {
|
package/dist/types.d.ts
CHANGED
|
@@ -403,6 +403,13 @@ type InitOptions = {
|
|
|
403
403
|
* Additionally, any subscribers from these keys to won't receive any data from Onyx.
|
|
404
404
|
*/
|
|
405
405
|
skippableCollectionMemberIDs?: string[];
|
|
406
|
+
/**
|
|
407
|
+
* Array of snapshot collection keys where full merge is supported and data structure can be changed after merge.
|
|
408
|
+
* For e.g. if oldSnapshotData is {report_1: {name 'Fitsum'}} and BE update is {report_1: {name:'Fitsum2', nickName:'Fitse'}}
|
|
409
|
+
* if it is fullyMergedSnapshotkey the `nickName` prop that didn't exist in the previous data will be merged
|
|
410
|
+
* otherwise only existing prop will be picked from the BE update and merged (in this case only name).
|
|
411
|
+
*/
|
|
412
|
+
fullyMergedSnapshotKeys?: string[];
|
|
406
413
|
};
|
|
407
414
|
type GenericFunction = (...args: any[]) => any;
|
|
408
415
|
/**
|
package/dist/useOnyx.js
CHANGED
|
@@ -74,9 +74,7 @@ function useOnyx(key, options, dependencies = []) {
|
|
|
74
74
|
try {
|
|
75
75
|
const previousCollectionKey = OnyxUtils_1.default.splitCollectionMemberKey(previousKey)[0];
|
|
76
76
|
const collectionKey = OnyxUtils_1.default.splitCollectionMemberKey(key)[0];
|
|
77
|
-
if (OnyxUtils_1.default.isCollectionMemberKey(previousCollectionKey, previousKey, previousCollectionKey
|
|
78
|
-
OnyxUtils_1.default.isCollectionMemberKey(collectionKey, key, collectionKey.length) &&
|
|
79
|
-
previousCollectionKey === collectionKey) {
|
|
77
|
+
if (OnyxUtils_1.default.isCollectionMemberKey(previousCollectionKey, previousKey) && OnyxUtils_1.default.isCollectionMemberKey(collectionKey, key) && previousCollectionKey === collectionKey) {
|
|
80
78
|
return;
|
|
81
79
|
}
|
|
82
80
|
}
|