react-native-onyx 2.0.41 → 2.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Onyx.js +61 -26
- package/dist/OnyxCache.d.ts +24 -18
- package/dist/OnyxCache.js +53 -31
- package/dist/OnyxUtils.d.ts +7 -7
- package/dist/OnyxUtils.js +43 -37
- package/dist/index.d.ts +6 -5
- package/dist/index.js +1 -1
- package/dist/storage/providers/IDBKeyValProvider.js +24 -3
- package/dist/types.d.ts +6 -15
- package/dist/utils.d.ts +20 -2
- package/dist/utils.js +52 -2
- package/dist/withOnyx/index.d.ts +15 -0
- package/dist/{withOnyx.js → withOnyx/index.js} +64 -67
- package/dist/{withOnyx.d.ts → withOnyx/types.d.ts} +45 -45
- package/dist/withOnyx/types.js +2 -0
- package/package.json +2 -2
package/dist/OnyxUtils.js
CHANGED
|
@@ -30,14 +30,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
/* eslint-disable no-continue */
|
|
31
31
|
const fast_equals_1 = require("fast-equals");
|
|
32
32
|
const clone_1 = __importDefault(require("lodash/clone"));
|
|
33
|
+
const DevTools_1 = __importDefault(require("./DevTools"));
|
|
33
34
|
const Logger = __importStar(require("./Logger"));
|
|
34
35
|
const OnyxCache_1 = __importDefault(require("./OnyxCache"));
|
|
35
|
-
const Str = __importStar(require("./Str"));
|
|
36
36
|
const PerformanceUtils = __importStar(require("./PerformanceUtils"));
|
|
37
|
+
const Str = __importStar(require("./Str"));
|
|
38
|
+
const batch_1 = __importDefault(require("./batch"));
|
|
37
39
|
const storage_1 = __importDefault(require("./storage"));
|
|
38
40
|
const utils_1 = __importDefault(require("./utils"));
|
|
39
|
-
const batch_1 = __importDefault(require("./batch"));
|
|
40
|
-
const DevTools_1 = __importDefault(require("./DevTools"));
|
|
41
41
|
// Method constants
|
|
42
42
|
const METHOD = {
|
|
43
43
|
SET: 'set',
|
|
@@ -163,7 +163,7 @@ function reduceCollectionWithSelector(collection, selector, withOnyxInstanceStat
|
|
|
163
163
|
function get(key) {
|
|
164
164
|
// When we already have the value in cache - resolve right away
|
|
165
165
|
if (OnyxCache_1.default.hasCacheForKey(key)) {
|
|
166
|
-
return Promise.resolve(OnyxCache_1.default.
|
|
166
|
+
return Promise.resolve(OnyxCache_1.default.get(key));
|
|
167
167
|
}
|
|
168
168
|
const taskName = `get:${key}`;
|
|
169
169
|
// When a value retrieving task for this key is still running hook to it
|
|
@@ -173,6 +173,10 @@ function get(key) {
|
|
|
173
173
|
// Otherwise retrieve the value from storage and capture a promise to aid concurrent usages
|
|
174
174
|
const promise = storage_1.default.getItem(key)
|
|
175
175
|
.then((val) => {
|
|
176
|
+
if (val === undefined) {
|
|
177
|
+
OnyxCache_1.default.addNullishStorageKey(key);
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
176
180
|
OnyxCache_1.default.set(key, val);
|
|
177
181
|
return val;
|
|
178
182
|
})
|
|
@@ -182,9 +186,9 @@ function get(key) {
|
|
|
182
186
|
/** Returns current key names stored in persisted storage */
|
|
183
187
|
function getAllKeys() {
|
|
184
188
|
// When we've already read stored keys, resolve right away
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
-
return Promise.resolve(
|
|
189
|
+
const cachedKeys = OnyxCache_1.default.getAllKeys();
|
|
190
|
+
if (cachedKeys.size > 0) {
|
|
191
|
+
return Promise.resolve(cachedKeys);
|
|
188
192
|
}
|
|
189
193
|
const taskName = 'getAllKeys';
|
|
190
194
|
// When a value retrieving task for all keys is still running hook to it
|
|
@@ -237,7 +241,7 @@ function isSafeEvictionKey(testKey) {
|
|
|
237
241
|
* If the requested key is a collection, it will return an object with all the collection members.
|
|
238
242
|
*/
|
|
239
243
|
function tryGetCachedValue(key, mapping) {
|
|
240
|
-
let val = OnyxCache_1.default.
|
|
244
|
+
let val = OnyxCache_1.default.get(key);
|
|
241
245
|
if (isCollectionKey(key)) {
|
|
242
246
|
const allCacheKeys = OnyxCache_1.default.getAllKeys();
|
|
243
247
|
// It is possible we haven't loaded all keys yet so we do not know if the
|
|
@@ -247,7 +251,7 @@ function tryGetCachedValue(key, mapping) {
|
|
|
247
251
|
}
|
|
248
252
|
const matchingKeys = Array.from(allCacheKeys).filter((k) => k.startsWith(key));
|
|
249
253
|
const values = matchingKeys.reduce((finalObject, matchedKey) => {
|
|
250
|
-
const cachedValue = OnyxCache_1.default.
|
|
254
|
+
const cachedValue = OnyxCache_1.default.get(matchedKey);
|
|
251
255
|
if (cachedValue) {
|
|
252
256
|
// This is permissible because we're in the process of constructing the final object in a reduce function.
|
|
253
257
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -334,23 +338,22 @@ function getCachedCollection(collectionKey, collectionMemberKeys) {
|
|
|
334
338
|
if (!collectionMemberKeys && !isCollectionMemberKey(collectionKey, key)) {
|
|
335
339
|
return;
|
|
336
340
|
}
|
|
337
|
-
collection[key] = OnyxCache_1.default.
|
|
341
|
+
collection[key] = OnyxCache_1.default.get(key);
|
|
338
342
|
});
|
|
339
343
|
return collection;
|
|
340
344
|
}
|
|
341
345
|
/**
|
|
342
346
|
* When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
|
|
343
347
|
*/
|
|
344
|
-
function keysChanged(collectionKey, partialCollection,
|
|
345
|
-
const previousCollectionWithoutNestedNulls = previousPartialCollection === undefined ? {} : utils_1.default.removeNestedNullValues(previousPartialCollection);
|
|
348
|
+
function keysChanged(collectionKey, partialCollection, partialPreviousCollection, notifyRegularSubscibers = true, notifyWithOnyxSubscibers = true) {
|
|
346
349
|
// We prepare the "cached collection" which is the entire collection + the new partial data that
|
|
347
350
|
// was merged in via mergeCollection().
|
|
348
351
|
const cachedCollection = getCachedCollection(collectionKey);
|
|
349
|
-
const cachedCollectionWithoutNestedNulls = utils_1.default.removeNestedNullValues(cachedCollection);
|
|
350
352
|
// If the previous collection equals the new collection then we do not need to notify any subscribers.
|
|
351
|
-
if (
|
|
353
|
+
if (partialPreviousCollection !== undefined && (0, fast_equals_1.deepEqual)(cachedCollection, partialPreviousCollection)) {
|
|
352
354
|
return;
|
|
353
355
|
}
|
|
356
|
+
const previousCollection = partialPreviousCollection !== null && partialPreviousCollection !== void 0 ? partialPreviousCollection : {};
|
|
354
357
|
// We are iterating over all subscribers similar to keyChanged(). However, we are looking for subscribers who are subscribing to either a collection key or
|
|
355
358
|
// 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
|
|
356
359
|
// 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().
|
|
@@ -381,7 +384,7 @@ function keysChanged(collectionKey, partialCollection, previousPartialCollection
|
|
|
381
384
|
// send the whole cached collection.
|
|
382
385
|
if (isSubscribedToCollectionKey) {
|
|
383
386
|
if (subscriber.waitForCollectionCallback) {
|
|
384
|
-
subscriber.callback(
|
|
387
|
+
subscriber.callback(cachedCollection);
|
|
385
388
|
continue;
|
|
386
389
|
}
|
|
387
390
|
// If they are not using waitForCollectionCallback then we notify the subscriber with
|
|
@@ -389,21 +392,21 @@ function keysChanged(collectionKey, partialCollection, previousPartialCollection
|
|
|
389
392
|
const dataKeys = Object.keys(partialCollection !== null && partialCollection !== void 0 ? partialCollection : {});
|
|
390
393
|
for (let j = 0; j < dataKeys.length; j++) {
|
|
391
394
|
const dataKey = dataKeys[j];
|
|
392
|
-
if ((0, fast_equals_1.deepEqual)(
|
|
395
|
+
if ((0, fast_equals_1.deepEqual)(cachedCollection[dataKey], previousCollection[dataKey])) {
|
|
393
396
|
continue;
|
|
394
397
|
}
|
|
395
|
-
subscriber.callback(
|
|
398
|
+
subscriber.callback(cachedCollection[dataKey], dataKey);
|
|
396
399
|
}
|
|
397
400
|
continue;
|
|
398
401
|
}
|
|
399
402
|
// And if the subscriber is specifically only tracking a particular collection member key then we will
|
|
400
403
|
// notify them with the cached data for that key only.
|
|
401
404
|
if (isSubscribedToCollectionMemberKey) {
|
|
402
|
-
if ((0, fast_equals_1.deepEqual)(
|
|
405
|
+
if ((0, fast_equals_1.deepEqual)(cachedCollection[subscriber.key], previousCollection[subscriber.key])) {
|
|
403
406
|
continue;
|
|
404
407
|
}
|
|
405
408
|
const subscriberCallback = subscriber.callback;
|
|
406
|
-
subscriberCallback(
|
|
409
|
+
subscriberCallback(cachedCollection[subscriber.key], subscriber.key);
|
|
407
410
|
continue;
|
|
408
411
|
}
|
|
409
412
|
continue;
|
|
@@ -449,7 +452,7 @@ function keysChanged(collectionKey, partialCollection, previousPartialCollection
|
|
|
449
452
|
}
|
|
450
453
|
// If a React component is only interested in a single key then we can set the cached value directly to the state name.
|
|
451
454
|
if (isSubscribedToCollectionMemberKey) {
|
|
452
|
-
if ((0, fast_equals_1.deepEqual)(
|
|
455
|
+
if ((0, fast_equals_1.deepEqual)(cachedCollection[subscriber.key], previousCollection[subscriber.key])) {
|
|
453
456
|
continue;
|
|
454
457
|
}
|
|
455
458
|
// However, we only want to update this subscriber if the partial data contains a change.
|
|
@@ -525,14 +528,12 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
|
|
|
525
528
|
}
|
|
526
529
|
if (isCollectionKey(subscriber.key) && subscriber.waitForCollectionCallback) {
|
|
527
530
|
const cachedCollection = getCachedCollection(subscriber.key);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
subscriber.callback(cachedCollectionWithoutNestedNulls);
|
|
531
|
+
cachedCollection[key] = value;
|
|
532
|
+
subscriber.callback(cachedCollection);
|
|
531
533
|
continue;
|
|
532
534
|
}
|
|
533
|
-
const valueWithoutNestedNulls = utils_1.default.removeNestedNullValues(value);
|
|
534
535
|
const subscriberCallback = subscriber.callback;
|
|
535
|
-
subscriberCallback(
|
|
536
|
+
subscriberCallback(value, key);
|
|
536
537
|
continue;
|
|
537
538
|
}
|
|
538
539
|
// Subscriber connected via withOnyx() HOC
|
|
@@ -612,7 +613,7 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
|
|
|
612
613
|
* - sets state on the withOnyxInstances
|
|
613
614
|
* - triggers the callback function
|
|
614
615
|
*/
|
|
615
|
-
function sendDataToConnection(mapping,
|
|
616
|
+
function sendDataToConnection(mapping, value, matchedKey, isBatched) {
|
|
616
617
|
var _a, _b;
|
|
617
618
|
// If the mapping no longer exists then we should not send any data.
|
|
618
619
|
// This means our subscriber disconnected or withOnyx wrapped component unmounted.
|
|
@@ -620,15 +621,15 @@ function sendDataToConnection(mapping, val, matchedKey, isBatched) {
|
|
|
620
621
|
return;
|
|
621
622
|
}
|
|
622
623
|
if ('withOnyxInstance' in mapping && mapping.withOnyxInstance) {
|
|
623
|
-
let newData =
|
|
624
|
+
let newData = value;
|
|
624
625
|
// If the mapping has a selector, then the component's state must only be updated with the data
|
|
625
626
|
// returned by the selector.
|
|
626
627
|
if (mapping.selector) {
|
|
627
628
|
if (isCollectionKey(mapping.key)) {
|
|
628
|
-
newData = reduceCollectionWithSelector(
|
|
629
|
+
newData = reduceCollectionWithSelector(value, mapping.selector, mapping.withOnyxInstance.state);
|
|
629
630
|
}
|
|
630
631
|
else {
|
|
631
|
-
newData = mapping.selector(
|
|
632
|
+
newData = mapping.selector(value, mapping.withOnyxInstance.state);
|
|
632
633
|
}
|
|
633
634
|
}
|
|
634
635
|
PerformanceUtils.logSetStateCall(mapping, null, newData, 'sendDataToConnection');
|
|
@@ -640,8 +641,13 @@ function sendDataToConnection(mapping, val, matchedKey, isBatched) {
|
|
|
640
641
|
}
|
|
641
642
|
return;
|
|
642
643
|
}
|
|
643
|
-
|
|
644
|
-
|
|
644
|
+
// When there are no matching keys in "Onyx.connect", we pass null to "sendDataToConnection" explicitly,
|
|
645
|
+
// to allow the withOnyx instance to set the value in the state initially and therefore stop the loading state once all
|
|
646
|
+
// required keys have been set.
|
|
647
|
+
// If we would pass undefined to setWithOnyxInstance instead, withOnyx would not set the value in the state.
|
|
648
|
+
// withOnyx will internally replace null values with undefined and never pass null values to wrapped components.
|
|
649
|
+
// For regular callbacks, we never want to pass null values, but always just undefined if a value is not set in cache or storage.
|
|
650
|
+
(_b = (_a = mapping).callback) === null || _b === void 0 ? void 0 : _b.call(_a, value === null ? undefined : value, matchedKey);
|
|
645
651
|
}
|
|
646
652
|
/**
|
|
647
653
|
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
@@ -682,7 +688,7 @@ function getCollectionDataAndSendAsObject(matchingKeys, mapping) {
|
|
|
682
688
|
* These missingKeys will be later to use to multiGet the data from the storage.
|
|
683
689
|
*/
|
|
684
690
|
matchingKeys.forEach((key) => {
|
|
685
|
-
const cacheValue = OnyxCache_1.default.
|
|
691
|
+
const cacheValue = OnyxCache_1.default.get(key);
|
|
686
692
|
if (cacheValue) {
|
|
687
693
|
data[key] = cacheValue;
|
|
688
694
|
return;
|
|
@@ -755,7 +761,7 @@ function scheduleNotifyCollectionSubscribers(key, value, previousValue) {
|
|
|
755
761
|
* Remove a key from Onyx and update the subscribers
|
|
756
762
|
*/
|
|
757
763
|
function remove(key) {
|
|
758
|
-
const prevValue = OnyxCache_1.default.
|
|
764
|
+
const prevValue = OnyxCache_1.default.get(key, false);
|
|
759
765
|
OnyxCache_1.default.drop(key);
|
|
760
766
|
scheduleSubscriberUpdate(key, null, prevValue);
|
|
761
767
|
return storage_1.default.removeItem(key).then(() => undefined);
|
|
@@ -798,11 +804,11 @@ function evictStorageAndRetry(error, onyxMethod, ...args) {
|
|
|
798
804
|
/**
|
|
799
805
|
* Notifies subscribers and writes current value to cache
|
|
800
806
|
*/
|
|
801
|
-
function broadcastUpdate(key, value, hasChanged
|
|
802
|
-
const prevValue = OnyxCache_1.default.
|
|
807
|
+
function broadcastUpdate(key, value, hasChanged) {
|
|
808
|
+
const prevValue = OnyxCache_1.default.get(key, false);
|
|
803
809
|
// Update subscribers if the cached value has changed, or when the subscriber specifically requires
|
|
804
810
|
// all updates regardless of value changes (indicated by initWithStoredValues set to false).
|
|
805
|
-
if (hasChanged
|
|
811
|
+
if (hasChanged) {
|
|
806
812
|
OnyxCache_1.default.set(key, value);
|
|
807
813
|
}
|
|
808
814
|
else {
|
|
@@ -823,7 +829,7 @@ function hasPendingMergeForKey(key) {
|
|
|
823
829
|
function removeNullValues(key, value, shouldRemoveNestedNulls = true) {
|
|
824
830
|
if (value === null) {
|
|
825
831
|
remove(key);
|
|
826
|
-
return { value, wasRemoved: true };
|
|
832
|
+
return { value: null, wasRemoved: true };
|
|
827
833
|
}
|
|
828
834
|
// We can remove all null values in an object by merging it with itself
|
|
829
835
|
// utils.fastMerge recursively goes through the object and removes all null values
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type { ConnectOptions, OnyxUpdate } from './Onyx';
|
|
1
2
|
import Onyx from './Onyx';
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type { UseOnyxResult, FetchStatus, ResultMetadata } from './useOnyx';
|
|
3
|
+
import type { CustomTypeOptions, KeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue, Selector } from './types';
|
|
4
|
+
import type { FetchStatus, ResultMetadata, UseOnyxResult } from './useOnyx';
|
|
5
5
|
import useOnyx from './useOnyx';
|
|
6
6
|
import withOnyx from './withOnyx';
|
|
7
|
+
import type { WithOnyxState } from './withOnyx/types';
|
|
7
8
|
export default Onyx;
|
|
8
|
-
export {
|
|
9
|
-
export type {
|
|
9
|
+
export { useOnyx, withOnyx };
|
|
10
|
+
export type { ConnectOptions, CustomTypeOptions, FetchStatus, KeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxUpdate, OnyxValue, ResultMetadata, Selector, UseOnyxResult, WithOnyxState, };
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.withOnyx = exports.useOnyx = void 0;
|
|
7
7
|
const Onyx_1 = __importDefault(require("./Onyx"));
|
|
8
8
|
const useOnyx_1 = __importDefault(require("./useOnyx"));
|
|
9
9
|
exports.useOnyx = useOnyx_1.default;
|
|
@@ -22,14 +22,26 @@ const provider = {
|
|
|
22
22
|
throw Error('IDBKeyVal store could not be created');
|
|
23
23
|
idbKeyValStore = newIdbKeyValStore;
|
|
24
24
|
},
|
|
25
|
-
setItem: (key, value) =>
|
|
25
|
+
setItem: (key, value) => {
|
|
26
|
+
if (value === null) {
|
|
27
|
+
provider.removeItem(key);
|
|
28
|
+
}
|
|
29
|
+
return (0, idb_keyval_1.set)(key, value, idbKeyValStore);
|
|
30
|
+
},
|
|
26
31
|
multiGet: (keysParam) => (0, idb_keyval_1.getMany)(keysParam, idbKeyValStore).then((values) => values.map((value, index) => [keysParam[index], value])),
|
|
27
32
|
multiMerge: (pairs) => idbKeyValStore('readwrite', (store) => {
|
|
28
33
|
// Note: we are using the manual store transaction here, to fit the read and update
|
|
29
34
|
// of the items in one transaction to achieve best performance.
|
|
30
35
|
const getValues = Promise.all(pairs.map(([key]) => (0, idb_keyval_1.promisifyRequest)(store.get(key))));
|
|
31
36
|
return getValues.then((values) => {
|
|
32
|
-
const
|
|
37
|
+
const pairsWithoutNull = pairs.filter(([key, value]) => {
|
|
38
|
+
if (value === null) {
|
|
39
|
+
provider.removeItem(key);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
});
|
|
44
|
+
const upsertMany = pairsWithoutNull.map(([key, value], index) => {
|
|
33
45
|
const prev = values[index];
|
|
34
46
|
const newValue = utils_1.default.fastMerge(prev, value);
|
|
35
47
|
return (0, idb_keyval_1.promisifyRequest)(store.put(newValue, key));
|
|
@@ -41,7 +53,16 @@ const provider = {
|
|
|
41
53
|
// Since Onyx also merged the existing value with the changes, we can just set the value directly
|
|
42
54
|
return provider.setItem(key, preMergedValue);
|
|
43
55
|
},
|
|
44
|
-
multiSet: (pairs) =>
|
|
56
|
+
multiSet: (pairs) => {
|
|
57
|
+
const pairsWithoutNull = pairs.filter(([key, value]) => {
|
|
58
|
+
if (value === null) {
|
|
59
|
+
provider.removeItem(key);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
});
|
|
64
|
+
return (0, idb_keyval_1.setMany)(pairsWithoutNull, idbKeyValStore);
|
|
65
|
+
},
|
|
45
66
|
clear: () => (0, idb_keyval_1.clear)(idbKeyValStore),
|
|
46
67
|
getAllKeys: () => (0, idb_keyval_1.keys)(idbKeyValStore),
|
|
47
68
|
getItem: (key) => (0, idb_keyval_1.get)(key, idbKeyValStore)
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Component } from 'react';
|
|
2
1
|
import type { Merge } from 'type-fest';
|
|
3
2
|
import type { BuiltIns } from 'type-fest/source/internal';
|
|
4
3
|
import type OnyxUtils from './OnyxUtils';
|
|
4
|
+
import type { WithOnyxInstance, WithOnyxState } from './withOnyx/types';
|
|
5
5
|
/**
|
|
6
6
|
* Utility type that excludes `null` from the type `TValue`.
|
|
7
7
|
*/
|
|
@@ -132,7 +132,7 @@ type NullableKeyValueMapping = {
|
|
|
132
132
|
* The type `TKey` extends `OnyxKey` and it is the key used to access a value in `KeyValueMapping`.
|
|
133
133
|
* `TReturnType` is the type of the returned value from the selector function.
|
|
134
134
|
*/
|
|
135
|
-
type Selector<TKey extends OnyxKey, TOnyxProps, TReturnType> = (value: OnyxEntry<KeyValueMapping[TKey]>, state
|
|
135
|
+
type Selector<TKey extends OnyxKey, TOnyxProps, TReturnType> = (value: OnyxEntry<KeyValueMapping[TKey]>, state?: WithOnyxState<TOnyxProps>) => TReturnType;
|
|
136
136
|
/**
|
|
137
137
|
* Represents a single Onyx entry, that can be either `TOnyxValue` or `null` / `undefined` if it doesn't exist.
|
|
138
138
|
*
|
|
@@ -161,7 +161,7 @@ type Selector<TKey extends OnyxKey, TOnyxProps, TReturnType> = (value: OnyxEntry
|
|
|
161
161
|
* })(Component);
|
|
162
162
|
* ```
|
|
163
163
|
*/
|
|
164
|
-
type OnyxEntry<TOnyxValue> = TOnyxValue |
|
|
164
|
+
type OnyxEntry<TOnyxValue> = TOnyxValue | undefined;
|
|
165
165
|
/**
|
|
166
166
|
* Represents an Onyx collection of entries, that can be either a record of `TOnyxValue`s or `null` / `undefined` if it is empty or doesn't exist.
|
|
167
167
|
*
|
|
@@ -190,7 +190,7 @@ type OnyxEntry<TOnyxValue> = TOnyxValue | null | undefined;
|
|
|
190
190
|
* })(Component);
|
|
191
191
|
* ```
|
|
192
192
|
*/
|
|
193
|
-
type OnyxCollection<TOnyxValue> = OnyxEntry<Record<string, TOnyxValue |
|
|
193
|
+
type OnyxCollection<TOnyxValue> = OnyxEntry<Record<string, TOnyxValue | undefined>>;
|
|
194
194
|
/** Utility type to extract `TOnyxValue` from `OnyxCollection<TOnyxValue>` */
|
|
195
195
|
type ExtractOnyxCollectionValue<TOnyxCollection> = TOnyxCollection extends NonNullable<OnyxCollection<infer U>> ? U : never;
|
|
196
196
|
type NonTransformableTypes = BuiltIns | ((...args: any[]) => unknown) | Map<unknown, unknown> | Set<unknown> | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | unknown[] | readonly unknown[];
|
|
@@ -220,12 +220,6 @@ type NullishDeep<T> = T extends NonTransformableTypes ? T : T extends object ? N
|
|
|
220
220
|
type NullishObjectDeep<ObjectType extends object> = {
|
|
221
221
|
[KeyType in keyof ObjectType]?: NullishDeep<ObjectType[KeyType]> | null;
|
|
222
222
|
};
|
|
223
|
-
/**
|
|
224
|
-
* Represents withOnyx's internal state, containing the Onyx props and a `loading` flag.
|
|
225
|
-
*/
|
|
226
|
-
type WithOnyxInstanceState<TOnyxProps> = (TOnyxProps & {
|
|
227
|
-
loading: boolean;
|
|
228
|
-
}) | undefined;
|
|
229
223
|
/**
|
|
230
224
|
* Represents a mapping between Onyx collection keys and their respective values.
|
|
231
225
|
*
|
|
@@ -238,10 +232,6 @@ type WithOnyxInstanceState<TOnyxProps> = (TOnyxProps & {
|
|
|
238
232
|
type Collection<TKey extends CollectionKeyBase, TMap, TValue> = {
|
|
239
233
|
[MapK in keyof TMap]: MapK extends `${TKey}${string}` ? MapK extends `${TKey}` ? never : TValue : never;
|
|
240
234
|
};
|
|
241
|
-
type WithOnyxInstance = Component<unknown, WithOnyxInstanceState<NullableKeyValueMapping>> & {
|
|
242
|
-
setStateProxy: (cb: (state: Record<string, OnyxCollection<KeyValueMapping[OnyxKey]>>) => OnyxValue<OnyxKey>) => void;
|
|
243
|
-
setWithOnyxState: (statePropertyName: OnyxKey, value: OnyxValue<OnyxKey>) => void;
|
|
244
|
-
};
|
|
245
235
|
/** Represents the base options used in `Onyx.connect()` method. */
|
|
246
236
|
type BaseConnectOptions = {
|
|
247
237
|
initWithStoredValues?: boolean;
|
|
@@ -342,4 +332,5 @@ type InitOptions = {
|
|
|
342
332
|
/** Enables debugging setState() calls to connected components */
|
|
343
333
|
debugSetState?: boolean;
|
|
344
334
|
};
|
|
345
|
-
|
|
335
|
+
type GenericFunction = (...args: any[]) => any;
|
|
336
|
+
export type { BaseConnectOptions, Collection, CollectionConnectCallback, CollectionConnectOptions, CollectionKey, CollectionKeyBase, ConnectOptions, CustomTypeOptions, DeepRecord, DefaultConnectCallback, DefaultConnectOptions, ExtractOnyxCollectionValue, GenericFunction, InitOptions, Key, KeyValueMapping, Mapping, NonNull, NonUndefined, NullableKeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxUpdate, OnyxValue, Selector, WithOnyxConnectOptions, };
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { OnyxKey } from './types';
|
|
1
|
+
import type { OnyxKey, OnyxValue } from './types';
|
|
2
2
|
type EmptyObject = Record<string, never>;
|
|
3
3
|
type EmptyValue = EmptyObject | null | undefined;
|
|
4
4
|
/** Checks whether the given object is an object and not null/undefined. */
|
|
@@ -12,7 +12,7 @@ declare function isEmptyObject<T>(obj: T | EmptyValue): obj is EmptyValue;
|
|
|
12
12
|
*/
|
|
13
13
|
declare function fastMerge<TObject extends Record<string, unknown>>(target: TObject | null, source: TObject | null, shouldRemoveNestedNulls?: boolean): TObject | null;
|
|
14
14
|
/** Deep removes the nested null values from the given value. */
|
|
15
|
-
declare function removeNestedNullValues<
|
|
15
|
+
declare function removeNestedNullValues<TValue extends OnyxValue<OnyxKey> | unknown | unknown[]>(value: TValue | null): TValue | null;
|
|
16
16
|
/** Formats the action name by uppercasing and adding the key if provided. */
|
|
17
17
|
declare function formatActionName(method: string, key?: OnyxKey): string;
|
|
18
18
|
/** validate that the update and the existing value are compatible */
|
|
@@ -21,11 +21,29 @@ declare function checkCompatibilityWithExistingValue(value: unknown, existingVal
|
|
|
21
21
|
existingValueType?: string;
|
|
22
22
|
newValueType?: string;
|
|
23
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Picks entries from an object based on a condition.
|
|
26
|
+
*
|
|
27
|
+
* @param obj - The object to pick entries from.
|
|
28
|
+
* @param condition - The condition to determine which entries to pick.
|
|
29
|
+
* @returns The object containing only the picked entries.
|
|
30
|
+
*/
|
|
31
|
+
declare function pick<TValue>(obj: Record<string, TValue>, condition: string | string[] | ((entry: [string, TValue]) => boolean)): Record<string, TValue>;
|
|
32
|
+
/**
|
|
33
|
+
* Omits entries from an object based on a condition.
|
|
34
|
+
*
|
|
35
|
+
* @param obj - The object to omit entries from.
|
|
36
|
+
* @param condition - The condition to determine which entries to omit.
|
|
37
|
+
* @returns The object containing only the remaining entries after omission.
|
|
38
|
+
*/
|
|
39
|
+
declare function omit<TValue>(obj: Record<string, TValue>, condition: string | string[] | ((entry: [string, TValue]) => boolean)): Record<string, TValue>;
|
|
24
40
|
declare const _default: {
|
|
25
41
|
isEmptyObject: typeof isEmptyObject;
|
|
26
42
|
fastMerge: typeof fastMerge;
|
|
27
43
|
formatActionName: typeof formatActionName;
|
|
28
44
|
removeNestedNullValues: typeof removeNestedNullValues;
|
|
29
45
|
checkCompatibilityWithExistingValue: typeof checkCompatibilityWithExistingValue;
|
|
46
|
+
pick: typeof pick;
|
|
47
|
+
omit: typeof omit;
|
|
30
48
|
};
|
|
31
49
|
export default _default;
|
package/dist/utils.js
CHANGED
|
@@ -90,7 +90,8 @@ function fastMerge(target, source, shouldRemoveNestedNulls = true) {
|
|
|
90
90
|
/** Deep removes the nested null values from the given value. */
|
|
91
91
|
function removeNestedNullValues(value) {
|
|
92
92
|
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
93
|
-
|
|
93
|
+
const objectValue = value;
|
|
94
|
+
return fastMerge(objectValue, objectValue);
|
|
94
95
|
}
|
|
95
96
|
return value;
|
|
96
97
|
}
|
|
@@ -118,4 +119,53 @@ function checkCompatibilityWithExistingValue(value, existingValue) {
|
|
|
118
119
|
isCompatible: true,
|
|
119
120
|
};
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
+
/**
|
|
123
|
+
* Filters an object based on a condition and an inclusion flag.
|
|
124
|
+
*
|
|
125
|
+
* @param obj - The object to filter.
|
|
126
|
+
* @param condition - The condition to apply.
|
|
127
|
+
* @param include - If true, include entries that match the condition; otherwise, exclude them.
|
|
128
|
+
* @returns The filtered object.
|
|
129
|
+
*/
|
|
130
|
+
function filterObject(obj, condition, include) {
|
|
131
|
+
const result = {};
|
|
132
|
+
const entries = Object.entries(obj);
|
|
133
|
+
for (let i = 0; i < entries.length; i++) {
|
|
134
|
+
const [key, value] = entries[i];
|
|
135
|
+
let shouldInclude;
|
|
136
|
+
if (Array.isArray(condition)) {
|
|
137
|
+
shouldInclude = condition.includes(key);
|
|
138
|
+
}
|
|
139
|
+
else if (typeof condition === 'string') {
|
|
140
|
+
shouldInclude = key === condition;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
shouldInclude = condition(entries[i]);
|
|
144
|
+
}
|
|
145
|
+
if (include ? shouldInclude : !shouldInclude) {
|
|
146
|
+
result[key] = value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return result;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Picks entries from an object based on a condition.
|
|
153
|
+
*
|
|
154
|
+
* @param obj - The object to pick entries from.
|
|
155
|
+
* @param condition - The condition to determine which entries to pick.
|
|
156
|
+
* @returns The object containing only the picked entries.
|
|
157
|
+
*/
|
|
158
|
+
function pick(obj, condition) {
|
|
159
|
+
return filterObject(obj, condition, true);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Omits entries from an object based on a condition.
|
|
163
|
+
*
|
|
164
|
+
* @param obj - The object to omit entries from.
|
|
165
|
+
* @param condition - The condition to determine which entries to omit.
|
|
166
|
+
* @returns The object containing only the remaining entries after omission.
|
|
167
|
+
*/
|
|
168
|
+
function omit(obj, condition) {
|
|
169
|
+
return filterObject(obj, condition, false);
|
|
170
|
+
}
|
|
171
|
+
exports.default = { isEmptyObject, fastMerge, formatActionName, removeNestedNullValues, checkCompatibilityWithExistingValue, pick, omit };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is a higher order component that provides the ability to map a state property directly to
|
|
3
|
+
* something in Onyx (a key/value store). That way, as soon as data in Onyx changes, the state will be set and the view
|
|
4
|
+
* will automatically change to reflect the new data.
|
|
5
|
+
*/
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import type { MapOnyxToState } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* @deprecated Use `useOnyx` instead of `withOnyx` whenever possible.
|
|
10
|
+
*
|
|
11
|
+
* This is a higher order component that provides the ability to map a state property directly to
|
|
12
|
+
* something in Onyx (a key/value store). That way, as soon as data in Onyx changes, the state will be set and the view
|
|
13
|
+
* will automatically change to reflect the new data.
|
|
14
|
+
*/
|
|
15
|
+
export default function <TComponentProps, TOnyxProps>(mapOnyxToState: MapOnyxToState<TComponentProps, TOnyxProps>, shouldDelayUpdates?: boolean): (component: React.ComponentType<TComponentProps>) => React.ComponentType<Omit<TComponentProps, keyof TOnyxProps>>;
|