react-native-onyx 1.0.131 → 2.0.2

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.
Files changed (64) hide show
  1. package/API.md +83 -22
  2. package/README.md +3 -5
  3. package/dist/DevTools.d.ts +23 -0
  4. package/{lib → dist}/DevTools.js +16 -18
  5. package/dist/Logger.js +32 -0
  6. package/dist/MDTable.d.ts +36 -0
  7. package/{lib → dist}/MDTable.js +12 -17
  8. package/{lib → dist}/Onyx.js +278 -477
  9. package/dist/OnyxCache.d.ts +121 -0
  10. package/{lib → dist}/OnyxCache.js +16 -53
  11. package/{lib/Str.js → dist/Str.d.ts} +2 -11
  12. package/dist/Str.js +31 -0
  13. package/dist/SyncQueue.d.ts +32 -0
  14. package/{lib → dist}/SyncQueue.js +9 -11
  15. package/dist/batch.d.ts +2 -0
  16. package/dist/batch.js +4 -0
  17. package/dist/batch.native.d.ts +2 -0
  18. package/dist/batch.native.js +4 -0
  19. package/dist/compose.d.ts +19 -0
  20. package/{lib → dist}/compose.js +5 -8
  21. package/dist/createDeferredTask.d.ts +12 -0
  22. package/{lib → dist}/createDeferredTask.js +4 -2
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.js +10 -0
  25. package/dist/metrics/PerformanceUtils.d.ts +14 -0
  26. package/{lib → dist}/metrics/PerformanceUtils.js +16 -16
  27. package/dist/metrics/index.d.ts +4 -0
  28. package/dist/metrics/index.js +14 -0
  29. package/dist/metrics/index.native.d.ts +43 -0
  30. package/{lib → dist}/metrics/index.native.js +80 -102
  31. package/{lib/storage/NativeStorage.js → dist/storage/NativeStorage.d.ts} +1 -2
  32. package/dist/storage/NativeStorage.js +7 -0
  33. package/dist/storage/WebStorage.d.ts +19 -0
  34. package/{lib → dist}/storage/WebStorage.js +24 -34
  35. package/dist/storage/__mocks__/index.d.ts +23 -0
  36. package/{lib → dist}/storage/__mocks__/index.js +17 -19
  37. package/{lib/storage/index.web.js → dist/storage/index.d.ts} +1 -2
  38. package/dist/storage/index.js +7 -0
  39. package/{lib/storage/index.native.js → dist/storage/index.native.d.ts} +1 -2
  40. package/dist/storage/index.native.js +7 -0
  41. package/dist/storage/providers/IDBKeyVal.d.ts +26 -0
  42. package/{lib → dist}/storage/providers/IDBKeyVal.js +38 -52
  43. package/dist/storage/providers/SQLiteStorage.d.ts +52 -0
  44. package/{lib → dist}/storage/providers/SQLiteStorage.js +27 -42
  45. package/{lib → dist}/utils.js +14 -27
  46. package/{lib → dist}/withOnyx.js +122 -159
  47. package/package.json +23 -54
  48. package/dist/web.development.js +0 -4308
  49. package/dist/web.development.js.map +0 -1
  50. package/dist/web.min.js +0 -2
  51. package/dist/web.min.js.map +0 -1
  52. package/lib/Logger.js +0 -31
  53. package/lib/batch.js +0 -3
  54. package/lib/batch.native.js +0 -3
  55. package/lib/index.d.ts +0 -6
  56. package/lib/index.js +0 -5
  57. package/lib/metrics/index.web.js +0 -10
  58. package/native.js +0 -11
  59. package/web.js +0 -12
  60. /package/{lib → dist}/Logger.d.ts +0 -0
  61. /package/{lib → dist}/Onyx.d.ts +0 -0
  62. /package/{lib → dist}/types.d.ts +0 -0
  63. /package/{lib → dist}/utils.d.ts +0 -0
  64. /package/{lib → dist}/withOnyx.d.ts +0 -0
@@ -1,4308 +0,0 @@
1
- (function webpackUniversalModuleDefinition(root, factory) {
2
- if(typeof exports === 'object' && typeof module === 'object')
3
- module.exports = factory(require("fast-equals"), require("underscore"), require("react-dom"), require("idb-keyval"), require("lodash/transform"), require("react"));
4
- else if(typeof define === 'function' && define.amd)
5
- define(["fast-equals", "underscore", "react-dom", "idb-keyval", "lodash/transform", "react"], factory);
6
- else if(typeof exports === 'object')
7
- exports["react-native-onyx/web"] = factory(require("fast-equals"), require("underscore"), require("react-dom"), require("idb-keyval"), require("lodash/transform"), require("react"));
8
- else
9
- root["react-native-onyx/web"] = factory(root["fast-equals"], root["underscore"], root["react-dom"], root["idb-keyval"], root["lodash/transform"], root["react"]);
10
- })(self, (__WEBPACK_EXTERNAL_MODULE_fast_equals__, __WEBPACK_EXTERNAL_MODULE_underscore__, __WEBPACK_EXTERNAL_MODULE_react_dom__, __WEBPACK_EXTERNAL_MODULE_idb_keyval__, __WEBPACK_EXTERNAL_MODULE_lodash_transform__, __WEBPACK_EXTERNAL_MODULE_react__) => {
11
- return /******/ (() => { // webpackBootstrap
12
- /******/ var __webpack_modules__ = ({
13
-
14
- /***/ "./lib/DevTools.js":
15
- /*!*************************!*\
16
- !*** ./lib/DevTools.js ***!
17
- \*************************/
18
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
19
-
20
- "use strict";
21
- __webpack_require__.r(__webpack_exports__);
22
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
23
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
24
- /* harmony export */ });
25
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
26
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
27
-
28
-
29
- const ERROR_LABEL = 'Onyx DevTools - Error: ';
30
-
31
- /* eslint-disable no-underscore-dangle */
32
- class DevTools {
33
- constructor() {
34
- this.remoteDev = this.connectViaExtension();
35
- this.state = {};
36
- this.defaultState = {};
37
- }
38
-
39
- connectViaExtension(options) {
40
- try {
41
- if (options && options.remote || typeof window === 'undefined' || !window.__REDUX_DEVTOOLS_EXTENSION__) {
42
- return;
43
- }
44
- return window.__REDUX_DEVTOOLS_EXTENSION__.connect(options);
45
- } catch (e) {
46
- console.error(ERROR_LABEL, e);
47
- }
48
- }
49
-
50
- /**
51
- * Registers an action that updated the current state of the storage
52
- *
53
- * @param {string} type - name of the action
54
- * @param {any} payload - data written to the storage
55
- * @param {object} stateChanges - partial state that got updated after the changes
56
- */
57
- registerAction(type) {let payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;let stateChanges = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
58
- try {
59
- if (!this.remoteDev) {
60
- return;
61
- }
62
- const newState = {
63
- ...this.state,
64
- ...stateChanges
65
- };
66
- this.remoteDev.send({ type, payload }, newState);
67
- this.state = newState;
68
- } catch (e) {
69
- console.error(ERROR_LABEL, e);
70
- }
71
- }
72
-
73
- initState() {let initialState = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
74
- try {
75
- if (!this.remoteDev) {
76
- return;
77
- }
78
- this.remoteDev.init(initialState);
79
- this.state = initialState;
80
- this.defaultState = initialState;
81
- } catch (e) {
82
- console.error(ERROR_LABEL, e);
83
- }
84
- }
85
-
86
- /**
87
- * This clears the internal state of the DevTools, preserving the keys included in `keysToPreserve`
88
- *
89
- * @param {string[]} keysToPreserve
90
- */
91
- clearState() {let keysToPreserve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
92
- const newState = underscore__WEBPACK_IMPORTED_MODULE_0___default().mapObject(this.state, (value, key) => keysToPreserve.includes(key) ? value : this.defaultState[key]);
93
- this.registerAction('CLEAR', undefined, newState);
94
- }
95
- }
96
-
97
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (new DevTools());
98
-
99
- /***/ }),
100
-
101
- /***/ "./lib/Logger.js":
102
- /*!***********************!*\
103
- !*** ./lib/Logger.js ***!
104
- \***********************/
105
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
106
-
107
- "use strict";
108
- __webpack_require__.r(__webpack_exports__);
109
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
110
- /* harmony export */ "logAlert": () => (/* binding */ logAlert),
111
- /* harmony export */ "logInfo": () => (/* binding */ logInfo),
112
- /* harmony export */ "registerLogger": () => (/* binding */ registerLogger)
113
- /* harmony export */ });
114
- // Logging callback
115
- let logger = () => {};
116
-
117
- /**
118
- * Register the logging callback
119
- *
120
- * @param {Function} callback
121
- */
122
- function registerLogger(callback) {
123
- logger = callback;
124
- }
125
-
126
- /**
127
- * Send an alert message to the logger
128
- *
129
- * @param {String} message
130
- */
131
- function logAlert(message) {
132
- logger({ message: `[Onyx] ${message}`, level: 'alert' });
133
- }
134
-
135
- /**
136
- * Send an info message to the logger
137
- *
138
- * @param {String} message
139
- */
140
- function logInfo(message) {
141
- logger({ message: `[Onyx] ${message}`, level: 'info' });
142
- }
143
-
144
-
145
-
146
- /***/ }),
147
-
148
- /***/ "./lib/Onyx.js":
149
- /*!*********************!*\
150
- !*** ./lib/Onyx.js ***!
151
- \*********************/
152
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
153
-
154
- "use strict";
155
- __webpack_require__.r(__webpack_exports__);
156
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
157
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
158
- /* harmony export */ });
159
- /* harmony import */ var fast_equals__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! fast-equals */ "fast-equals");
160
- /* harmony import */ var fast_equals__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(fast_equals__WEBPACK_IMPORTED_MODULE_0__);
161
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! underscore */ "underscore");
162
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_1__);
163
- /* harmony import */ var _Logger__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./Logger */ "./lib/Logger.js");
164
- /* harmony import */ var _OnyxCache__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./OnyxCache */ "./lib/OnyxCache.js");
165
- /* harmony import */ var _Str__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./Str */ "./lib/Str.js");
166
- /* harmony import */ var _createDeferredTask__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./createDeferredTask */ "./lib/createDeferredTask.js");
167
- /* harmony import */ var _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./metrics/PerformanceUtils */ "./lib/metrics/PerformanceUtils.js");
168
- /* harmony import */ var _storage__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./storage */ "./lib/storage/index.web.js");
169
- /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./utils */ "./lib/utils.js");
170
- /* harmony import */ var _batch__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./batch */ "./lib/batch.js");
171
- /* harmony import */ var _DevTools__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./DevTools */ "./lib/DevTools.js");
172
- /* eslint-disable no-continue */
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
- // Method constants
186
- const METHOD = {
187
- SET: 'set',
188
- MERGE: 'merge',
189
- MERGE_COLLECTION: 'mergecollection',
190
- MULTI_SET: 'multiset',
191
- CLEAR: 'clear'
192
- };
193
-
194
- // Key/value store of Onyx key and arrays of values to merge
195
- const mergeQueue = {};
196
- const mergeQueuePromise = {};
197
-
198
- // Keeps track of the last connectionID that was used so we can keep incrementing it
199
- let lastConnectionID = 0;
200
-
201
- // Holds a mapping of all the react components that want their state subscribed to a store key
202
- const callbackToStateMapping = {};
203
-
204
- // Keeps a copy of the values of the onyx collection keys as a map for faster lookups
205
- let onyxCollectionKeyMap = new Map();
206
-
207
- // Holds a list of keys that have been directly subscribed to or recently modified from least to most recent
208
- let recentlyAccessedKeys = [];
209
-
210
- // Holds a list of keys that are safe to remove when we reach max storage. If a key does not match with
211
- // whatever appears in this list it will NEVER be a candidate for eviction.
212
- let evictionAllowList = [];
213
-
214
- // Holds a map of keys and connectionID arrays whose keys will never be automatically evicted as
215
- // long as we have at least one subscriber that returns false for the canEvict property.
216
- const evictionBlocklist = {};
217
-
218
- // Optional user-provided key value states set when Onyx initializes or clears
219
- let defaultKeyStates = {};
220
-
221
- // Connections can be made before `Onyx.init`. They would wait for this task before resolving
222
- const deferredInitTask = (0,_createDeferredTask__WEBPACK_IMPORTED_MODULE_2__["default"])();
223
-
224
- let batchUpdatesPromise = null;
225
- let batchUpdatesQueue = [];
226
-
227
- /**
228
- * Sends an action to DevTools extension
229
- *
230
- * @param {string} method - Onyx method from METHOD
231
- * @param {string} key - Onyx key that was changed
232
- * @param {any} value - contains the change that was made by the method
233
- * @param {any} mergedValue - (optional) value that was written in the storage after a merge method was executed.
234
- */
235
- function sendActionToDevTools(method, key, value) {let mergedValue = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined;
236
- _DevTools__WEBPACK_IMPORTED_MODULE_3__["default"].registerAction(_utils__WEBPACK_IMPORTED_MODULE_4__["default"].formatActionName(method, key), value, key ? { [key]: mergedValue || value } : value);
237
- }
238
-
239
- /**
240
- * We are batching together onyx updates. This helps with use cases where we schedule onyx updates after each other.
241
- * This happens for example in the Onyx.update function, where we process API responses that might contain a lot of
242
- * update operations. Instead of calling the subscribers for each update operation, we batch them together which will
243
- * cause react to schedule the updates at once instead of after each other. This is mainly a performance optimization.
244
- * @returns {Promise}
245
- */
246
- function maybeFlushBatchUpdates() {
247
- if (batchUpdatesPromise) {
248
- return batchUpdatesPromise;
249
- }
250
-
251
- batchUpdatesPromise = new Promise((resolve) => {
252
- /* We use (setTimeout, 0) here which should be called once native module calls are flushed (usually at the end of the frame)
253
- * We may investigate if (setTimeout, 1) (which in React Native is equal to requestAnimationFrame) works even better
254
- * then the batch will be flushed on next frame.
255
- */
256
- setTimeout(() => {
257
- const updatesCopy = batchUpdatesQueue;
258
- batchUpdatesQueue = [];
259
- batchUpdatesPromise = null;
260
- (0,_batch__WEBPACK_IMPORTED_MODULE_5__["default"])(() => {
261
- updatesCopy.forEach((applyUpdates) => {
262
- applyUpdates();
263
- });
264
- });
265
-
266
- resolve();
267
- }, 0);
268
- });
269
- return batchUpdatesPromise;
270
- }
271
-
272
- function batchUpdates(updates) {
273
- batchUpdatesQueue.push(updates);
274
- return maybeFlushBatchUpdates();
275
- }
276
-
277
- /**
278
- * Uses a selector function to return a simplified version of sourceData
279
- * @param {Mixed} sourceData
280
- * @param {Function} selector Function that takes sourceData and returns a simplified version of it
281
- * @param {Object} [withOnyxInstanceState]
282
- * @returns {Mixed}
283
- */
284
- const getSubsetOfData = (sourceData, selector, withOnyxInstanceState) => selector(sourceData, withOnyxInstanceState);
285
-
286
- /**
287
- * Takes a collection of items (eg. {testKey_1:{a:'a'}, testKey_2:{b:'b'}})
288
- * and runs it through a reducer function to return a subset of the data according to a selector.
289
- * The resulting collection will only contain items that are returned by the selector.
290
- * @param {Object} collection
291
- * @param {String|Function} selector (see method docs for getSubsetOfData() for full details)
292
- * @param {Object} [withOnyxInstanceState]
293
- * @returns {Object}
294
- */
295
- const reduceCollectionWithSelector = (collection, selector, withOnyxInstanceState) =>
296
- underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(
297
- collection,
298
- (finalCollection, item, key) => {
299
- // eslint-disable-next-line no-param-reassign
300
- finalCollection[key] = getSubsetOfData(item, selector, withOnyxInstanceState);
301
-
302
- return finalCollection;
303
- },
304
- {});
305
-
306
-
307
- /**
308
- * Get some data from the store
309
- *
310
- * @private
311
- * @param {string} key
312
- * @returns {Promise<*>}
313
- */
314
- function get(key) {
315
- // When we already have the value in cache - resolve right away
316
- if (_OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].hasCacheForKey(key)) {
317
- return Promise.resolve(_OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getValue(key));
318
- }
319
-
320
- const taskName = `get:${key}`;
321
-
322
- // When a value retrieving task for this key is still running hook to it
323
- if (_OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].hasPendingTask(taskName)) {
324
- return _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getTaskPromise(taskName);
325
- }
326
-
327
- // Otherwise retrieve the value from storage and capture a promise to aid concurrent usages
328
- const promise = _storage__WEBPACK_IMPORTED_MODULE_7__["default"].getItem(key).
329
- then((val) => {
330
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(key, val);
331
- return val;
332
- }).
333
- catch((err) => _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo(`Unable to get item from persistent storage. Key: ${key} Error: ${err}`));
334
-
335
- return _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].captureTask(taskName, promise);
336
- }
337
-
338
- /**
339
- * Returns current key names stored in persisted storage
340
- * @private
341
- * @returns {Promise<string[]>}
342
- */
343
- function getAllKeys() {
344
- // When we've already read stored keys, resolve right away
345
- const storedKeys = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getAllKeys();
346
- if (storedKeys.length > 0) {
347
- return Promise.resolve(storedKeys);
348
- }
349
-
350
- const taskName = 'getAllKeys';
351
-
352
- // When a value retrieving task for all keys is still running hook to it
353
- if (_OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].hasPendingTask(taskName)) {
354
- return _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getTaskPromise(taskName);
355
- }
356
-
357
- // Otherwise retrieve the keys from storage and capture a promise to aid concurrent usages
358
- const promise = _storage__WEBPACK_IMPORTED_MODULE_7__["default"].getAllKeys().then((keys) => {
359
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keys, (key) => _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].addKey(key));
360
- return keys;
361
- });
362
-
363
- return _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].captureTask(taskName, promise);
364
- }
365
-
366
- /**
367
- * Checks to see if the a subscriber's supplied key
368
- * is associated with a collection of keys.
369
- *
370
- * @private
371
- * @param {String} key
372
- * @returns {Boolean}
373
- */
374
- function isCollectionKey(key) {
375
- return onyxCollectionKeyMap.has(key);
376
- }
377
-
378
- /**
379
- * @param {String} collectionKey
380
- * @param {String} key
381
- * @returns {Boolean}
382
- */
383
- function isCollectionMemberKey(collectionKey, key) {
384
- return _Str__WEBPACK_IMPORTED_MODULE_9__.startsWith(key, collectionKey) && key.length > collectionKey.length;
385
- }
386
-
387
- /**
388
- * Checks to see if a provided key is the exact configured key of our connected subscriber
389
- * or if the provided key is a collection member key (in case our configured key is a "collection key")
390
- *
391
- * @private
392
- * @param {String} configKey
393
- * @param {String} key
394
- * @return {Boolean}
395
- */
396
- function isKeyMatch(configKey, key) {
397
- return isCollectionKey(configKey) ? _Str__WEBPACK_IMPORTED_MODULE_9__.startsWith(key, configKey) : configKey === key;
398
- }
399
-
400
- /**
401
- * Checks to see if this key has been flagged as
402
- * safe for removal.
403
- *
404
- * @private
405
- * @param {String} testKey
406
- * @returns {Boolean}
407
- */
408
- function isSafeEvictionKey(testKey) {
409
- return underscore__WEBPACK_IMPORTED_MODULE_1___default().some(evictionAllowList, (key) => isKeyMatch(key, testKey));
410
- }
411
-
412
- /**
413
- * Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
414
- * If the requested key is a collection, it will return an object with all the collection members.
415
- *
416
- * @param {String} key
417
- * @param {Object} mapping
418
- * @returns {Mixed}
419
- */
420
- function tryGetCachedValue(key) {let mapping = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
421
- let val = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getValue(key);
422
-
423
- if (isCollectionKey(key)) {
424
- const allCacheKeys = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getAllKeys();
425
-
426
- // It is possible we haven't loaded all keys yet so we do not know if the
427
- // collection actually exists.
428
- if (allCacheKeys.length === 0) {
429
- return;
430
- }
431
- const matchingKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().filter(allCacheKeys, (k) => k.startsWith(key));
432
- const values = underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(
433
- matchingKeys,
434
- (finalObject, matchedKey) => {
435
- const cachedValue = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getValue(matchedKey);
436
- if (cachedValue) {
437
- // This is permissible because we're in the process of constructing the final object in a reduce function.
438
- // eslint-disable-next-line no-param-reassign
439
- finalObject[matchedKey] = cachedValue;
440
- }
441
- return finalObject;
442
- },
443
- {});
444
-
445
-
446
- val = values;
447
- }
448
-
449
- if (mapping.selector) {
450
- const state = mapping.withOnyxInstance ? mapping.withOnyxInstance.state : undefined;
451
- if (isCollectionKey(key)) {
452
- return reduceCollectionWithSelector(val, mapping.selector, state);
453
- }
454
- return getSubsetOfData(val, mapping.selector, state);
455
- }
456
-
457
- return val;
458
- }
459
-
460
- /**
461
- * Remove a key from the recently accessed key list.
462
- *
463
- * @private
464
- * @param {String} key
465
- */
466
- function removeLastAccessedKey(key) {
467
- recentlyAccessedKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().without(recentlyAccessedKeys, key);
468
- }
469
-
470
- /**
471
- * Add a key to the list of recently accessed keys. The least
472
- * recently accessed key should be at the head and the most
473
- * recently accessed key at the tail.
474
- *
475
- * @private
476
- * @param {String} key
477
- */
478
- function addLastAccessedKey(key) {
479
- // Only specific keys belong in this list since we cannot remove an entire collection.
480
- if (isCollectionKey(key) || !isSafeEvictionKey(key)) {
481
- return;
482
- }
483
-
484
- removeLastAccessedKey(key);
485
- recentlyAccessedKeys.push(key);
486
- }
487
-
488
- /**
489
- * Removes a key previously added to this list
490
- * which will enable it to be deleted again.
491
- *
492
- * @private
493
- * @param {String} key
494
- * @param {Number} connectionID
495
- */
496
- function removeFromEvictionBlockList(key, connectionID) {
497
- evictionBlocklist[key] = underscore__WEBPACK_IMPORTED_MODULE_1___default().without(evictionBlocklist[key] || [], connectionID);
498
-
499
- // Remove the key if there are no more subscribers
500
- if (evictionBlocklist[key].length === 0) {
501
- delete evictionBlocklist[key];
502
- }
503
- }
504
-
505
- /**
506
- * Keys added to this list can never be deleted.
507
- *
508
- * @private
509
- * @param {String} key
510
- * @param {Number} connectionID
511
- */
512
- function addToEvictionBlockList(key, connectionID) {
513
- removeFromEvictionBlockList(key, connectionID);
514
-
515
- if (!evictionBlocklist[key]) {
516
- evictionBlocklist[key] = [];
517
- }
518
-
519
- evictionBlocklist[key].push(connectionID);
520
- }
521
-
522
- /**
523
- * Take all the keys that are safe to evict and add them to
524
- * the recently accessed list when initializing the app. This
525
- * enables keys that have not recently been accessed to be
526
- * removed.
527
- *
528
- * @private
529
- * @returns {Promise}
530
- */
531
- function addAllSafeEvictionKeysToRecentlyAccessedList() {
532
- return getAllKeys().then((keys) => {
533
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(evictionAllowList, (safeEvictionKey) => {
534
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keys, (key) => {
535
- if (!isKeyMatch(safeEvictionKey, key)) {
536
- return;
537
- }
538
- addLastAccessedKey(key);
539
- });
540
- });
541
- });
542
- }
543
-
544
- /**
545
- * @private
546
- * @param {String} collectionKey
547
- * @returns {Object}
548
- */
549
- function getCachedCollection(collectionKey) {
550
- const collectionMemberKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().filter(_OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getAllKeys(), (storedKey) => isCollectionMemberKey(collectionKey, storedKey));
551
-
552
- return underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(
553
- collectionMemberKeys,
554
- (prev, curr) => {
555
- const cachedValue = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getValue(curr);
556
- if (!cachedValue) {
557
- return prev;
558
- }
559
-
560
- // eslint-disable-next-line no-param-reassign
561
- prev[curr] = cachedValue;
562
- return prev;
563
- },
564
- {});
565
-
566
- }
567
-
568
- /**
569
- * When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
570
- *
571
- * @private
572
- * @param {String} collectionKey
573
- * @param {Object} partialCollection - a partial collection of grouped member keys
574
- * @param {boolean} [notifyRegularSubscibers=true]
575
- * @param {boolean} [notifyWithOnyxSubscibers=true]
576
- */
577
- function keysChanged(collectionKey, partialCollection) {let notifyRegularSubscibers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;let notifyWithOnyxSubscibers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;
578
- // We are iterating over all subscribers similar to keyChanged(). However, we are looking for subscribers who are subscribing to either a collection key or
579
- // 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
580
- // 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().
581
- const stateMappingKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(callbackToStateMapping);
582
- for (let i = 0; i < stateMappingKeys.length; i++) {
583
- const subscriber = callbackToStateMapping[stateMappingKeys[i]];
584
- if (!subscriber) {
585
- continue;
586
- }
587
-
588
- // Skip iteration if we do not have a collection key or a collection member key on this subscriber
589
- if (!_Str__WEBPACK_IMPORTED_MODULE_9__.startsWith(subscriber.key, collectionKey)) {
590
- continue;
591
- }
592
-
593
- /**
594
- * e.g. Onyx.connect({key: ONYXKEYS.COLLECTION.REPORT, callback: ...});
595
- */
596
- const isSubscribedToCollectionKey = subscriber.key === collectionKey;
597
-
598
- /**
599
- * e.g. Onyx.connect({key: `${ONYXKEYS.COLLECTION.REPORT}{reportID}`, callback: ...});
600
- */
601
- const isSubscribedToCollectionMemberKey = isCollectionMemberKey(collectionKey, subscriber.key);
602
-
603
- // We prepare the "cached collection" which is the entire collection + the new partial data that
604
- // was merged in via mergeCollection().
605
- const cachedCollection = getCachedCollection(collectionKey);
606
-
607
- // Regular Onyx.connect() subscriber found.
608
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(subscriber.callback)) {
609
- if (!notifyRegularSubscibers) {
610
- continue;
611
- }
612
-
613
- // If they are subscribed to the collection key and using waitForCollectionCallback then we'll
614
- // send the whole cached collection.
615
- if (isSubscribedToCollectionKey) {
616
- if (subscriber.waitForCollectionCallback) {
617
- subscriber.callback(cachedCollection);
618
- continue;
619
- }
620
-
621
- // If they are not using waitForCollectionCallback then we notify the subscriber with
622
- // the new merged data but only for any keys in the partial collection.
623
- const dataKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(partialCollection);
624
- for (let j = 0; j < dataKeys.length; j++) {
625
- const dataKey = dataKeys[j];
626
- subscriber.callback(cachedCollection[dataKey], dataKey);
627
- }
628
- continue;
629
- }
630
-
631
- // And if the subscriber is specifically only tracking a particular collection member key then we will
632
- // notify them with the cached data for that key only.
633
- if (isSubscribedToCollectionMemberKey) {
634
- subscriber.callback(cachedCollection[subscriber.key], subscriber.key);
635
- continue;
636
- }
637
-
638
- continue;
639
- }
640
-
641
- // React component subscriber found.
642
- if (subscriber.withOnyxInstance) {
643
- if (!notifyWithOnyxSubscibers) {
644
- continue;
645
- }
646
-
647
- // We are subscribed to a collection key so we must update the data in state with the new
648
- // collection member key values from the partial update.
649
- if (isSubscribedToCollectionKey) {
650
- // If the subscriber has a selector, then the component's state must only be updated with the data
651
- // returned by the selector.
652
- if (subscriber.selector) {
653
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
654
- const previousData = prevState[subscriber.statePropertyName];
655
- const newData = reduceCollectionWithSelector(cachedCollection, subscriber.selector, subscriber.withOnyxInstance.state);
656
-
657
- if (!(0,fast_equals__WEBPACK_IMPORTED_MODULE_0__.deepEqual)(previousData, newData)) {
658
- return {
659
- [subscriber.statePropertyName]: newData
660
- };
661
- }
662
- return null;
663
- });
664
- continue;
665
- }
666
-
667
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
668
- const finalCollection = underscore__WEBPACK_IMPORTED_MODULE_1___default().clone(prevState[subscriber.statePropertyName] || {});
669
- const dataKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(partialCollection);
670
- for (let j = 0; j < dataKeys.length; j++) {
671
- const dataKey = dataKeys[j];
672
- finalCollection[dataKey] = cachedCollection[dataKey];
673
- }
674
-
675
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, prevState[subscriber.statePropertyName], finalCollection, 'keysChanged', collectionKey);
676
- return {
677
- [subscriber.statePropertyName]: finalCollection
678
- };
679
- });
680
- continue;
681
- }
682
-
683
- // If a React component is only interested in a single key then we can set the cached value directly to the state name.
684
- if (isSubscribedToCollectionMemberKey) {
685
- // However, we only want to update this subscriber if the partial data contains a change.
686
- // Otherwise, we would update them with a value they already have and trigger an unnecessary re-render.
687
- const dataFromCollection = partialCollection[subscriber.key];
688
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isUndefined(dataFromCollection)) {
689
- continue;
690
- }
691
-
692
- // If the subscriber has a selector, then the component's state must only be updated with the data
693
- // returned by the selector and the state should only change when the subset of data changes from what
694
- // it was previously.
695
- if (subscriber.selector) {
696
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
697
- const prevData = prevState[subscriber.statePropertyName];
698
- const newData = getSubsetOfData(cachedCollection[subscriber.key], subscriber.selector, subscriber.withOnyxInstance.state);
699
- if (!(0,fast_equals__WEBPACK_IMPORTED_MODULE_0__.deepEqual)(prevData, newData)) {
700
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, prevData, newData, 'keysChanged', collectionKey);
701
- return {
702
- [subscriber.statePropertyName]: newData
703
- };
704
- }
705
-
706
- return null;
707
- });
708
- continue;
709
- }
710
-
711
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
712
- const data = cachedCollection[subscriber.key];
713
- const previousData = prevState[subscriber.statePropertyName];
714
-
715
- // Avoids triggering unnecessary re-renders when feeding empty objects
716
- if (_utils__WEBPACK_IMPORTED_MODULE_4__["default"].areObjectsEmpty(data, previousData)) {
717
- return null;
718
- }
719
- if (data === previousData) {
720
- return null;
721
- }
722
-
723
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, previousData, data, 'keysChanged', collectionKey);
724
- return {
725
- [subscriber.statePropertyName]: data
726
- };
727
- });
728
- }
729
- }
730
- }
731
- }
732
-
733
- /**
734
- * When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
735
- *
736
- * @example
737
- * keyChanged(key, value, subscriber => subscriber.initWithStoredValues === false)
738
- *
739
- * @private
740
- * @param {String} key
741
- * @param {*} data
742
- * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
743
- * @param {boolean} [notifyRegularSubscibers=true]
744
- * @param {boolean} [notifyWithOnyxSubscibers=true]
745
- */
746
- function keyChanged(key, data, canUpdateSubscriber) {let notifyRegularSubscibers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;let notifyWithOnyxSubscibers = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
747
- // Add or remove this key from the recentlyAccessedKeys lists
748
- if (!underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(data)) {
749
- addLastAccessedKey(key);
750
- } else {
751
- removeLastAccessedKey(key);
752
- }
753
-
754
- // We are iterating over all subscribers to see if they are interested in the key that has just changed. If the subscriber's key is a collection key then we will
755
- // 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
756
- // was connected via withOnyx we will call setState() directly on the withOnyx instance. If it is a regular connection we will pass the data to the provided callback.
757
- const stateMappingKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(callbackToStateMapping);
758
- for (let i = 0; i < stateMappingKeys.length; i++) {
759
- const subscriber = callbackToStateMapping[stateMappingKeys[i]];
760
- if (!subscriber || !isKeyMatch(subscriber.key, key) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(canUpdateSubscriber) && !canUpdateSubscriber(subscriber)) {
761
- continue;
762
- }
763
-
764
- // Subscriber is a regular call to connect() and provided a callback
765
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(subscriber.callback)) {
766
- if (!notifyRegularSubscibers) {
767
- continue;
768
- }
769
- if (isCollectionKey(subscriber.key) && subscriber.waitForCollectionCallback) {
770
- const cachedCollection = getCachedCollection(subscriber.key);
771
- cachedCollection[key] = data;
772
- subscriber.callback(cachedCollection);
773
- continue;
774
- }
775
-
776
- subscriber.callback(data, key);
777
- continue;
778
- }
779
-
780
- // Subscriber connected via withOnyx() HOC
781
- if (subscriber.withOnyxInstance) {
782
- if (!notifyWithOnyxSubscibers) {
783
- continue;
784
- }
785
-
786
- // Check if we are subscribing to a collection key and overwrite the collection member key value in state
787
- if (isCollectionKey(subscriber.key)) {
788
- // If the subscriber has a selector, then the consumer of this data must only be given the data
789
- // returned by the selector and only when the selected data has changed.
790
- if (subscriber.selector) {
791
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
792
- const prevData = prevState[subscriber.statePropertyName];
793
- const newData = {
794
- [key]: getSubsetOfData(data, subscriber.selector, subscriber.withOnyxInstance.state)
795
- };
796
- const prevDataWithNewData = {
797
- ...prevData,
798
- ...newData
799
- };
800
- if (!(0,fast_equals__WEBPACK_IMPORTED_MODULE_0__.deepEqual)(prevData, prevDataWithNewData)) {
801
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, prevData, newData, 'keyChanged', key);
802
- return {
803
- [subscriber.statePropertyName]: prevDataWithNewData
804
- };
805
- }
806
- return null;
807
- });
808
- continue;
809
- }
810
-
811
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
812
- const collection = prevState[subscriber.statePropertyName] || {};
813
- const newCollection = {
814
- ...collection,
815
- [key]: data
816
- };
817
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, collection, newCollection, 'keyChanged', key);
818
- return {
819
- [subscriber.statePropertyName]: newCollection
820
- };
821
- });
822
- continue;
823
- }
824
-
825
- // If the subscriber has a selector, then the component's state must only be updated with the data
826
- // returned by the selector and only if the selected data has changed.
827
- if (subscriber.selector) {
828
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
829
- const previousValue = getSubsetOfData(prevState[subscriber.statePropertyName], subscriber.selector, subscriber.withOnyxInstance.state);
830
- const newValue = getSubsetOfData(data, subscriber.selector, subscriber.withOnyxInstance.state);
831
- if (!(0,fast_equals__WEBPACK_IMPORTED_MODULE_0__.deepEqual)(previousValue, newValue)) {
832
- return {
833
- [subscriber.statePropertyName]: newValue
834
- };
835
- }
836
- return null;
837
- });
838
- continue;
839
- }
840
-
841
- // If we did not match on a collection key then we just set the new data to the state property
842
- subscriber.withOnyxInstance.setStateProxy((prevState) => {
843
- const previousData = prevState[subscriber.statePropertyName];
844
-
845
- // Avoids triggering unnecessary re-renders when feeding empty objects
846
- if (_utils__WEBPACK_IMPORTED_MODULE_4__["default"].areObjectsEmpty(data, previousData)) {
847
- return null;
848
- }
849
- if (previousData === data) {
850
- return null;
851
- }
852
-
853
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(subscriber, previousData, data, 'keyChanged', key);
854
- return {
855
- [subscriber.statePropertyName]: data
856
- };
857
- });
858
- continue;
859
- }
860
-
861
- console.error('Warning: Found a matching subscriber to a key that changed, but no callback or withOnyxInstance could be found.');
862
- }
863
- }
864
-
865
- /**
866
- * Sends the data obtained from the keys to the connection. It either:
867
- * - sets state on the withOnyxInstances
868
- * - triggers the callback function
869
- *
870
- * @private
871
- * @param {Object} mapping
872
- * @param {Object} [mapping.withOnyxInstance]
873
- * @param {String} [mapping.statePropertyName]
874
- * @param {Function} [mapping.callback]
875
- * @param {String} [mapping.selector]
876
- * @param {*|null} val
877
- * @param {String|undefined} matchedKey
878
- * @param {Boolean} isBatched
879
- */
880
- function sendDataToConnection(mapping, val, matchedKey, isBatched) {
881
- // If the mapping no longer exists then we should not send any data.
882
- // This means our subscriber disconnected or withOnyx wrapped component unmounted.
883
- if (!callbackToStateMapping[mapping.connectionID]) {
884
- return;
885
- }
886
-
887
- if (mapping.withOnyxInstance) {
888
- let newData = val;
889
-
890
- // If the mapping has a selector, then the component's state must only be updated with the data
891
- // returned by the selector.
892
- if (mapping.selector) {
893
- if (isCollectionKey(mapping.key)) {
894
- newData = reduceCollectionWithSelector(val, mapping.selector, mapping.withOnyxInstance.state);
895
- } else {
896
- newData = getSubsetOfData(val, mapping.selector, mapping.withOnyxInstance.state);
897
- }
898
- }
899
-
900
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.logSetStateCall(mapping, null, newData, 'sendDataToConnection');
901
- if (isBatched) {
902
- batchUpdates(() => {
903
- mapping.withOnyxInstance.setWithOnyxState(mapping.statePropertyName, newData);
904
- });
905
- } else {
906
- mapping.withOnyxInstance.setWithOnyxState(mapping.statePropertyName, newData);
907
- }
908
- return;
909
- }
910
-
911
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(mapping.callback)) {
912
- mapping.callback(val, matchedKey);
913
- }
914
- }
915
-
916
- /**
917
- * We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
918
- * run out of storage the least recently accessed key can be removed.
919
- *
920
- * @private
921
- * @param {Object} mapping
922
- */
923
- function addKeyToRecentlyAccessedIfNeeded(mapping) {
924
- if (!isSafeEvictionKey(mapping.key)) {
925
- return;
926
- }
927
-
928
- // Try to free some cache whenever we connect to a safe eviction key
929
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].removeLeastRecentlyUsedKeys();
930
-
931
- if (mapping.withOnyxInstance && !isCollectionKey(mapping.key)) {
932
- // All React components subscribing to a key flagged as a safe eviction key must implement the canEvict property.
933
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isUndefined(mapping.canEvict)) {
934
- throw new Error(`Cannot subscribe to safe eviction key '${mapping.key}' without providing a canEvict value.`);
935
- }
936
-
937
- addLastAccessedKey(mapping.key);
938
- }
939
- }
940
-
941
- /**
942
- * Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
943
- *
944
- * @private
945
- * @param {Array} matchingKeys
946
- * @param {Object} mapping
947
- */
948
- function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
949
- Promise.all(underscore__WEBPACK_IMPORTED_MODULE_1___default().map(matchingKeys, (key) => get(key))).
950
- then((values) =>
951
- underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(
952
- values,
953
- (finalObject, value, i) => {
954
- // eslint-disable-next-line no-param-reassign
955
- finalObject[matchingKeys[i]] = value;
956
- return finalObject;
957
- },
958
- {})).
959
-
960
-
961
- then((val) => sendDataToConnection(mapping, val, undefined, true));
962
- }
963
-
964
- /**
965
- * Subscribes a react component's state directly to a store key
966
- *
967
- * @example
968
- * const connectionID = Onyx.connect({
969
- * key: ONYXKEYS.SESSION,
970
- * callback: onSessionChange,
971
- * });
972
- *
973
- * @param {Object} mapping the mapping information to connect Onyx to the components state
974
- * @param {String} mapping.key ONYXKEY to subscribe to
975
- * @param {String} [mapping.statePropertyName] the name of the property in the state to connect the data to
976
- * @param {Object} [mapping.withOnyxInstance] whose setState() method will be called with any changed data
977
- * This is used by React components to connect to Onyx
978
- * @param {Function} [mapping.callback] a method that will be called with changed data
979
- * This is used by any non-React code to connect to Onyx
980
- * @param {Boolean} [mapping.initWithStoredValues] If set to false, then no data will be prefilled into the
981
- * component
982
- * @param {Boolean} [mapping.waitForCollectionCallback] If set to true, it will return the entire collection to the callback as a single object
983
- * @param {Function} [mapping.selector] THIS PARAM IS ONLY USED WITH withOnyx(). If included, this will be used to subscribe to a subset of an Onyx key's data.
984
- * The sourceData and withOnyx state are passed to the selector and should return the simplified data. Using this setting on `withOnyx` can have very positive
985
- * performance benefits because the component will only re-render when the subset of data changes. Otherwise, any change of data on any property would normally
986
- * cause the component to re-render (and that can be expensive from a performance standpoint).
987
- * @param {String | Number | Boolean | Object} [mapping.initialValue] THIS PARAM IS ONLY USED WITH withOnyx().
988
- * If included, this will be passed to the component so that something can be rendered while data is being fetched from the DB.
989
- * Note that it will not cause the component to have the loading prop set to true. |
990
- * @returns {Number} an ID to use when calling disconnect
991
- */
992
- function connect(mapping) {
993
- const connectionID = lastConnectionID++;
994
- callbackToStateMapping[connectionID] = mapping;
995
- callbackToStateMapping[connectionID].connectionID = connectionID;
996
-
997
- if (mapping.initWithStoredValues === false) {
998
- return connectionID;
999
- }
1000
-
1001
- // Commit connection only after init passes
1002
- deferredInitTask.promise.
1003
- then(() => addKeyToRecentlyAccessedIfNeeded(mapping)).
1004
- then(() => {
1005
- // Performance improvement
1006
- // If the mapping is connected to an onyx key that is not a collection
1007
- // we can skip the call to getAllKeys() and return an array with a single item
1008
- if (Boolean(mapping.key) && typeof mapping.key === 'string' && !mapping.key.endsWith('_') && _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].storageKeys.has(mapping.key)) {
1009
- return [mapping.key];
1010
- }
1011
- return getAllKeys();
1012
- }).
1013
- then((keys) => {
1014
- // We search all the keys in storage to see if any are a "match" for the subscriber we are connecting so that we
1015
- // can send data back to the subscriber. Note that multiple keys can match as a subscriber could either be
1016
- // subscribed to a "collection key" or a single key.
1017
- const matchingKeys = underscore__WEBPACK_IMPORTED_MODULE_1___default().filter(keys, (key) => isKeyMatch(mapping.key, key));
1018
-
1019
- // If the key being connected to does not exist we initialize the value with null. For subscribers that connected
1020
- // directly via connect() they will simply get a null value sent to them without any information about which key matched
1021
- // since there are none matched. In withOnyx() we wait for all connected keys to return a value before rendering the child
1022
- // component. This null value will be filtered out so that the connected component can utilize defaultProps.
1023
- if (matchingKeys.length === 0) {
1024
- if (mapping.key && !isCollectionKey(mapping.key)) {
1025
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(mapping.key, null);
1026
- }
1027
-
1028
- // Here we cannot use batching because the null value is expected to be set immediately for default props
1029
- // or they will be undefined.
1030
- sendDataToConnection(mapping, null, undefined, false);
1031
- return;
1032
- }
1033
-
1034
- // When using a callback subscriber we will either trigger the provided callback for each key we find or combine all values
1035
- // into an object and just make a single call. The latter behavior is enabled by providing a waitForCollectionCallback key
1036
- // combined with a subscription to a collection key.
1037
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(mapping.callback)) {
1038
- if (isCollectionKey(mapping.key)) {
1039
- if (mapping.waitForCollectionCallback) {
1040
- getCollectionDataAndSendAsObject(matchingKeys, mapping);
1041
- return;
1042
- }
1043
-
1044
- // We did not opt into using waitForCollectionCallback mode so the callback is called for every matching key.
1045
- for (let i = 0; i < matchingKeys.length; i++) {
1046
- get(matchingKeys[i]).then((val) => sendDataToConnection(mapping, val, matchingKeys[i], true));
1047
- }
1048
- return;
1049
- }
1050
-
1051
- // If we are not subscribed to a collection key then there's only a single key to send an update for.
1052
- get(mapping.key).then((val) => sendDataToConnection(mapping, val, mapping.key, true));
1053
- return;
1054
- }
1055
-
1056
- // If we have a withOnyxInstance that means a React component has subscribed via the withOnyx() HOC and we need to
1057
- // group collection key member data into an object.
1058
- if (mapping.withOnyxInstance) {
1059
- if (isCollectionKey(mapping.key)) {
1060
- getCollectionDataAndSendAsObject(matchingKeys, mapping);
1061
- return;
1062
- }
1063
-
1064
- // If the subscriber is not using a collection key then we just send a single value back to the subscriber
1065
- get(mapping.key).then((val) => sendDataToConnection(mapping, val, mapping.key, true));
1066
- return;
1067
- }
1068
-
1069
- console.error('Warning: Onyx.connect() was found without a callback or withOnyxInstance');
1070
- });
1071
-
1072
- // The connectionID is returned back to the caller so that it can be used to clean up the connection when it's no longer needed
1073
- // by calling Onyx.disconnect(connectionID).
1074
- return connectionID;
1075
- }
1076
-
1077
- /**
1078
- * Remove the listener for a react component
1079
- * @example
1080
- * Onyx.disconnect(connectionID);
1081
- *
1082
- * @param {Number} connectionID unique id returned by call to Onyx.connect()
1083
- * @param {String} [keyToRemoveFromEvictionBlocklist]
1084
- */
1085
- function disconnect(connectionID, keyToRemoveFromEvictionBlocklist) {
1086
- if (!callbackToStateMapping[connectionID]) {
1087
- return;
1088
- }
1089
-
1090
- // Remove this key from the eviction block list as we are no longer
1091
- // subscribing to it and it should be safe to delete again
1092
- if (keyToRemoveFromEvictionBlocklist) {
1093
- removeFromEvictionBlockList(keyToRemoveFromEvictionBlocklist, connectionID);
1094
- }
1095
-
1096
- delete callbackToStateMapping[connectionID];
1097
- }
1098
-
1099
- /**
1100
- * Schedules an update that will be appended to the macro task queue (so it doesn't update the subscribers immediately).
1101
- *
1102
- * @example
1103
- * scheduleSubscriberUpdate(key, value, subscriber => subscriber.initWithStoredValues === false)
1104
- *
1105
- * @param {String} key
1106
- * @param {*} value
1107
- * @param {Function} [canUpdateSubscriber] only subscribers that pass this truth test will be updated
1108
- * @returns {Promise}
1109
- */
1110
- function scheduleSubscriberUpdate(key, value, canUpdateSubscriber) {
1111
- const promise = Promise.resolve().then(() => keyChanged(key, value, canUpdateSubscriber, true, false));
1112
- batchUpdates(() => keyChanged(key, value, canUpdateSubscriber, false, true));
1113
- return Promise.all([maybeFlushBatchUpdates(), promise]);
1114
- }
1115
-
1116
- /**
1117
- * This method is similar to notifySubscribersOnNextTick but it is built for working specifically with collections
1118
- * so that keysChanged() is triggered for the collection and not keyChanged(). If this was not done, then the
1119
- * subscriber callbacks receive the data in a different format than they normally expect and it breaks code.
1120
- *
1121
- * @param {String} key
1122
- * @param {*} value
1123
- * @returns {Promise}
1124
- */
1125
- function scheduleNotifyCollectionSubscribers(key, value) {
1126
- const promise = Promise.resolve().then(() => keysChanged(key, value, true, false));
1127
- batchUpdates(() => keysChanged(key, value, false, true));
1128
- return Promise.all([maybeFlushBatchUpdates(), promise]);
1129
- }
1130
-
1131
- /**
1132
- * Remove a key from Onyx and update the subscribers
1133
- *
1134
- * @private
1135
- * @param {String} key
1136
- * @return {Promise}
1137
- */
1138
- function remove(key) {
1139
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].drop(key);
1140
- scheduleSubscriberUpdate(key, null);
1141
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].removeItem(key);
1142
- }
1143
-
1144
- /**
1145
- * @private
1146
- * @returns {Promise<void>}
1147
- */
1148
- function reportStorageQuota() {
1149
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].getDatabaseSize().
1150
- then((_ref) => {let { bytesUsed, bytesRemaining } = _ref;
1151
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo(`Storage Quota Check -- bytesUsed: ${bytesUsed} bytesRemaining: ${bytesRemaining}`);
1152
- }).
1153
- catch((dbSizeError) => {
1154
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logAlert(`Unable to get database size. Error: ${dbSizeError}`);
1155
- });
1156
- }
1157
-
1158
- /**
1159
- * If we fail to set or merge we must handle this by
1160
- * evicting some data from Onyx and then retrying to do
1161
- * whatever it is we attempted to do.
1162
- *
1163
- * @private
1164
- * @param {Error} error
1165
- * @param {Function} onyxMethod
1166
- * @param {...any} args
1167
- * @return {Promise}
1168
- */
1169
- function evictStorageAndRetry(error, onyxMethod) {for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {args[_key - 2] = arguments[_key];}
1170
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo(`Failed to save to storage. Error: ${error}. onyxMethod: ${onyxMethod.name}`);
1171
-
1172
- if (error && _Str__WEBPACK_IMPORTED_MODULE_9__.startsWith(error.message, "Failed to execute 'put' on 'IDBObjectStore'")) {
1173
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logAlert('Attempted to set invalid data set in Onyx. Please ensure all data is serializable.');
1174
- throw error;
1175
- }
1176
-
1177
- // Find the first key that we can remove that has no subscribers in our blocklist
1178
- const keyForRemoval = underscore__WEBPACK_IMPORTED_MODULE_1___default().find(recentlyAccessedKeys, (key) => !evictionBlocklist[key]);
1179
- if (!keyForRemoval) {
1180
- // If we have no acceptable keys to remove then we are possibly trying to save mission critical data. If this is the case,
1181
- // 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
1182
- // will allow this write to be skipped.
1183
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logAlert('Out of storage. But found no acceptable keys to remove.');
1184
- return reportStorageQuota();
1185
- }
1186
-
1187
- // Remove the least recently viewed key that is not currently being accessed and retry.
1188
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo(`Out of storage. Evicting least recently accessed key (${keyForRemoval}) and retrying.`);
1189
- reportStorageQuota();
1190
- return remove(keyForRemoval).then(() => onyxMethod(...args));
1191
- }
1192
-
1193
- /**
1194
- * Notifys subscribers and writes current value to cache
1195
- *
1196
- * @param {String} key
1197
- * @param {*} value
1198
- * @param {String} method
1199
- * @param {Boolean} hasChanged
1200
- * @param {Boolean} wasRemoved
1201
- * @returns {Promise}
1202
- */
1203
- function broadcastUpdate(key, value, method, hasChanged) {let wasRemoved = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
1204
- // Logging properties only since values could be sensitive things we don't want to log
1205
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo(`${method}() called for key: ${key}${underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(value) ? ` properties: ${underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(value).join(',')}` : ''}`);
1206
-
1207
- // Update subscribers if the cached value has changed, or when the subscriber specifically requires
1208
- // all updates regardless of value changes (indicated by initWithStoredValues set to false).
1209
- if (hasChanged && !wasRemoved) {
1210
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(key, value);
1211
- } else {
1212
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].addToAccessedKeys(key);
1213
- }
1214
-
1215
- return scheduleSubscriberUpdate(key, value, (subscriber) => hasChanged || subscriber.initWithStoredValues === false);
1216
- }
1217
-
1218
- /**
1219
- * @param {String} key
1220
- * @returns {Boolean}
1221
- */
1222
- function hasPendingMergeForKey(key) {
1223
- return Boolean(mergeQueue[key]);
1224
- }
1225
-
1226
- /**
1227
- * Removes a key from storage if the value is null.
1228
- * Otherwise removes all nested null values in objects and returns the object
1229
- * @param {String} key
1230
- * @param {Mixed} value
1231
- * @returns {Mixed} The value without null values and a boolean "wasRemoved", which indicates if the key got removed completely
1232
- */
1233
- function removeNullValues(key, value) {
1234
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(value)) {
1235
- remove(key);
1236
- return { value, wasRemoved: true };
1237
- }
1238
-
1239
- // We can remove all null values in an object by merging it with itself
1240
- // utils.fastMerge recursively goes through the object and removes all null values
1241
- // Passing two identical objects as source and target to fastMerge will not change it, but only remove the null values
1242
- return { value: _utils__WEBPACK_IMPORTED_MODULE_4__["default"].removeNestedNullValues(value), wasRemoved: false };
1243
- }
1244
-
1245
- /**
1246
- * Write a value to our store with the given key
1247
- *
1248
- * @param {String} key ONYXKEY to set
1249
- * @param {*} value value to store
1250
- *
1251
- * @returns {Promise}
1252
- */
1253
- function set(key, value) {
1254
- // If the value is null, we remove the key from storage
1255
- const { value: valueAfterRemoving, wasRemoved } = removeNullValues(key, value);
1256
-
1257
- if (hasPendingMergeForKey(key)) {
1258
- delete mergeQueue[key];
1259
- }
1260
-
1261
- const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].hasValueChanged(key, valueAfterRemoving);
1262
-
1263
- // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
1264
- const updatePromise = broadcastUpdate(key, valueAfterRemoving, 'set', hasChanged, wasRemoved);
1265
-
1266
- // If the value has not changed or the key got removed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
1267
- if (!hasChanged || wasRemoved) {
1268
- return updatePromise;
1269
- }
1270
-
1271
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].setItem(key, valueAfterRemoving).
1272
- catch((error) => evictStorageAndRetry(error, set, key, valueAfterRemoving)).
1273
- then(() => {
1274
- sendActionToDevTools(METHOD.SET, key, valueAfterRemoving);
1275
- return updatePromise;
1276
- });
1277
- }
1278
-
1279
- /**
1280
- * Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
1281
- * This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
1282
- * to an array of key-value pairs in the above format and removes key-value pairs that are being set to null
1283
- * @private
1284
- * @param {Record} data
1285
- * @return {Array} an array of key - value pairs <[key, value]>
1286
- */
1287
- function prepareKeyValuePairsForStorage(data) {
1288
- const keyValuePairs = [];
1289
-
1290
- underscore__WEBPACK_IMPORTED_MODULE_1___default().forEach(data, (value, key) => {
1291
- const { value: valueAfterRemoving, wasRemoved } = removeNullValues(key, value);
1292
-
1293
- if (wasRemoved) return;
1294
-
1295
- keyValuePairs.push([key, valueAfterRemoving]);
1296
- });
1297
-
1298
- return keyValuePairs;
1299
- }
1300
-
1301
- /**
1302
- * Sets multiple keys and values
1303
- *
1304
- * @example Onyx.multiSet({'key1': 'a', 'key2': 'b'});
1305
- *
1306
- * @param {Object} data object keyed by ONYXKEYS and the values to set
1307
- * @returns {Promise}
1308
- */
1309
- function multiSet(data) {
1310
- const keyValuePairs = prepareKeyValuePairsForStorage(data);
1311
-
1312
- const updatePromises = underscore__WEBPACK_IMPORTED_MODULE_1___default().map(keyValuePairs, (_ref2) => {let [key, value] = _ref2;
1313
- // Update cache and optimistically inform subscribers on the next tick
1314
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(key, value);
1315
- return scheduleSubscriberUpdate(key, value);
1316
- });
1317
-
1318
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].multiSet(keyValuePairs).
1319
- catch((error) => evictStorageAndRetry(error, multiSet, data)).
1320
- then(() => {
1321
- sendActionToDevTools(METHOD.MULTI_SET, undefined, data);
1322
- return Promise.all(updatePromises);
1323
- });
1324
- }
1325
-
1326
- /**
1327
- * Merges an array of changes with an existing value
1328
- *
1329
- * @private
1330
- * @param {*} existingValue
1331
- * @param {Array<*>} changes Array of changes that should be applied to the existing value
1332
- * @param {Boolean} shouldRemoveNullObjectValues
1333
- * @returns {*}
1334
- */
1335
- function applyMerge(existingValue, changes, shouldRemoveNullObjectValues) {
1336
- const lastChange = underscore__WEBPACK_IMPORTED_MODULE_1___default().last(changes);
1337
-
1338
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(lastChange)) {
1339
- return lastChange;
1340
- }
1341
-
1342
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().some(changes, (underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject))) {
1343
- // Object values are then merged one after the other
1344
- return underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(changes, (modifiedData, change) => _utils__WEBPACK_IMPORTED_MODULE_4__["default"].fastMerge(modifiedData, change, shouldRemoveNullObjectValues), existingValue || {});
1345
- }
1346
-
1347
- // If we have anything else we can't merge it so we'll
1348
- // simply return the last value that was queued
1349
- return lastChange;
1350
- }
1351
-
1352
- /**
1353
- * Merge a new value into an existing value at a key.
1354
- *
1355
- * The types of values that can be merged are `Object` and `Array`. To set another type of value use `Onyx.set()`.
1356
- * Values of type `Object` get merged with the old value, whilst for `Array`'s we simply replace the current value with the new one.
1357
- *
1358
- * Calls to `Onyx.merge()` are batched so that any calls performed in a single tick will stack in a queue and get
1359
- * applied in the order they were called. Note: `Onyx.set()` calls do not work this way so use caution when mixing
1360
- * `Onyx.merge()` and `Onyx.set()`.
1361
- *
1362
- * @example
1363
- * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Joe']); // -> ['Joe']
1364
- * Onyx.merge(ONYXKEYS.EMPLOYEE_LIST, ['Jack']); // -> ['Joe', 'Jack']
1365
- * Onyx.merge(ONYXKEYS.POLICY, {id: 1}); // -> {id: 1}
1366
- * Onyx.merge(ONYXKEYS.POLICY, {name: 'My Workspace'}); // -> {id: 1, name: 'My Workspace'}
1367
- *
1368
- * @param {String} key ONYXKEYS key
1369
- * @param {(Object|Array)} changes Object or Array value to merge
1370
- * @returns {Promise}
1371
- */
1372
- function merge(key, changes) {
1373
- // Top-level undefined values are ignored
1374
- // Therefore we need to prevent adding them to the merge queue
1375
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isUndefined(changes)) {
1376
- return mergeQueue[key] ? mergeQueuePromise[key] : Promise.resolve();
1377
- }
1378
-
1379
- // Merge attempts are batched together. The delta should be applied after a single call to get() to prevent a race condition.
1380
- // Using the initial value from storage in subsequent merge attempts will lead to an incorrect final merged value.
1381
- if (mergeQueue[key]) {
1382
- mergeQueue[key].push(changes);
1383
- return mergeQueuePromise[key];
1384
- }
1385
- mergeQueue[key] = [changes];
1386
-
1387
- mergeQueuePromise[key] = get(key).then((existingValue) => {
1388
- // Calls to Onyx.set after a merge will terminate the current merge process and clear the merge queue
1389
- if (mergeQueue[key] == null) return;
1390
-
1391
- try {
1392
- // We first only merge the changes, so we can provide these to the native implementation (SQLite uses only delta changes in "JSON_PATCH" to merge)
1393
- // We don't want to remove null values from the "batchedChanges", because SQLite uses them to remove keys from storage natively.
1394
- let batchedChanges = applyMerge(undefined, mergeQueue[key], false);
1395
-
1396
- // The presence of a `null` in the merge queue instructs us to drop the existing value.
1397
- // In this case, we can't simply merge the batched changes with the existing value, because then the null in the merge queue would have no effect
1398
- const shouldOverwriteExistingValue = underscore__WEBPACK_IMPORTED_MODULE_1___default().includes(mergeQueue[key], null);
1399
-
1400
- // Clean up the write queue, so we don't apply these changes again
1401
- delete mergeQueue[key];
1402
- delete mergeQueuePromise[key];
1403
-
1404
- // If the batched changes equal null, we want to remove the key from storage, to reduce storage size
1405
- const { wasRemoved } = removeNullValues(key, batchedChanges);
1406
-
1407
- // After that we merge the batched changes with the existing value
1408
- // We can remove null values from the "modifiedData", because "null" implicates that the user wants to remove a value from storage.
1409
- // The "modifiedData" will be directly "set" in storage instead of being merged
1410
- const modifiedData = shouldOverwriteExistingValue ? batchedChanges : applyMerge(existingValue, [batchedChanges], true);
1411
-
1412
- // On native platforms we use SQLite which utilises JSON_PATCH to merge changes.
1413
- // JSON_PATCH generally removes null values from the stored object.
1414
- // When there is no existing value though, SQLite will just insert the changes as a new value and thus the null values won't be removed.
1415
- // Therefore we need to remove null values from the `batchedChanges` which are sent to the SQLite, if no existing value is present.
1416
- if (!existingValue) {
1417
- batchedChanges = applyMerge(undefined, [batchedChanges], true);
1418
- }
1419
-
1420
- const hasChanged = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].hasValueChanged(key, modifiedData);
1421
-
1422
- // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
1423
- const updatePromise = broadcastUpdate(key, modifiedData, 'merge', hasChanged, wasRemoved);
1424
-
1425
- // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
1426
- if (!hasChanged || wasRemoved) {
1427
- return updatePromise;
1428
- }
1429
-
1430
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].mergeItem(key, batchedChanges, modifiedData).then(() => {
1431
- sendActionToDevTools(METHOD.MERGE, key, changes, modifiedData);
1432
- return updatePromise;
1433
- });
1434
- } catch (error) {
1435
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logAlert(`An error occurred while applying merge for key: ${key}, Error: ${error}`);
1436
- return Promise.resolve();
1437
- }
1438
- });
1439
-
1440
- return mergeQueuePromise[key];
1441
- }
1442
-
1443
- /**
1444
- * Merge user provided default key value pairs.
1445
- * @private
1446
- * @returns {Promise}
1447
- */
1448
- function initializeWithDefaultKeyStates() {
1449
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].multiGet(underscore__WEBPACK_IMPORTED_MODULE_1___default().keys(defaultKeyStates)).then((pairs) => {
1450
- const asObject = underscore__WEBPACK_IMPORTED_MODULE_1___default().object(pairs);
1451
-
1452
- const merged = _utils__WEBPACK_IMPORTED_MODULE_4__["default"].fastMerge(asObject, defaultKeyStates);
1453
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].merge(merged);
1454
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(merged, (val, key) => keyChanged(key, val));
1455
- });
1456
- }
1457
-
1458
- /**
1459
- * Clear out all the data in the store
1460
- *
1461
- * Note that calling Onyx.clear() and then Onyx.set() on a key with a default
1462
- * key state may store an unexpected value in Storage.
1463
- *
1464
- * E.g.
1465
- * Onyx.clear();
1466
- * Onyx.set(ONYXKEYS.DEFAULT_KEY, 'default');
1467
- * Storage.getItem(ONYXKEYS.DEFAULT_KEY)
1468
- * .then((storedValue) => console.log(storedValue));
1469
- * null is logged instead of the expected 'default'
1470
- *
1471
- * Onyx.set() might call Storage.setItem() before Onyx.clear() calls
1472
- * Storage.setItem(). Use Onyx.merge() instead if possible. Onyx.merge() calls
1473
- * Onyx.get(key) before calling Storage.setItem() via Onyx.set().
1474
- * Storage.setItem() from Onyx.clear() will have already finished and the merged
1475
- * value will be saved to storage after the default value.
1476
- *
1477
- * @param {Array} keysToPreserve is a list of ONYXKEYS that should not be cleared with the rest of the data
1478
- * @returns {Promise<void>}
1479
- */
1480
- function clear() {let keysToPreserve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
1481
- return getAllKeys().then((keys) => {
1482
- const keysToBeClearedFromStorage = [];
1483
- const keyValuesToResetAsCollection = {};
1484
- const keyValuesToResetIndividually = {};
1485
-
1486
- // The only keys that should not be cleared are:
1487
- // 1. Anything specifically passed in keysToPreserve (because some keys like language preferences, offline
1488
- // status, or activeClients need to remain in Onyx even when signed out)
1489
- // 2. Any keys with a default state (because they need to remain in Onyx as their default, and setting them
1490
- // to null would cause unknown behavior)
1491
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keys, (key) => {
1492
- const isKeyToPreserve = underscore__WEBPACK_IMPORTED_MODULE_1___default().contains(keysToPreserve, key);
1493
- const isDefaultKey = underscore__WEBPACK_IMPORTED_MODULE_1___default().has(defaultKeyStates, key);
1494
-
1495
- // If the key is being removed or reset to default:
1496
- // 1. Update it in the cache
1497
- // 2. Figure out whether it is a collection key or not,
1498
- // since collection key subscribers need to be updated differently
1499
- if (!isKeyToPreserve) {
1500
- const oldValue = _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].getValue(key);
1501
- const newValue = underscore__WEBPACK_IMPORTED_MODULE_1___default().get(defaultKeyStates, key, null);
1502
- if (newValue !== oldValue) {
1503
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(key, newValue);
1504
- const collectionKey = key.substring(0, key.indexOf('_') + 1);
1505
- if (collectionKey) {
1506
- if (!keyValuesToResetAsCollection[collectionKey]) {
1507
- keyValuesToResetAsCollection[collectionKey] = {};
1508
- }
1509
- keyValuesToResetAsCollection[collectionKey][key] = newValue;
1510
- } else {
1511
- keyValuesToResetIndividually[key] = newValue;
1512
- }
1513
- }
1514
- }
1515
-
1516
- if (isKeyToPreserve || isDefaultKey) {
1517
- return;
1518
- }
1519
-
1520
- // If it isn't preserved and doesn't have a default, we'll remove it
1521
- keysToBeClearedFromStorage.push(key);
1522
- });
1523
-
1524
- const updatePromises = [];
1525
-
1526
- // Notify the subscribers for each key/value group so they can receive the new values
1527
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keyValuesToResetIndividually, (value, key) => {
1528
- updatePromises.push(scheduleSubscriberUpdate(key, value));
1529
- });
1530
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keyValuesToResetAsCollection, (value, key) => {
1531
- updatePromises.push(scheduleNotifyCollectionSubscribers(key, value));
1532
- });
1533
-
1534
- const defaultKeyValuePairs = underscore__WEBPACK_IMPORTED_MODULE_1___default().pairs(underscore__WEBPACK_IMPORTED_MODULE_1___default().omit(defaultKeyStates, keysToPreserve));
1535
-
1536
- // Remove only the items that we want cleared from storage, and reset others to default
1537
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(keysToBeClearedFromStorage, (key) => _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].drop(key));
1538
- return _storage__WEBPACK_IMPORTED_MODULE_7__["default"].removeItems(keysToBeClearedFromStorage).
1539
- then(() => _storage__WEBPACK_IMPORTED_MODULE_7__["default"].multiSet(defaultKeyValuePairs)).
1540
- then(() => {
1541
- _DevTools__WEBPACK_IMPORTED_MODULE_3__["default"].clearState(keysToPreserve);
1542
- return Promise.all(updatePromises);
1543
- });
1544
- });
1545
- }
1546
-
1547
- /**
1548
- * Merges a collection based on their keys
1549
- *
1550
- * @example
1551
- *
1552
- * Onyx.mergeCollection(ONYXKEYS.COLLECTION.REPORT, {
1553
- * [`${ONYXKEYS.COLLECTION.REPORT}1`]: report1,
1554
- * [`${ONYXKEYS.COLLECTION.REPORT}2`]: report2,
1555
- * });
1556
- *
1557
- * @param {String} collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
1558
- * @param {Object} collection Object collection keyed by individual collection member keys and values
1559
- * @returns {Promise}
1560
- */
1561
- function mergeCollection(collectionKey, collection) {
1562
- if (!underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(collection) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(collection) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isEmpty(collection)) {
1563
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logInfo('mergeCollection() called with invalid or empty value. Skipping this update.');
1564
- return Promise.resolve();
1565
- }
1566
-
1567
- // Confirm all the collection keys belong to the same parent
1568
- let hasCollectionKeyCheckFailed = false;
1569
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(collection, (_data, dataKey) => {
1570
- if (isKeyMatch(collectionKey, dataKey)) {
1571
- return;
1572
- }
1573
-
1574
- if (true) {
1575
- throw new Error(`Provided collection doesn't have all its data belonging to the same parent. CollectionKey: ${collectionKey}, DataKey: ${dataKey}`);
1576
- }
1577
-
1578
- hasCollectionKeyCheckFailed = true;
1579
- _Logger__WEBPACK_IMPORTED_MODULE_8__.logAlert(`Provided collection doesn't have all its data belonging to the same parent. CollectionKey: ${collectionKey}, DataKey: ${dataKey}`);
1580
- });
1581
-
1582
- // Gracefully handle bad mergeCollection updates so it doesn't block the merge queue
1583
- if (hasCollectionKeyCheckFailed) {
1584
- return Promise.resolve();
1585
- }
1586
-
1587
- return getAllKeys().then((persistedKeys) => {
1588
- // Split to keys that exist in storage and keys that don't
1589
- const [existingKeys, newKeys] = underscore__WEBPACK_IMPORTED_MODULE_1___default().chain(collection).
1590
- pick((value, key) => {
1591
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isNull(value)) {
1592
- remove(key);
1593
- return false;
1594
- }
1595
- return true;
1596
- }).
1597
- keys().
1598
- partition((key) => persistedKeys.includes(key)).
1599
- value();
1600
-
1601
- const existingKeyCollection = underscore__WEBPACK_IMPORTED_MODULE_1___default().pick(collection, existingKeys);
1602
- const newCollection = underscore__WEBPACK_IMPORTED_MODULE_1___default().pick(collection, newKeys);
1603
- const keyValuePairsForExistingCollection = prepareKeyValuePairsForStorage(existingKeyCollection);
1604
- const keyValuePairsForNewCollection = prepareKeyValuePairsForStorage(newCollection);
1605
-
1606
- const promises = [];
1607
-
1608
- // New keys will be added via multiSet while existing keys will be updated using multiMerge
1609
- // This is because setting a key that doesn't exist yet with multiMerge will throw errors
1610
- if (keyValuePairsForExistingCollection.length > 0) {
1611
- promises.push(_storage__WEBPACK_IMPORTED_MODULE_7__["default"].multiMerge(keyValuePairsForExistingCollection));
1612
- }
1613
-
1614
- if (keyValuePairsForNewCollection.length > 0) {
1615
- promises.push(_storage__WEBPACK_IMPORTED_MODULE_7__["default"].multiSet(keyValuePairsForNewCollection));
1616
- }
1617
-
1618
- // Prefill cache if necessary by calling get() on any existing keys and then merge original data to cache
1619
- // and update all subscribers
1620
- const promiseUpdate = Promise.all(underscore__WEBPACK_IMPORTED_MODULE_1___default().map(existingKeys, get)).then(() => {
1621
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].merge(collection);
1622
- return scheduleNotifyCollectionSubscribers(collectionKey, collection);
1623
- });
1624
-
1625
- return Promise.all(promises).
1626
- catch((error) => evictStorageAndRetry(error, mergeCollection, collection)).
1627
- then(() => {
1628
- sendActionToDevTools(METHOD.MERGE_COLLECTION, undefined, collection);
1629
- return promiseUpdate;
1630
- });
1631
- });
1632
- }
1633
-
1634
- /**
1635
- * Insert API responses and lifecycle data into Onyx
1636
- *
1637
- * @param {Array} data An array of objects with shape {onyxMethod: oneOf('set', 'merge', 'mergeCollection', 'multiSet', 'clear'), key: string, value: *}
1638
- * @returns {Promise} resolves when all operations are complete
1639
- */
1640
- function update(data) {
1641
- // First, validate the Onyx object is in the format we expect
1642
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(data, (_ref3) => {let { onyxMethod, key, value } = _ref3;
1643
- if (!underscore__WEBPACK_IMPORTED_MODULE_1___default().contains([METHOD.CLEAR, METHOD.SET, METHOD.MERGE, METHOD.MERGE_COLLECTION, METHOD.MULTI_SET], onyxMethod)) {
1644
- throw new Error(`Invalid onyxMethod ${onyxMethod} in Onyx update.`);
1645
- }
1646
- if (onyxMethod === METHOD.MULTI_SET) {
1647
- // For multiset, we just expect the value to be an object
1648
- if (!underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(value) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isArray(value) || underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(value)) {
1649
- throw new Error('Invalid value provided in Onyx multiSet. Onyx multiSet value must be of type object.');
1650
- }
1651
- } else if (onyxMethod !== METHOD.CLEAR && !underscore__WEBPACK_IMPORTED_MODULE_1___default().isString(key)) {
1652
- throw new Error(`Invalid ${typeof key} key provided in Onyx update. Onyx key must be of type string.`);
1653
- }
1654
- });
1655
-
1656
- const promises = [];
1657
- let clearPromise = Promise.resolve();
1658
-
1659
- underscore__WEBPACK_IMPORTED_MODULE_1___default().each(data, (_ref4) => {let { onyxMethod, key, value } = _ref4;
1660
- switch (onyxMethod) {
1661
- case METHOD.SET:
1662
- promises.push(() => set(key, value));
1663
- break;
1664
- case METHOD.MERGE:
1665
- promises.push(() => merge(key, value));
1666
- break;
1667
- case METHOD.MERGE_COLLECTION:
1668
- promises.push(() => mergeCollection(key, value));
1669
- break;
1670
- case METHOD.MULTI_SET:
1671
- promises.push(() => multiSet(value));
1672
- break;
1673
- case METHOD.CLEAR:
1674
- clearPromise = clear();
1675
- break;
1676
- default:
1677
- break;}
1678
-
1679
- });
1680
-
1681
- return clearPromise.then(() => Promise.all(underscore__WEBPACK_IMPORTED_MODULE_1___default().map(promises, (p) => p())));
1682
- }
1683
-
1684
- /**
1685
- * When set these keys will not be persisted to storage
1686
- * @param {string[]} keyList
1687
- */
1688
- function setMemoryOnlyKeys(keyList) {
1689
- _storage__WEBPACK_IMPORTED_MODULE_7__["default"].setMemoryOnlyKeys(keyList);
1690
-
1691
- // When in memory only mode for certain keys we do not want to ever drop items from the cache as the user will have no way to recover them again via storage.
1692
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].setRecentKeysLimit(Infinity);
1693
- }
1694
-
1695
- /**
1696
- * Initialize the store with actions and listening for storage events
1697
- *
1698
- * @param {Object} [options={}] config object
1699
- * @param {Object} [options.keys={}] `ONYXKEYS` constants object
1700
- * @param {Object} [options.initialKeyStates={}] initial data to set when `init()` and `clear()` is called
1701
- * @param {String[]} [options.safeEvictionKeys=[]] This is an array of keys
1702
- * (individual or collection patterns) that when provided to Onyx are flagged
1703
- * as "safe" for removal. Any components subscribing to these keys must also
1704
- * implement a canEvict option. See the README for more info.
1705
- * @param {Number} [options.maxCachedKeysCount=55] Sets how many recent keys should we try to keep in cache
1706
- * Setting this to 0 would practically mean no cache
1707
- * We try to free cache when we connect to a safe eviction key
1708
- * @param {Boolean} [options.captureMetrics] Enables Onyx benchmarking and exposes the get/print/reset functions
1709
- * @param {Boolean} [options.shouldSyncMultipleInstances] Auto synchronize storage events between multiple instances
1710
- * of Onyx running in different tabs/windows. Defaults to true for platforms that support local storage (web/desktop)
1711
- * @param {Boolean} [options.debugSetState] Enables debugging setState() calls to connected components.
1712
- * @example
1713
- * Onyx.init({
1714
- * keys: ONYXKEYS,
1715
- * initialKeyStates: {
1716
- * [ONYXKEYS.SESSION]: {loading: false},
1717
- * },
1718
- * });
1719
- */
1720
- function init()
1721
-
1722
-
1723
-
1724
-
1725
-
1726
-
1727
-
1728
- {let { keys = {}, initialKeyStates = {}, safeEvictionKeys = [], maxCachedKeysCount = 1000, captureMetrics = false, shouldSyncMultipleInstances = Boolean(__webpack_require__.g.localStorage), debugSetState = false } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
1729
- if (captureMetrics) {
1730
- // The code here is only bundled and applied when the captureMetrics is set
1731
- // eslint-disable-next-line no-use-before-define
1732
- applyDecorators();
1733
- }
1734
-
1735
- if (debugSetState) {
1736
- _metrics_PerformanceUtils__WEBPACK_IMPORTED_MODULE_10__.setShouldDebugSetState(true);
1737
- }
1738
-
1739
- if (maxCachedKeysCount > 0) {
1740
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].setRecentKeysLimit(maxCachedKeysCount);
1741
- }
1742
-
1743
- // We need the value of the collection keys later for checking if a
1744
- // key is a collection. We store it in a map for faster lookup.
1745
- const collectionValues = underscore__WEBPACK_IMPORTED_MODULE_1___default().values(keys.COLLECTION);
1746
- onyxCollectionKeyMap = underscore__WEBPACK_IMPORTED_MODULE_1___default().reduce(
1747
- collectionValues,
1748
- (acc, val) => {
1749
- acc.set(val, true);
1750
- return acc;
1751
- },
1752
- new Map());
1753
-
1754
-
1755
- // Set our default key states to use when initializing and clearing Onyx data
1756
- defaultKeyStates = initialKeyStates;
1757
-
1758
- _DevTools__WEBPACK_IMPORTED_MODULE_3__["default"].initState(initialKeyStates);
1759
-
1760
- // Let Onyx know about which keys are safe to evict
1761
- evictionAllowList = safeEvictionKeys;
1762
-
1763
- // Initialize all of our keys with data provided then give green light to any pending connections
1764
- Promise.all([addAllSafeEvictionKeysToRecentlyAccessedList(), initializeWithDefaultKeyStates()]).then(deferredInitTask.resolve);
1765
-
1766
- if (shouldSyncMultipleInstances && underscore__WEBPACK_IMPORTED_MODULE_1___default().isFunction(_storage__WEBPACK_IMPORTED_MODULE_7__["default"].keepInstancesSync)) {
1767
- _storage__WEBPACK_IMPORTED_MODULE_7__["default"].keepInstancesSync((key, value) => {
1768
- _OnyxCache__WEBPACK_IMPORTED_MODULE_6__["default"].set(key, value);
1769
- keyChanged(key, value);
1770
- });
1771
- }
1772
- }
1773
-
1774
- const Onyx = {
1775
- connect,
1776
- disconnect,
1777
- set,
1778
- multiSet,
1779
- merge,
1780
- mergeCollection,
1781
- update,
1782
- clear,
1783
- getAllKeys,
1784
- init,
1785
- registerLogger: _Logger__WEBPACK_IMPORTED_MODULE_8__.registerLogger,
1786
- addToEvictionBlockList,
1787
- removeFromEvictionBlockList,
1788
- isSafeEvictionKey,
1789
- METHOD,
1790
- setMemoryOnlyKeys,
1791
- tryGetCachedValue,
1792
- hasPendingMergeForKey
1793
- };
1794
-
1795
- /**
1796
- * Apply calls statistic decorators to benchmark Onyx
1797
- *
1798
- * @private
1799
- */
1800
- function applyDecorators() {
1801
- // We're requiring the script dynamically here so that it's only evaluated when decorators are used
1802
- const decorate = __webpack_require__(/*! ./metrics */ "./lib/metrics/index.web.js");
1803
-
1804
- // Re-assign with decorated functions
1805
- /* eslint-disable no-func-assign */
1806
- get = decorate.decorateWithMetrics(get, 'Onyx:get');
1807
- set = decorate.decorateWithMetrics(set, 'Onyx:set');
1808
- multiSet = decorate.decorateWithMetrics(multiSet, 'Onyx:multiSet');
1809
- clear = decorate.decorateWithMetrics(clear, 'Onyx:clear');
1810
- merge = decorate.decorateWithMetrics(merge, 'Onyx:merge');
1811
- mergeCollection = decorate.decorateWithMetrics(mergeCollection, 'Onyx:mergeCollection');
1812
- getAllKeys = decorate.decorateWithMetrics(getAllKeys, 'Onyx:getAllKeys');
1813
- initializeWithDefaultKeyStates = decorate.decorateWithMetrics(initializeWithDefaultKeyStates, 'Onyx:defaults');
1814
- update = decorate.decorateWithMetrics(update, 'Onyx:update');
1815
- /* eslint-enable */
1816
-
1817
- // Re-expose decorated methods
1818
- /* eslint-disable rulesdir/prefer-actions-set-data */
1819
- Onyx.set = set;
1820
- Onyx.multiSet = multiSet;
1821
- Onyx.clear = clear;
1822
- Onyx.merge = merge;
1823
- Onyx.mergeCollection = mergeCollection;
1824
- Onyx.update = update;
1825
- /* eslint-enable */
1826
-
1827
- // Expose stats methods on Onyx
1828
- Onyx.getMetrics = decorate.getMetrics;
1829
- Onyx.resetMetrics = decorate.resetMetrics;
1830
- Onyx.printMetrics = decorate.printMetrics;
1831
- }
1832
-
1833
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Onyx);
1834
-
1835
- /***/ }),
1836
-
1837
- /***/ "./lib/OnyxCache.js":
1838
- /*!**************************!*\
1839
- !*** ./lib/OnyxCache.js ***!
1840
- \**************************/
1841
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1842
-
1843
- "use strict";
1844
- __webpack_require__.r(__webpack_exports__);
1845
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1846
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
1847
- /* harmony export */ });
1848
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
1849
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
1850
- /* harmony import */ var fast_equals__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fast-equals */ "fast-equals");
1851
- /* harmony import */ var fast_equals__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fast_equals__WEBPACK_IMPORTED_MODULE_1__);
1852
- /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./utils */ "./lib/utils.js");
1853
-
1854
-
1855
-
1856
-
1857
- const isDefined = underscore__WEBPACK_IMPORTED_MODULE_0___default().negate((underscore__WEBPACK_IMPORTED_MODULE_0___default().isUndefined));
1858
-
1859
- /**
1860
- * In memory cache providing data by reference
1861
- * Encapsulates Onyx cache related functionality
1862
- */
1863
- class OnyxCache {
1864
- constructor() {
1865
- /**
1866
- * @private
1867
- * Cache of all the storage keys available in persistent storage
1868
- * @type {Set<string>}
1869
- */
1870
- this.storageKeys = new Set();
1871
-
1872
- /**
1873
- * @private
1874
- * Unique list of keys maintained in access order (most recent at the end)
1875
- * @type {Set<string>}
1876
- */
1877
- this.recentKeys = new Set();
1878
-
1879
- /**
1880
- * @private
1881
- * A map of cached values
1882
- * @type {Record<string, *>}
1883
- */
1884
- this.storageMap = {};
1885
-
1886
- /**
1887
- * @private
1888
- * Captured pending tasks for already running storage methods
1889
- * Using a map yields better performance on operations such a delete
1890
- * https://www.zhenghao.io/posts/object-vs-map
1891
- * @type {Map<string, Promise>}
1892
- */
1893
- this.pendingPromises = new Map();
1894
-
1895
- // bind all public methods to prevent problems with `this`
1896
- underscore__WEBPACK_IMPORTED_MODULE_0___default().bindAll(
1897
- this,
1898
- 'getAllKeys',
1899
- 'getValue',
1900
- 'hasCacheForKey',
1901
- 'addKey',
1902
- 'set',
1903
- 'drop',
1904
- 'merge',
1905
- 'hasPendingTask',
1906
- 'getTaskPromise',
1907
- 'captureTask',
1908
- 'removeLeastRecentlyUsedKeys',
1909
- 'setRecentKeysLimit');
1910
-
1911
- }
1912
-
1913
- /**
1914
- * Get all the storage keys
1915
- * @returns {string[]}
1916
- */
1917
- getAllKeys() {
1918
- return Array.from(this.storageKeys);
1919
- }
1920
-
1921
- /**
1922
- * Get a cached value from storage
1923
- * @param {string} key
1924
- * @returns {*}
1925
- */
1926
- getValue(key) {
1927
- this.addToAccessedKeys(key);
1928
- return this.storageMap[key];
1929
- }
1930
-
1931
- /**
1932
- * Check whether cache has data for the given key
1933
- * @param {string} key
1934
- * @returns {boolean}
1935
- */
1936
- hasCacheForKey(key) {
1937
- return isDefined(this.storageMap[key]);
1938
- }
1939
-
1940
- /**
1941
- * Saves a key in the storage keys list
1942
- * Serves to keep the result of `getAllKeys` up to date
1943
- * @param {string} key
1944
- */
1945
- addKey(key) {
1946
- this.storageKeys.add(key);
1947
- }
1948
-
1949
- /**
1950
- * Set's a key value in cache
1951
- * Adds the key to the storage keys list as well
1952
- * @param {string} key
1953
- * @param {*} value
1954
- * @returns {*} value - returns the cache value
1955
- */
1956
- set(key, value) {
1957
- this.addKey(key);
1958
- this.addToAccessedKeys(key);
1959
- this.storageMap[key] = value;
1960
-
1961
- return value;
1962
- }
1963
-
1964
- /**
1965
- * Forget the cached value for the given key
1966
- * @param {string} key
1967
- */
1968
- drop(key) {
1969
- delete this.storageMap[key];
1970
- this.storageKeys.delete(key);
1971
- this.recentKeys.delete(key);
1972
- }
1973
-
1974
- /**
1975
- * Deep merge data to cache, any non existing keys will be created
1976
- * @param {Record<string, *>} data - a map of (cache) key - values
1977
- */
1978
- merge(data) {
1979
- if (!underscore__WEBPACK_IMPORTED_MODULE_0___default().isObject(data) || underscore__WEBPACK_IMPORTED_MODULE_0___default().isArray(data)) {
1980
- throw new Error('data passed to cache.merge() must be an Object of onyx key/value pairs');
1981
- }
1982
-
1983
- // lodash adds a small overhead so we don't use it here
1984
- // eslint-disable-next-line prefer-object-spread, rulesdir/prefer-underscore-method
1985
- this.storageMap = Object.assign({}, _utils__WEBPACK_IMPORTED_MODULE_2__["default"].fastMerge(this.storageMap, data, false));
1986
-
1987
- const storageKeys = this.getAllKeys();
1988
- const mergedKeys = underscore__WEBPACK_IMPORTED_MODULE_0___default().keys(data);
1989
- this.storageKeys = new Set([...storageKeys, ...mergedKeys]);
1990
- underscore__WEBPACK_IMPORTED_MODULE_0___default().each(mergedKeys, (key) => this.addToAccessedKeys(key));
1991
- }
1992
-
1993
- /**
1994
- * Check whether the given task is already running
1995
- * @param {string} taskName - unique name given for the task
1996
- * @returns {*}
1997
- */
1998
- hasPendingTask(taskName) {
1999
- return isDefined(this.pendingPromises.get(taskName));
2000
- }
2001
-
2002
- /**
2003
- * Use this method to prevent concurrent calls for the same thing
2004
- * Instead of calling the same task again use the existing promise
2005
- * provided from this function
2006
- * @template T
2007
- * @param {string} taskName - unique name given for the task
2008
- * @returns {Promise<T>}
2009
- */
2010
- getTaskPromise(taskName) {
2011
- return this.pendingPromises.get(taskName);
2012
- }
2013
-
2014
- /**
2015
- * Capture a promise for a given task so other caller can
2016
- * hook up to the promise if it's still pending
2017
- * @template T
2018
- * @param {string} taskName - unique name for the task
2019
- * @param {Promise<T>} promise
2020
- * @returns {Promise<T>}
2021
- */
2022
- captureTask(taskName, promise) {
2023
- const returnPromise = promise.finally(() => {
2024
- this.pendingPromises.delete(taskName);
2025
- });
2026
-
2027
- this.pendingPromises.set(taskName, returnPromise);
2028
-
2029
- return returnPromise;
2030
- }
2031
-
2032
- /**
2033
- * @private
2034
- * Adds a key to the top of the recently accessed keys
2035
- * @param {string} key
2036
- */
2037
- addToAccessedKeys(key) {
2038
- // Removing and re-adding a key ensures it's at the end of the list
2039
- this.recentKeys.delete(key);
2040
- this.recentKeys.add(key);
2041
- }
2042
-
2043
- /**
2044
- * Remove keys that don't fall into the range of recently used keys
2045
- */
2046
- removeLeastRecentlyUsedKeys() {
2047
- let numKeysToRemove = this.recentKeys.size - this.maxRecentKeysSize;
2048
- if (numKeysToRemove <= 0) {
2049
- return;
2050
- }
2051
- const iterator = this.recentKeys.values();
2052
- const temp = [];
2053
- while (numKeysToRemove > 0) {
2054
- const value = iterator.next().value;
2055
- temp.push(value);
2056
- numKeysToRemove--;
2057
- }
2058
-
2059
- for (let i = 0; i < temp.length; ++i) {
2060
- delete this.storageMap[temp[i]];
2061
- this.recentKeys.delete(temp[i]);
2062
- }
2063
- }
2064
-
2065
- /**
2066
- * Set the recent keys list size
2067
- * @param {number} limit
2068
- */
2069
- setRecentKeysLimit(limit) {
2070
- this.maxRecentKeysSize = limit;
2071
- }
2072
-
2073
- /**
2074
- * @param {String} key
2075
- * @param {*} value
2076
- * @returns {Boolean}
2077
- */
2078
- hasValueChanged(key, value) {
2079
- return !(0,fast_equals__WEBPACK_IMPORTED_MODULE_1__.deepEqual)(this.storageMap[key], value);
2080
- }
2081
- }
2082
-
2083
- const instance = new OnyxCache();
2084
-
2085
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (instance);
2086
-
2087
- /***/ }),
2088
-
2089
- /***/ "./lib/Str.js":
2090
- /*!********************!*\
2091
- !*** ./lib/Str.js ***!
2092
- \********************/
2093
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2094
-
2095
- "use strict";
2096
- __webpack_require__.r(__webpack_exports__);
2097
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2098
- /* harmony export */ "result": () => (/* binding */ result),
2099
- /* harmony export */ "startsWith": () => (/* binding */ startsWith)
2100
- /* harmony export */ });
2101
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
2102
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
2103
-
2104
-
2105
- /**
2106
- * Returns true if the haystack begins with the needle
2107
- *
2108
- * @param {String} haystack The full string to be searched
2109
- * @param {String} needle The case-sensitive string to search for
2110
- * @return {Boolean} Returns true if the haystack starts with the needle.
2111
- */
2112
- function startsWith(haystack, needle) {
2113
- return underscore__WEBPACK_IMPORTED_MODULE_0___default().isString(haystack) && underscore__WEBPACK_IMPORTED_MODULE_0___default().isString(needle) && haystack.startsWith(needle);
2114
- }
2115
-
2116
- /**
2117
- * Checks if parameter is a string or function.
2118
- * If it is a string, then we will just return it.
2119
- * If it is a function, then we will call it with
2120
- * any additional arguments and return the result.
2121
- *
2122
- * @param {String|Function} parameter
2123
- * @returns {*}
2124
- */
2125
- function result(parameter) {for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {args[_key - 1] = arguments[_key];}
2126
- return underscore__WEBPACK_IMPORTED_MODULE_0___default().isFunction(parameter) ? parameter(...args) : parameter;
2127
- }
2128
-
2129
-
2130
-
2131
- /***/ }),
2132
-
2133
- /***/ "./lib/batch.js":
2134
- /*!**********************!*\
2135
- !*** ./lib/batch.js ***!
2136
- \**********************/
2137
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2138
-
2139
- "use strict";
2140
- __webpack_require__.r(__webpack_exports__);
2141
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2142
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2143
- /* harmony export */ });
2144
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react-dom */ "react-dom");
2145
- /* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_0__);
2146
-
2147
-
2148
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (react_dom__WEBPACK_IMPORTED_MODULE_0__.unstable_batchedUpdates);
2149
-
2150
- /***/ }),
2151
-
2152
- /***/ "./lib/createDeferredTask.js":
2153
- /*!***********************************!*\
2154
- !*** ./lib/createDeferredTask.js ***!
2155
- \***********************************/
2156
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2157
-
2158
- "use strict";
2159
- __webpack_require__.r(__webpack_exports__);
2160
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2161
- /* harmony export */ "default": () => (/* binding */ createDeferredTask)
2162
- /* harmony export */ });
2163
- /**
2164
- * Create a deferred task that can be resolved when we call `resolve()`
2165
- * The returned promise will complete when we call `resolve`
2166
- * Useful when we want to wait for a tasks that is resolved from an external action
2167
- *
2168
- * @template T
2169
- * @returns {{ resolve: function(*), promise: Promise<T|void> }}
2170
- */
2171
- function createDeferredTask() {
2172
- const deferred = {};
2173
- deferred.promise = new Promise((res) => {
2174
- deferred.resolve = res;
2175
- });
2176
-
2177
- return deferred;
2178
- }
2179
-
2180
- /***/ }),
2181
-
2182
- /***/ "./lib/metrics/PerformanceUtils.js":
2183
- /*!*****************************************!*\
2184
- !*** ./lib/metrics/PerformanceUtils.js ***!
2185
- \*****************************************/
2186
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2187
-
2188
- "use strict";
2189
- __webpack_require__.r(__webpack_exports__);
2190
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2191
- /* harmony export */ "logSetStateCall": () => (/* binding */ logSetStateCall),
2192
- /* harmony export */ "setShouldDebugSetState": () => (/* binding */ setShouldDebugSetState)
2193
- /* harmony export */ });
2194
- /* harmony import */ var lodash_transform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! lodash/transform */ "lodash/transform");
2195
- /* harmony import */ var lodash_transform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(lodash_transform__WEBPACK_IMPORTED_MODULE_0__);
2196
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! underscore */ "underscore");
2197
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_1__);
2198
-
2199
-
2200
-
2201
- let debugSetState = false;
2202
-
2203
- /**
2204
- * @param {Boolean} debug
2205
- */
2206
- function setShouldDebugSetState(debug) {
2207
- debugSetState = debug;
2208
- }
2209
-
2210
- /**
2211
- * Deep diff between two objects. Useful for figuring out what changed about an object from one render to the next so
2212
- * that state and props updates can be optimized.
2213
- *
2214
- * @param {Object} object
2215
- * @param {Object} base
2216
- * @return {Object}
2217
- */
2218
- function diffObject(object, base) {
2219
- function changes(obj, comparisonObject) {
2220
- return lodash_transform__WEBPACK_IMPORTED_MODULE_0___default()(obj, (result, value, key) => {
2221
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isEqual(value, comparisonObject[key])) {
2222
- return;
2223
- }
2224
-
2225
- // eslint-disable-next-line no-param-reassign
2226
- result[key] = underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(value) && underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(comparisonObject[key]) ? changes(value, comparisonObject[key]) : value;
2227
- });
2228
- }
2229
- return changes(object, base);
2230
- }
2231
-
2232
- /**
2233
- * Provide insights into why a setState() call occurred by diffing the before and after values.
2234
- *
2235
- * @param {Object} mapping
2236
- * @param {*} previousValue
2237
- * @param {*} newValue
2238
- * @param {String} caller
2239
- * @param {String} [keyThatChanged]
2240
- */
2241
- function logSetStateCall(mapping, previousValue, newValue, caller, keyThatChanged) {
2242
- if (!debugSetState) {
2243
- return;
2244
- }
2245
-
2246
- const logParams = {};
2247
- if (keyThatChanged) {
2248
- logParams.keyThatChanged = keyThatChanged;
2249
- }
2250
- if (underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(newValue) && underscore__WEBPACK_IMPORTED_MODULE_1___default().isObject(previousValue)) {
2251
- logParams.difference = diffObject(previousValue, newValue);
2252
- } else {
2253
- logParams.previousValue = previousValue;
2254
- logParams.newValue = newValue;
2255
- }
2256
-
2257
- console.debug(`[Onyx-Debug] ${mapping.displayName} setState() called. Subscribed to key '${mapping.key}' (${caller})`, logParams);
2258
- }
2259
-
2260
-
2261
-
2262
- /***/ }),
2263
-
2264
- /***/ "./lib/metrics/index.web.js":
2265
- /*!**********************************!*\
2266
- !*** ./lib/metrics/index.web.js ***!
2267
- \**********************************/
2268
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2269
-
2270
- "use strict";
2271
- __webpack_require__.r(__webpack_exports__);
2272
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2273
- /* harmony export */ "decorateWithMetrics": () => (/* binding */ decorateWithMetrics),
2274
- /* harmony export */ "getMetrics": () => (/* binding */ getMetrics),
2275
- /* harmony export */ "printMetrics": () => (/* binding */ printMetrics),
2276
- /* harmony export */ "resetMetrics": () => (/* binding */ resetMetrics)
2277
- /* harmony export */ });
2278
- // For web-only implementations of Onyx, this module will just be a no-op
2279
-
2280
- function decorateWithMetrics(func) {
2281
- return func;
2282
- }
2283
- function getMetrics() {}
2284
- function printMetrics() {}
2285
- function resetMetrics() {}
2286
-
2287
-
2288
-
2289
- /***/ }),
2290
-
2291
- /***/ "./lib/storage/WebStorage.js":
2292
- /*!***********************************!*\
2293
- !*** ./lib/storage/WebStorage.js ***!
2294
- \***********************************/
2295
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2296
-
2297
- "use strict";
2298
- __webpack_require__.r(__webpack_exports__);
2299
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2300
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2301
- /* harmony export */ });
2302
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
2303
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
2304
- /* harmony import */ var _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./providers/IDBKeyVal */ "./lib/storage/providers/IDBKeyVal.js");
2305
- /**
2306
- * This file is here to wrap IDBKeyVal with a layer that provides data-changed events like the ones that exist
2307
- * when using LocalStorage APIs in the browser. These events are great because multiple tabs can listen for when
2308
- * data changes and then stay up-to-date with everything happening in Onyx.
2309
- */
2310
-
2311
-
2312
-
2313
- const SYNC_ONYX = 'SYNC_ONYX';
2314
-
2315
- /**
2316
- * Raise an event thorough `localStorage` to let other tabs know a value changed
2317
- * @param {String} onyxKey
2318
- */
2319
- function raiseStorageSyncEvent(onyxKey) {
2320
- __webpack_require__.g.localStorage.setItem(SYNC_ONYX, onyxKey);
2321
- __webpack_require__.g.localStorage.removeItem(SYNC_ONYX, onyxKey);
2322
- }
2323
-
2324
- function raiseStorageSyncManyKeysEvent(onyxKeys) {
2325
- underscore__WEBPACK_IMPORTED_MODULE_0___default().each(onyxKeys, (onyxKey) => {
2326
- raiseStorageSyncEvent(onyxKey);
2327
- });
2328
- }
2329
-
2330
- const webStorage = {
2331
- ..._providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"],
2332
-
2333
- /**
2334
- * @param {Function} onStorageKeyChanged Storage synchronization mechanism keeping all opened tabs in sync
2335
- */
2336
- keepInstancesSync(onStorageKeyChanged) {
2337
- // Override set, remove and clear to raise storage events that we intercept in other tabs
2338
- this.setItem = (key, value) => _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].setItem(key, value).then(() => raiseStorageSyncEvent(key));
2339
-
2340
- this.removeItem = (key) => _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].removeItem(key).then(() => raiseStorageSyncEvent(key));
2341
-
2342
- this.removeItems = (keys) => _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].removeItems(keys).then(() => raiseStorageSyncManyKeysEvent(keys));
2343
-
2344
- this.mergeItem = (key, batchedChanges, modifiedData) => _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].mergeItem(key, batchedChanges, modifiedData).then(() => raiseStorageSyncEvent(key));
2345
-
2346
- // If we just call Storage.clear other tabs will have no idea which keys were available previously
2347
- // so that they can call keysChanged for them. That's why we iterate over every key and raise a storage sync
2348
- // event for each one
2349
- this.clear = () => {
2350
- let allKeys;
2351
-
2352
- // The keys must be retrieved before storage is cleared or else the list of keys would be empty
2353
- return _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].getAllKeys().
2354
- then((keys) => {
2355
- allKeys = keys;
2356
- }).
2357
- then(() => _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].clear()).
2358
- then(() => {
2359
- // Now that storage is cleared, the storage sync event can happen which is a more atomic action
2360
- // for other browser tabs
2361
- underscore__WEBPACK_IMPORTED_MODULE_0___default().each(allKeys, raiseStorageSyncEvent);
2362
- });
2363
- };
2364
-
2365
- // This listener will only be triggered by events coming from other tabs
2366
- __webpack_require__.g.addEventListener('storage', (event) => {
2367
- // Ignore events that don't originate from the SYNC_ONYX logic
2368
- if (event.key !== SYNC_ONYX || !event.newValue) {
2369
- return;
2370
- }
2371
-
2372
- const onyxKey = event.newValue;
2373
- _providers_IDBKeyVal__WEBPACK_IMPORTED_MODULE_1__["default"].getItem(onyxKey).then((value) => onStorageKeyChanged(onyxKey, value));
2374
- });
2375
- }
2376
- };
2377
-
2378
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (webStorage);
2379
-
2380
- /***/ }),
2381
-
2382
- /***/ "./lib/storage/index.web.js":
2383
- /*!**********************************!*\
2384
- !*** ./lib/storage/index.web.js ***!
2385
- \**********************************/
2386
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2387
-
2388
- "use strict";
2389
- __webpack_require__.r(__webpack_exports__);
2390
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2391
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2392
- /* harmony export */ });
2393
- /* harmony import */ var _WebStorage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./WebStorage */ "./lib/storage/WebStorage.js");
2394
-
2395
-
2396
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_WebStorage__WEBPACK_IMPORTED_MODULE_0__["default"]);
2397
-
2398
- /***/ }),
2399
-
2400
- /***/ "./lib/storage/providers/IDBKeyVal.js":
2401
- /*!********************************************!*\
2402
- !*** ./lib/storage/providers/IDBKeyVal.js ***!
2403
- \********************************************/
2404
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2405
-
2406
- "use strict";
2407
- __webpack_require__.r(__webpack_exports__);
2408
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2409
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2410
- /* harmony export */ });
2411
- /* harmony import */ var idb_keyval__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! idb-keyval */ "idb-keyval");
2412
- /* harmony import */ var idb_keyval__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(idb_keyval__WEBPACK_IMPORTED_MODULE_0__);
2413
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! underscore */ "underscore");
2414
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_1__);
2415
- /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../utils */ "./lib/utils.js");
2416
-
2417
-
2418
-
2419
-
2420
- // We don't want to initialize the store while the JS bundle loads as idb-keyval will try to use global.indexedDB
2421
- // which might not be available in certain environments that load the bundle (e.g. electron main process).
2422
- let customStoreInstance;
2423
- const getCustomStore = () => {
2424
- if (!customStoreInstance) {
2425
- customStoreInstance = (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.createStore)('OnyxDB', 'keyvaluepairs');
2426
- }
2427
- return customStoreInstance;
2428
- };
2429
-
2430
- const provider = {
2431
- /**
2432
- * Sets the value for a given key. The only requirement is that the value should be serializable to JSON string
2433
- * @param {String} key
2434
- * @param {*} value
2435
- * @return {Promise<void>}
2436
- */
2437
- setItem: (key, value) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.set)(key, value, getCustomStore()),
2438
-
2439
- /**
2440
- * Get multiple key-value pairs for the give array of keys in a batch.
2441
- * This is optimized to use only one database transaction.
2442
- * @param {String[]} keysParam
2443
- * @return {Promise<Array<[key, value]>>}
2444
- */
2445
- multiGet: (keysParam) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.getMany)(keysParam, getCustomStore()).then((values) => underscore__WEBPACK_IMPORTED_MODULE_1___default().map(values, (value, index) => [keysParam[index], value])),
2446
-
2447
- /**
2448
- * Multiple merging of existing and new values in a batch
2449
- * @param {Array<[key, value]>} pairs
2450
- * This function also removes all nested null values from an object.
2451
- * @return {Promise<void>}
2452
- */
2453
- multiMerge: (pairs) =>
2454
- getCustomStore()('readwrite', (store) => {
2455
- // Note: we are using the manual store transaction here, to fit the read and update
2456
- // of the items in one transaction to achieve best performance.
2457
-
2458
- const getValues = Promise.all(underscore__WEBPACK_IMPORTED_MODULE_1___default().map(pairs, (_ref) => {let [key] = _ref;return (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.promisifyRequest)(store.get(key));}));
2459
-
2460
- return getValues.then((values) => {
2461
- const upsertMany = underscore__WEBPACK_IMPORTED_MODULE_1___default().map(pairs, (_ref2, index) => {let [key, value] = _ref2;
2462
- const prev = values[index];
2463
- const newValue = _utils__WEBPACK_IMPORTED_MODULE_2__["default"].fastMerge(prev, value);
2464
- return (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.promisifyRequest)(store.put(newValue, key));
2465
- });
2466
- return Promise.all(upsertMany);
2467
- });
2468
- }),
2469
-
2470
- /**
2471
- * Merging an existing value with a new one
2472
- * @param {String} key
2473
- * @param {any} _changes - not used, as we rely on the pre-merged data from the `modifiedData`
2474
- * @param {any} modifiedData - the pre-merged data from `Onyx.applyMerge`
2475
- * @return {Promise<void>}
2476
- */
2477
- mergeItem(key, _changes, modifiedData) {
2478
- // Since Onyx also merged the existing value with the changes, we can just set the value directly
2479
- return provider.setItem(key, modifiedData);
2480
- },
2481
-
2482
- /**
2483
- * Stores multiple key-value pairs in a batch
2484
- * @param {Array<[key, value]>} pairs
2485
- * @return {Promise<void>}
2486
- */
2487
- multiSet: (pairs) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.setMany)(pairs, getCustomStore()),
2488
-
2489
- /**
2490
- * Clear everything from storage and also stops the SyncQueue from adding anything more to storage
2491
- * @returns {Promise<void>}
2492
- */
2493
- clear: () => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.clear)(getCustomStore()),
2494
-
2495
- // This is a noop for now in order to keep clients from crashing see https://github.com/Expensify/Expensify/issues/312438
2496
- setMemoryOnlyKeys: () => {},
2497
-
2498
- /**
2499
- * Returns all keys available in storage
2500
- * @returns {Promise<String[]>}
2501
- */
2502
- getAllKeys: () => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.keys)(getCustomStore()),
2503
-
2504
- /**
2505
- * Get the value of a given key or return `null` if it's not available in storage
2506
- * @param {String} key
2507
- * @return {Promise<*>}
2508
- */
2509
- getItem: (key) =>
2510
- (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.get)(key, getCustomStore())
2511
- // idb-keyval returns undefined for missing items, but this needs to return null so that idb-keyval does the same thing as SQLiteStorage.
2512
- .then((val) => val === undefined ? null : val),
2513
-
2514
- /**
2515
- * Remove given key and it's value from storage
2516
- * @param {String} key
2517
- * @returns {Promise<void>}
2518
- */
2519
- removeItem: (key) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.del)(key, getCustomStore()),
2520
-
2521
- /**
2522
- * Remove given keys and their values from storage
2523
- *
2524
- * @param {Array} keysParam
2525
- * @returns {Promise}
2526
- */
2527
- removeItems: (keysParam) => (0,idb_keyval__WEBPACK_IMPORTED_MODULE_0__.delMany)(keysParam, getCustomStore()),
2528
-
2529
- /**
2530
- * Gets the total bytes of the database file
2531
- * @returns {Promise<number>}
2532
- */
2533
- getDatabaseSize() {
2534
- if (!window.navigator || !window.navigator.storage) {
2535
- throw new Error('StorageManager browser API unavailable');
2536
- }
2537
-
2538
- return window.navigator.storage.
2539
- estimate().
2540
- then((value) => ({
2541
- bytesUsed: value.usage,
2542
- bytesRemaining: value.quota - value.usage
2543
- })).
2544
- catch((error) => {
2545
- throw new Error(`Unable to estimate web storage quota. Original error: ${error}`);
2546
- });
2547
- }
2548
- };
2549
-
2550
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (provider);
2551
-
2552
- /***/ }),
2553
-
2554
- /***/ "./lib/utils.js":
2555
- /*!**********************!*\
2556
- !*** ./lib/utils.js ***!
2557
- \**********************/
2558
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2559
-
2560
- "use strict";
2561
- __webpack_require__.r(__webpack_exports__);
2562
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2563
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
2564
- /* harmony export */ });
2565
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! underscore */ "underscore");
2566
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_0__);
2567
-
2568
-
2569
- function areObjectsEmpty(a, b) {
2570
- return typeof a === 'object' && typeof b === 'object' && underscore__WEBPACK_IMPORTED_MODULE_0___default().isEmpty(a) && underscore__WEBPACK_IMPORTED_MODULE_0___default().isEmpty(b);
2571
- }
2572
-
2573
- // Mostly copied from https://medium.com/@lubaka.a/how-to-remove-lodash-performance-improvement-b306669ad0e1
2574
-
2575
- /**
2576
- * @param {mixed} val
2577
- * @returns {boolean}
2578
- */
2579
- function isMergeableObject(val) {
2580
- const nonNullObject = val != null ? typeof val === 'object' : false;
2581
- return (
2582
- nonNullObject &&
2583
- Object.prototype.toString.call(val) !== '[object RegExp]' &&
2584
- Object.prototype.toString.call(val) !== '[object Date]' &&
2585
- // eslint-disable-next-line rulesdir/prefer-underscore-method
2586
- !Array.isArray(val));
2587
-
2588
- }
2589
-
2590
- /**
2591
- * @param {Object} target
2592
- * @param {Object} source
2593
- * @param {Boolean} shouldRemoveNullObjectValues
2594
- * @returns {Object}
2595
- */
2596
- function mergeObject(target, source) {let shouldRemoveNullObjectValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
2597
- const destination = {};
2598
- if (isMergeableObject(target)) {
2599
- // lodash adds a small overhead so we don't use it here
2600
- // eslint-disable-next-line rulesdir/prefer-underscore-method
2601
- const targetKeys = Object.keys(target);
2602
- for (let i = 0; i < targetKeys.length; ++i) {
2603
- const key = targetKeys[i];
2604
-
2605
- // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
2606
- const isSourceOrTargetNull = target[key] === null || source[key] === null;
2607
- const shouldOmitSourceKey = shouldRemoveNullObjectValues && isSourceOrTargetNull;
2608
-
2609
- if (!shouldOmitSourceKey) {
2610
- destination[key] = target[key];
2611
- }
2612
- }
2613
- }
2614
-
2615
- // lodash adds a small overhead so we don't use it here
2616
- // eslint-disable-next-line rulesdir/prefer-underscore-method
2617
- const sourceKeys = Object.keys(source);
2618
- for (let i = 0; i < sourceKeys.length; ++i) {
2619
- const key = sourceKeys[i];
2620
-
2621
- // If shouldRemoveNullObjectValues is true, we want to remove null values from the merged object
2622
- const shouldOmitSourceKey = shouldRemoveNullObjectValues && source[key] === null;
2623
-
2624
- // If we pass undefined as the updated value for a key, we want to generally ignore it
2625
- const isSourceKeyUndefined = source[key] === undefined;
2626
-
2627
- if (!isSourceKeyUndefined && !shouldOmitSourceKey) {
2628
- const isSourceKeyMergable = isMergeableObject(source[key]);
2629
-
2630
- if (isSourceKeyMergable && target[key]) {
2631
- if (!shouldRemoveNullObjectValues || isSourceKeyMergable) {
2632
- // eslint-disable-next-line no-use-before-define
2633
- destination[key] = fastMerge(target[key], source[key], shouldRemoveNullObjectValues);
2634
- }
2635
- } else if (!shouldRemoveNullObjectValues || source[key] !== null) {
2636
- destination[key] = source[key];
2637
- }
2638
- }
2639
- }
2640
-
2641
- return destination;
2642
- }
2643
-
2644
- /**
2645
- * Merges two objects and removes null values if "shouldRemoveNullObjectValues" is set to true
2646
- *
2647
- * We generally want to remove null values from objects written to disk and cache, because it decreases the amount of data stored in memory and on disk.
2648
- * On native, when merging an existing value with new changes, SQLite will use JSON_PATCH, which removes top-level nullish values.
2649
- * To be consistent with the behaviour for merge, we'll also want to remove null values for "set" operations.
2650
- *
2651
- * @param {Object|Array} target
2652
- * @param {Object|Array} source
2653
- * @param {Boolean} shouldRemoveNullObjectValues
2654
- * @returns {Object|Array}
2655
- */
2656
- function fastMerge(target, source) {let shouldRemoveNullObjectValues = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
2657
- // We have to ignore arrays and nullish values here,
2658
- // otherwise "mergeObject" will throw an error,
2659
- // because it expects an object as "source"
2660
- if (underscore__WEBPACK_IMPORTED_MODULE_0___default().isArray(source) || source === null || source === undefined) {
2661
- return source;
2662
- }
2663
- return mergeObject(target, source, shouldRemoveNullObjectValues);
2664
- }
2665
-
2666
- function removeNestedNullValues(value) {
2667
- if (typeof value === 'object' && !underscore__WEBPACK_IMPORTED_MODULE_0___default().isArray(value)) {
2668
- return fastMerge(value, value);
2669
- }
2670
-
2671
- return value;
2672
- }
2673
-
2674
- function formatActionName(method, key) {
2675
- return key ? `${method.toUpperCase()}/${key}` : method.toUpperCase();
2676
- }
2677
-
2678
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ areObjectsEmpty, fastMerge, formatActionName, removeNestedNullValues });
2679
-
2680
- /***/ }),
2681
-
2682
- /***/ "./lib/withOnyx.js":
2683
- /*!*************************!*\
2684
- !*** ./lib/withOnyx.js ***!
2685
- \*************************/
2686
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
2687
-
2688
- "use strict";
2689
- __webpack_require__.r(__webpack_exports__);
2690
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
2691
- /* harmony export */ "default": () => (/* export default binding */ __WEBPACK_DEFAULT_EXPORT__)
2692
- /* harmony export */ });
2693
- /* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! prop-types */ "./node_modules/prop-types/index.js");
2694
- /* harmony import */ var prop_types__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(prop_types__WEBPACK_IMPORTED_MODULE_0__);
2695
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react */ "react");
2696
- /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_1__);
2697
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! underscore */ "underscore");
2698
- /* harmony import */ var underscore__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(underscore__WEBPACK_IMPORTED_MODULE_2__);
2699
- /* harmony import */ var _Onyx__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Onyx */ "./lib/Onyx.js");
2700
- /* harmony import */ var _Str__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Str */ "./lib/Str.js");
2701
- /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./utils */ "./lib/utils.js");
2702
- function _extends() {_extends = Object.assign ? Object.assign.bind() : function (target) {for (var i = 1; i < arguments.length; i++) {var source = arguments[i];for (var key in source) {if (Object.prototype.hasOwnProperty.call(source, key)) {target[key] = source[key];}}}return target;};return _extends.apply(this, arguments);}function _defineProperty(obj, key, value) {key = _toPropertyKey(key);if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}function _toPropertyKey(arg) {var key = _toPrimitive(arg, "string");return typeof key === "symbol" ? key : String(key);}function _toPrimitive(input, hint) {if (typeof input !== "object" || input === null) return input;var prim = input[Symbol.toPrimitive];if (prim !== undefined) {var res = prim.call(input, hint || "default");if (typeof res !== "object") return res;throw new TypeError("@@toPrimitive must return a primitive value.");}return (hint === "string" ? String : Number)(input);} /**
2703
- * This is a higher order component that provides the ability to map a state property directly to
2704
- * something in Onyx (a key/value store). That way, as soon as data in Onyx changes, the state will be set and the view
2705
- * will automatically change to reflect the new data.
2706
- */
2707
-
2708
-
2709
-
2710
-
2711
-
2712
-
2713
-
2714
- // This is a list of keys that can exist on a `mapping`, but are not directly related to loading data from Onyx. When the keys of a mapping are looped over to check
2715
- // if a key has changed, it's a good idea to skip looking at these properties since they would have unexpected results.
2716
- const mappingPropertiesToIgnoreChangesTo = ['initialValue', 'allowStaleData'];
2717
-
2718
- /**
2719
- * Returns the display name of a component
2720
- *
2721
- * @param {object} component
2722
- * @returns {string}
2723
- */
2724
- function getDisplayName(component) {
2725
- return component.displayName || component.name || 'Component';
2726
- }
2727
-
2728
- /**
2729
- * Removes all the keys from state that are unrelated to the onyx data being mapped to the component.
2730
- *
2731
- * @param {Object} state of the component
2732
- * @param {Object} onyxToStateMapping the object holding all of the mapping configuration for the component
2733
- * @returns {Object}
2734
- */
2735
- const getOnyxDataFromState = (state, onyxToStateMapping) => underscore__WEBPACK_IMPORTED_MODULE_2___default().pick(state, underscore__WEBPACK_IMPORTED_MODULE_2___default().keys(onyxToStateMapping));
2736
-
2737
- /* harmony default export */ function __WEBPACK_DEFAULT_EXPORT__(mapOnyxToState) {let shouldDelayUpdates = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
2738
- // A list of keys that must be present in tempState before we can render the WrappedComponent
2739
- const requiredKeysForInit = underscore__WEBPACK_IMPORTED_MODULE_2___default().chain(mapOnyxToState).
2740
- omit((config) => config.initWithStoredValues === false).
2741
- keys().
2742
- value();
2743
- return (WrappedComponent) => {
2744
- const displayName = getDisplayName(WrappedComponent);
2745
- class withOnyx extends (react__WEBPACK_IMPORTED_MODULE_1___default().Component) {
2746
-
2747
-
2748
- constructor(props) {
2749
- super(props);_defineProperty(this, "pendingSetStates", []);
2750
- this.shouldDelayUpdates = shouldDelayUpdates;
2751
- this.setWithOnyxState = this.setWithOnyxState.bind(this);
2752
- this.flushPendingSetStates = this.flushPendingSetStates.bind(this);
2753
-
2754
- // This stores all the Onyx connection IDs to be used when the component unmounts so everything can be
2755
- // disconnected. It is a key value store with the format {[mapping.key]: connectionID}.
2756
- this.activeConnectionIDs = {};
2757
-
2758
- const cachedState = underscore__WEBPACK_IMPORTED_MODULE_2___default().reduce(
2759
- mapOnyxToState,
2760
- (resultObj, mapping, propertyName) => {
2761
- const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, props);
2762
- let value = _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].tryGetCachedValue(key, mapping);
2763
- if (!value && mapping.initialValue) {
2764
- value = mapping.initialValue;
2765
- }
2766
-
2767
- /**
2768
- * If we have a pending merge for a key it could mean that data is being set via Onyx.merge() and someone expects a component to have this data immediately.
2769
- *
2770
- * @example
2771
- *
2772
- * Onyx.merge('report_123', value);
2773
- * Navigation.navigate(route); // Where "route" expects the "value" to be available immediately once rendered.
2774
- *
2775
- * In reality, Onyx.merge() will only update the subscriber after all merges have been batched and the previous value is retrieved via a get() (returns a promise).
2776
- * So, we won't use the cache optimization here as it will lead us to arbitrarily defer various actions in the application code.
2777
- */
2778
- if (value !== undefined && !_Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].hasPendingMergeForKey(key) || mapping.allowStaleData) {
2779
- // eslint-disable-next-line no-param-reassign
2780
- resultObj[propertyName] = value;
2781
- }
2782
-
2783
- return resultObj;
2784
- },
2785
- {});
2786
-
2787
-
2788
- // If we have all the data we need, then we can render the component immediately
2789
- cachedState.loading = underscore__WEBPACK_IMPORTED_MODULE_2___default().size(cachedState) < requiredKeysForInit.length;
2790
-
2791
- // Object holding the temporary initial state for the component while we load the various Onyx keys
2792
- this.tempState = cachedState;
2793
-
2794
- this.state = cachedState;
2795
- }
2796
-
2797
- componentDidMount() {
2798
- const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
2799
-
2800
- // Subscribe each of the state properties to the proper Onyx key
2801
- underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping, propertyName) => {
2802
- if (underscore__WEBPACK_IMPORTED_MODULE_2___default().includes(mappingPropertiesToIgnoreChangesTo, propertyName)) {
2803
- return;
2804
- }
2805
- const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...onyxDataFromState });
2806
- this.connectMappingToOnyx(mapping, propertyName, key);
2807
- });
2808
- this.checkEvictableKeys();
2809
- }
2810
-
2811
- componentDidUpdate(prevProps, prevState) {
2812
- // The whole purpose of this method is to check to see if a key that is subscribed to Onyx has changed, and then Onyx needs to be disconnected from the old
2813
- // key and connected to the new key.
2814
- // For example, a key could change if KeyB depends on data loading from Onyx for KeyA.
2815
- const isFirstTimeUpdatingAfterLoading = prevState.loading && !this.state.loading;
2816
- const onyxDataFromState = getOnyxDataFromState(this.state, mapOnyxToState);
2817
- const prevOnyxDataFromState = getOnyxDataFromState(prevState, mapOnyxToState);
2818
-
2819
- underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping, propName) => {
2820
- // Some properties can be ignored because they aren't related to onyx keys and they will never change
2821
- if (underscore__WEBPACK_IMPORTED_MODULE_2___default().includes(mappingPropertiesToIgnoreChangesTo, propName)) {
2822
- return;
2823
- }
2824
-
2825
- // The previous key comes from either:
2826
- // 1) The initial key that was connected to (ie. set from `componentDidMount()`)
2827
- // 2) The updated props which caused `componentDidUpdate()` to run
2828
- // The first case cannot be used all the time because of race conditions where `componentDidUpdate()` can be triggered before connectingMappingToOnyx() is done
2829
- // (eg. if a user switches chats really quickly). In this case, it's much more stable to always look at the changes to prevProp and prevState to derive the key.
2830
- // The second case cannot be used all the time because the onyx data doesn't change the first time that `componentDidUpdate()` runs after loading. In this case,
2831
- // the `mapping.previousKey` must be used for the comparison or else this logic never detects that onyx data could have changed during the loading process.
2832
- const previousKey = isFirstTimeUpdatingAfterLoading ? mapping.previousKey : _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...prevProps, ...prevOnyxDataFromState });
2833
- const newKey = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...onyxDataFromState });
2834
- if (previousKey !== newKey) {
2835
- _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].disconnect(this.activeConnectionIDs[previousKey], previousKey);
2836
- delete this.activeConnectionIDs[previousKey];
2837
- this.connectMappingToOnyx(mapping, propName, newKey);
2838
- }
2839
- });
2840
- this.checkEvictableKeys();
2841
- }
2842
-
2843
- componentWillUnmount() {
2844
- // Disconnect everything from Onyx
2845
- underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping) => {
2846
- const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, { ...this.props, ...getOnyxDataFromState(this.state, mapOnyxToState) });
2847
- _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].disconnect(this.activeConnectionIDs[key], key);
2848
- });
2849
- }
2850
-
2851
- setStateProxy(modifier) {
2852
- if (this.shouldDelayUpdates) {
2853
- this.pendingSetStates.push(modifier);
2854
- } else {
2855
- this.setState(modifier);
2856
- }
2857
- }
2858
-
2859
- /**
2860
- * This method is used by the internal raw Onyx `sendDataToConnection`, it is designed to prevent unnecessary renders while a component
2861
- * still in a "loading" (read "mounting") state. The temporary initial state is saved to the HOC instance and setState()
2862
- * only called once all the necessary data has been collected.
2863
- *
2864
- * There is however the possibility the component could have been updated by a call to setState()
2865
- * before the data was "initially" collected. A race condition.
2866
- * For example some update happened on some key, while onyx was still gathering the initial hydration data.
2867
- * This update is disptached directly to setStateProxy and therefore the component has the most up-to-date data
2868
- *
2869
- * This is a design flaw in Onyx itself as dispatching updates before initial hydration is not a correct event flow.
2870
- * We however need to workaround this issue in the HOC. The addition of initialValue makes things even more complex,
2871
- * since you cannot be really sure if the component has been updated before or after the initial hydration. Therefore if
2872
- * initialValue is there, we just check if the update is different than that and then try to handle it as best as we can.
2873
- *
2874
- * @param {String} statePropertyName
2875
- * @param {*} val
2876
- */
2877
- setWithOnyxState(statePropertyName, val) {
2878
- const prevValue = this.state[statePropertyName];
2879
-
2880
- // If the component is not loading (read "mounting"), then we can just update the state
2881
- // There is a small race condition.
2882
- // When calling setWithOnyxState we delete the tempState object that is used to hold temporary state updates while the HOC is gathering data.
2883
- // However the loading flag is only set on the setState callback down below. setState however is an async operation that is also batched,
2884
- // therefore there is a small window of time where the loading flag is not false but the tempState is already gone
2885
- // (while the update is queued and waiting to be applied).
2886
- // This simply bypasses the loading check if the tempState is gone and the update can be safely queued with a normal setStateProxy.
2887
- if (!this.state.loading || !this.tempState) {
2888
- // Performance optimization, do not trigger update with same values
2889
- if (prevValue === val || _utils__WEBPACK_IMPORTED_MODULE_5__["default"].areObjectsEmpty(prevValue, val)) {
2890
- return;
2891
- }
2892
-
2893
- this.setStateProxy({ [statePropertyName]: val });
2894
- return;
2895
- }
2896
-
2897
- this.tempState[statePropertyName] = val;
2898
-
2899
- // If some key does not have a value yet, do not update the state yet
2900
- const tempStateIsMissingKey = underscore__WEBPACK_IMPORTED_MODULE_2___default().some(requiredKeysForInit, (key) => underscore__WEBPACK_IMPORTED_MODULE_2___default().isUndefined(this.tempState[key]));
2901
- if (tempStateIsMissingKey) {
2902
- return;
2903
- }
2904
-
2905
- const stateUpdate = { ...this.tempState };
2906
- delete this.tempState;
2907
-
2908
- // Full of hacky workarounds to prevent the race condition described above.
2909
- this.setState((prevState) => {
2910
- const finalState = underscore__WEBPACK_IMPORTED_MODULE_2___default().reduce(
2911
- stateUpdate,
2912
- (result, value, key) => {
2913
- if (key === 'loading') {
2914
- return result;
2915
- }
2916
-
2917
- const initialValue = mapOnyxToState[key].initialValue;
2918
-
2919
- // If initialValue is there and the state contains something different it means
2920
- // an update has already been received and we can discard the value we are trying to hydrate
2921
- if (!underscore__WEBPACK_IMPORTED_MODULE_2___default().isUndefined(initialValue) && !underscore__WEBPACK_IMPORTED_MODULE_2___default().isUndefined(prevState[key]) && prevState[key] !== initialValue) {
2922
- // eslint-disable-next-line no-param-reassign
2923
- result[key] = prevState[key];
2924
-
2925
- // if value is already there (without initial value) then we can discard the value we are trying to hydrate
2926
- } else if (!underscore__WEBPACK_IMPORTED_MODULE_2___default().isUndefined(prevState[key])) {
2927
- // eslint-disable-next-line no-param-reassign
2928
- result[key] = prevState[key];
2929
- } else {
2930
- // eslint-disable-next-line no-param-reassign
2931
- result[key] = value;
2932
- }
2933
- return result;
2934
- },
2935
- {});
2936
-
2937
-
2938
- finalState.loading = false;
2939
- return finalState;
2940
- });
2941
- }
2942
-
2943
- /**
2944
- * Makes sure each Onyx key we requested has been set to state with a value of some kind.
2945
- * We are doing this so that the wrapped component will only render when all the data
2946
- * it needs is available to it.
2947
- */
2948
- checkEvictableKeys() {
2949
- // We will add this key to our list of recently accessed keys
2950
- // if the canEvict function returns true. This is necessary criteria
2951
- // we MUST use to specify if a key can be removed or not.
2952
- underscore__WEBPACK_IMPORTED_MODULE_2___default().each(mapOnyxToState, (mapping) => {
2953
- if (underscore__WEBPACK_IMPORTED_MODULE_2___default().isUndefined(mapping.canEvict)) {
2954
- return;
2955
- }
2956
-
2957
- const canEvict = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.canEvict, this.props);
2958
- const key = _Str__WEBPACK_IMPORTED_MODULE_3__.result(mapping.key, this.props);
2959
-
2960
- if (!_Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].isSafeEvictionKey(key)) {
2961
- 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: []}).`);
2962
- }
2963
-
2964
- if (canEvict) {
2965
- _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].removeFromEvictionBlockList(key, mapping.connectionID);
2966
- } else {
2967
- _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].addToEvictionBlockList(key, mapping.connectionID);
2968
- }
2969
- });
2970
- }
2971
-
2972
- /**
2973
- * Takes a single mapping and binds the state of the component to the store
2974
- *
2975
- * @param {object} mapping
2976
- * @param {string|function} mapping.key key to connect to. can be a string or a
2977
- * function that takes this.props as an argument and returns a string
2978
- * @param {string} statePropertyName the name of the state property that Onyx will add the data to
2979
- * @param {boolean} [mapping.initWithStoredValues] If set to false, then no data will be prefilled into the
2980
- * component
2981
- * @param {string} key to connect to Onyx with
2982
- */
2983
- connectMappingToOnyx(mapping, statePropertyName, key) {
2984
- // Remember what the previous key was so that key changes can be detected when data is being loaded from Onyx. This will allow
2985
- // dependent keys to finish loading their data.
2986
- // eslint-disable-next-line no-param-reassign
2987
- mapOnyxToState[statePropertyName].previousKey = key;
2988
-
2989
- // eslint-disable-next-line rulesdir/prefer-onyx-connect-in-libs
2990
- this.activeConnectionIDs[key] = _Onyx__WEBPACK_IMPORTED_MODULE_4__["default"].connect({
2991
- ...mapping,
2992
- key,
2993
- statePropertyName,
2994
- withOnyxInstance: this,
2995
- displayName
2996
- });
2997
- }
2998
-
2999
- flushPendingSetStates() {
3000
- if (!this.shouldDelayUpdates) {
3001
- return;
3002
- }
3003
-
3004
- this.shouldDelayUpdates = false;
3005
-
3006
- this.pendingSetStates.forEach((modifier) => {
3007
- this.setState(modifier);
3008
- });
3009
- this.pendingSetStates = [];
3010
- }
3011
-
3012
- render() {
3013
- // Remove any null values so that React replaces them with default props
3014
- const propsToPass = underscore__WEBPACK_IMPORTED_MODULE_2___default().omit(this.props, (underscore__WEBPACK_IMPORTED_MODULE_2___default().isNull));
3015
-
3016
- if (this.state.loading) {
3017
- return null;
3018
- }
3019
-
3020
- // Remove any internal state properties used by withOnyx
3021
- // that should not be passed to a wrapped component
3022
- let stateToPass = underscore__WEBPACK_IMPORTED_MODULE_2___default().omit(this.state, 'loading');
3023
- stateToPass = underscore__WEBPACK_IMPORTED_MODULE_2___default().omit(stateToPass, (underscore__WEBPACK_IMPORTED_MODULE_2___default().isNull));
3024
-
3025
- // Spreading props and state is necessary in an HOC where the data cannot be predicted
3026
- return /*#__PURE__*/(
3027
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(WrappedComponent, _extends({
3028
- markReadyForHydration: this.flushPendingSetStates
3029
- // eslint-disable-next-line react/jsx-props-no-spreading
3030
- }, propsToPass,
3031
-
3032
- stateToPass, {
3033
- ref: this.props.forwardedRef })));
3034
-
3035
-
3036
- }
3037
- }
3038
-
3039
- withOnyx.propTypes = {
3040
- forwardedRef: prop_types__WEBPACK_IMPORTED_MODULE_0___default().oneOfType([
3041
- (prop_types__WEBPACK_IMPORTED_MODULE_0___default().func),
3042
- // eslint-disable-next-line react/forbid-prop-types
3043
- prop_types__WEBPACK_IMPORTED_MODULE_0___default().shape({ current: (prop_types__WEBPACK_IMPORTED_MODULE_0___default().object) })])
3044
-
3045
- };
3046
- withOnyx.defaultProps = {
3047
- forwardedRef: undefined
3048
- };
3049
- withOnyx.displayName = `withOnyx(${displayName})`;
3050
- return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().forwardRef((props, ref) => {
3051
- const Component = withOnyx;
3052
- return /*#__PURE__*/(
3053
- react__WEBPACK_IMPORTED_MODULE_1___default().createElement(Component
3054
- // eslint-disable-next-line react/jsx-props-no-spreading
3055
- , _extends({}, props, {
3056
- forwardedRef: ref })));
3057
-
3058
-
3059
- });
3060
- };
3061
- }
3062
-
3063
- /***/ }),
3064
-
3065
- /***/ "./node_modules/object-assign/index.js":
3066
- /*!*********************************************!*\
3067
- !*** ./node_modules/object-assign/index.js ***!
3068
- \*********************************************/
3069
- /***/ ((module) => {
3070
-
3071
- "use strict";
3072
- /*
3073
- object-assign
3074
- (c) Sindre Sorhus
3075
- @license MIT
3076
- */
3077
-
3078
-
3079
- /* eslint-disable no-unused-vars */
3080
- var getOwnPropertySymbols = Object.getOwnPropertySymbols;
3081
- var hasOwnProperty = Object.prototype.hasOwnProperty;
3082
- var propIsEnumerable = Object.prototype.propertyIsEnumerable;
3083
-
3084
- function toObject(val) {
3085
- if (val === null || val === undefined) {
3086
- throw new TypeError('Object.assign cannot be called with null or undefined');
3087
- }
3088
-
3089
- return Object(val);
3090
- }
3091
-
3092
- function shouldUseNative() {
3093
- try {
3094
- if (!Object.assign) {
3095
- return false;
3096
- }
3097
-
3098
- // Detect buggy property enumeration order in older V8 versions.
3099
-
3100
- // https://bugs.chromium.org/p/v8/issues/detail?id=4118
3101
- var test1 = new String('abc'); // eslint-disable-line no-new-wrappers
3102
- test1[5] = 'de';
3103
- if (Object.getOwnPropertyNames(test1)[0] === '5') {
3104
- return false;
3105
- }
3106
-
3107
- // https://bugs.chromium.org/p/v8/issues/detail?id=3056
3108
- var test2 = {};
3109
- for (var i = 0; i < 10; i++) {
3110
- test2['_' + String.fromCharCode(i)] = i;
3111
- }
3112
- var order2 = Object.getOwnPropertyNames(test2).map(function (n) {
3113
- return test2[n];
3114
- });
3115
- if (order2.join('') !== '0123456789') {
3116
- return false;
3117
- }
3118
-
3119
- // https://bugs.chromium.org/p/v8/issues/detail?id=3056
3120
- var test3 = {};
3121
- 'abcdefghijklmnopqrst'.split('').forEach(function (letter) {
3122
- test3[letter] = letter;
3123
- });
3124
- if (Object.keys(Object.assign({}, test3)).join('') !==
3125
- 'abcdefghijklmnopqrst') {
3126
- return false;
3127
- }
3128
-
3129
- return true;
3130
- } catch (err) {
3131
- // We don't expect any of the above to throw, but better to be safe.
3132
- return false;
3133
- }
3134
- }
3135
-
3136
- module.exports = shouldUseNative() ? Object.assign : function (target, source) {
3137
- var from;
3138
- var to = toObject(target);
3139
- var symbols;
3140
-
3141
- for (var s = 1; s < arguments.length; s++) {
3142
- from = Object(arguments[s]);
3143
-
3144
- for (var key in from) {
3145
- if (hasOwnProperty.call(from, key)) {
3146
- to[key] = from[key];
3147
- }
3148
- }
3149
-
3150
- if (getOwnPropertySymbols) {
3151
- symbols = getOwnPropertySymbols(from);
3152
- for (var i = 0; i < symbols.length; i++) {
3153
- if (propIsEnumerable.call(from, symbols[i])) {
3154
- to[symbols[i]] = from[symbols[i]];
3155
- }
3156
- }
3157
- }
3158
- }
3159
-
3160
- return to;
3161
- };
3162
-
3163
-
3164
- /***/ }),
3165
-
3166
- /***/ "./node_modules/prop-types/checkPropTypes.js":
3167
- /*!***************************************************!*\
3168
- !*** ./node_modules/prop-types/checkPropTypes.js ***!
3169
- \***************************************************/
3170
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
3171
-
3172
- "use strict";
3173
- /**
3174
- * Copyright (c) 2013-present, Facebook, Inc.
3175
- *
3176
- * This source code is licensed under the MIT license found in the
3177
- * LICENSE file in the root directory of this source tree.
3178
- */
3179
-
3180
-
3181
-
3182
- var printWarning = function() {};
3183
-
3184
- if (true) {
3185
- var ReactPropTypesSecret = __webpack_require__(/*! ./lib/ReactPropTypesSecret */ "./node_modules/prop-types/lib/ReactPropTypesSecret.js");
3186
- var loggedTypeFailures = {};
3187
- var has = Function.call.bind(Object.prototype.hasOwnProperty);
3188
-
3189
- printWarning = function(text) {
3190
- var message = 'Warning: ' + text;
3191
- if (typeof console !== 'undefined') {
3192
- console.error(message);
3193
- }
3194
- try {
3195
- // --- Welcome to debugging React ---
3196
- // This error was thrown as a convenience so that you can use this stack
3197
- // to find the callsite that caused this warning to fire.
3198
- throw new Error(message);
3199
- } catch (x) {}
3200
- };
3201
- }
3202
-
3203
- /**
3204
- * Assert that the values match with the type specs.
3205
- * Error messages are memorized and will only be shown once.
3206
- *
3207
- * @param {object} typeSpecs Map of name to a ReactPropType
3208
- * @param {object} values Runtime values that need to be type-checked
3209
- * @param {string} location e.g. "prop", "context", "child context"
3210
- * @param {string} componentName Name of the component for error messages.
3211
- * @param {?Function} getStack Returns the component stack.
3212
- * @private
3213
- */
3214
- function checkPropTypes(typeSpecs, values, location, componentName, getStack) {
3215
- if (true) {
3216
- for (var typeSpecName in typeSpecs) {
3217
- if (has(typeSpecs, typeSpecName)) {
3218
- var error;
3219
- // Prop type validation may throw. In case they do, we don't want to
3220
- // fail the render phase where it didn't fail before. So we log it.
3221
- // After these have been cleaned up, we'll let them throw.
3222
- try {
3223
- // This is intentionally an invariant that gets caught. It's the same
3224
- // behavior as without this statement except with a better message.
3225
- if (typeof typeSpecs[typeSpecName] !== 'function') {
3226
- var err = Error(
3227
- (componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' +
3228
- 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.'
3229
- );
3230
- err.name = 'Invariant Violation';
3231
- throw err;
3232
- }
3233
- error = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, ReactPropTypesSecret);
3234
- } catch (ex) {
3235
- error = ex;
3236
- }
3237
- if (error && !(error instanceof Error)) {
3238
- printWarning(
3239
- (componentName || 'React class') + ': type specification of ' +
3240
- location + ' `' + typeSpecName + '` is invalid; the type checker ' +
3241
- 'function must return `null` or an `Error` but returned a ' + typeof error + '. ' +
3242
- 'You may have forgotten to pass an argument to the type checker ' +
3243
- 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' +
3244
- 'shape all require an argument).'
3245
- );
3246
- }
3247
- if (error instanceof Error && !(error.message in loggedTypeFailures)) {
3248
- // Only monitor this failure once because there tends to be a lot of the
3249
- // same error.
3250
- loggedTypeFailures[error.message] = true;
3251
-
3252
- var stack = getStack ? getStack() : '';
3253
-
3254
- printWarning(
3255
- 'Failed ' + location + ' type: ' + error.message + (stack != null ? stack : '')
3256
- );
3257
- }
3258
- }
3259
- }
3260
- }
3261
- }
3262
-
3263
- /**
3264
- * Resets warning cache when testing.
3265
- *
3266
- * @private
3267
- */
3268
- checkPropTypes.resetWarningCache = function() {
3269
- if (true) {
3270
- loggedTypeFailures = {};
3271
- }
3272
- }
3273
-
3274
- module.exports = checkPropTypes;
3275
-
3276
-
3277
- /***/ }),
3278
-
3279
- /***/ "./node_modules/prop-types/factoryWithTypeCheckers.js":
3280
- /*!************************************************************!*\
3281
- !*** ./node_modules/prop-types/factoryWithTypeCheckers.js ***!
3282
- \************************************************************/
3283
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
3284
-
3285
- "use strict";
3286
- /**
3287
- * Copyright (c) 2013-present, Facebook, Inc.
3288
- *
3289
- * This source code is licensed under the MIT license found in the
3290
- * LICENSE file in the root directory of this source tree.
3291
- */
3292
-
3293
-
3294
-
3295
- var ReactIs = __webpack_require__(/*! react-is */ "./node_modules/react-is/index.js");
3296
- var assign = __webpack_require__(/*! object-assign */ "./node_modules/object-assign/index.js");
3297
-
3298
- var ReactPropTypesSecret = __webpack_require__(/*! ./lib/ReactPropTypesSecret */ "./node_modules/prop-types/lib/ReactPropTypesSecret.js");
3299
- var checkPropTypes = __webpack_require__(/*! ./checkPropTypes */ "./node_modules/prop-types/checkPropTypes.js");
3300
-
3301
- var has = Function.call.bind(Object.prototype.hasOwnProperty);
3302
- var printWarning = function() {};
3303
-
3304
- if (true) {
3305
- printWarning = function(text) {
3306
- var message = 'Warning: ' + text;
3307
- if (typeof console !== 'undefined') {
3308
- console.error(message);
3309
- }
3310
- try {
3311
- // --- Welcome to debugging React ---
3312
- // This error was thrown as a convenience so that you can use this stack
3313
- // to find the callsite that caused this warning to fire.
3314
- throw new Error(message);
3315
- } catch (x) {}
3316
- };
3317
- }
3318
-
3319
- function emptyFunctionThatReturnsNull() {
3320
- return null;
3321
- }
3322
-
3323
- module.exports = function(isValidElement, throwOnDirectAccess) {
3324
- /* global Symbol */
3325
- var ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;
3326
- var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
3327
-
3328
- /**
3329
- * Returns the iterator method function contained on the iterable object.
3330
- *
3331
- * Be sure to invoke the function with the iterable as context:
3332
- *
3333
- * var iteratorFn = getIteratorFn(myIterable);
3334
- * if (iteratorFn) {
3335
- * var iterator = iteratorFn.call(myIterable);
3336
- * ...
3337
- * }
3338
- *
3339
- * @param {?object} maybeIterable
3340
- * @return {?function}
3341
- */
3342
- function getIteratorFn(maybeIterable) {
3343
- var iteratorFn = maybeIterable && (ITERATOR_SYMBOL && maybeIterable[ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]);
3344
- if (typeof iteratorFn === 'function') {
3345
- return iteratorFn;
3346
- }
3347
- }
3348
-
3349
- /**
3350
- * Collection of methods that allow declaration and validation of props that are
3351
- * supplied to React components. Example usage:
3352
- *
3353
- * var Props = require('ReactPropTypes');
3354
- * var MyArticle = React.createClass({
3355
- * propTypes: {
3356
- * // An optional string prop named "description".
3357
- * description: Props.string,
3358
- *
3359
- * // A required enum prop named "category".
3360
- * category: Props.oneOf(['News','Photos']).isRequired,
3361
- *
3362
- * // A prop named "dialog" that requires an instance of Dialog.
3363
- * dialog: Props.instanceOf(Dialog).isRequired
3364
- * },
3365
- * render: function() { ... }
3366
- * });
3367
- *
3368
- * A more formal specification of how these methods are used:
3369
- *
3370
- * type := array|bool|func|object|number|string|oneOf([...])|instanceOf(...)
3371
- * decl := ReactPropTypes.{type}(.isRequired)?
3372
- *
3373
- * Each and every declaration produces a function with the same signature. This
3374
- * allows the creation of custom validation functions. For example:
3375
- *
3376
- * var MyLink = React.createClass({
3377
- * propTypes: {
3378
- * // An optional string or URI prop named "href".
3379
- * href: function(props, propName, componentName) {
3380
- * var propValue = props[propName];
3381
- * if (propValue != null && typeof propValue !== 'string' &&
3382
- * !(propValue instanceof URI)) {
3383
- * return new Error(
3384
- * 'Expected a string or an URI for ' + propName + ' in ' +
3385
- * componentName
3386
- * );
3387
- * }
3388
- * }
3389
- * },
3390
- * render: function() {...}
3391
- * });
3392
- *
3393
- * @internal
3394
- */
3395
-
3396
- var ANONYMOUS = '<<anonymous>>';
3397
-
3398
- // Important!
3399
- // Keep this list in sync with production version in `./factoryWithThrowingShims.js`.
3400
- var ReactPropTypes = {
3401
- array: createPrimitiveTypeChecker('array'),
3402
- bool: createPrimitiveTypeChecker('boolean'),
3403
- func: createPrimitiveTypeChecker('function'),
3404
- number: createPrimitiveTypeChecker('number'),
3405
- object: createPrimitiveTypeChecker('object'),
3406
- string: createPrimitiveTypeChecker('string'),
3407
- symbol: createPrimitiveTypeChecker('symbol'),
3408
-
3409
- any: createAnyTypeChecker(),
3410
- arrayOf: createArrayOfTypeChecker,
3411
- element: createElementTypeChecker(),
3412
- elementType: createElementTypeTypeChecker(),
3413
- instanceOf: createInstanceTypeChecker,
3414
- node: createNodeChecker(),
3415
- objectOf: createObjectOfTypeChecker,
3416
- oneOf: createEnumTypeChecker,
3417
- oneOfType: createUnionTypeChecker,
3418
- shape: createShapeTypeChecker,
3419
- exact: createStrictShapeTypeChecker,
3420
- };
3421
-
3422
- /**
3423
- * inlined Object.is polyfill to avoid requiring consumers ship their own
3424
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
3425
- */
3426
- /*eslint-disable no-self-compare*/
3427
- function is(x, y) {
3428
- // SameValue algorithm
3429
- if (x === y) {
3430
- // Steps 1-5, 7-10
3431
- // Steps 6.b-6.e: +0 != -0
3432
- return x !== 0 || 1 / x === 1 / y;
3433
- } else {
3434
- // Step 6.a: NaN == NaN
3435
- return x !== x && y !== y;
3436
- }
3437
- }
3438
- /*eslint-enable no-self-compare*/
3439
-
3440
- /**
3441
- * We use an Error-like object for backward compatibility as people may call
3442
- * PropTypes directly and inspect their output. However, we don't use real
3443
- * Errors anymore. We don't inspect their stack anyway, and creating them
3444
- * is prohibitively expensive if they are created too often, such as what
3445
- * happens in oneOfType() for any type before the one that matched.
3446
- */
3447
- function PropTypeError(message) {
3448
- this.message = message;
3449
- this.stack = '';
3450
- }
3451
- // Make `instanceof Error` still work for returned errors.
3452
- PropTypeError.prototype = Error.prototype;
3453
-
3454
- function createChainableTypeChecker(validate) {
3455
- if (true) {
3456
- var manualPropTypeCallCache = {};
3457
- var manualPropTypeWarningCount = 0;
3458
- }
3459
- function checkType(isRequired, props, propName, componentName, location, propFullName, secret) {
3460
- componentName = componentName || ANONYMOUS;
3461
- propFullName = propFullName || propName;
3462
-
3463
- if (secret !== ReactPropTypesSecret) {
3464
- if (throwOnDirectAccess) {
3465
- // New behavior only for users of `prop-types` package
3466
- var err = new Error(
3467
- 'Calling PropTypes validators directly is not supported by the `prop-types` package. ' +
3468
- 'Use `PropTypes.checkPropTypes()` to call them. ' +
3469
- 'Read more at http://fb.me/use-check-prop-types'
3470
- );
3471
- err.name = 'Invariant Violation';
3472
- throw err;
3473
- } else if ( true && typeof console !== 'undefined') {
3474
- // Old behavior for people using React.PropTypes
3475
- var cacheKey = componentName + ':' + propName;
3476
- if (
3477
- !manualPropTypeCallCache[cacheKey] &&
3478
- // Avoid spamming the console because they are often not actionable except for lib authors
3479
- manualPropTypeWarningCount < 3
3480
- ) {
3481
- printWarning(
3482
- 'You are manually calling a React.PropTypes validation ' +
3483
- 'function for the `' + propFullName + '` prop on `' + componentName + '`. This is deprecated ' +
3484
- 'and will throw in the standalone `prop-types` package. ' +
3485
- 'You may be seeing this warning due to a third-party PropTypes ' +
3486
- 'library. See https://fb.me/react-warning-dont-call-proptypes ' + 'for details.'
3487
- );
3488
- manualPropTypeCallCache[cacheKey] = true;
3489
- manualPropTypeWarningCount++;
3490
- }
3491
- }
3492
- }
3493
- if (props[propName] == null) {
3494
- if (isRequired) {
3495
- if (props[propName] === null) {
3496
- return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
3497
- }
3498
- return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
3499
- }
3500
- return null;
3501
- } else {
3502
- return validate(props, propName, componentName, location, propFullName);
3503
- }
3504
- }
3505
-
3506
- var chainedCheckType = checkType.bind(null, false);
3507
- chainedCheckType.isRequired = checkType.bind(null, true);
3508
-
3509
- return chainedCheckType;
3510
- }
3511
-
3512
- function createPrimitiveTypeChecker(expectedType) {
3513
- function validate(props, propName, componentName, location, propFullName, secret) {
3514
- var propValue = props[propName];
3515
- var propType = getPropType(propValue);
3516
- if (propType !== expectedType) {
3517
- // `propValue` being instance of, say, date/regexp, pass the 'object'
3518
- // check, but we can offer a more precise error message here rather than
3519
- // 'of type `object`'.
3520
- var preciseType = getPreciseType(propValue);
3521
-
3522
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + preciseType + '` supplied to `' + componentName + '`, expected ') + ('`' + expectedType + '`.'));
3523
- }
3524
- return null;
3525
- }
3526
- return createChainableTypeChecker(validate);
3527
- }
3528
-
3529
- function createAnyTypeChecker() {
3530
- return createChainableTypeChecker(emptyFunctionThatReturnsNull);
3531
- }
3532
-
3533
- function createArrayOfTypeChecker(typeChecker) {
3534
- function validate(props, propName, componentName, location, propFullName) {
3535
- if (typeof typeChecker !== 'function') {
3536
- return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside arrayOf.');
3537
- }
3538
- var propValue = props[propName];
3539
- if (!Array.isArray(propValue)) {
3540
- var propType = getPropType(propValue);
3541
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an array.'));
3542
- }
3543
- for (var i = 0; i < propValue.length; i++) {
3544
- var error = typeChecker(propValue, i, componentName, location, propFullName + '[' + i + ']', ReactPropTypesSecret);
3545
- if (error instanceof Error) {
3546
- return error;
3547
- }
3548
- }
3549
- return null;
3550
- }
3551
- return createChainableTypeChecker(validate);
3552
- }
3553
-
3554
- function createElementTypeChecker() {
3555
- function validate(props, propName, componentName, location, propFullName) {
3556
- var propValue = props[propName];
3557
- if (!isValidElement(propValue)) {
3558
- var propType = getPropType(propValue);
3559
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement.'));
3560
- }
3561
- return null;
3562
- }
3563
- return createChainableTypeChecker(validate);
3564
- }
3565
-
3566
- function createElementTypeTypeChecker() {
3567
- function validate(props, propName, componentName, location, propFullName) {
3568
- var propValue = props[propName];
3569
- if (!ReactIs.isValidElementType(propValue)) {
3570
- var propType = getPropType(propValue);
3571
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected a single ReactElement type.'));
3572
- }
3573
- return null;
3574
- }
3575
- return createChainableTypeChecker(validate);
3576
- }
3577
-
3578
- function createInstanceTypeChecker(expectedClass) {
3579
- function validate(props, propName, componentName, location, propFullName) {
3580
- if (!(props[propName] instanceof expectedClass)) {
3581
- var expectedClassName = expectedClass.name || ANONYMOUS;
3582
- var actualClassName = getClassName(props[propName]);
3583
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + actualClassName + '` supplied to `' + componentName + '`, expected ') + ('instance of `' + expectedClassName + '`.'));
3584
- }
3585
- return null;
3586
- }
3587
- return createChainableTypeChecker(validate);
3588
- }
3589
-
3590
- function createEnumTypeChecker(expectedValues) {
3591
- if (!Array.isArray(expectedValues)) {
3592
- if (true) {
3593
- if (arguments.length > 1) {
3594
- printWarning(
3595
- 'Invalid arguments supplied to oneOf, expected an array, got ' + arguments.length + ' arguments. ' +
3596
- 'A common mistake is to write oneOf(x, y, z) instead of oneOf([x, y, z]).'
3597
- );
3598
- } else {
3599
- printWarning('Invalid argument supplied to oneOf, expected an array.');
3600
- }
3601
- }
3602
- return emptyFunctionThatReturnsNull;
3603
- }
3604
-
3605
- function validate(props, propName, componentName, location, propFullName) {
3606
- var propValue = props[propName];
3607
- for (var i = 0; i < expectedValues.length; i++) {
3608
- if (is(propValue, expectedValues[i])) {
3609
- return null;
3610
- }
3611
- }
3612
-
3613
- var valuesString = JSON.stringify(expectedValues, function replacer(key, value) {
3614
- var type = getPreciseType(value);
3615
- if (type === 'symbol') {
3616
- return String(value);
3617
- }
3618
- return value;
3619
- });
3620
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of value `' + String(propValue) + '` ' + ('supplied to `' + componentName + '`, expected one of ' + valuesString + '.'));
3621
- }
3622
- return createChainableTypeChecker(validate);
3623
- }
3624
-
3625
- function createObjectOfTypeChecker(typeChecker) {
3626
- function validate(props, propName, componentName, location, propFullName) {
3627
- if (typeof typeChecker !== 'function') {
3628
- return new PropTypeError('Property `' + propFullName + '` of component `' + componentName + '` has invalid PropType notation inside objectOf.');
3629
- }
3630
- var propValue = props[propName];
3631
- var propType = getPropType(propValue);
3632
- if (propType !== 'object') {
3633
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type ' + ('`' + propType + '` supplied to `' + componentName + '`, expected an object.'));
3634
- }
3635
- for (var key in propValue) {
3636
- if (has(propValue, key)) {
3637
- var error = typeChecker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
3638
- if (error instanceof Error) {
3639
- return error;
3640
- }
3641
- }
3642
- }
3643
- return null;
3644
- }
3645
- return createChainableTypeChecker(validate);
3646
- }
3647
-
3648
- function createUnionTypeChecker(arrayOfTypeCheckers) {
3649
- if (!Array.isArray(arrayOfTypeCheckers)) {
3650
- true ? printWarning('Invalid argument supplied to oneOfType, expected an instance of array.') : 0;
3651
- return emptyFunctionThatReturnsNull;
3652
- }
3653
-
3654
- for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
3655
- var checker = arrayOfTypeCheckers[i];
3656
- if (typeof checker !== 'function') {
3657
- printWarning(
3658
- 'Invalid argument supplied to oneOfType. Expected an array of check functions, but ' +
3659
- 'received ' + getPostfixForTypeWarning(checker) + ' at index ' + i + '.'
3660
- );
3661
- return emptyFunctionThatReturnsNull;
3662
- }
3663
- }
3664
-
3665
- function validate(props, propName, componentName, location, propFullName) {
3666
- for (var i = 0; i < arrayOfTypeCheckers.length; i++) {
3667
- var checker = arrayOfTypeCheckers[i];
3668
- if (checker(props, propName, componentName, location, propFullName, ReactPropTypesSecret) == null) {
3669
- return null;
3670
- }
3671
- }
3672
-
3673
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`.'));
3674
- }
3675
- return createChainableTypeChecker(validate);
3676
- }
3677
-
3678
- function createNodeChecker() {
3679
- function validate(props, propName, componentName, location, propFullName) {
3680
- if (!isNode(props[propName])) {
3681
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` supplied to ' + ('`' + componentName + '`, expected a ReactNode.'));
3682
- }
3683
- return null;
3684
- }
3685
- return createChainableTypeChecker(validate);
3686
- }
3687
-
3688
- function createShapeTypeChecker(shapeTypes) {
3689
- function validate(props, propName, componentName, location, propFullName) {
3690
- var propValue = props[propName];
3691
- var propType = getPropType(propValue);
3692
- if (propType !== 'object') {
3693
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
3694
- }
3695
- for (var key in shapeTypes) {
3696
- var checker = shapeTypes[key];
3697
- if (!checker) {
3698
- continue;
3699
- }
3700
- var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
3701
- if (error) {
3702
- return error;
3703
- }
3704
- }
3705
- return null;
3706
- }
3707
- return createChainableTypeChecker(validate);
3708
- }
3709
-
3710
- function createStrictShapeTypeChecker(shapeTypes) {
3711
- function validate(props, propName, componentName, location, propFullName) {
3712
- var propValue = props[propName];
3713
- var propType = getPropType(propValue);
3714
- if (propType !== 'object') {
3715
- return new PropTypeError('Invalid ' + location + ' `' + propFullName + '` of type `' + propType + '` ' + ('supplied to `' + componentName + '`, expected `object`.'));
3716
- }
3717
- // We need to check all keys in case some are required but missing from
3718
- // props.
3719
- var allKeys = assign({}, props[propName], shapeTypes);
3720
- for (var key in allKeys) {
3721
- var checker = shapeTypes[key];
3722
- if (!checker) {
3723
- return new PropTypeError(
3724
- 'Invalid ' + location + ' `' + propFullName + '` key `' + key + '` supplied to `' + componentName + '`.' +
3725
- '\nBad object: ' + JSON.stringify(props[propName], null, ' ') +
3726
- '\nValid keys: ' + JSON.stringify(Object.keys(shapeTypes), null, ' ')
3727
- );
3728
- }
3729
- var error = checker(propValue, key, componentName, location, propFullName + '.' + key, ReactPropTypesSecret);
3730
- if (error) {
3731
- return error;
3732
- }
3733
- }
3734
- return null;
3735
- }
3736
-
3737
- return createChainableTypeChecker(validate);
3738
- }
3739
-
3740
- function isNode(propValue) {
3741
- switch (typeof propValue) {
3742
- case 'number':
3743
- case 'string':
3744
- case 'undefined':
3745
- return true;
3746
- case 'boolean':
3747
- return !propValue;
3748
- case 'object':
3749
- if (Array.isArray(propValue)) {
3750
- return propValue.every(isNode);
3751
- }
3752
- if (propValue === null || isValidElement(propValue)) {
3753
- return true;
3754
- }
3755
-
3756
- var iteratorFn = getIteratorFn(propValue);
3757
- if (iteratorFn) {
3758
- var iterator = iteratorFn.call(propValue);
3759
- var step;
3760
- if (iteratorFn !== propValue.entries) {
3761
- while (!(step = iterator.next()).done) {
3762
- if (!isNode(step.value)) {
3763
- return false;
3764
- }
3765
- }
3766
- } else {
3767
- // Iterator will provide entry [k,v] tuples rather than values.
3768
- while (!(step = iterator.next()).done) {
3769
- var entry = step.value;
3770
- if (entry) {
3771
- if (!isNode(entry[1])) {
3772
- return false;
3773
- }
3774
- }
3775
- }
3776
- }
3777
- } else {
3778
- return false;
3779
- }
3780
-
3781
- return true;
3782
- default:
3783
- return false;
3784
- }
3785
- }
3786
-
3787
- function isSymbol(propType, propValue) {
3788
- // Native Symbol.
3789
- if (propType === 'symbol') {
3790
- return true;
3791
- }
3792
-
3793
- // falsy value can't be a Symbol
3794
- if (!propValue) {
3795
- return false;
3796
- }
3797
-
3798
- // 19.4.3.5 Symbol.prototype[@@toStringTag] === 'Symbol'
3799
- if (propValue['@@toStringTag'] === 'Symbol') {
3800
- return true;
3801
- }
3802
-
3803
- // Fallback for non-spec compliant Symbols which are polyfilled.
3804
- if (typeof Symbol === 'function' && propValue instanceof Symbol) {
3805
- return true;
3806
- }
3807
-
3808
- return false;
3809
- }
3810
-
3811
- // Equivalent of `typeof` but with special handling for array and regexp.
3812
- function getPropType(propValue) {
3813
- var propType = typeof propValue;
3814
- if (Array.isArray(propValue)) {
3815
- return 'array';
3816
- }
3817
- if (propValue instanceof RegExp) {
3818
- // Old webkits (at least until Android 4.0) return 'function' rather than
3819
- // 'object' for typeof a RegExp. We'll normalize this here so that /bla/
3820
- // passes PropTypes.object.
3821
- return 'object';
3822
- }
3823
- if (isSymbol(propType, propValue)) {
3824
- return 'symbol';
3825
- }
3826
- return propType;
3827
- }
3828
-
3829
- // This handles more types than `getPropType`. Only used for error messages.
3830
- // See `createPrimitiveTypeChecker`.
3831
- function getPreciseType(propValue) {
3832
- if (typeof propValue === 'undefined' || propValue === null) {
3833
- return '' + propValue;
3834
- }
3835
- var propType = getPropType(propValue);
3836
- if (propType === 'object') {
3837
- if (propValue instanceof Date) {
3838
- return 'date';
3839
- } else if (propValue instanceof RegExp) {
3840
- return 'regexp';
3841
- }
3842
- }
3843
- return propType;
3844
- }
3845
-
3846
- // Returns a string that is postfixed to a warning about an invalid type.
3847
- // For example, "undefined" or "of type array"
3848
- function getPostfixForTypeWarning(value) {
3849
- var type = getPreciseType(value);
3850
- switch (type) {
3851
- case 'array':
3852
- case 'object':
3853
- return 'an ' + type;
3854
- case 'boolean':
3855
- case 'date':
3856
- case 'regexp':
3857
- return 'a ' + type;
3858
- default:
3859
- return type;
3860
- }
3861
- }
3862
-
3863
- // Returns class name of the object, if any.
3864
- function getClassName(propValue) {
3865
- if (!propValue.constructor || !propValue.constructor.name) {
3866
- return ANONYMOUS;
3867
- }
3868
- return propValue.constructor.name;
3869
- }
3870
-
3871
- ReactPropTypes.checkPropTypes = checkPropTypes;
3872
- ReactPropTypes.resetWarningCache = checkPropTypes.resetWarningCache;
3873
- ReactPropTypes.PropTypes = ReactPropTypes;
3874
-
3875
- return ReactPropTypes;
3876
- };
3877
-
3878
-
3879
- /***/ }),
3880
-
3881
- /***/ "./node_modules/prop-types/index.js":
3882
- /*!******************************************!*\
3883
- !*** ./node_modules/prop-types/index.js ***!
3884
- \******************************************/
3885
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
3886
-
3887
- /**
3888
- * Copyright (c) 2013-present, Facebook, Inc.
3889
- *
3890
- * This source code is licensed under the MIT license found in the
3891
- * LICENSE file in the root directory of this source tree.
3892
- */
3893
-
3894
- if (true) {
3895
- var ReactIs = __webpack_require__(/*! react-is */ "./node_modules/react-is/index.js");
3896
-
3897
- // By explicitly using `prop-types` you are opting into new development behavior.
3898
- // http://fb.me/prop-types-in-prod
3899
- var throwOnDirectAccess = true;
3900
- module.exports = __webpack_require__(/*! ./factoryWithTypeCheckers */ "./node_modules/prop-types/factoryWithTypeCheckers.js")(ReactIs.isElement, throwOnDirectAccess);
3901
- } else {}
3902
-
3903
-
3904
- /***/ }),
3905
-
3906
- /***/ "./node_modules/prop-types/lib/ReactPropTypesSecret.js":
3907
- /*!*************************************************************!*\
3908
- !*** ./node_modules/prop-types/lib/ReactPropTypesSecret.js ***!
3909
- \*************************************************************/
3910
- /***/ ((module) => {
3911
-
3912
- "use strict";
3913
- /**
3914
- * Copyright (c) 2013-present, Facebook, Inc.
3915
- *
3916
- * This source code is licensed under the MIT license found in the
3917
- * LICENSE file in the root directory of this source tree.
3918
- */
3919
-
3920
-
3921
-
3922
- var ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
3923
-
3924
- module.exports = ReactPropTypesSecret;
3925
-
3926
-
3927
- /***/ }),
3928
-
3929
- /***/ "./node_modules/react-is/cjs/react-is.development.js":
3930
- /*!***********************************************************!*\
3931
- !*** ./node_modules/react-is/cjs/react-is.development.js ***!
3932
- \***********************************************************/
3933
- /***/ ((__unused_webpack_module, exports) => {
3934
-
3935
- "use strict";
3936
- /** @license React v16.13.1
3937
- * react-is.development.js
3938
- *
3939
- * Copyright (c) Facebook, Inc. and its affiliates.
3940
- *
3941
- * This source code is licensed under the MIT license found in the
3942
- * LICENSE file in the root directory of this source tree.
3943
- */
3944
-
3945
-
3946
-
3947
-
3948
-
3949
- if (true) {
3950
- (function() {
3951
- 'use strict';
3952
-
3953
- // The Symbol used to tag the ReactElement-like types. If there is no native Symbol
3954
- // nor polyfill, then a plain number is used for performance.
3955
- var hasSymbol = typeof Symbol === 'function' && Symbol.for;
3956
- var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for('react.element') : 0xeac7;
3957
- var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
3958
- var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
3959
- var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;
3960
- var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for('react.profiler') : 0xead2;
3961
- var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
3962
- var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for('react.context') : 0xeace; // TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary
3963
- // (unstable) APIs that have been removed. Can we remove the symbols?
3964
-
3965
- var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
3966
- var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for('react.concurrent_mode') : 0xeacf;
3967
- var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
3968
- var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for('react.suspense') : 0xead1;
3969
- var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for('react.suspense_list') : 0xead8;
3970
- var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3;
3971
- var REACT_LAZY_TYPE = hasSymbol ? Symbol.for('react.lazy') : 0xead4;
3972
- var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for('react.block') : 0xead9;
3973
- var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for('react.fundamental') : 0xead5;
3974
- var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for('react.responder') : 0xead6;
3975
- var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for('react.scope') : 0xead7;
3976
-
3977
- function isValidElementType(type) {
3978
- return typeof type === 'string' || typeof type === 'function' || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill.
3979
- type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === 'object' && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE);
3980
- }
3981
-
3982
- function typeOf(object) {
3983
- if (typeof object === 'object' && object !== null) {
3984
- var $$typeof = object.$$typeof;
3985
-
3986
- switch ($$typeof) {
3987
- case REACT_ELEMENT_TYPE:
3988
- var type = object.type;
3989
-
3990
- switch (type) {
3991
- case REACT_ASYNC_MODE_TYPE:
3992
- case REACT_CONCURRENT_MODE_TYPE:
3993
- case REACT_FRAGMENT_TYPE:
3994
- case REACT_PROFILER_TYPE:
3995
- case REACT_STRICT_MODE_TYPE:
3996
- case REACT_SUSPENSE_TYPE:
3997
- return type;
3998
-
3999
- default:
4000
- var $$typeofType = type && type.$$typeof;
4001
-
4002
- switch ($$typeofType) {
4003
- case REACT_CONTEXT_TYPE:
4004
- case REACT_FORWARD_REF_TYPE:
4005
- case REACT_LAZY_TYPE:
4006
- case REACT_MEMO_TYPE:
4007
- case REACT_PROVIDER_TYPE:
4008
- return $$typeofType;
4009
-
4010
- default:
4011
- return $$typeof;
4012
- }
4013
-
4014
- }
4015
-
4016
- case REACT_PORTAL_TYPE:
4017
- return $$typeof;
4018
- }
4019
- }
4020
-
4021
- return undefined;
4022
- } // AsyncMode is deprecated along with isAsyncMode
4023
-
4024
- var AsyncMode = REACT_ASYNC_MODE_TYPE;
4025
- var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE;
4026
- var ContextConsumer = REACT_CONTEXT_TYPE;
4027
- var ContextProvider = REACT_PROVIDER_TYPE;
4028
- var Element = REACT_ELEMENT_TYPE;
4029
- var ForwardRef = REACT_FORWARD_REF_TYPE;
4030
- var Fragment = REACT_FRAGMENT_TYPE;
4031
- var Lazy = REACT_LAZY_TYPE;
4032
- var Memo = REACT_MEMO_TYPE;
4033
- var Portal = REACT_PORTAL_TYPE;
4034
- var Profiler = REACT_PROFILER_TYPE;
4035
- var StrictMode = REACT_STRICT_MODE_TYPE;
4036
- var Suspense = REACT_SUSPENSE_TYPE;
4037
- var hasWarnedAboutDeprecatedIsAsyncMode = false; // AsyncMode should be deprecated
4038
-
4039
- function isAsyncMode(object) {
4040
- {
4041
- if (!hasWarnedAboutDeprecatedIsAsyncMode) {
4042
- hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
4043
-
4044
- console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 17+. Update your code to use ' + 'ReactIs.isConcurrentMode() instead. It has the exact same API.');
4045
- }
4046
- }
4047
-
4048
- return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE;
4049
- }
4050
- function isConcurrentMode(object) {
4051
- return typeOf(object) === REACT_CONCURRENT_MODE_TYPE;
4052
- }
4053
- function isContextConsumer(object) {
4054
- return typeOf(object) === REACT_CONTEXT_TYPE;
4055
- }
4056
- function isContextProvider(object) {
4057
- return typeOf(object) === REACT_PROVIDER_TYPE;
4058
- }
4059
- function isElement(object) {
4060
- return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
4061
- }
4062
- function isForwardRef(object) {
4063
- return typeOf(object) === REACT_FORWARD_REF_TYPE;
4064
- }
4065
- function isFragment(object) {
4066
- return typeOf(object) === REACT_FRAGMENT_TYPE;
4067
- }
4068
- function isLazy(object) {
4069
- return typeOf(object) === REACT_LAZY_TYPE;
4070
- }
4071
- function isMemo(object) {
4072
- return typeOf(object) === REACT_MEMO_TYPE;
4073
- }
4074
- function isPortal(object) {
4075
- return typeOf(object) === REACT_PORTAL_TYPE;
4076
- }
4077
- function isProfiler(object) {
4078
- return typeOf(object) === REACT_PROFILER_TYPE;
4079
- }
4080
- function isStrictMode(object) {
4081
- return typeOf(object) === REACT_STRICT_MODE_TYPE;
4082
- }
4083
- function isSuspense(object) {
4084
- return typeOf(object) === REACT_SUSPENSE_TYPE;
4085
- }
4086
-
4087
- exports.AsyncMode = AsyncMode;
4088
- exports.ConcurrentMode = ConcurrentMode;
4089
- exports.ContextConsumer = ContextConsumer;
4090
- exports.ContextProvider = ContextProvider;
4091
- exports.Element = Element;
4092
- exports.ForwardRef = ForwardRef;
4093
- exports.Fragment = Fragment;
4094
- exports.Lazy = Lazy;
4095
- exports.Memo = Memo;
4096
- exports.Portal = Portal;
4097
- exports.Profiler = Profiler;
4098
- exports.StrictMode = StrictMode;
4099
- exports.Suspense = Suspense;
4100
- exports.isAsyncMode = isAsyncMode;
4101
- exports.isConcurrentMode = isConcurrentMode;
4102
- exports.isContextConsumer = isContextConsumer;
4103
- exports.isContextProvider = isContextProvider;
4104
- exports.isElement = isElement;
4105
- exports.isForwardRef = isForwardRef;
4106
- exports.isFragment = isFragment;
4107
- exports.isLazy = isLazy;
4108
- exports.isMemo = isMemo;
4109
- exports.isPortal = isPortal;
4110
- exports.isProfiler = isProfiler;
4111
- exports.isStrictMode = isStrictMode;
4112
- exports.isSuspense = isSuspense;
4113
- exports.isValidElementType = isValidElementType;
4114
- exports.typeOf = typeOf;
4115
- })();
4116
- }
4117
-
4118
-
4119
- /***/ }),
4120
-
4121
- /***/ "./node_modules/react-is/index.js":
4122
- /*!****************************************!*\
4123
- !*** ./node_modules/react-is/index.js ***!
4124
- \****************************************/
4125
- /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
4126
-
4127
- "use strict";
4128
-
4129
-
4130
- if (false) {} else {
4131
- module.exports = __webpack_require__(/*! ./cjs/react-is.development.js */ "./node_modules/react-is/cjs/react-is.development.js");
4132
- }
4133
-
4134
-
4135
- /***/ }),
4136
-
4137
- /***/ "fast-equals":
4138
- /*!******************************!*\
4139
- !*** external "fast-equals" ***!
4140
- \******************************/
4141
- /***/ ((module) => {
4142
-
4143
- "use strict";
4144
- module.exports = __WEBPACK_EXTERNAL_MODULE_fast_equals__;
4145
-
4146
- /***/ }),
4147
-
4148
- /***/ "idb-keyval":
4149
- /*!*****************************!*\
4150
- !*** external "idb-keyval" ***!
4151
- \*****************************/
4152
- /***/ ((module) => {
4153
-
4154
- "use strict";
4155
- module.exports = __WEBPACK_EXTERNAL_MODULE_idb_keyval__;
4156
-
4157
- /***/ }),
4158
-
4159
- /***/ "lodash/transform":
4160
- /*!***********************************!*\
4161
- !*** external "lodash/transform" ***!
4162
- \***********************************/
4163
- /***/ ((module) => {
4164
-
4165
- "use strict";
4166
- module.exports = __WEBPACK_EXTERNAL_MODULE_lodash_transform__;
4167
-
4168
- /***/ }),
4169
-
4170
- /***/ "react":
4171
- /*!************************!*\
4172
- !*** external "react" ***!
4173
- \************************/
4174
- /***/ ((module) => {
4175
-
4176
- "use strict";
4177
- module.exports = __WEBPACK_EXTERNAL_MODULE_react__;
4178
-
4179
- /***/ }),
4180
-
4181
- /***/ "react-dom":
4182
- /*!****************************!*\
4183
- !*** external "react-dom" ***!
4184
- \****************************/
4185
- /***/ ((module) => {
4186
-
4187
- "use strict";
4188
- module.exports = __WEBPACK_EXTERNAL_MODULE_react_dom__;
4189
-
4190
- /***/ }),
4191
-
4192
- /***/ "underscore":
4193
- /*!*****************************!*\
4194
- !*** external "underscore" ***!
4195
- \*****************************/
4196
- /***/ ((module) => {
4197
-
4198
- "use strict";
4199
- module.exports = __WEBPACK_EXTERNAL_MODULE_underscore__;
4200
-
4201
- /***/ })
4202
-
4203
- /******/ });
4204
- /************************************************************************/
4205
- /******/ // The module cache
4206
- /******/ var __webpack_module_cache__ = {};
4207
- /******/
4208
- /******/ // The require function
4209
- /******/ function __webpack_require__(moduleId) {
4210
- /******/ // Check if module is in cache
4211
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
4212
- /******/ if (cachedModule !== undefined) {
4213
- /******/ return cachedModule.exports;
4214
- /******/ }
4215
- /******/ // Create a new module (and put it into the cache)
4216
- /******/ var module = __webpack_module_cache__[moduleId] = {
4217
- /******/ // no module.id needed
4218
- /******/ // no module.loaded needed
4219
- /******/ exports: {}
4220
- /******/ };
4221
- /******/
4222
- /******/ // Execute the module function
4223
- /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
4224
- /******/
4225
- /******/ // Return the exports of the module
4226
- /******/ return module.exports;
4227
- /******/ }
4228
- /******/
4229
- /************************************************************************/
4230
- /******/ /* webpack/runtime/compat get default export */
4231
- /******/ (() => {
4232
- /******/ // getDefaultExport function for compatibility with non-harmony modules
4233
- /******/ __webpack_require__.n = (module) => {
4234
- /******/ var getter = module && module.__esModule ?
4235
- /******/ () => (module['default']) :
4236
- /******/ () => (module);
4237
- /******/ __webpack_require__.d(getter, { a: getter });
4238
- /******/ return getter;
4239
- /******/ };
4240
- /******/ })();
4241
- /******/
4242
- /******/ /* webpack/runtime/define property getters */
4243
- /******/ (() => {
4244
- /******/ // define getter functions for harmony exports
4245
- /******/ __webpack_require__.d = (exports, definition) => {
4246
- /******/ for(var key in definition) {
4247
- /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
4248
- /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
4249
- /******/ }
4250
- /******/ }
4251
- /******/ };
4252
- /******/ })();
4253
- /******/
4254
- /******/ /* webpack/runtime/global */
4255
- /******/ (() => {
4256
- /******/ __webpack_require__.g = (function() {
4257
- /******/ if (typeof globalThis === 'object') return globalThis;
4258
- /******/ try {
4259
- /******/ return this || new Function('return this')();
4260
- /******/ } catch (e) {
4261
- /******/ if (typeof window === 'object') return window;
4262
- /******/ }
4263
- /******/ })();
4264
- /******/ })();
4265
- /******/
4266
- /******/ /* webpack/runtime/hasOwnProperty shorthand */
4267
- /******/ (() => {
4268
- /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
4269
- /******/ })();
4270
- /******/
4271
- /******/ /* webpack/runtime/make namespace object */
4272
- /******/ (() => {
4273
- /******/ // define __esModule on exports
4274
- /******/ __webpack_require__.r = (exports) => {
4275
- /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
4276
- /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4277
- /******/ }
4278
- /******/ Object.defineProperty(exports, '__esModule', { value: true });
4279
- /******/ };
4280
- /******/ })();
4281
- /******/
4282
- /************************************************************************/
4283
- var __webpack_exports__ = {};
4284
- // This entry need to be wrapped in an IIFE because it need to be in strict mode.
4285
- (() => {
4286
- "use strict";
4287
- /*!**********************!*\
4288
- !*** ./lib/index.js ***!
4289
- \**********************/
4290
- __webpack_require__.r(__webpack_exports__);
4291
- /* harmony export */ __webpack_require__.d(__webpack_exports__, {
4292
- /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__),
4293
- /* harmony export */ "withOnyx": () => (/* reexport safe */ _withOnyx__WEBPACK_IMPORTED_MODULE_1__["default"])
4294
- /* harmony export */ });
4295
- /* harmony import */ var _Onyx__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Onyx */ "./lib/Onyx.js");
4296
- /* harmony import */ var _withOnyx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./withOnyx */ "./lib/withOnyx.js");
4297
-
4298
-
4299
-
4300
- /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_Onyx__WEBPACK_IMPORTED_MODULE_0__["default"]);
4301
-
4302
- })();
4303
-
4304
- /******/ return __webpack_exports__;
4305
- /******/ })()
4306
- ;
4307
- });
4308
- //# sourceMappingURL=web.development.js.map