react-native-onyx 2.0.63 → 2.0.65
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/API.md +27 -23
- package/dist/Onyx.d.ts +31 -26
- package/dist/Onyx.js +34 -128
- package/dist/OnyxConnectionManager.d.ts +69 -0
- package/dist/OnyxConnectionManager.js +195 -0
- package/dist/OnyxUtils.d.ts +29 -38
- package/dist/OnyxUtils.js +161 -66
- package/dist/Str.d.ts +5 -1
- package/dist/Str.js +13 -1
- package/dist/createDeferredTask.d.ts +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/types.d.ts +40 -19
- package/dist/useOnyx.d.ts +2 -2
- package/dist/useOnyx.js +24 -20
- package/dist/utils.d.ts +6 -1
- package/dist/utils.js +7 -1
- package/dist/withOnyx/index.js +10 -10
- package/dist/withOnyx/types.d.ts +1 -1
- package/package.json +1 -1
package/dist/OnyxUtils.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ValueOf } from 'type-fest';
|
|
2
2
|
import type Onyx from './Onyx';
|
|
3
|
-
import type { CollectionKey, CollectionKeyBase, DeepRecord, KeyValueMapping, Mapping, OnyxCollection, OnyxEntry, OnyxInput, OnyxKey, OnyxMergeCollectionInput, OnyxValue
|
|
3
|
+
import type { CollectionKey, CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, Mapping, OnyxCollection, OnyxEntry, OnyxInput, OnyxKey, OnyxMergeCollectionInput, OnyxValue } from './types';
|
|
4
|
+
import type { DeferredTask } from './createDeferredTask';
|
|
4
5
|
declare const METHOD: {
|
|
5
6
|
readonly SET: "set";
|
|
6
7
|
readonly MERGE: "merge";
|
|
@@ -18,14 +19,18 @@ declare function getMergeQueue(): Record<OnyxKey, Array<OnyxValue<OnyxKey>>>;
|
|
|
18
19
|
* Getter - returns the merge queue promise.
|
|
19
20
|
*/
|
|
20
21
|
declare function getMergeQueuePromise(): Record<OnyxKey, Promise<void>>;
|
|
21
|
-
/**
|
|
22
|
-
* Getter - returns the callback to state mapping.
|
|
23
|
-
*/
|
|
24
|
-
declare function getCallbackToStateMapping(): Record<string, Mapping<OnyxKey>>;
|
|
25
22
|
/**
|
|
26
23
|
* Getter - returns the default key states.
|
|
27
24
|
*/
|
|
28
25
|
declare function getDefaultKeyStates(): Record<OnyxKey, OnyxValue<OnyxKey>>;
|
|
26
|
+
/**
|
|
27
|
+
* Getter - returns the deffered init task.
|
|
28
|
+
*/
|
|
29
|
+
declare function getDeferredInitTask(): DeferredTask;
|
|
30
|
+
/**
|
|
31
|
+
* Getter - returns the eviction block list.
|
|
32
|
+
*/
|
|
33
|
+
declare function getEvictionBlocklist(): Record<OnyxKey, string[] | undefined>;
|
|
29
34
|
/**
|
|
30
35
|
* Sets the initial values for the Onyx store
|
|
31
36
|
*
|
|
@@ -55,19 +60,6 @@ declare function batchUpdates(updates: () => void): Promise<void>;
|
|
|
55
60
|
/** Get some data from the store */
|
|
56
61
|
declare function get<TKey extends OnyxKey, TValue extends OnyxValue<TKey>>(key: TKey): Promise<TValue>;
|
|
57
62
|
declare function multiGet<TKey extends OnyxKey>(keys: CollectionKeyBase[]): Promise<Map<OnyxKey, OnyxValue<TKey>>>;
|
|
58
|
-
/**
|
|
59
|
-
* Stores a connection ID associated with a given key.
|
|
60
|
-
*
|
|
61
|
-
* @param connectionID - a connection ID of the subscriber
|
|
62
|
-
* @param key - a key that the subscriber is connected to
|
|
63
|
-
*/
|
|
64
|
-
declare function storeKeyByConnections(key: OnyxKey, connectionID: number): void;
|
|
65
|
-
/**
|
|
66
|
-
* Deletes a connection ID associated with its corresponding key.
|
|
67
|
-
*
|
|
68
|
-
* @param {number} connectionID - The connection ID to be deleted.
|
|
69
|
-
*/
|
|
70
|
-
declare function deleteKeyByConnections(connectionID: number): void;
|
|
71
63
|
/** Returns current key names stored in persisted storage */
|
|
72
64
|
declare function getAllKeys(): Promise<Set<OnyxKey>>;
|
|
73
65
|
/**
|
|
@@ -85,7 +77,7 @@ declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>
|
|
|
85
77
|
* @param key - The collection member key to split.
|
|
86
78
|
* @returns A tuple where the first element is the collection part and the second element is the ID part.
|
|
87
79
|
*/
|
|
88
|
-
declare function splitCollectionMemberKey<TKey extends CollectionKey
|
|
80
|
+
declare function splitCollectionMemberKey<TKey extends CollectionKey, CollectionKeyType = TKey extends `${infer Prefix}_${string}` ? `${Prefix}_` : never>(key: TKey): [CollectionKeyType, string];
|
|
89
81
|
/**
|
|
90
82
|
* Checks to see if a provided key is the exact configured key of our connected subscriber
|
|
91
83
|
* or if the provided key is a collection member key (in case our configured key is a "collection key")
|
|
@@ -109,7 +101,7 @@ declare function getCollectionKey(key: OnyxKey): string;
|
|
|
109
101
|
* Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
|
|
110
102
|
* If the requested key is a collection, it will return an object with all the collection members.
|
|
111
103
|
*/
|
|
112
|
-
declare function tryGetCachedValue<TKey extends OnyxKey>(key: TKey, mapping?: Partial<
|
|
104
|
+
declare function tryGetCachedValue<TKey extends OnyxKey>(key: TKey, mapping?: Partial<Mapping<TKey>>): OnyxValue<OnyxKey>;
|
|
113
105
|
/**
|
|
114
106
|
* Remove a key from the recently accessed key list.
|
|
115
107
|
*/
|
|
@@ -120,13 +112,6 @@ declare function removeLastAccessedKey(key: OnyxKey): void;
|
|
|
120
112
|
* recently accessed key at the tail.
|
|
121
113
|
*/
|
|
122
114
|
declare function addLastAccessedKey(key: OnyxKey): void;
|
|
123
|
-
/**
|
|
124
|
-
* Removes a key previously added to this list
|
|
125
|
-
* which will enable it to be deleted again.
|
|
126
|
-
*/
|
|
127
|
-
declare function removeFromEvictionBlockList(key: OnyxKey, connectionID: number): void;
|
|
128
|
-
/** Keys added to this list can never be deleted. */
|
|
129
|
-
declare function addToEvictionBlockList(key: OnyxKey, connectionID: number): void;
|
|
130
115
|
/**
|
|
131
116
|
* Take all the keys that are safe to evict and add them to
|
|
132
117
|
* the recently accessed list when initializing the app. This
|
|
@@ -152,11 +137,6 @@ declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TK
|
|
|
152
137
|
* - triggers the callback function
|
|
153
138
|
*/
|
|
154
139
|
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: Mapping<TKey>, value: OnyxValue<TKey> | null, matchedKey: TKey | undefined, isBatched: boolean): void;
|
|
155
|
-
/**
|
|
156
|
-
* We check to see if this key is flagged as safe for eviction and add it to the recentlyAccessedKeys list so that when we
|
|
157
|
-
* run out of storage the least recently accessed key can be removed.
|
|
158
|
-
*/
|
|
159
|
-
declare function addKeyToRecentlyAccessedIfNeeded<TKey extends OnyxKey>(mapping: Mapping<TKey>): void;
|
|
160
140
|
/**
|
|
161
141
|
* Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
|
|
162
142
|
*/
|
|
@@ -228,6 +208,19 @@ declare function isValidNonEmptyCollectionForMerge<TKey extends CollectionKeyBas
|
|
|
228
208
|
* Verify if all the collection keys belong to the same parent
|
|
229
209
|
*/
|
|
230
210
|
declare function doAllCollectionItemsBelongToSameParent<TKey extends CollectionKeyBase>(collectionKey: TKey, collectionKeys: string[]): boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Subscribes to an Onyx key and listens to its changes.
|
|
213
|
+
*
|
|
214
|
+
* @param connectOptions The options object that will define the behavior of the connection.
|
|
215
|
+
* @returns The subscription ID to use when calling `OnyxUtils.unsubscribeFromKey()`.
|
|
216
|
+
*/
|
|
217
|
+
declare function subscribeToKey<TKey extends OnyxKey>(connectOptions: ConnectOptions<TKey>): number;
|
|
218
|
+
/**
|
|
219
|
+
* Disconnects and removes the listener from the Onyx key.
|
|
220
|
+
*
|
|
221
|
+
* @param subscriptionID Subscription ID returned by calling `OnyxUtils.subscribeToKey()`.
|
|
222
|
+
*/
|
|
223
|
+
declare function unsubscribeFromKey(subscriptionID: number): void;
|
|
231
224
|
declare const OnyxUtils: {
|
|
232
225
|
METHOD: {
|
|
233
226
|
readonly SET: "set";
|
|
@@ -238,8 +231,8 @@ declare const OnyxUtils: {
|
|
|
238
231
|
};
|
|
239
232
|
getMergeQueue: typeof getMergeQueue;
|
|
240
233
|
getMergeQueuePromise: typeof getMergeQueuePromise;
|
|
241
|
-
getCallbackToStateMapping: typeof getCallbackToStateMapping;
|
|
242
234
|
getDefaultKeyStates: typeof getDefaultKeyStates;
|
|
235
|
+
getDeferredInitTask: typeof getDeferredInitTask;
|
|
243
236
|
initStoreValues: typeof initStoreValues;
|
|
244
237
|
sendActionToDevTools: typeof sendActionToDevTools;
|
|
245
238
|
maybeFlushBatchUpdates: typeof maybeFlushBatchUpdates;
|
|
@@ -255,14 +248,11 @@ declare const OnyxUtils: {
|
|
|
255
248
|
tryGetCachedValue: typeof tryGetCachedValue;
|
|
256
249
|
removeLastAccessedKey: typeof removeLastAccessedKey;
|
|
257
250
|
addLastAccessedKey: typeof addLastAccessedKey;
|
|
258
|
-
removeFromEvictionBlockList: typeof removeFromEvictionBlockList;
|
|
259
|
-
addToEvictionBlockList: typeof addToEvictionBlockList;
|
|
260
251
|
addAllSafeEvictionKeysToRecentlyAccessedList: typeof addAllSafeEvictionKeysToRecentlyAccessedList;
|
|
261
252
|
getCachedCollection: typeof getCachedCollection;
|
|
262
253
|
keysChanged: typeof keysChanged;
|
|
263
254
|
keyChanged: typeof keyChanged;
|
|
264
255
|
sendDataToConnection: typeof sendDataToConnection;
|
|
265
|
-
addKeyToRecentlyAccessedIfNeeded: typeof addKeyToRecentlyAccessedIfNeeded;
|
|
266
256
|
getCollectionKey: typeof getCollectionKey;
|
|
267
257
|
getCollectionDataAndSendAsObject: typeof getCollectionDataAndSendAsObject;
|
|
268
258
|
scheduleSubscriberUpdate: typeof scheduleSubscriberUpdate;
|
|
@@ -276,11 +266,12 @@ declare const OnyxUtils: {
|
|
|
276
266
|
prepareKeyValuePairsForStorage: typeof prepareKeyValuePairsForStorage;
|
|
277
267
|
applyMerge: typeof applyMerge;
|
|
278
268
|
initializeWithDefaultKeyStates: typeof initializeWithDefaultKeyStates;
|
|
279
|
-
storeKeyByConnections: typeof storeKeyByConnections;
|
|
280
|
-
deleteKeyByConnections: typeof deleteKeyByConnections;
|
|
281
269
|
getSnapshotKey: typeof getSnapshotKey;
|
|
282
270
|
multiGet: typeof multiGet;
|
|
283
271
|
isValidNonEmptyCollectionForMerge: typeof isValidNonEmptyCollectionForMerge;
|
|
284
272
|
doAllCollectionItemsBelongToSameParent: typeof doAllCollectionItemsBelongToSameParent;
|
|
273
|
+
subscribeToKey: typeof subscribeToKey;
|
|
274
|
+
unsubscribeFromKey: typeof unsubscribeFromKey;
|
|
275
|
+
getEvictionBlocklist: typeof getEvictionBlocklist;
|
|
285
276
|
};
|
|
286
277
|
export default OnyxUtils;
|
package/dist/OnyxUtils.js
CHANGED
|
@@ -38,6 +38,7 @@ const Str = __importStar(require("./Str"));
|
|
|
38
38
|
const batch_1 = __importDefault(require("./batch"));
|
|
39
39
|
const storage_1 = __importDefault(require("./storage"));
|
|
40
40
|
const utils_1 = __importDefault(require("./utils"));
|
|
41
|
+
const createDeferredTask_1 = __importDefault(require("./createDeferredTask"));
|
|
41
42
|
// Method constants
|
|
42
43
|
const METHOD = {
|
|
43
44
|
SET: 'set',
|
|
@@ -53,14 +54,14 @@ const mergeQueuePromise = {};
|
|
|
53
54
|
const callbackToStateMapping = {};
|
|
54
55
|
// Keeps a copy of the values of the onyx collection keys as a map for faster lookups
|
|
55
56
|
let onyxCollectionKeySet = new Set();
|
|
56
|
-
// Holds a mapping of the connected key to the
|
|
57
|
-
const
|
|
57
|
+
// Holds a mapping of the connected key to the subscriptionID for faster lookups
|
|
58
|
+
const onyxKeyToSubscriptionIDs = new Map();
|
|
58
59
|
// Holds a list of keys that have been directly subscribed to or recently modified from least to most recent
|
|
59
60
|
let recentlyAccessedKeys = [];
|
|
60
61
|
// Holds a list of keys that are safe to remove when we reach max storage. If a key does not match with
|
|
61
62
|
// whatever appears in this list it will NEVER be a candidate for eviction.
|
|
62
63
|
let evictionAllowList = [];
|
|
63
|
-
// Holds a map of keys and
|
|
64
|
+
// Holds a map of keys and connection arrays whose keys will never be automatically evicted as
|
|
64
65
|
// long as we have at least one subscriber that returns false for the canEvict property.
|
|
65
66
|
const evictionBlocklist = {};
|
|
66
67
|
// Optional user-provided key value states set when Onyx initializes or clears
|
|
@@ -70,6 +71,10 @@ let batchUpdatesQueue = [];
|
|
|
70
71
|
// Used for comparison with a new update to avoid invoking the Onyx.connect callback with the same data.
|
|
71
72
|
const lastConnectionCallbackData = new Map();
|
|
72
73
|
let snapshotKey = null;
|
|
74
|
+
// Keeps track of the last subscriptionID that was used so we can keep incrementing it
|
|
75
|
+
let lastSubscriptionID = 0;
|
|
76
|
+
// Connections can be made before `Onyx.init`. They would wait for this task before resolving
|
|
77
|
+
const deferredInitTask = (0, createDeferredTask_1.default)();
|
|
73
78
|
function getSnapshotKey() {
|
|
74
79
|
return snapshotKey;
|
|
75
80
|
}
|
|
@@ -85,18 +90,24 @@ function getMergeQueue() {
|
|
|
85
90
|
function getMergeQueuePromise() {
|
|
86
91
|
return mergeQueuePromise;
|
|
87
92
|
}
|
|
88
|
-
/**
|
|
89
|
-
* Getter - returns the callback to state mapping.
|
|
90
|
-
*/
|
|
91
|
-
function getCallbackToStateMapping() {
|
|
92
|
-
return callbackToStateMapping;
|
|
93
|
-
}
|
|
94
93
|
/**
|
|
95
94
|
* Getter - returns the default key states.
|
|
96
95
|
*/
|
|
97
96
|
function getDefaultKeyStates() {
|
|
98
97
|
return defaultKeyStates;
|
|
99
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Getter - returns the deffered init task.
|
|
101
|
+
*/
|
|
102
|
+
function getDeferredInitTask() {
|
|
103
|
+
return deferredInitTask;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Getter - returns the eviction block list.
|
|
107
|
+
*/
|
|
108
|
+
function getEvictionBlocklist() {
|
|
109
|
+
return evictionBlocklist;
|
|
110
|
+
}
|
|
100
111
|
/**
|
|
101
112
|
* Sets the initial values for the Onyx store
|
|
102
113
|
*
|
|
@@ -258,29 +269,29 @@ function multiGet(keys) {
|
|
|
258
269
|
}));
|
|
259
270
|
}
|
|
260
271
|
/**
|
|
261
|
-
* Stores a
|
|
272
|
+
* Stores a subscription ID associated with a given key.
|
|
262
273
|
*
|
|
263
|
-
* @param
|
|
264
|
-
* @param key -
|
|
274
|
+
* @param subscriptionID - A subscription ID of the subscriber.
|
|
275
|
+
* @param key - A key that the subscriber is subscribed to.
|
|
265
276
|
*/
|
|
266
|
-
function
|
|
267
|
-
if (!
|
|
268
|
-
|
|
277
|
+
function storeKeyBySubscriptions(key, subscriptionID) {
|
|
278
|
+
if (!onyxKeyToSubscriptionIDs.has(key)) {
|
|
279
|
+
onyxKeyToSubscriptionIDs.set(key, []);
|
|
269
280
|
}
|
|
270
|
-
|
|
281
|
+
onyxKeyToSubscriptionIDs.get(key).push(subscriptionID);
|
|
271
282
|
}
|
|
272
283
|
/**
|
|
273
|
-
* Deletes a
|
|
284
|
+
* Deletes a subscription ID associated with its corresponding key.
|
|
274
285
|
*
|
|
275
|
-
* @param
|
|
286
|
+
* @param subscriptionID - The subscription ID to be deleted.
|
|
276
287
|
*/
|
|
277
|
-
function
|
|
278
|
-
const subscriber = callbackToStateMapping[
|
|
279
|
-
if (subscriber &&
|
|
280
|
-
const
|
|
281
|
-
|
|
288
|
+
function deleteKeyBySubscriptions(subscriptionID) {
|
|
289
|
+
const subscriber = callbackToStateMapping[subscriptionID];
|
|
290
|
+
if (subscriber && onyxKeyToSubscriptionIDs.has(subscriber.key)) {
|
|
291
|
+
const updatedSubscriptionsIDs = onyxKeyToSubscriptionIDs.get(subscriber.key).filter((id) => id !== subscriptionID);
|
|
292
|
+
onyxKeyToSubscriptionIDs.set(subscriber.key, updatedSubscriptionsIDs);
|
|
282
293
|
}
|
|
283
|
-
lastConnectionCallbackData.delete(
|
|
294
|
+
lastConnectionCallbackData.delete(subscriptionID);
|
|
284
295
|
}
|
|
285
296
|
/** Returns current key names stored in persisted storage */
|
|
286
297
|
function getAllKeys() {
|
|
@@ -328,7 +339,9 @@ function splitCollectionMemberKey(key) {
|
|
|
328
339
|
if (underscoreIndex === -1) {
|
|
329
340
|
throw new Error(`Invalid ${key} key provided, only collection keys are allowed.`);
|
|
330
341
|
}
|
|
331
|
-
|
|
342
|
+
const collectionKey = key.substring(0, underscoreIndex + 1);
|
|
343
|
+
const memberKey = key.substring(underscoreIndex + 1);
|
|
344
|
+
return [collectionKey, memberKey];
|
|
332
345
|
}
|
|
333
346
|
/**
|
|
334
347
|
* Checks to see if a provided key is the exact configured key of our connected subscriber
|
|
@@ -409,26 +422,6 @@ function addLastAccessedKey(key) {
|
|
|
409
422
|
removeLastAccessedKey(key);
|
|
410
423
|
recentlyAccessedKeys.push(key);
|
|
411
424
|
}
|
|
412
|
-
/**
|
|
413
|
-
* Removes a key previously added to this list
|
|
414
|
-
* which will enable it to be deleted again.
|
|
415
|
-
*/
|
|
416
|
-
function removeFromEvictionBlockList(key, connectionID) {
|
|
417
|
-
var _a, _b, _c;
|
|
418
|
-
evictionBlocklist[key] = (_b = (_a = evictionBlocklist[key]) === null || _a === void 0 ? void 0 : _a.filter((evictionKey) => evictionKey !== connectionID)) !== null && _b !== void 0 ? _b : [];
|
|
419
|
-
// Remove the key if there are no more subscribers
|
|
420
|
-
if (((_c = evictionBlocklist[key]) === null || _c === void 0 ? void 0 : _c.length) === 0) {
|
|
421
|
-
delete evictionBlocklist[key];
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
/** Keys added to this list can never be deleted. */
|
|
425
|
-
function addToEvictionBlockList(key, connectionID) {
|
|
426
|
-
removeFromEvictionBlockList(key, connectionID);
|
|
427
|
-
if (!evictionBlocklist[key]) {
|
|
428
|
-
evictionBlocklist[key] = [];
|
|
429
|
-
}
|
|
430
|
-
evictionBlocklist[key].push(connectionID);
|
|
431
|
-
}
|
|
432
425
|
/**
|
|
433
426
|
* Take all the keys that are safe to evict and add them to
|
|
434
427
|
* the recently accessed list when initializing the app. This
|
|
@@ -506,7 +499,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
|
|
|
506
499
|
// send the whole cached collection.
|
|
507
500
|
if (isSubscribedToCollectionKey) {
|
|
508
501
|
if (subscriber.waitForCollectionCallback) {
|
|
509
|
-
subscriber.callback(cachedCollection);
|
|
502
|
+
subscriber.callback(cachedCollection, subscriber.key);
|
|
510
503
|
continue;
|
|
511
504
|
}
|
|
512
505
|
// If they are not using waitForCollectionCallback then we notify the subscriber with
|
|
@@ -534,7 +527,7 @@ function keysChanged(collectionKey, partialCollection, partialPreviousCollection
|
|
|
534
527
|
continue;
|
|
535
528
|
}
|
|
536
529
|
// React component subscriber found.
|
|
537
|
-
if (
|
|
530
|
+
if (utils_1.default.hasWithOnyxInstance(subscriber)) {
|
|
538
531
|
if (!notifyWithOnyxSubscibers) {
|
|
539
532
|
continue;
|
|
540
533
|
}
|
|
@@ -645,12 +638,12 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
|
|
|
645
638
|
// Given the amount of times this function is called we need to make sure we are not iterating over all subscribers every time. On the other hand, we don't need to
|
|
646
639
|
// do the same in keysChanged, because we only call that function when a collection key changes, and it doesn't happen that often.
|
|
647
640
|
// For performance reason, we look for the given key and later if don't find it we look for the collection key, instead of checking if it is a collection key first.
|
|
648
|
-
let stateMappingKeys = (_a =
|
|
641
|
+
let stateMappingKeys = (_a = onyxKeyToSubscriptionIDs.get(key)) !== null && _a !== void 0 ? _a : [];
|
|
649
642
|
const collectionKey = getCollectionKey(key);
|
|
650
643
|
const plainCollectionKey = collectionKey.lastIndexOf('_') !== -1 ? collectionKey : undefined;
|
|
651
644
|
if (plainCollectionKey) {
|
|
652
645
|
// Getting the collection key from the specific key because only collection keys were stored in the mapping.
|
|
653
|
-
stateMappingKeys = [...stateMappingKeys, ...((_b =
|
|
646
|
+
stateMappingKeys = [...stateMappingKeys, ...((_b = onyxKeyToSubscriptionIDs.get(plainCollectionKey)) !== null && _b !== void 0 ? _b : [])];
|
|
654
647
|
if (stateMappingKeys.length === 0) {
|
|
655
648
|
return;
|
|
656
649
|
}
|
|
@@ -666,7 +659,7 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
|
|
|
666
659
|
if (!notifyConnectSubscribers) {
|
|
667
660
|
continue;
|
|
668
661
|
}
|
|
669
|
-
if (lastConnectionCallbackData.has(subscriber.
|
|
662
|
+
if (lastConnectionCallbackData.has(subscriber.subscriptionID) && lastConnectionCallbackData.get(subscriber.subscriptionID) === value) {
|
|
670
663
|
continue;
|
|
671
664
|
}
|
|
672
665
|
if (isCollectionKey(subscriber.key) && subscriber.waitForCollectionCallback) {
|
|
@@ -676,16 +669,16 @@ function keyChanged(key, value, previousValue, canUpdateSubscriber = () => true,
|
|
|
676
669
|
cachedCollections[subscriber.key] = cachedCollection;
|
|
677
670
|
}
|
|
678
671
|
cachedCollection[key] = value;
|
|
679
|
-
subscriber.callback(cachedCollection);
|
|
672
|
+
subscriber.callback(cachedCollection, subscriber.key);
|
|
680
673
|
continue;
|
|
681
674
|
}
|
|
682
675
|
const subscriberCallback = subscriber.callback;
|
|
683
676
|
subscriberCallback(value, key);
|
|
684
|
-
lastConnectionCallbackData.set(subscriber.
|
|
677
|
+
lastConnectionCallbackData.set(subscriber.subscriptionID, value);
|
|
685
678
|
continue;
|
|
686
679
|
}
|
|
687
680
|
// Subscriber connected via withOnyx() HOC
|
|
688
|
-
if (
|
|
681
|
+
if (utils_1.default.hasWithOnyxInstance(subscriber)) {
|
|
689
682
|
if (!notifyWithOnyxSubscribers) {
|
|
690
683
|
continue;
|
|
691
684
|
}
|
|
@@ -768,10 +761,10 @@ function sendDataToConnection(mapping, value, matchedKey, isBatched) {
|
|
|
768
761
|
var _a, _b;
|
|
769
762
|
// If the mapping no longer exists then we should not send any data.
|
|
770
763
|
// This means our subscriber disconnected or withOnyx wrapped component unmounted.
|
|
771
|
-
if (!callbackToStateMapping[mapping.
|
|
764
|
+
if (!callbackToStateMapping[mapping.subscriptionID]) {
|
|
772
765
|
return;
|
|
773
766
|
}
|
|
774
|
-
if (
|
|
767
|
+
if (utils_1.default.hasWithOnyxInstance(mapping)) {
|
|
775
768
|
let newData = value;
|
|
776
769
|
// If the mapping has a selector, then the component's state must only be updated with the data
|
|
777
770
|
// returned by the selector.
|
|
@@ -799,10 +792,10 @@ function sendDataToConnection(mapping, value, matchedKey, isBatched) {
|
|
|
799
792
|
// withOnyx will internally replace null values with undefined and never pass null values to wrapped components.
|
|
800
793
|
// For regular callbacks, we never want to pass null values, but always just undefined if a value is not set in cache or storage.
|
|
801
794
|
const valueToPass = value === null ? undefined : value;
|
|
802
|
-
const lastValue = lastConnectionCallbackData.get(mapping.
|
|
803
|
-
lastConnectionCallbackData.get(mapping.
|
|
795
|
+
const lastValue = lastConnectionCallbackData.get(mapping.subscriptionID);
|
|
796
|
+
lastConnectionCallbackData.get(mapping.subscriptionID);
|
|
804
797
|
// If the value has not changed we do not need to trigger the callback
|
|
805
|
-
if (lastConnectionCallbackData.has(mapping.
|
|
798
|
+
if (lastConnectionCallbackData.has(mapping.subscriptionID) && valueToPass === lastValue) {
|
|
806
799
|
return;
|
|
807
800
|
}
|
|
808
801
|
(_b = (_a = mapping).callback) === null || _b === void 0 ? void 0 : _b.call(_a, valueToPass, matchedKey);
|
|
@@ -817,7 +810,7 @@ function addKeyToRecentlyAccessedIfNeeded(mapping) {
|
|
|
817
810
|
}
|
|
818
811
|
// Try to free some cache whenever we connect to a safe eviction key
|
|
819
812
|
OnyxCache_1.default.removeLeastRecentlyUsedKeys();
|
|
820
|
-
if (
|
|
813
|
+
if (utils_1.default.hasWithOnyxInstance(mapping) && !isCollectionKey(mapping.key)) {
|
|
821
814
|
// All React components subscribing to a key flagged as a safe eviction key must implement the canEvict property.
|
|
822
815
|
if (mapping.canEvict === undefined) {
|
|
823
816
|
throw new Error(`Cannot subscribe to safe eviction key '${mapping.key}' without providing a canEvict value.`);
|
|
@@ -994,7 +987,7 @@ function isValidNonEmptyCollectionForMerge(collection) {
|
|
|
994
987
|
function doAllCollectionItemsBelongToSameParent(collectionKey, collectionKeys) {
|
|
995
988
|
let hasCollectionKeyCheckFailed = false;
|
|
996
989
|
collectionKeys.forEach((dataKey) => {
|
|
997
|
-
if (
|
|
990
|
+
if (isKeyMatch(collectionKey, dataKey)) {
|
|
998
991
|
return;
|
|
999
992
|
}
|
|
1000
993
|
if (process.env.NODE_ENV === 'development') {
|
|
@@ -1005,12 +998,116 @@ function doAllCollectionItemsBelongToSameParent(collectionKey, collectionKeys) {
|
|
|
1005
998
|
});
|
|
1006
999
|
return !hasCollectionKeyCheckFailed;
|
|
1007
1000
|
}
|
|
1001
|
+
/**
|
|
1002
|
+
* Subscribes to an Onyx key and listens to its changes.
|
|
1003
|
+
*
|
|
1004
|
+
* @param connectOptions The options object that will define the behavior of the connection.
|
|
1005
|
+
* @returns The subscription ID to use when calling `OnyxUtils.unsubscribeFromKey()`.
|
|
1006
|
+
*/
|
|
1007
|
+
function subscribeToKey(connectOptions) {
|
|
1008
|
+
const mapping = connectOptions;
|
|
1009
|
+
const subscriptionID = lastSubscriptionID++;
|
|
1010
|
+
callbackToStateMapping[subscriptionID] = mapping;
|
|
1011
|
+
callbackToStateMapping[subscriptionID].subscriptionID = subscriptionID;
|
|
1012
|
+
// When keyChanged is called, a key is passed and the method looks through all the Subscribers in callbackToStateMapping for the matching key to get the subscriptionID
|
|
1013
|
+
// to avoid having to loop through all the Subscribers all the time (even when just one connection belongs to one key),
|
|
1014
|
+
// We create a mapping from key to lists of subscriptionIDs to access the specific list of subscriptionIDs.
|
|
1015
|
+
storeKeyBySubscriptions(mapping.key, callbackToStateMapping[subscriptionID].subscriptionID);
|
|
1016
|
+
if (mapping.initWithStoredValues === false) {
|
|
1017
|
+
return subscriptionID;
|
|
1018
|
+
}
|
|
1019
|
+
// Commit connection only after init passes
|
|
1020
|
+
deferredInitTask.promise
|
|
1021
|
+
.then(() => addKeyToRecentlyAccessedIfNeeded(mapping))
|
|
1022
|
+
.then(() => {
|
|
1023
|
+
// Performance improvement
|
|
1024
|
+
// If the mapping is connected to an onyx key that is not a collection
|
|
1025
|
+
// we can skip the call to getAllKeys() and return an array with a single item
|
|
1026
|
+
if (Boolean(mapping.key) && typeof mapping.key === 'string' && !mapping.key.endsWith('_') && OnyxCache_1.default.getAllKeys().has(mapping.key)) {
|
|
1027
|
+
return new Set([mapping.key]);
|
|
1028
|
+
}
|
|
1029
|
+
return getAllKeys();
|
|
1030
|
+
})
|
|
1031
|
+
.then((keys) => {
|
|
1032
|
+
// We search all the keys in storage to see if any are a "match" for the subscriber we are connecting so that we
|
|
1033
|
+
// can send data back to the subscriber. Note that multiple keys can match as a subscriber could either be
|
|
1034
|
+
// subscribed to a "collection key" or a single key.
|
|
1035
|
+
const matchingKeys = [];
|
|
1036
|
+
keys.forEach((key) => {
|
|
1037
|
+
if (!isKeyMatch(mapping.key, key)) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
1040
|
+
matchingKeys.push(key);
|
|
1041
|
+
});
|
|
1042
|
+
// If the key being connected to does not exist we initialize the value with null. For subscribers that connected
|
|
1043
|
+
// directly via connect() they will simply get a null value sent to them without any information about which key matched
|
|
1044
|
+
// since there are none matched. In withOnyx() we wait for all connected keys to return a value before rendering the child
|
|
1045
|
+
// component. This null value will be filtered out so that the connected component can utilize defaultProps.
|
|
1046
|
+
if (matchingKeys.length === 0) {
|
|
1047
|
+
if (mapping.key && !isCollectionKey(mapping.key)) {
|
|
1048
|
+
OnyxCache_1.default.addNullishStorageKey(mapping.key);
|
|
1049
|
+
}
|
|
1050
|
+
// Here we cannot use batching because the nullish value is expected to be set immediately for default props
|
|
1051
|
+
// or they will be undefined.
|
|
1052
|
+
sendDataToConnection(mapping, null, undefined, false);
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
// When using a callback subscriber we will either trigger the provided callback for each key we find or combine all values
|
|
1056
|
+
// into an object and just make a single call. The latter behavior is enabled by providing a waitForCollectionCallback key
|
|
1057
|
+
// combined with a subscription to a collection key.
|
|
1058
|
+
if (typeof mapping.callback === 'function') {
|
|
1059
|
+
if (isCollectionKey(mapping.key)) {
|
|
1060
|
+
if (mapping.waitForCollectionCallback) {
|
|
1061
|
+
getCollectionDataAndSendAsObject(matchingKeys, mapping);
|
|
1062
|
+
return;
|
|
1063
|
+
}
|
|
1064
|
+
// We did not opt into using waitForCollectionCallback mode so the callback is called for every matching key.
|
|
1065
|
+
multiGet(matchingKeys).then((values) => {
|
|
1066
|
+
values.forEach((val, key) => {
|
|
1067
|
+
sendDataToConnection(mapping, val, key, true);
|
|
1068
|
+
});
|
|
1069
|
+
});
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1072
|
+
// If we are not subscribed to a collection key then there's only a single key to send an update for.
|
|
1073
|
+
get(mapping.key).then((val) => sendDataToConnection(mapping, val, mapping.key, true));
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
// If we have a withOnyxInstance that means a React component has subscribed via the withOnyx() HOC and we need to
|
|
1077
|
+
// group collection key member data into an object.
|
|
1078
|
+
if (utils_1.default.hasWithOnyxInstance(mapping)) {
|
|
1079
|
+
if (isCollectionKey(mapping.key)) {
|
|
1080
|
+
getCollectionDataAndSendAsObject(matchingKeys, mapping);
|
|
1081
|
+
return;
|
|
1082
|
+
}
|
|
1083
|
+
// If the subscriber is not using a collection key then we just send a single value back to the subscriber
|
|
1084
|
+
get(mapping.key).then((val) => sendDataToConnection(mapping, val, mapping.key, true));
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
console.error('Warning: Onyx.connect() was found without a callback or withOnyxInstance');
|
|
1088
|
+
});
|
|
1089
|
+
// The subscriptionID is returned back to the caller so that it can be used to clean up the connection when it's no longer needed
|
|
1090
|
+
// by calling OnyxUtils.unsubscribeFromKey(subscriptionID).
|
|
1091
|
+
return subscriptionID;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Disconnects and removes the listener from the Onyx key.
|
|
1095
|
+
*
|
|
1096
|
+
* @param subscriptionID Subscription ID returned by calling `OnyxUtils.subscribeToKey()`.
|
|
1097
|
+
*/
|
|
1098
|
+
function unsubscribeFromKey(subscriptionID) {
|
|
1099
|
+
if (!callbackToStateMapping[subscriptionID]) {
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
deleteKeyBySubscriptions(lastSubscriptionID);
|
|
1103
|
+
delete callbackToStateMapping[subscriptionID];
|
|
1104
|
+
}
|
|
1008
1105
|
const OnyxUtils = {
|
|
1009
1106
|
METHOD,
|
|
1010
1107
|
getMergeQueue,
|
|
1011
1108
|
getMergeQueuePromise,
|
|
1012
|
-
getCallbackToStateMapping,
|
|
1013
1109
|
getDefaultKeyStates,
|
|
1110
|
+
getDeferredInitTask,
|
|
1014
1111
|
initStoreValues,
|
|
1015
1112
|
sendActionToDevTools,
|
|
1016
1113
|
maybeFlushBatchUpdates,
|
|
@@ -1026,14 +1123,11 @@ const OnyxUtils = {
|
|
|
1026
1123
|
tryGetCachedValue,
|
|
1027
1124
|
removeLastAccessedKey,
|
|
1028
1125
|
addLastAccessedKey,
|
|
1029
|
-
removeFromEvictionBlockList,
|
|
1030
|
-
addToEvictionBlockList,
|
|
1031
1126
|
addAllSafeEvictionKeysToRecentlyAccessedList,
|
|
1032
1127
|
getCachedCollection,
|
|
1033
1128
|
keysChanged,
|
|
1034
1129
|
keyChanged,
|
|
1035
1130
|
sendDataToConnection,
|
|
1036
|
-
addKeyToRecentlyAccessedIfNeeded,
|
|
1037
1131
|
getCollectionKey,
|
|
1038
1132
|
getCollectionDataAndSendAsObject,
|
|
1039
1133
|
scheduleSubscriberUpdate,
|
|
@@ -1047,11 +1141,12 @@ const OnyxUtils = {
|
|
|
1047
1141
|
prepareKeyValuePairsForStorage,
|
|
1048
1142
|
applyMerge,
|
|
1049
1143
|
initializeWithDefaultKeyStates,
|
|
1050
|
-
storeKeyByConnections,
|
|
1051
|
-
deleteKeyByConnections,
|
|
1052
1144
|
getSnapshotKey,
|
|
1053
1145
|
multiGet,
|
|
1054
1146
|
isValidNonEmptyCollectionForMerge,
|
|
1055
1147
|
doAllCollectionItemsBelongToSameParent,
|
|
1148
|
+
subscribeToKey,
|
|
1149
|
+
unsubscribeFromKey,
|
|
1150
|
+
getEvictionBlocklist,
|
|
1056
1151
|
};
|
|
1057
1152
|
exports.default = OnyxUtils;
|
package/dist/Str.d.ts
CHANGED
|
@@ -14,4 +14,8 @@ declare function startsWith(haystack: string, needle: string): boolean;
|
|
|
14
14
|
*/
|
|
15
15
|
declare function result(parameter: string): string;
|
|
16
16
|
declare function result<TFunction extends (...a: TArgs) => unknown, TArgs extends unknown[]>(parameter: TFunction, ...args: TArgs): ReturnType<TFunction>;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* A simple GUID generator taken from https://stackoverflow.com/a/32760401/9114791
|
|
19
|
+
*/
|
|
20
|
+
declare function guid(): string;
|
|
21
|
+
export { guid, result, startsWith };
|
package/dist/Str.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.result = exports.
|
|
3
|
+
exports.startsWith = exports.result = exports.guid = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Returns true if the haystack begins with the needle
|
|
6
6
|
*
|
|
@@ -16,3 +16,15 @@ function result(parameter, ...args) {
|
|
|
16
16
|
return typeof parameter === 'function' ? parameter(...args) : parameter;
|
|
17
17
|
}
|
|
18
18
|
exports.result = result;
|
|
19
|
+
/**
|
|
20
|
+
* A simple GUID generator taken from https://stackoverflow.com/a/32760401/9114791
|
|
21
|
+
*/
|
|
22
|
+
function guid() {
|
|
23
|
+
function s4() {
|
|
24
|
+
return Math.floor((1 + Math.random()) * 0x10000)
|
|
25
|
+
.toString(16)
|
|
26
|
+
.substring(1);
|
|
27
|
+
}
|
|
28
|
+
return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`;
|
|
29
|
+
}
|
|
30
|
+
exports.guid = guid;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,10 @@ import type { ConnectOptions, OnyxUpdate } from './Onyx';
|
|
|
2
2
|
import Onyx from './Onyx';
|
|
3
3
|
import type { CustomTypeOptions, KeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxValue, Selector, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput } from './types';
|
|
4
4
|
import type { FetchStatus, ResultMetadata, UseOnyxResult } from './useOnyx';
|
|
5
|
+
import type { Connection } from './OnyxConnectionManager';
|
|
5
6
|
import useOnyx from './useOnyx';
|
|
6
7
|
import withOnyx from './withOnyx';
|
|
7
8
|
import type { WithOnyxState } from './withOnyx/types';
|
|
8
9
|
export default Onyx;
|
|
9
10
|
export { useOnyx, withOnyx };
|
|
10
|
-
export type { ConnectOptions, CustomTypeOptions, FetchStatus, KeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, ResultMetadata, Selector, UseOnyxResult, WithOnyxState, };
|
|
11
|
+
export type { ConnectOptions, CustomTypeOptions, FetchStatus, KeyValueMapping, NullishDeep, OnyxCollection, OnyxEntry, OnyxKey, OnyxInputValue, OnyxCollectionInputValue, OnyxInput, OnyxSetInput, OnyxMultiSetInput, OnyxMergeInput, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, ResultMetadata, Selector, UseOnyxResult, WithOnyxState, Connection, };
|