react-native-onyx 2.0.103 → 2.0.104

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/README.md CHANGED
@@ -388,14 +388,14 @@ Different platforms come with varying storage capacities and Onyx has a way to g
388
388
  By default, Onyx will not evict anything from storage and will presume all keys are "unsafe" to remove unless explicitly told otherwise.
389
389
 
390
390
  **To flag a key as safe for removal:**
391
- - Add the key to the `safeEvictionKeys` option in `Onyx.init(options)`
391
+ - Add the key to the `evictableKeys` option in `Onyx.init(options)`
392
392
  - Implement `canEvict` in the Onyx config for each component subscribing to a key
393
393
  - The key will only be deleted when all subscribers return `true` for `canEvict`
394
394
 
395
395
  e.g.
396
396
  ```js
397
397
  Onyx.init({
398
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
398
+ evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
399
399
  });
400
400
  ```
401
401
 
@@ -423,7 +423,7 @@ Provide the `captureMetrics` boolean flag to `Onyx.init` to capture call statist
423
423
  ```js
424
424
  Onyx.init({
425
425
  keys: ONYXKEYS,
426
- safeEvictionKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
426
+ evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
427
427
  captureMetrics: Config.BENCHMARK_ONYX,
428
428
  });
429
429
  ```
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, safeEvictionKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, skippableCollectionMemberIDs, }: InitOptions): void;
5
+ declare function init({ keys, initialKeyStates, evictableKeys, maxCachedKeysCount, shouldSyncMultipleInstances, debugSetState, enablePerformanceMetrics, skippableCollectionMemberIDs, }: 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 = {}, safeEvictionKeys = [], 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 = [], }) {
44
44
  var _a;
45
45
  if (enablePerformanceMetrics) {
46
46
  GlobalSettings.setPerformanceMetricsEnabled(true);
@@ -61,9 +61,9 @@ function init({ keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCach
61
61
  if (maxCachedKeysCount > 0) {
62
62
  OnyxCache_1.default.setRecentKeysLimit(maxCachedKeysCount);
63
63
  }
64
- OnyxUtils_1.default.initStoreValues(keys, initialKeyStates, safeEvictionKeys);
64
+ OnyxUtils_1.default.initStoreValues(keys, initialKeyStates, evictableKeys);
65
65
  // Initialize all of our keys with data provided then give green light to any pending connections
66
- Promise.all([OnyxUtils_1.default.addAllSafeEvictionKeysToRecentlyAccessedList(), OnyxUtils_1.default.initializeWithDefaultKeyStates()]).then(OnyxUtils_1.default.getDeferredInitTask().resolve);
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
  }
68
68
  /**
69
69
  * Connects to an Onyx key given the options passed and listens to its changes.
@@ -26,6 +26,12 @@ declare class OnyxCache {
26
26
  private pendingPromises;
27
27
  /** Maximum size of the keys store din cache */
28
28
  private maxRecentKeysSize;
29
+ /** List of keys that are safe to remove when we reach max storage */
30
+ private evictionAllowList;
31
+ /** Map of keys and connection arrays whose keys will never be automatically evicted */
32
+ private evictionBlocklist;
33
+ /** List of keys that have been directly subscribed to or recently modified from least to most recent */
34
+ private recentlyAccessedKeys;
29
35
  constructor();
30
36
  /** Get all the storage keys */
31
37
  getAllKeys(): Set<OnyxKey>;
@@ -96,6 +102,49 @@ declare class OnyxCache {
96
102
  setRecentKeysLimit(limit: number): void;
97
103
  /** Check if the value has changed */
98
104
  hasValueChanged(key: OnyxKey, value: OnyxValue<OnyxKey>): boolean;
105
+ /**
106
+ * Sets the list of keys that are considered safe for eviction
107
+ * @param keys - Array of OnyxKeys that are safe to evict
108
+ */
109
+ setEvictionAllowList(keys: OnyxKey[]): void;
110
+ /**
111
+ * Get the eviction block list that prevents keys from being evicted
112
+ */
113
+ getEvictionBlocklist(): Record<OnyxKey, string[] | undefined>;
114
+ /**
115
+ * Checks to see if this key has been flagged as safe for removal.
116
+ * @param testKey - Key to check
117
+ */
118
+ isEvictableKey(testKey: OnyxKey): boolean;
119
+ /**
120
+ * Check if a given key matches a pattern key
121
+ * @param configKey - Pattern that may contain a wildcard
122
+ * @param key - Key to test against the pattern
123
+ */
124
+ private isKeyMatch;
125
+ /**
126
+ * Remove a key from the recently accessed key list.
127
+ */
128
+ removeLastAccessedKey(key: OnyxKey): void;
129
+ /**
130
+ * Add a key to the list of recently accessed keys. The least
131
+ * recently accessed key should be at the head and the most
132
+ * recently accessed key at the tail.
133
+ */
134
+ addLastAccessedKey(key: OnyxKey, isCollectionKey: boolean): void;
135
+ /**
136
+ * Take all the keys that are safe to evict and add them to
137
+ * the recently accessed list when initializing the app. This
138
+ * enables keys that have not recently been accessed to be
139
+ * removed.
140
+ * @param isCollectionKeyFn - Function to determine if a key is a collection key
141
+ * @param getAllKeysFn - Function to get all keys, defaults to Storage.getAllKeys
142
+ */
143
+ addEvictableKeysToRecentlyAccessedList(isCollectionKeyFn: (key: OnyxKey) => boolean, getAllKeysFn: () => Promise<Set<OnyxKey>>): Promise<void>;
144
+ /**
145
+ * Finds a key that can be safely evicted
146
+ */
147
+ getKeyForEviction(): OnyxKey | undefined;
99
148
  }
100
149
  declare const instance: OnyxCache;
101
150
  export default instance;
package/dist/OnyxCache.js CHANGED
@@ -1,4 +1,27 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
@@ -7,6 +30,7 @@ exports.TASK = void 0;
7
30
  const fast_equals_1 = require("fast-equals");
8
31
  const bindAll_1 = __importDefault(require("lodash/bindAll"));
9
32
  const utils_1 = __importDefault(require("./utils"));
33
+ const Str = __importStar(require("./Str"));
10
34
  // Task constants
11
35
  const TASK = {
12
36
  GET: 'get',
@@ -22,13 +46,19 @@ class OnyxCache {
22
46
  constructor() {
23
47
  /** Maximum size of the keys store din cache */
24
48
  this.maxRecentKeysSize = 0;
49
+ /** List of keys that are safe to remove when we reach max storage */
50
+ this.evictionAllowList = [];
51
+ /** Map of keys and connection arrays whose keys will never be automatically evicted */
52
+ this.evictionBlocklist = {};
53
+ /** List of keys that have been directly subscribed to or recently modified from least to most recent */
54
+ this.recentlyAccessedKeys = [];
25
55
  this.storageKeys = new Set();
26
56
  this.nullishStorageKeys = new Set();
27
57
  this.recentKeys = new Set();
28
58
  this.storageMap = {};
29
59
  this.pendingPromises = new Map();
30
60
  // bind all public methods to prevent problems with `this`
31
- (0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys');
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');
32
62
  }
33
63
  /** Get all the storage keys */
34
64
  getAllKeys() {
@@ -158,18 +188,25 @@ class OnyxCache {
158
188
  }
159
189
  /** Remove keys that don't fall into the range of recently used keys */
160
190
  removeLeastRecentlyUsedKeys() {
161
- let numKeysToRemove = this.recentKeys.size - this.maxRecentKeysSize;
191
+ const numKeysToRemove = this.recentKeys.size - this.maxRecentKeysSize;
162
192
  if (numKeysToRemove <= 0) {
163
193
  return;
164
194
  }
165
195
  const iterator = this.recentKeys.values();
166
- const temp = [];
167
- while (numKeysToRemove > 0) {
168
- const value = iterator.next().value;
169
- temp.push(value);
170
- numKeysToRemove--;
196
+ const keysToRemove = [];
197
+ const recentKeysArray = Array.from(this.recentKeys);
198
+ const mostRecentKey = recentKeysArray[recentKeysArray.length - 1];
199
+ let iterResult = iterator.next();
200
+ while (!iterResult.done) {
201
+ const key = iterResult.value;
202
+ // Don't consider the most recently accessed key for eviction
203
+ // This ensures we don't immediately evict a key we just added
204
+ if (key !== undefined && key !== mostRecentKey && this.isEvictableKey(key)) {
205
+ keysToRemove.push(key);
206
+ }
207
+ iterResult = iterator.next();
171
208
  }
172
- for (const key of temp) {
209
+ for (const key of keysToRemove) {
173
210
  delete this.storageMap[key];
174
211
  this.recentKeys.delete(key);
175
212
  }
@@ -182,6 +219,80 @@ class OnyxCache {
182
219
  hasValueChanged(key, value) {
183
220
  return !(0, fast_equals_1.deepEqual)(this.storageMap[key], value);
184
221
  }
222
+ /**
223
+ * Sets the list of keys that are considered safe for eviction
224
+ * @param keys - Array of OnyxKeys that are safe to evict
225
+ */
226
+ setEvictionAllowList(keys) {
227
+ this.evictionAllowList = keys;
228
+ }
229
+ /**
230
+ * Get the eviction block list that prevents keys from being evicted
231
+ */
232
+ getEvictionBlocklist() {
233
+ return this.evictionBlocklist;
234
+ }
235
+ /**
236
+ * Checks to see if this key has been flagged as safe for removal.
237
+ * @param testKey - Key to check
238
+ */
239
+ isEvictableKey(testKey) {
240
+ return this.evictionAllowList.some((key) => this.isKeyMatch(key, testKey));
241
+ }
242
+ /**
243
+ * Check if a given key matches a pattern key
244
+ * @param configKey - Pattern that may contain a wildcard
245
+ * @param key - Key to test against the pattern
246
+ */
247
+ isKeyMatch(configKey, key) {
248
+ const isCollectionKey = configKey.endsWith('_');
249
+ return isCollectionKey ? Str.startsWith(key, configKey) : configKey === key;
250
+ }
251
+ /**
252
+ * Remove a key from the recently accessed key list.
253
+ */
254
+ removeLastAccessedKey(key) {
255
+ this.recentlyAccessedKeys = this.recentlyAccessedKeys.filter((recentlyAccessedKey) => recentlyAccessedKey !== key);
256
+ }
257
+ /**
258
+ * Add a key to the list of recently accessed keys. The least
259
+ * recently accessed key should be at the head and the most
260
+ * recently accessed key at the tail.
261
+ */
262
+ addLastAccessedKey(key, isCollectionKey) {
263
+ // Only specific keys belong in this list since we cannot remove an entire collection.
264
+ if (isCollectionKey || !this.isEvictableKey(key)) {
265
+ return;
266
+ }
267
+ this.removeLastAccessedKey(key);
268
+ this.recentlyAccessedKeys.push(key);
269
+ }
270
+ /**
271
+ * Take all the keys that are safe to evict and add them to
272
+ * the recently accessed list when initializing the app. This
273
+ * enables keys that have not recently been accessed to be
274
+ * removed.
275
+ * @param isCollectionKeyFn - Function to determine if a key is a collection key
276
+ * @param getAllKeysFn - Function to get all keys, defaults to Storage.getAllKeys
277
+ */
278
+ addEvictableKeysToRecentlyAccessedList(isCollectionKeyFn, getAllKeysFn) {
279
+ return getAllKeysFn().then((keys) => {
280
+ this.evictionAllowList.forEach((evictableKey) => {
281
+ keys.forEach((key) => {
282
+ if (!this.isKeyMatch(evictableKey, key)) {
283
+ return;
284
+ }
285
+ this.addLastAccessedKey(key, isCollectionKeyFn(key));
286
+ });
287
+ });
288
+ });
289
+ }
290
+ /**
291
+ * Finds a key that can be safely evicted
292
+ */
293
+ getKeyForEviction() {
294
+ return this.recentlyAccessedKeys.find((key) => !this.evictionBlocklist[key]);
295
+ }
185
296
  }
186
297
  const instance = new OnyxCache();
187
298
  exports.default = instance;
@@ -31,6 +31,7 @@ const Logger = __importStar(require("./Logger"));
31
31
  const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
32
32
  const Str = __importStar(require("./Str"));
33
33
  const utils_1 = __importDefault(require("./utils"));
34
+ const OnyxCache_1 = __importDefault(require("./OnyxCache"));
34
35
  /**
35
36
  * Manages Onyx connections of `Onyx.connect()`, `useOnyx()` and `withOnyx()` subscribers.
36
37
  */
@@ -192,7 +193,7 @@ class OnyxConnectionManager {
192
193
  Logger.logInfo(`[ConnectionManager] Attempted to add connection to eviction block list but no connection was found.`);
193
194
  return;
194
195
  }
195
- const evictionBlocklist = OnyxUtils_1.default.getEvictionBlocklist();
196
+ const evictionBlocklist = OnyxCache_1.default.getEvictionBlocklist();
196
197
  if (!evictionBlocklist[connectionMetadata.onyxKey]) {
197
198
  evictionBlocklist[connectionMetadata.onyxKey] = [];
198
199
  }
@@ -213,7 +214,7 @@ class OnyxConnectionManager {
213
214
  Logger.logInfo(`[ConnectionManager] Attempted to remove connection from eviction block list but no connection was found.`);
214
215
  return;
215
216
  }
216
- const evictionBlocklist = OnyxUtils_1.default.getEvictionBlocklist();
217
+ const evictionBlocklist = OnyxCache_1.default.getEvictionBlocklist();
217
218
  evictionBlocklist[connectionMetadata.onyxKey] =
218
219
  (_b = (_a = evictionBlocklist[connectionMetadata.onyxKey]) === null || _a === void 0 ? void 0 : _a.filter((evictionKey) => evictionKey !== `${connection.id}_${connection.callbackID}`)) !== null && _b !== void 0 ? _b : [];
219
220
  // Remove the key if there are no more subscribers.
@@ -29,10 +29,6 @@ declare function getDefaultKeyStates(): Record<OnyxKey, OnyxValue<OnyxKey>>;
29
29
  * Getter - returns the deffered init task.
30
30
  */
31
31
  declare function getDeferredInitTask(): DeferredTask;
32
- /**
33
- * Getter - returns the eviction block list.
34
- */
35
- declare function getEvictionBlocklist(): Record<OnyxKey, string[] | undefined>;
36
32
  /**
37
33
  * Getter - returns the skippable collection member IDs.
38
34
  */
@@ -46,9 +42,9 @@ declare function setSkippableCollectionMemberIDs(ids: Set<string>): void;
46
42
  *
47
43
  * @param keys - `ONYXKEYS` constants object from Onyx.init()
48
44
  * @param initialKeyStates - initial data to set when `init()` and `clear()` are called
49
- * @param safeEvictionKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
45
+ * @param evictableKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
50
46
  */
51
- declare function initStoreValues(keys: DeepRecord<string, OnyxKey>, initialKeyStates: Partial<KeyValueMapping>, safeEvictionKeys: OnyxKey[]): void;
47
+ declare function initStoreValues(keys: DeepRecord<string, OnyxKey>, initialKeyStates: Partial<KeyValueMapping>, evictableKeys: OnyxKey[]): void;
52
48
  /**
53
49
  * Sends an action to DevTools extension
54
50
  *
@@ -123,8 +119,6 @@ declare function splitCollectionMemberKey<TKey extends CollectionKey, Collection
123
119
  * or if the provided key is a collection member key (in case our configured key is a "collection key")
124
120
  */
125
121
  declare function isKeyMatch(configKey: OnyxKey, key: OnyxKey): boolean;
126
- /** Checks to see if this key has been flagged as safe for removal. */
127
- declare function isSafeEvictionKey(testKey: OnyxKey): boolean;
128
122
  /**
129
123
  * Extracts the collection identifier of a given collection member key.
130
124
  *
@@ -143,23 +137,6 @@ declare function getCollectionKey(key: CollectionKey): string;
143
137
  * If the requested key is a collection, it will return an object with all the collection members.
144
138
  */
145
139
  declare function tryGetCachedValue<TKey extends OnyxKey>(key: TKey, mapping?: Partial<Mapping<TKey>>): OnyxValue<OnyxKey>;
146
- /**
147
- * Remove a key from the recently accessed key list.
148
- */
149
- declare function removeLastAccessedKey(key: OnyxKey): void;
150
- /**
151
- * Add a key to the list of recently accessed keys. The least
152
- * recently accessed key should be at the head and the most
153
- * recently accessed key at the tail.
154
- */
155
- declare function addLastAccessedKey(key: OnyxKey): void;
156
- /**
157
- * Take all the keys that are safe to evict and add them to
158
- * the recently accessed list when initializing the app. This
159
- * enables keys that have not recently been accessed to be
160
- * removed.
161
- */
162
- declare function addAllSafeEvictionKeysToRecentlyAccessedList(): Promise<void>;
163
140
  declare function getCachedCollection<TKey extends CollectionKeyBase>(collectionKey: TKey, collectionMemberKeys?: string[]): NonNullable<OnyxCollection<KeyValueMapping[TKey]>>;
164
141
  /**
165
142
  * When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
@@ -292,11 +269,7 @@ declare const OnyxUtils: {
292
269
  isCollectionMemberKey: typeof isCollectionMemberKey;
293
270
  splitCollectionMemberKey: typeof splitCollectionMemberKey;
294
271
  isKeyMatch: typeof isKeyMatch;
295
- isSafeEvictionKey: typeof isSafeEvictionKey;
296
272
  tryGetCachedValue: typeof tryGetCachedValue;
297
- removeLastAccessedKey: typeof removeLastAccessedKey;
298
- addLastAccessedKey: typeof addLastAccessedKey;
299
- addAllSafeEvictionKeysToRecentlyAccessedList: typeof addAllSafeEvictionKeysToRecentlyAccessedList;
300
273
  getCachedCollection: typeof getCachedCollection;
301
274
  keysChanged: typeof keysChanged;
302
275
  keyChanged: typeof keyChanged;
@@ -321,7 +294,6 @@ declare const OnyxUtils: {
321
294
  doAllCollectionItemsBelongToSameParent: typeof doAllCollectionItemsBelongToSameParent;
322
295
  subscribeToKey: typeof subscribeToKey;
323
296
  unsubscribeFromKey: typeof unsubscribeFromKey;
324
- getEvictionBlocklist: typeof getEvictionBlocklist;
325
297
  getSkippableCollectionMemberIDs: typeof getSkippableCollectionMemberIDs;
326
298
  setSkippableCollectionMemberIDs: typeof setSkippableCollectionMemberIDs;
327
299
  storeKeyBySubscriptions: typeof storeKeyBySubscriptions;
package/dist/OnyxUtils.js CHANGED
@@ -59,14 +59,6 @@ const callbackToStateMapping = {};
59
59
  let onyxCollectionKeySet = new Set();
60
60
  // Holds a mapping of the connected key to the subscriptionID for faster lookups
61
61
  const onyxKeyToSubscriptionIDs = new Map();
62
- // Holds a list of keys that have been directly subscribed to or recently modified from least to most recent
63
- let recentlyAccessedKeys = [];
64
- // Holds a list of keys that are safe to remove when we reach max storage. If a key does not match with
65
- // whatever appears in this list it will NEVER be a candidate for eviction.
66
- let evictionAllowList = [];
67
- // Holds a map of keys and connection arrays whose keys will never be automatically evicted as
68
- // long as we have at least one subscriber that returns false for the canEvict property.
69
- const evictionBlocklist = {};
70
62
  // Optional user-provided key value states set when Onyx initializes or clears
71
63
  let defaultKeyStates = {};
72
64
  let batchUpdatesPromise = null;
@@ -107,12 +99,6 @@ function getDefaultKeyStates() {
107
99
  function getDeferredInitTask() {
108
100
  return deferredInitTask;
109
101
  }
110
- /**
111
- * Getter - returns the eviction block list.
112
- */
113
- function getEvictionBlocklist() {
114
- return evictionBlocklist;
115
- }
116
102
  /**
117
103
  * Getter - returns the skippable collection member IDs.
118
104
  */
@@ -130,9 +116,9 @@ function setSkippableCollectionMemberIDs(ids) {
130
116
  *
131
117
  * @param keys - `ONYXKEYS` constants object from Onyx.init()
132
118
  * @param initialKeyStates - initial data to set when `init()` and `clear()` are called
133
- * @param safeEvictionKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
119
+ * @param evictableKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
134
120
  */
135
- function initStoreValues(keys, initialKeyStates, safeEvictionKeys) {
121
+ function initStoreValues(keys, initialKeyStates, evictableKeys) {
136
122
  var _a;
137
123
  // We need the value of the collection keys later for checking if a
138
124
  // key is a collection. We store it in a map for faster lookup.
@@ -145,7 +131,7 @@ function initStoreValues(keys, initialKeyStates, safeEvictionKeys) {
145
131
  defaultKeyStates = initialKeyStates;
146
132
  DevTools_1.default.initState(initialKeyStates);
147
133
  // Let Onyx know about which keys are safe to evict
148
- evictionAllowList = safeEvictionKeys;
134
+ OnyxCache_1.default.setEvictionAllowList(evictableKeys);
149
135
  if (typeof keys.COLLECTION === 'object' && typeof keys.COLLECTION.SNAPSHOT === 'string') {
150
136
  snapshotKey = keys.COLLECTION.SNAPSHOT;
151
137
  }
@@ -403,10 +389,6 @@ function splitCollectionMemberKey(key, collectionKey) {
403
389
  function isKeyMatch(configKey, key) {
404
390
  return isCollectionKey(configKey) ? Str.startsWith(key, configKey) : configKey === key;
405
391
  }
406
- /** Checks to see if this key has been flagged as safe for removal. */
407
- function isSafeEvictionKey(testKey) {
408
- return evictionAllowList.some((key) => isKeyMatch(key, testKey));
409
- }
410
392
  /**
411
393
  * Extracts the collection identifier of a given collection member key.
412
394
  *
@@ -466,43 +448,6 @@ function tryGetCachedValue(key, mapping) {
466
448
  }
467
449
  return val;
468
450
  }
469
- /**
470
- * Remove a key from the recently accessed key list.
471
- */
472
- function removeLastAccessedKey(key) {
473
- recentlyAccessedKeys = recentlyAccessedKeys.filter((recentlyAccessedKey) => recentlyAccessedKey !== key);
474
- }
475
- /**
476
- * Add a key to the list of recently accessed keys. The least
477
- * recently accessed key should be at the head and the most
478
- * recently accessed key at the tail.
479
- */
480
- function addLastAccessedKey(key) {
481
- // Only specific keys belong in this list since we cannot remove an entire collection.
482
- if (isCollectionKey(key) || !isSafeEvictionKey(key)) {
483
- return;
484
- }
485
- removeLastAccessedKey(key);
486
- recentlyAccessedKeys.push(key);
487
- }
488
- /**
489
- * Take all the keys that are safe to evict and add them to
490
- * the recently accessed list when initializing the app. This
491
- * enables keys that have not recently been accessed to be
492
- * removed.
493
- */
494
- function addAllSafeEvictionKeysToRecentlyAccessedList() {
495
- return getAllKeys().then((keys) => {
496
- evictionAllowList.forEach((safeEvictionKey) => {
497
- keys.forEach((key) => {
498
- if (!isKeyMatch(safeEvictionKey, key)) {
499
- return;
500
- }
501
- addLastAccessedKey(key);
502
- });
503
- });
504
- });
505
- }
506
451
  function getCachedCollection(collectionKey, collectionMemberKeys) {
507
452
  const allKeys = collectionMemberKeys || OnyxCache_1.default.getAllKeys();
508
453
  const collection = {};
@@ -688,10 +633,10 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
688
633
  var _a, _b;
689
634
  // Add or remove this key from the recentlyAccessedKeys lists
690
635
  if (value !== null) {
691
- addLastAccessedKey(key);
636
+ OnyxCache_1.default.addLastAccessedKey(key, isCollectionKey(key));
692
637
  }
693
638
  else {
694
- removeLastAccessedKey(key);
639
+ OnyxCache_1.default.removeLastAccessedKey(key);
695
640
  }
696
641
  // We get the subscribers interested in the key that has just changed. If the subscriber's key is a collection key then we will
697
642
  // notify them if the key that changed is a collection member. Or if it is a regular key notify them when there is an exact match. Depending on whether the subscriber
@@ -872,9 +817,11 @@ function sendDataToConnection(mapping, value, matchedKey, isBatched) {
872
817
  * run out of storage the least recently accessed key can be removed.
873
818
  */
874
819
  function addKeyToRecentlyAccessedIfNeeded(mapping) {
875
- if (!isSafeEvictionKey(mapping.key)) {
820
+ if (!OnyxCache_1.default.isEvictableKey(mapping.key)) {
876
821
  return;
877
822
  }
823
+ // Add the key to recentKeys first (this makes it the most recent key)
824
+ OnyxCache_1.default.addToAccessedKeys(mapping.key);
878
825
  // Try to free some cache whenever we connect to a safe eviction key
879
826
  OnyxCache_1.default.removeLeastRecentlyUsedKeys();
880
827
  if (utils_1.default.hasWithOnyxInstance(mapping) && !isCollectionKey(mapping.key)) {
@@ -882,7 +829,7 @@ function addKeyToRecentlyAccessedIfNeeded(mapping) {
882
829
  if (mapping.canEvict === undefined) {
883
830
  throw new Error(`Cannot subscribe to safe eviction key '${mapping.key}' without providing a canEvict value.`);
884
831
  }
885
- addLastAccessedKey(mapping.key);
832
+ OnyxCache_1.default.addLastAccessedKey(mapping.key, isCollectionKey(mapping.key));
886
833
  }
887
834
  }
888
835
  /**
@@ -945,7 +892,7 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
945
892
  throw error;
946
893
  }
947
894
  // Find the first key that we can remove that has no subscribers in our blocklist
948
- const keyForRemoval = recentlyAccessedKeys.find((key) => !evictionBlocklist[key]);
895
+ const keyForRemoval = OnyxCache_1.default.getKeyForEviction();
949
896
  if (!keyForRemoval) {
950
897
  // If we have no acceptable keys to remove then we are possibly trying to save mission critical data. If this is the case,
951
898
  // then we should stop retrying as there is not much the user can do to fix this. Instead of getting them stuck in an infinite loop we
@@ -1231,11 +1178,7 @@ const OnyxUtils = {
1231
1178
  isCollectionMemberKey,
1232
1179
  splitCollectionMemberKey,
1233
1180
  isKeyMatch,
1234
- isSafeEvictionKey,
1235
1181
  tryGetCachedValue,
1236
- removeLastAccessedKey,
1237
- addLastAccessedKey,
1238
- addAllSafeEvictionKeysToRecentlyAccessedList,
1239
1182
  getCachedCollection,
1240
1183
  keysChanged,
1241
1184
  keyChanged,
@@ -1260,7 +1203,6 @@ const OnyxUtils = {
1260
1203
  doAllCollectionItemsBelongToSameParent,
1261
1204
  subscribeToKey,
1262
1205
  unsubscribeFromKey,
1263
- getEvictionBlocklist,
1264
1206
  getSkippableCollectionMemberIDs,
1265
1207
  setSkippableCollectionMemberIDs,
1266
1208
  storeKeyBySubscriptions,
@@ -1287,7 +1229,7 @@ GlobalSettings.addGlobalSettingsChangeListener(({ enablePerformanceMetrics }) =>
1287
1229
  // @ts-expect-error Reassign
1288
1230
  getCollectionKeys = (0, metrics_1.default)(getCollectionKeys, 'OnyxUtils.getCollectionKeys');
1289
1231
  // @ts-expect-error Reassign
1290
- addAllSafeEvictionKeysToRecentlyAccessedList = (0, metrics_1.default)(addAllSafeEvictionKeysToRecentlyAccessedList, 'OnyxUtils.addAllSafeEvictionKeysToRecentlyAccessedList');
1232
+ addEvictableKeysToRecentlyAccessedList = (0, metrics_1.default)(OnyxCache_1.default.addEvictableKeysToRecentlyAccessedList, 'OnyxCache.addEvictableKeysToRecentlyAccessedList');
1291
1233
  // @ts-expect-error Reassign
1292
1234
  keysChanged = (0, metrics_1.default)(keysChanged, 'OnyxUtils.keysChanged');
1293
1235
  // @ts-expect-error Reassign
package/dist/types.d.ts CHANGED
@@ -379,7 +379,7 @@ type InitOptions = {
379
379
  * This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged
380
380
  * as "safe" for removal. Any components subscribing to these keys must also implement a canEvict option. See the README for more info.
381
381
  */
382
- safeEvictionKeys?: OnyxKey[];
382
+ evictableKeys?: OnyxKey[];
383
383
  /**
384
384
  * Sets how many recent keys should we try to keep in cache
385
385
  * Setting this to 0 would practically mean no cache
package/dist/useOnyx.js CHANGED
@@ -124,8 +124,8 @@ function useOnyx(key, options, dependencies = []) {
124
124
  if ((options === null || options === void 0 ? void 0 : options.canEvict) === undefined || !connectionRef.current) {
125
125
  return;
126
126
  }
127
- if (!OnyxUtils_1.default.isSafeEvictionKey(key)) {
128
- throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({safeEvictionKeys: []}).`);
127
+ if (!OnyxCache_1.default.isEvictableKey(key)) {
128
+ throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({evictableKeys: []}).`);
129
129
  }
130
130
  if (options.canEvict) {
131
131
  OnyxConnectionManager_1.default.removeFromEvictionBlockList(connectionRef.current);
@@ -257,8 +257,8 @@ function default_1(mapOnyxToState, shouldDelayUpdates = false) {
257
257
  }
258
258
  const canEvict = !!Str.result(mapping.canEvict, this.props);
259
259
  const key = Str.result(mapping.key, this.props);
260
- if (!OnyxUtils_1.default.isSafeEvictionKey(key)) {
261
- throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({safeEvictionKeys: []}).`);
260
+ if (!OnyxCache_1.default.isEvictableKey(key)) {
261
+ throw new Error(`canEvict can't be used on key '${key}'. This key must explicitly be flagged as safe for removal by adding it to Onyx.init({evictableKeys: []}).`);
262
262
  }
263
263
  if (canEvict) {
264
264
  OnyxConnectionManager_1.default.removeFromEvictionBlockList(this.activeConnections[key]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-onyx",
3
- "version": "2.0.103",
3
+ "version": "2.0.104",
4
4
  "author": "Expensify, Inc.",
5
5
  "homepage": "https://expensify.com",
6
6
  "description": "State management for React Native",