react-native-onyx 2.0.115 → 2.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/OnyxCache.d.ts +24 -0
- package/dist/OnyxCache.js +97 -2
- package/dist/OnyxUtils.js +39 -10
- package/package.json +1 -1
package/dist/OnyxCache.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ declare class OnyxCache {
|
|
|
19
19
|
private recentKeys;
|
|
20
20
|
/** A map of cached values */
|
|
21
21
|
private storageMap;
|
|
22
|
+
/** Index mapping collection keys to their member keys for O(1) lookup */
|
|
23
|
+
private collectionIndex;
|
|
22
24
|
/**
|
|
23
25
|
* Captured pending tasks for already running storage methods
|
|
24
26
|
* Using a map yields better performance on operations such a delete
|
|
@@ -32,6 +34,8 @@ declare class OnyxCache {
|
|
|
32
34
|
private evictionBlocklist;
|
|
33
35
|
/** List of keys that have been directly subscribed to or recently modified from least to most recent */
|
|
34
36
|
private recentlyAccessedKeys;
|
|
37
|
+
/** Set of collection keys for fast lookup */
|
|
38
|
+
private collectionKeys;
|
|
35
39
|
constructor();
|
|
36
40
|
/** Get all the storage keys */
|
|
37
41
|
getAllKeys(): Set<OnyxKey>;
|
|
@@ -145,6 +149,26 @@ declare class OnyxCache {
|
|
|
145
149
|
* Finds a key that can be safely evicted
|
|
146
150
|
*/
|
|
147
151
|
getKeyForEviction(): OnyxKey | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Set the collection keys for optimized storage
|
|
154
|
+
*/
|
|
155
|
+
setCollectionKeys(collectionKeys: Set<OnyxKey>): void;
|
|
156
|
+
/**
|
|
157
|
+
* Check if a key is a collection key
|
|
158
|
+
*/
|
|
159
|
+
isCollectionKey(key: OnyxKey): boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Get the collection key for a given member key
|
|
162
|
+
*/
|
|
163
|
+
getCollectionKey(key: OnyxKey): OnyxKey | null;
|
|
164
|
+
/**
|
|
165
|
+
* Get all data for a collection key
|
|
166
|
+
*/
|
|
167
|
+
getCollectionData(collectionKey: OnyxKey): Record<OnyxKey, OnyxValue<OnyxKey>> | undefined;
|
|
168
|
+
/**
|
|
169
|
+
* Get all member keys for a collection key
|
|
170
|
+
*/
|
|
171
|
+
getCollectionMemberKeys(collectionKey: OnyxKey): Set<OnyxKey> | undefined;
|
|
148
172
|
}
|
|
149
173
|
declare const instance: OnyxCache;
|
|
150
174
|
export default instance;
|
package/dist/OnyxCache.js
CHANGED
|
@@ -52,13 +52,16 @@ class OnyxCache {
|
|
|
52
52
|
this.evictionBlocklist = {};
|
|
53
53
|
/** List of keys that have been directly subscribed to or recently modified from least to most recent */
|
|
54
54
|
this.recentlyAccessedKeys = new Set();
|
|
55
|
+
/** Set of collection keys for fast lookup */
|
|
56
|
+
this.collectionKeys = new Set();
|
|
55
57
|
this.storageKeys = new Set();
|
|
56
58
|
this.nullishStorageKeys = new Set();
|
|
57
59
|
this.recentKeys = new Set();
|
|
58
60
|
this.storageMap = {};
|
|
61
|
+
this.collectionIndex = {};
|
|
59
62
|
this.pendingPromises = new Map();
|
|
60
63
|
// bind all public methods to prevent problems with `this`
|
|
61
|
-
(0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction');
|
|
64
|
+
(0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction', 'setCollectionKeys', 'isCollectionKey', 'getCollectionKey', 'getCollectionData', 'getCollectionMemberKeys');
|
|
62
65
|
}
|
|
63
66
|
/** Get all the storage keys */
|
|
64
67
|
getAllKeys() {
|
|
@@ -120,16 +123,37 @@ class OnyxCache {
|
|
|
120
123
|
// When a key is explicitly set in cache, we can remove it from the list of nullish keys,
|
|
121
124
|
// since it will either be set to a non nullish value or removed from the cache completely.
|
|
122
125
|
this.nullishStorageKeys.delete(key);
|
|
126
|
+
const collectionKey = this.getCollectionKey(key);
|
|
123
127
|
if (value === null || value === undefined) {
|
|
124
128
|
delete this.storageMap[key];
|
|
129
|
+
// Remove from collection index if it's a collection member
|
|
130
|
+
if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
|
|
131
|
+
this.collectionIndex[collectionKey].delete(key);
|
|
132
|
+
}
|
|
125
133
|
return undefined;
|
|
126
134
|
}
|
|
127
135
|
this.storageMap[key] = value;
|
|
136
|
+
// Update collection index if this is a collection member
|
|
137
|
+
if (collectionKey) {
|
|
138
|
+
if (!this.getCollectionMemberKeys(collectionKey)) {
|
|
139
|
+
this.collectionIndex[collectionKey] = new Set();
|
|
140
|
+
}
|
|
141
|
+
this.collectionIndex[collectionKey].add(key);
|
|
142
|
+
}
|
|
128
143
|
return value;
|
|
129
144
|
}
|
|
130
145
|
/** Forget the cached value for the given key */
|
|
131
146
|
drop(key) {
|
|
132
147
|
delete this.storageMap[key];
|
|
148
|
+
// Update collection index if this is a collection member
|
|
149
|
+
const collectionKey = this.getCollectionKey(key);
|
|
150
|
+
if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
|
|
151
|
+
this.collectionIndex[collectionKey].delete(key);
|
|
152
|
+
}
|
|
153
|
+
// If this is a collection key, clear its index
|
|
154
|
+
if (this.isCollectionKey(key)) {
|
|
155
|
+
delete this.collectionIndex[key];
|
|
156
|
+
}
|
|
133
157
|
this.storageKeys.delete(key);
|
|
134
158
|
this.recentKeys.delete(key);
|
|
135
159
|
}
|
|
@@ -145,11 +169,23 @@ class OnyxCache {
|
|
|
145
169
|
Object.entries(data).forEach(([key, value]) => {
|
|
146
170
|
this.addKey(key);
|
|
147
171
|
this.addToAccessedKeys(key);
|
|
172
|
+
const collectionKey = this.getCollectionKey(key);
|
|
148
173
|
if (value === null || value === undefined) {
|
|
149
174
|
this.addNullishStorageKey(key);
|
|
175
|
+
// Remove from collection index if it's a collection member
|
|
176
|
+
if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
|
|
177
|
+
this.collectionIndex[collectionKey].delete(key);
|
|
178
|
+
}
|
|
150
179
|
}
|
|
151
180
|
else {
|
|
152
181
|
this.nullishStorageKeys.delete(key);
|
|
182
|
+
// Update collection index if this is a collection member
|
|
183
|
+
if (collectionKey) {
|
|
184
|
+
if (!this.getCollectionMemberKeys(collectionKey)) {
|
|
185
|
+
this.collectionIndex[collectionKey] = new Set();
|
|
186
|
+
}
|
|
187
|
+
this.collectionIndex[collectionKey].add(key);
|
|
188
|
+
}
|
|
153
189
|
}
|
|
154
190
|
});
|
|
155
191
|
}
|
|
@@ -208,6 +244,11 @@ class OnyxCache {
|
|
|
208
244
|
}
|
|
209
245
|
for (const key of keysToRemove) {
|
|
210
246
|
delete this.storageMap[key];
|
|
247
|
+
// Update collection index if this is a collection member
|
|
248
|
+
const collectionKey = this.getCollectionKey(key);
|
|
249
|
+
if (collectionKey && this.getCollectionMemberKeys(collectionKey)) {
|
|
250
|
+
this.collectionIndex[collectionKey].delete(key);
|
|
251
|
+
}
|
|
211
252
|
this.recentKeys.delete(key);
|
|
212
253
|
}
|
|
213
254
|
}
|
|
@@ -217,7 +258,8 @@ class OnyxCache {
|
|
|
217
258
|
}
|
|
218
259
|
/** Check if the value has changed */
|
|
219
260
|
hasValueChanged(key, value) {
|
|
220
|
-
|
|
261
|
+
const currentValue = this.get(key, false);
|
|
262
|
+
return !(0, fast_equals_1.deepEqual)(currentValue, value);
|
|
221
263
|
}
|
|
222
264
|
/**
|
|
223
265
|
* Sets the list of keys that are considered safe for eviction
|
|
@@ -298,6 +340,59 @@ class OnyxCache {
|
|
|
298
340
|
}
|
|
299
341
|
return undefined;
|
|
300
342
|
}
|
|
343
|
+
/**
|
|
344
|
+
* Set the collection keys for optimized storage
|
|
345
|
+
*/
|
|
346
|
+
setCollectionKeys(collectionKeys) {
|
|
347
|
+
this.collectionKeys = collectionKeys;
|
|
348
|
+
// Initialize collection indexes for existing collection keys
|
|
349
|
+
collectionKeys.forEach((collectionKey) => {
|
|
350
|
+
if (this.getCollectionMemberKeys(collectionKey)) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
this.collectionIndex[collectionKey] = new Set();
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Check if a key is a collection key
|
|
358
|
+
*/
|
|
359
|
+
isCollectionKey(key) {
|
|
360
|
+
return this.collectionKeys.has(key);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Get the collection key for a given member key
|
|
364
|
+
*/
|
|
365
|
+
getCollectionKey(key) {
|
|
366
|
+
for (const collectionKey of this.collectionKeys) {
|
|
367
|
+
if (key.startsWith(collectionKey) && key.length > collectionKey.length) {
|
|
368
|
+
return collectionKey;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Get all data for a collection key
|
|
375
|
+
*/
|
|
376
|
+
getCollectionData(collectionKey) {
|
|
377
|
+
const memberKeys = this.getCollectionMemberKeys(collectionKey);
|
|
378
|
+
if (!memberKeys || memberKeys.size === 0) {
|
|
379
|
+
return undefined;
|
|
380
|
+
}
|
|
381
|
+
const collectionData = {};
|
|
382
|
+
memberKeys.forEach((memberKey) => {
|
|
383
|
+
const value = this.storageMap[memberKey];
|
|
384
|
+
if (value !== undefined) {
|
|
385
|
+
collectionData[memberKey] = value;
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
return collectionData;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Get all member keys for a collection key
|
|
392
|
+
*/
|
|
393
|
+
getCollectionMemberKeys(collectionKey) {
|
|
394
|
+
return this.collectionIndex[collectionKey];
|
|
395
|
+
}
|
|
301
396
|
}
|
|
302
397
|
const instance = new OnyxCache();
|
|
303
398
|
exports.default = instance;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -135,6 +135,8 @@ function initStoreValues(keys, initialKeyStates, evictableKeys, fullyMergedSnaps
|
|
|
135
135
|
DevTools_1.default.initState(initialKeyStates);
|
|
136
136
|
// Let Onyx know about which keys are safe to evict
|
|
137
137
|
OnyxCache_1.default.setEvictionAllowList(evictableKeys);
|
|
138
|
+
// Set collection keys in cache for optimized storage
|
|
139
|
+
OnyxCache_1.default.setCollectionKeys(onyxCollectionKeySet);
|
|
138
140
|
if (typeof keys.COLLECTION === 'object' && typeof keys.COLLECTION.SNAPSHOT === 'string') {
|
|
139
141
|
snapshotKey = keys.COLLECTION.SNAPSHOT;
|
|
140
142
|
fullyMergedSnapshotKeys = new Set(fullyMergedSnapshotKeysParam !== null && fullyMergedSnapshotKeysParam !== void 0 ? fullyMergedSnapshotKeysParam : []);
|
|
@@ -428,20 +430,27 @@ function getCollectionKey(key) {
|
|
|
428
430
|
function tryGetCachedValue(key, mapping) {
|
|
429
431
|
let val = OnyxCache_1.default.get(key);
|
|
430
432
|
if (isCollectionKey(key)) {
|
|
433
|
+
const collectionData = OnyxCache_1.default.getCollectionData(key);
|
|
431
434
|
const allCacheKeys = OnyxCache_1.default.getAllKeys();
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
if (allCacheKeys.size === 0) {
|
|
435
|
-
return;
|
|
435
|
+
if (collectionData !== undefined && allCacheKeys.size > 0) {
|
|
436
|
+
val = collectionData;
|
|
436
437
|
}
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
if
|
|
438
|
+
else {
|
|
439
|
+
// Fallback to original logic
|
|
440
|
+
// It is possible we haven't loaded all keys yet so we do not know if the
|
|
441
|
+
// collection actually exists.
|
|
442
|
+
if (allCacheKeys.size === 0) {
|
|
440
443
|
return;
|
|
441
444
|
}
|
|
442
|
-
values
|
|
443
|
-
|
|
444
|
-
|
|
445
|
+
const values = {};
|
|
446
|
+
allCacheKeys.forEach((cacheKey) => {
|
|
447
|
+
if (!cacheKey.startsWith(key)) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
values[cacheKey] = OnyxCache_1.default.get(cacheKey);
|
|
451
|
+
});
|
|
452
|
+
val = values;
|
|
453
|
+
}
|
|
445
454
|
}
|
|
446
455
|
if (mapping === null || mapping === void 0 ? void 0 : mapping.selector) {
|
|
447
456
|
const state = mapping.withOnyxInstance ? mapping.withOnyxInstance.state : undefined;
|
|
@@ -453,7 +462,27 @@ function tryGetCachedValue(key, mapping) {
|
|
|
453
462
|
return val;
|
|
454
463
|
}
|
|
455
464
|
function getCachedCollection(collectionKey, collectionMemberKeys) {
|
|
465
|
+
// Use optimized collection data retrieval when cache is populated
|
|
466
|
+
const collectionData = OnyxCache_1.default.getCollectionData(collectionKey);
|
|
456
467
|
const allKeys = collectionMemberKeys || OnyxCache_1.default.getAllKeys();
|
|
468
|
+
if (collectionData !== undefined && (Array.isArray(allKeys) ? allKeys.length > 0 : allKeys.size > 0)) {
|
|
469
|
+
// If we have specific member keys, filter the collection
|
|
470
|
+
if (collectionMemberKeys) {
|
|
471
|
+
const filteredCollection = {};
|
|
472
|
+
collectionMemberKeys.forEach((key) => {
|
|
473
|
+
if (collectionData[key] !== undefined) {
|
|
474
|
+
filteredCollection[key] = collectionData[key];
|
|
475
|
+
}
|
|
476
|
+
else if (OnyxCache_1.default.hasNullishStorageKey(key)) {
|
|
477
|
+
filteredCollection[key] = OnyxCache_1.default.get(key);
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
return filteredCollection;
|
|
481
|
+
}
|
|
482
|
+
// Return a copy to avoid mutations affecting the cache
|
|
483
|
+
return Object.assign({}, collectionData);
|
|
484
|
+
}
|
|
485
|
+
// Fallback to original implementation if collection data not available
|
|
457
486
|
const collection = {};
|
|
458
487
|
// forEach exists on both Set and Array
|
|
459
488
|
allKeys.forEach((key) => {
|