react-native-onyx 1.0.130 → 2.0.1

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