react-native-onyx 2.0.3 → 2.0.5

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 CHANGED
@@ -486,7 +486,7 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
486
486
  const data = cachedCollection[subscriber.key];
487
487
  const previousData = prevState[subscriber.statePropertyName];
488
488
  // Avoids triggering unnecessary re-renders when feeding empty objects
489
- if (utils_1.default.areObjectsEmpty(data, previousData)) {
489
+ if (utils_1.default.isEmptyObject(data) && utils_1.default.isEmptyObject(previousData)) {
490
490
  return null;
491
491
  }
492
492
  if (data === previousData) {
@@ -510,11 +510,12 @@ function keysChanged(collectionKey, partialCollection, notifyRegularSubscibers =
510
510
  * @private
511
511
  * @param {String} key
512
512
  * @param {*} data
513
+ * @param {*} prevData
513
514
  * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
514
515
  * @param {boolean} [notifyRegularSubscibers=true]
515
516
  * @param {boolean} [notifyWithOnyxSubscibers=true]
516
517
  */
517
- function keyChanged(key, data, canUpdateSubscriber, notifyRegularSubscibers = true, notifyWithOnyxSubscibers = true) {
518
+ function keyChanged(key, data, prevData, canUpdateSubscriber = () => true, notifyRegularSubscibers = true, notifyWithOnyxSubscibers = true) {
518
519
  // Add or remove this key from the recentlyAccessedKeys lists
519
520
  if (!underscore_1.default.isNull(data)) {
520
521
  addLastAccessedKey(key);
@@ -528,7 +529,7 @@ function keyChanged(key, data, canUpdateSubscriber, notifyRegularSubscibers = tr
528
529
  const stateMappingKeys = underscore_1.default.keys(callbackToStateMapping);
529
530
  for (let i = 0; i < stateMappingKeys.length; i++) {
530
531
  const subscriber = callbackToStateMapping[stateMappingKeys[i]];
531
- if (!subscriber || !isKeyMatch(subscriber.key, key) || (underscore_1.default.isFunction(canUpdateSubscriber) && !canUpdateSubscriber(subscriber))) {
532
+ if (!subscriber || !isKeyMatch(subscriber.key, key) || !canUpdateSubscriber(subscriber)) {
532
533
  continue;
533
534
  }
534
535
  // Subscriber is a regular call to connect() and provided a callback
@@ -556,13 +557,13 @@ function keyChanged(key, data, canUpdateSubscriber, notifyRegularSubscibers = tr
556
557
  // returned by the selector and only when the selected data has changed.
557
558
  if (subscriber.selector) {
558
559
  subscriber.withOnyxInstance.setStateProxy((prevState) => {
559
- const prevData = prevState[subscriber.statePropertyName];
560
- const newData = {
560
+ const prevWithOnyxData = prevState[subscriber.statePropertyName];
561
+ const newWithOnyxData = {
561
562
  [key]: getSubsetOfData(data, subscriber.selector, subscriber.withOnyxInstance.state),
562
563
  };
563
- const prevDataWithNewData = Object.assign(Object.assign({}, prevData), newData);
564
- if (!(0, fast_equals_1.deepEqual)(prevData, prevDataWithNewData)) {
565
- PerformanceUtils.logSetStateCall(subscriber, prevData, newData, 'keyChanged', key);
564
+ const prevDataWithNewData = Object.assign(Object.assign({}, prevWithOnyxData), newWithOnyxData);
565
+ if (!(0, fast_equals_1.deepEqual)(prevWithOnyxData, prevDataWithNewData)) {
566
+ PerformanceUtils.logSetStateCall(subscriber, prevWithOnyxData, newWithOnyxData, 'keyChanged', key);
566
567
  return {
567
568
  [subscriber.statePropertyName]: prevDataWithNewData,
568
569
  };
@@ -584,8 +585,8 @@ function keyChanged(key, data, canUpdateSubscriber, notifyRegularSubscibers = tr
584
585
  // If the subscriber has a selector, then the component's state must only be updated with the data
585
586
  // returned by the selector and only if the selected data has changed.
586
587
  if (subscriber.selector) {
587
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
588
- const previousValue = getSubsetOfData(prevState[subscriber.statePropertyName], subscriber.selector, subscriber.withOnyxInstance.state);
588
+ subscriber.withOnyxInstance.setStateProxy(() => {
589
+ const previousValue = getSubsetOfData(prevData, subscriber.selector, subscriber.withOnyxInstance.state);
589
590
  const newValue = getSubsetOfData(data, subscriber.selector, subscriber.withOnyxInstance.state);
590
591
  if (!(0, fast_equals_1.deepEqual)(previousValue, newValue)) {
591
592
  return {
@@ -598,15 +599,15 @@ function keyChanged(key, data, canUpdateSubscriber, notifyRegularSubscibers = tr
598
599
  }
599
600
  // If we did not match on a collection key then we just set the new data to the state property
600
601
  subscriber.withOnyxInstance.setStateProxy((prevState) => {
601
- const previousData = prevState[subscriber.statePropertyName];
602
+ const prevWithOnyxData = prevState[subscriber.statePropertyName];
602
603
  // Avoids triggering unnecessary re-renders when feeding empty objects
603
- if (utils_1.default.areObjectsEmpty(data, previousData)) {
604
+ if (utils_1.default.isEmptyObject(data) && utils_1.default.isEmptyObject(prevWithOnyxData)) {
604
605
  return null;
605
606
  }
606
- if (previousData === data) {
607
+ if (prevWithOnyxData === data) {
607
608
  return null;
608
609
  }
609
- PerformanceUtils.logSetStateCall(subscriber, previousData, data, 'keyChanged', key);
610
+ PerformanceUtils.logSetStateCall(subscriber, prevData, data, 'keyChanged', key);
610
611
  return {
611
612
  [subscriber.statePropertyName]: data,
612
613
  };
@@ -829,12 +830,13 @@ function disconnect(connectionID, keyToRemoveFromEvictionBlocklist) {
829
830
  *
830
831
  * @param {String} key
831
832
  * @param {*} value
833
+ * @param {*} prevValue
832
834
  * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
833
835
  * @returns {Promise}
834
836
  */
835
- function scheduleSubscriberUpdate(key, value, canUpdateSubscriber) {
836
- const promise = Promise.resolve().then(() => keyChanged(key, value, canUpdateSubscriber, true, false));
837
- batchUpdates(() => keyChanged(key, value, canUpdateSubscriber, false, true));
837
+ function scheduleSubscriberUpdate(key, value, prevValue, canUpdateSubscriber = () => true) {
838
+ const promise = Promise.resolve().then(() => keyChanged(key, value, prevValue, canUpdateSubscriber, true, false));
839
+ batchUpdates(() => keyChanged(key, value, prevValue, canUpdateSubscriber, false, true));
838
840
  return Promise.all([maybeFlushBatchUpdates(), promise]);
839
841
  }
840
842
  /**
@@ -859,8 +861,9 @@ function scheduleNotifyCollectionSubscribers(key, value) {
859
861
  * @return {Promise}
860
862
  */
861
863
  function remove(key) {
864
+ const prevValue = OnyxCache_1.default.getValue(key, false);
862
865
  OnyxCache_1.default.drop(key);
863
- scheduleSubscriberUpdate(key, null);
866
+ scheduleSubscriberUpdate(key, null, prevValue);
864
867
  return storage_1.default.removeItem(key);
865
868
  }
866
869
  /**
@@ -920,6 +923,7 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
920
923
  function broadcastUpdate(key, value, method, hasChanged, wasRemoved = false) {
921
924
  // Logging properties only since values could be sensitive things we don't want to log
922
925
  Logger.logInfo(`${method}() called for key: ${key}${underscore_1.default.isObject(value) ? ` properties: ${underscore_1.default.keys(value).join(',')}` : ''}`);
926
+ const prevValue = OnyxCache_1.default.getValue(key, false);
923
927
  // Update subscribers if the cached value has changed, or when the subscriber specifically requires
924
928
  // all updates regardless of value changes (indicated by initWithStoredValues set to false).
925
929
  if (hasChanged && !wasRemoved) {
@@ -928,7 +932,7 @@ function broadcastUpdate(key, value, method, hasChanged, wasRemoved = false) {
928
932
  else {
929
933
  OnyxCache_1.default.addToAccessedKeys(key);
930
934
  }
931
- return scheduleSubscriberUpdate(key, value, (subscriber) => hasChanged || subscriber.initWithStoredValues === false);
935
+ return scheduleSubscriberUpdate(key, value, prevValue, (subscriber) => hasChanged || subscriber.initWithStoredValues === false);
932
936
  }
933
937
  /**
934
938
  * @param {String} key
@@ -1011,9 +1015,10 @@ function prepareKeyValuePairsForStorage(data) {
1011
1015
  function multiSet(data) {
1012
1016
  const keyValuePairs = prepareKeyValuePairsForStorage(data);
1013
1017
  const updatePromises = underscore_1.default.map(keyValuePairs, ([key, value]) => {
1018
+ const prevValue = OnyxCache_1.default.getValue(key, false);
1014
1019
  // Update cache and optimistically inform subscribers on the next tick
1015
1020
  OnyxCache_1.default.set(key, value);
1016
- return scheduleSubscriberUpdate(key, value);
1021
+ return scheduleSubscriberUpdate(key, value, prevValue);
1017
1022
  });
1018
1023
  return storage_1.default.multiSet(keyValuePairs)
1019
1024
  .catch((error) => evictStorageAndRetry(error, multiSet, data))
@@ -1130,10 +1135,10 @@ function merge(key, changes) {
1130
1135
  */
1131
1136
  function initializeWithDefaultKeyStates() {
1132
1137
  return storage_1.default.multiGet(underscore_1.default.keys(defaultKeyStates)).then((pairs) => {
1133
- const asObject = underscore_1.default.object(pairs);
1134
- const merged = utils_1.default.fastMerge(asObject, defaultKeyStates);
1138
+ const existingDataAsObject = underscore_1.default.object(pairs);
1139
+ const merged = utils_1.default.fastMerge(existingDataAsObject, defaultKeyStates);
1135
1140
  OnyxCache_1.default.merge(merged);
1136
- underscore_1.default.each(merged, (val, key) => keyChanged(key, val));
1141
+ underscore_1.default.each(merged, (val, key) => keyChanged(key, val, existingDataAsObject));
1137
1142
  });
1138
1143
  }
1139
1144
  /**
@@ -1201,7 +1206,7 @@ function clear(keysToPreserve = []) {
1201
1206
  const updatePromises = [];
1202
1207
  // Notify the subscribers for each key/value group so they can receive the new values
1203
1208
  underscore_1.default.each(keyValuesToResetIndividually, (value, key) => {
1204
- updatePromises.push(scheduleSubscriberUpdate(key, value));
1209
+ updatePromises.push(scheduleSubscriberUpdate(key, value, OnyxCache_1.default.getValue(key, false)));
1205
1210
  });
1206
1211
  underscore_1.default.each(keyValuesToResetAsCollection, (value, key) => {
1207
1212
  updatePromises.push(scheduleNotifyCollectionSubscribers(key, value));
@@ -1401,8 +1406,9 @@ function init({ keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCach
1401
1406
  Promise.all([addAllSafeEvictionKeysToRecentlyAccessedList(), initializeWithDefaultKeyStates()]).then(deferredInitTask.resolve);
1402
1407
  if (shouldSyncMultipleInstances && underscore_1.default.isFunction(storage_1.default.keepInstancesSync)) {
1403
1408
  storage_1.default.keepInstancesSync((key, value) => {
1409
+ const prevValue = OnyxCache_1.default.getValue(key, false);
1404
1410
  OnyxCache_1.default.set(key, value);
1405
- keyChanged(key, value);
1411
+ keyChanged(key, value, prevValue);
1406
1412
  });
1407
1413
  }
1408
1414
  }
@@ -1,121 +1,75 @@
1
- export default instance;
2
- declare const instance: OnyxCache;
1
+ import type { Key, Value } from './storage/providers/types';
2
+ type StorageMap = Record<Key, Value>;
3
3
  /**
4
4
  * In memory cache providing data by reference
5
5
  * Encapsulates Onyx cache related functionality
6
6
  */
7
7
  declare class OnyxCache {
8
- /**
9
- * @private
10
- * Cache of all the storage keys available in persistent storage
11
- * @type {Set<string>}
12
- */
8
+ /** Cache of all the storage keys available in persistent storage */
13
9
  private storageKeys;
14
- /**
15
- * @private
16
- * Unique list of keys maintained in access order (most recent at the end)
17
- * @type {Set<string>}
18
- */
10
+ /** Unique list of keys maintained in access order (most recent at the end) */
19
11
  private recentKeys;
20
- /**
21
- * @private
22
- * A map of cached values
23
- * @type {Record<string, *>}
24
- */
12
+ /** A map of cached values */
25
13
  private storageMap;
26
14
  /**
27
- * @private
28
15
  * Captured pending tasks for already running storage methods
29
16
  * Using a map yields better performance on operations such a delete
30
- * https://www.zhenghao.io/posts/object-vs-map
31
- * @type {Map<string, Promise>}
32
17
  */
33
18
  private pendingPromises;
34
- /**
35
- * Get all the storage keys
36
- * @returns {string[]}
37
- */
38
- getAllKeys(): string[];
19
+ /** Maximum size of the keys store din cache */
20
+ private maxRecentKeysSize;
21
+ constructor();
22
+ /** Get all the storage keys */
23
+ getAllKeys(): Key[];
39
24
  /**
40
25
  * Get a cached value from storage
41
- * @param {string} key
42
- * @returns {*}
26
+ * @param [shouldReindexCache] – This is an LRU cache, and by default accessing a value will make it become last in line to be evicted. This flag can be used to skip that and just access the value directly without side-effects.
43
27
  */
44
- getValue(key: string): any;
45
- /**
46
- * Check whether cache has data for the given key
47
- * @param {string} key
48
- * @returns {boolean}
49
- */
50
- hasCacheForKey(key: string): boolean;
51
- /**
52
- * Saves a key in the storage keys list
28
+ getValue(key: Key, shouldReindexCache?: boolean): Value;
29
+ /** Check whether cache has data for the given key */
30
+ hasCacheForKey(key: Key): boolean;
31
+ /** Saves a key in the storage keys list
53
32
  * Serves to keep the result of `getAllKeys` up to date
54
- * @param {string} key
55
33
  */
56
- addKey(key: string): void;
34
+ addKey(key: Key): void;
57
35
  /**
58
36
  * Set's a key value in cache
59
37
  * Adds the key to the storage keys list as well
60
- * @param {string} key
61
- * @param {*} value
62
- * @returns {*} value - returns the cache value
63
38
  */
64
- set(key: string, value: any): any;
65
- /**
66
- * Forget the cached value for the given key
67
- * @param {string} key
68
- */
69
- drop(key: string): void;
39
+ set(key: Key, value: Value): Value;
40
+ /** Forget the cached value for the given key */
41
+ drop(key: Key): void;
70
42
  /**
71
43
  * Deep merge data to cache, any non existing keys will be created
72
- * @param {Record<string, *>} data - a map of (cache) key - values
44
+ * @param data - a map of (cache) key - values
73
45
  */
74
- merge(data: Record<string, any>): void;
46
+ merge(data: StorageMap): void;
75
47
  /**
76
48
  * Check whether the given task is already running
77
- * @param {string} taskName - unique name given for the task
78
- * @returns {*}
49
+ * @param taskName - unique name given for the task
79
50
  */
80
- hasPendingTask(taskName: string): any;
51
+ hasPendingTask(taskName: string): boolean;
81
52
  /**
82
53
  * Use this method to prevent concurrent calls for the same thing
83
54
  * Instead of calling the same task again use the existing promise
84
55
  * provided from this function
85
- * @template T
86
- * @param {string} taskName - unique name given for the task
87
- * @returns {Promise<T>}
56
+ * @param taskName - unique name given for the task
88
57
  */
89
- getTaskPromise<T>(taskName: string): Promise<T>;
58
+ getTaskPromise(taskName: string): Promise<unknown> | undefined;
90
59
  /**
91
60
  * Capture a promise for a given task so other caller can
92
61
  * hook up to the promise if it's still pending
93
- * @template T
94
- * @param {string} taskName - unique name for the task
95
- * @param {Promise<T>} promise
96
- * @returns {Promise<T>}
97
- */
98
- captureTask<T_1>(taskName: string, promise: Promise<T_1>): Promise<T_1>;
99
- /**
100
- * @private
101
- * Adds a key to the top of the recently accessed keys
102
- * @param {string} key
62
+ * @param taskName - unique name for the task
103
63
  */
64
+ captureTask(taskName: string, promise: Promise<unknown>): Promise<unknown>;
65
+ /** Adds a key to the top of the recently accessed keys */
104
66
  private addToAccessedKeys;
105
- /**
106
- * Remove keys that don't fall into the range of recently used keys
107
- */
67
+ /** Remove keys that don't fall into the range of recently used keys */
108
68
  removeLeastRecentlyUsedKeys(): void;
109
- /**
110
- * Set the recent keys list size
111
- * @param {number} limit
112
- */
69
+ /** Set the recent keys list size */
113
70
  setRecentKeysLimit(limit: number): void;
114
- maxRecentKeysSize: number | undefined;
115
- /**
116
- * @param {String} key
117
- * @param {*} value
118
- * @returns {Boolean}
119
- */
120
- hasValueChanged(key: string, value: any): boolean;
71
+ /** Check if the value has changed */
72
+ hasValueChanged(key: Key, value: Value): boolean;
121
73
  }
74
+ declare const instance: OnyxCache;
75
+ export default instance;
package/dist/OnyxCache.js CHANGED
@@ -3,73 +3,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const underscore_1 = __importDefault(require("underscore"));
7
6
  const fast_equals_1 = require("fast-equals");
7
+ const bindAll_1 = __importDefault(require("lodash/bindAll"));
8
8
  const utils_1 = __importDefault(require("./utils"));
9
- const isDefined = underscore_1.default.negate(underscore_1.default.isUndefined);
10
9
  /**
11
10
  * In memory cache providing data by reference
12
11
  * Encapsulates Onyx cache related functionality
13
12
  */
14
13
  class OnyxCache {
15
14
  constructor() {
16
- /**
17
- * @private
18
- * Cache of all the storage keys available in persistent storage
19
- * @type {Set<string>}
20
- */
15
+ /** Maximum size of the keys store din cache */
16
+ this.maxRecentKeysSize = 0;
21
17
  this.storageKeys = new Set();
22
- /**
23
- * @private
24
- * Unique list of keys maintained in access order (most recent at the end)
25
- * @type {Set<string>}
26
- */
27
18
  this.recentKeys = new Set();
28
- /**
29
- * @private
30
- * A map of cached values
31
- * @type {Record<string, *>}
32
- */
33
19
  this.storageMap = {};
34
- /**
35
- * @private
36
- * Captured pending tasks for already running storage methods
37
- * Using a map yields better performance on operations such a delete
38
- * https://www.zhenghao.io/posts/object-vs-map
39
- * @type {Map<string, Promise>}
40
- */
41
20
  this.pendingPromises = new Map();
42
21
  // bind all public methods to prevent problems with `this`
43
- underscore_1.default.bindAll(this, 'getAllKeys', 'getValue', 'hasCacheForKey', 'addKey', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit');
22
+ (0, bindAll_1.default)(this, 'getAllKeys', 'getValue', 'hasCacheForKey', 'addKey', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit');
44
23
  }
45
- /**
46
- * Get all the storage keys
47
- * @returns {string[]}
48
- */
24
+ /** Get all the storage keys */
49
25
  getAllKeys() {
50
26
  return Array.from(this.storageKeys);
51
27
  }
52
28
  /**
53
29
  * Get a cached value from storage
54
- * @param {string} key
55
- * @returns {*}
30
+ * @param [shouldReindexCache] – This is an LRU cache, and by default accessing a value will make it become last in line to be evicted. This flag can be used to skip that and just access the value directly without side-effects.
56
31
  */
57
- getValue(key) {
58
- this.addToAccessedKeys(key);
32
+ getValue(key, shouldReindexCache = true) {
33
+ if (shouldReindexCache) {
34
+ this.addToAccessedKeys(key);
35
+ }
59
36
  return this.storageMap[key];
60
37
  }
61
- /**
62
- * Check whether cache has data for the given key
63
- * @param {string} key
64
- * @returns {boolean}
65
- */
38
+ /** Check whether cache has data for the given key */
66
39
  hasCacheForKey(key) {
67
- return isDefined(this.storageMap[key]);
40
+ return this.storageMap[key] !== undefined;
68
41
  }
69
- /**
70
- * Saves a key in the storage keys list
42
+ /** Saves a key in the storage keys list
71
43
  * Serves to keep the result of `getAllKeys` up to date
72
- * @param {string} key
73
44
  */
74
45
  addKey(key) {
75
46
  this.storageKeys.add(key);
@@ -77,9 +48,6 @@ class OnyxCache {
77
48
  /**
78
49
  * Set's a key value in cache
79
50
  * Adds the key to the storage keys list as well
80
- * @param {string} key
81
- * @param {*} value
82
- * @returns {*} value - returns the cache value
83
51
  */
84
52
  set(key, value) {
85
53
  this.addKey(key);
@@ -87,10 +55,7 @@ class OnyxCache {
87
55
  this.storageMap[key] = value;
88
56
  return value;
89
57
  }
90
- /**
91
- * Forget the cached value for the given key
92
- * @param {string} key
93
- */
58
+ /** Forget the cached value for the given key */
94
59
  drop(key) {
95
60
  delete this.storageMap[key];
96
61
  this.storageKeys.delete(key);
@@ -98,35 +63,30 @@ class OnyxCache {
98
63
  }
99
64
  /**
100
65
  * Deep merge data to cache, any non existing keys will be created
101
- * @param {Record<string, *>} data - a map of (cache) key - values
66
+ * @param data - a map of (cache) key - values
102
67
  */
103
68
  merge(data) {
104
- if (!underscore_1.default.isObject(data) || underscore_1.default.isArray(data)) {
69
+ if (typeof data !== 'object' || Array.isArray(data)) {
105
70
  throw new Error('data passed to cache.merge() must be an Object of onyx key/value pairs');
106
71
  }
107
- // lodash adds a small overhead so we don't use it here
108
- // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
109
72
  this.storageMap = Object.assign({}, utils_1.default.fastMerge(this.storageMap, data, false));
110
73
  const storageKeys = this.getAllKeys();
111
- const mergedKeys = underscore_1.default.keys(data);
74
+ const mergedKeys = Object.keys(data);
112
75
  this.storageKeys = new Set([...storageKeys, ...mergedKeys]);
113
- underscore_1.default.each(mergedKeys, (key) => this.addToAccessedKeys(key));
76
+ mergedKeys.forEach((key) => this.addToAccessedKeys(key));
114
77
  }
115
78
  /**
116
79
  * Check whether the given task is already running
117
- * @param {string} taskName - unique name given for the task
118
- * @returns {*}
80
+ * @param taskName - unique name given for the task
119
81
  */
120
82
  hasPendingTask(taskName) {
121
- return isDefined(this.pendingPromises.get(taskName));
83
+ return this.pendingPromises.get(taskName) !== undefined;
122
84
  }
123
85
  /**
124
86
  * Use this method to prevent concurrent calls for the same thing
125
87
  * Instead of calling the same task again use the existing promise
126
88
  * provided from this function
127
- * @template T
128
- * @param {string} taskName - unique name given for the task
129
- * @returns {Promise<T>}
89
+ * @param taskName - unique name given for the task
130
90
  */
131
91
  getTaskPromise(taskName) {
132
92
  return this.pendingPromises.get(taskName);
@@ -134,10 +94,7 @@ class OnyxCache {
134
94
  /**
135
95
  * Capture a promise for a given task so other caller can
136
96
  * hook up to the promise if it's still pending
137
- * @template T
138
- * @param {string} taskName - unique name for the task
139
- * @param {Promise<T>} promise
140
- * @returns {Promise<T>}
97
+ * @param taskName - unique name for the task
141
98
  */
142
99
  captureTask(taskName, promise) {
143
100
  const returnPromise = promise.finally(() => {
@@ -146,19 +103,12 @@ class OnyxCache {
146
103
  this.pendingPromises.set(taskName, returnPromise);
147
104
  return returnPromise;
148
105
  }
149
- /**
150
- * @private
151
- * Adds a key to the top of the recently accessed keys
152
- * @param {string} key
153
- */
106
+ /** Adds a key to the top of the recently accessed keys */
154
107
  addToAccessedKeys(key) {
155
- // Removing and re-adding a key ensures it's at the end of the list
156
108
  this.recentKeys.delete(key);
157
109
  this.recentKeys.add(key);
158
110
  }
159
- /**
160
- * Remove keys that don't fall into the range of recently used keys
161
- */
111
+ /** Remove keys that don't fall into the range of recently used keys */
162
112
  removeLeastRecentlyUsedKeys() {
163
113
  let numKeysToRemove = this.recentKeys.size - this.maxRecentKeysSize;
164
114
  if (numKeysToRemove <= 0) {
@@ -171,23 +121,17 @@ class OnyxCache {
171
121
  temp.push(value);
172
122
  numKeysToRemove--;
173
123
  }
124
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
174
125
  for (let i = 0; i < temp.length; ++i) {
175
126
  delete this.storageMap[temp[i]];
176
127
  this.recentKeys.delete(temp[i]);
177
128
  }
178
129
  }
179
- /**
180
- * Set the recent keys list size
181
- * @param {number} limit
182
- */
130
+ /** Set the recent keys list size */
183
131
  setRecentKeysLimit(limit) {
184
132
  this.maxRecentKeysSize = limit;
185
133
  }
186
- /**
187
- * @param {String} key
188
- * @param {*} value
189
- * @returns {Boolean}
190
- */
134
+ /** Check if the value has changed */
191
135
  hasValueChanged(key, value) {
192
136
  return !(0, fast_equals_1.deepEqual)(this.storageMap[key], value);
193
137
  }
@@ -1,2 +1,2 @@
1
- export default SQLiteStorage;
2
1
  import SQLiteStorage from './providers/SQLiteStorage';
2
+ export default SQLiteStorage;
@@ -1,19 +1,3 @@
1
+ import type StorageProvider from './providers/types';
2
+ declare const webStorage: StorageProvider;
1
3
  export default webStorage;
2
- declare const webStorage: {
3
- /**
4
- * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
5
- */
6
- keepInstancesSync(onStorageKeyChanged: Function): void;
7
- setItem: (key: string, value: any) => Promise<void>;
8
- multiGet: (keysParam: string[]) => Promise<[key, value][]>;
9
- multiMerge: (pairs: [key, value][]) => Promise<void>;
10
- mergeItem(key: string, _changes: any, modifiedData: any): Promise<void>;
11
- multiSet: (pairs: [key, value][]) => Promise<void>;
12
- clear: () => Promise<void>;
13
- setMemoryOnlyKeys: () => void;
14
- getAllKeys: () => Promise<string[]>;
15
- getItem: (key: string) => Promise<any>;
16
- removeItem: (key: string) => Promise<void>;
17
- removeItems: (keysParam: any[]) => Promise<any>;
18
- getDatabaseSize(): Promise<number>;
19
- };
@@ -8,25 +8,23 @@ Object.defineProperty(exports, "__esModule", { value: true });
8
8
  * when using LocalStorage APIs in the browser. These events are great because multiple tabs can listen for when
9
9
  * data changes and then stay up-to-date with everything happening in Onyx.
10
10
  */
11
- const underscore_1 = __importDefault(require("underscore"));
12
11
  const IDBKeyVal_1 = __importDefault(require("./providers/IDBKeyVal"));
13
12
  const SYNC_ONYX = 'SYNC_ONYX';
14
13
  /**
15
14
  * Raise an event thorough `localStorage` to let other tabs know a value changed
16
- * @param {String} onyxKey
17
15
  */
18
16
  function raiseStorageSyncEvent(onyxKey) {
19
17
  global.localStorage.setItem(SYNC_ONYX, onyxKey);
20
- global.localStorage.removeItem(SYNC_ONYX, onyxKey);
18
+ global.localStorage.removeItem(SYNC_ONYX);
21
19
  }
22
20
  function raiseStorageSyncManyKeysEvent(onyxKeys) {
23
- underscore_1.default.each(onyxKeys, (onyxKey) => {
21
+ onyxKeys.forEach((onyxKey) => {
24
22
  raiseStorageSyncEvent(onyxKey);
25
23
  });
26
24
  }
27
25
  const webStorage = Object.assign(Object.assign({}, IDBKeyVal_1.default), {
28
26
  /**
29
- * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
27
+ * @param onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
30
28
  */
31
29
  keepInstancesSync(onStorageKeyChanged) {
32
30
  // Override set, remove and clear to raise storage events that we intercept in other tabs
@@ -48,7 +46,7 @@ const webStorage = Object.assign(Object.assign({}, IDBKeyVal_1.default), {
48
46
  .then(() => {
49
47
  // Now that storage is cleared, the storage sync event can happen which is a more atomic action
50
48
  // for other browser tabs
51
- underscore_1.default.each(allKeys, raiseStorageSyncEvent);
49
+ allKeys.forEach(raiseStorageSyncEvent);
52
50
  });
53
51
  };
54
52
  // This listener will only be triggered by events coming from other tabs
@@ -1,23 +1,23 @@
1
- export default idbKeyvalMockSpy;
2
- declare namespace idbKeyvalMockSpy {
3
- export { set as idbKeyvalSet };
4
- export let setItem: jest.Mock<Promise<any>, [key?: any, value?: any]>;
5
- export let getItem: jest.Mock<Promise<any>, [key?: any]>;
6
- export let removeItem: jest.Mock<Promise<void>, [key?: any]>;
7
- export let removeItems: jest.Mock<Promise<void>, [keys?: any]>;
8
- export let clear: jest.Mock<Promise<void>, []>;
9
- export let getAllKeys: jest.Mock<Promise<any>, []>;
10
- export let config: jest.Mock<void, []>;
11
- export let multiGet: jest.Mock<Promise<any>, [keys?: any]>;
12
- export let multiSet: jest.Mock<Promise<any>, [pairs?: any]>;
13
- export let multiMerge: jest.Mock<Promise<{}>, [pairs?: any]>;
14
- export let mergeItem: jest.Mock<Promise<any>, [key?: any, _changes?: any, modifiedData?: any]>;
15
- export let getStorageMap: jest.Mock<{}, []>;
16
- export let setInitialMockData: jest.Mock<void, [data?: any]>;
17
- export let getDatabaseSize: jest.Mock<Promise<{
18
- bytesRemaining: number;
1
+ /// <reference types="jest" />
2
+ import type { KeyValuePairList } from '../providers/types';
3
+ declare const idbKeyvalMockSpy: {
4
+ idbKeyvalSet: jest.Mock<Promise<any>, [key: any, value: any]>;
5
+ setItem: jest.Mock<Promise<void | import("react-native-quick-sqlite").QueryResult>, [key: string, value: IDBValidKey]>;
6
+ getItem: jest.Mock<Promise<IDBValidKey | null>, [key: string]>;
7
+ removeItem: jest.Mock<Promise<void | import("react-native-quick-sqlite").QueryResult>, [key: string]>;
8
+ removeItems: jest.Mock<Promise<void | import("react-native-quick-sqlite").QueryResult>, [keys: import("../providers/types").KeyList]>;
9
+ clear: jest.Mock<Promise<void | import("react-native-quick-sqlite").QueryResult>, []>;
10
+ getAllKeys: jest.Mock<Promise<import("../providers/types").KeyList>, []>;
11
+ multiGet: jest.Mock<Promise<KeyValuePairList>, [keys: import("../providers/types").KeyList]>;
12
+ multiSet: jest.Mock<Promise<void | import("react-native-quick-sqlite").BatchQueryResult>, [pairs: KeyValuePairList]>;
13
+ multiMerge: jest.Mock<Promise<import("react-native-quick-sqlite").BatchQueryResult | IDBValidKey[]>, [pairs: KeyValuePairList]>;
14
+ mergeItem: jest.Mock<Promise<void | import("react-native-quick-sqlite").BatchQueryResult>, [key: string, changes: IDBValidKey, modifiedData: IDBValidKey]>;
15
+ getStorageMap: jest.Mock<Record<string, IDBValidKey>, []>;
16
+ setInitialMockData: jest.Mock<void, [data: any]>;
17
+ getDatabaseSize: jest.Mock<Promise<{
19
18
  bytesUsed: number;
19
+ bytesRemaining: number;
20
20
  }>, []>;
21
- export let setMemoryOnlyKeys: jest.Mock<void, []>;
22
- }
23
- declare const set: jest.Mock<Promise<any>, [key?: any, value?: any]>;
21
+ setMemoryOnlyKeys: jest.Mock<void, []>;
22
+ };
23
+ export default idbKeyvalMockSpy;