react-native-onyx 3.0.53 → 3.0.55
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/README.md +0 -53
- package/dist/DevTools/RealDevTools.js +2 -2
- package/dist/Onyx.d.ts +1 -1
- package/dist/Onyx.js +12 -36
- package/dist/OnyxCache.d.ts +0 -26
- package/dist/OnyxCache.js +15 -85
- package/dist/OnyxConnectionManager.js +2 -1
- package/dist/OnyxKeys.d.ts +93 -0
- package/dist/OnyxKeys.js +204 -0
- package/dist/OnyxMerge/index.js +2 -1
- package/dist/OnyxMerge/index.native.js +2 -1
- package/dist/OnyxSnapshotCache.js +2 -2
- package/dist/OnyxUtils.d.ts +1 -69
- package/dist/OnyxUtils.js +37 -200
- package/dist/storage/index.js +0 -19
- package/dist/types.d.ts +0 -5
- package/dist/useOnyx.js +3 -10
- package/package.json +2 -7
- package/dist/GlobalSettings.d.ts +0 -11
- package/dist/GlobalSettings.js +0 -29
- package/dist/dependencies/ModuleProxy.d.ts +0 -10
- package/dist/dependencies/ModuleProxy.js +0 -37
- package/dist/dependencies/PerformanceProxy/index.d.ts +0 -1
- package/dist/dependencies/PerformanceProxy/index.js +0 -4
- package/dist/dependencies/PerformanceProxy/index.native.d.ts +0 -20
- package/dist/dependencies/PerformanceProxy/index.native.js +0 -12
- package/dist/metrics.d.ts +0 -8
- package/dist/metrics.js +0 -47
package/README.md
CHANGED
|
@@ -351,59 +351,6 @@ const ReportActionsView = ({reportID, isActiveReport}) => {
|
|
|
351
351
|
export default ReportActionsView;
|
|
352
352
|
```
|
|
353
353
|
|
|
354
|
-
# Benchmarks
|
|
355
|
-
|
|
356
|
-
Provide the `captureMetrics` boolean flag to `Onyx.init` to capture call statistics
|
|
357
|
-
|
|
358
|
-
```js
|
|
359
|
-
Onyx.init({
|
|
360
|
-
keys: ONYXKEYS,
|
|
361
|
-
evictableKeys: [ONYXKEYS.COLLECTION.REPORT_ACTIONS],
|
|
362
|
-
captureMetrics: Config.BENCHMARK_ONYX,
|
|
363
|
-
});
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
At any point you can get the collected statistics using `Onyx.getMetrics()`.
|
|
367
|
-
This will return an object containing `totalTime`, `averageTime` and `summaries`.
|
|
368
|
-
`summaries` is a collection of statistics for each method it contains data about:
|
|
369
|
-
- method name
|
|
370
|
-
- total, max, min, average times for this method calls
|
|
371
|
-
- calls - a list of individual calls with each having: start time; end time; call duration; call arguments
|
|
372
|
-
- start/end times are relative to application launch time - 0.00 being exactly at launch
|
|
373
|
-
|
|
374
|
-
If you wish to reset the metrics and start over use `Onyx.resetMetrics()`
|
|
375
|
-
|
|
376
|
-
Finally, there's a `Onyx.printMetrics()` method which prints human statistics information on the dev console. You can use this method during debugging. For example add an `Onyx.printMetrics()` line somewhere in code or call it through the dev console. It supports 3 popular formats *MD* - human friendly markdown, *CSV* and *JSON*. The default is MD if you want to print another format call `Onyx.printMetrics({ format: 'csv' })` or
|
|
377
|
-
`Onyx.printMetrics({ format: 'json' })`.
|
|
378
|
-
|
|
379
|
-
Sample output of `Onyx.printMetrics()`
|
|
380
|
-
|
|
381
|
-
```
|
|
382
|
-
### Onyx Benchmark
|
|
383
|
-
- Total: 1.5min
|
|
384
|
-
- Last call finished at: 12.55sec
|
|
385
|
-
|
|
386
|
-
| method | total time spent | max | min | avg | time last call completed | calls made |
|
|
387
|
-
|-----------------|-----------------:|----------:|---------:|----------:|-------------------------:|-----------:|
|
|
388
|
-
| Onyx:getAllKeys | 1.2min | 2.16sec | 0.159ms | 782.230ms | 12.55sec | 90 |
|
|
389
|
-
| Onyx:merge | 4.73sec | 2.00sec | 74.412ms | 591.642ms | 10.24sec | 8 |
|
|
390
|
-
| Onyx:set | 3.90sec | 846.760ms | 43.663ms | 433.056ms | 7.47sec | 9 |
|
|
391
|
-
| Onyx:get | 8.87sec | 2.00sec | 0.063ms | 61.998ms | 10.24sec | 143 |
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
| Onyx:set |
|
|
395
|
-
|---------------------------------------------------------------|
|
|
396
|
-
| start time | end time | duration | args |
|
|
397
|
-
|-----------:|----------:|----------:|--------------------------|
|
|
398
|
-
| 291.042ms | 553.079ms | 262.037ms | session, [object Object] |
|
|
399
|
-
| 293.719ms | 553.316ms | 259.597ms | account, [object Object] |
|
|
400
|
-
| 294.541ms | 553.651ms | 259.109ms | network, [object Object] |
|
|
401
|
-
| 365.378ms | 554.246ms | 188.867ms | iou, [object Object] |
|
|
402
|
-
| 1.08sec | 2.20sec | 1.12sec | network, [object Object] |
|
|
403
|
-
| 1.08sec | 2.20sec | 1.12sec | iou, [object Object] |
|
|
404
|
-
| 1.17sec | 2.20sec | 1.03sec | currentURL, / |
|
|
405
|
-
```
|
|
406
|
-
|
|
407
354
|
# Debug mode
|
|
408
355
|
|
|
409
356
|
It can be useful to log why Onyx is calling `setState()` on a particular React component so that we can understand which key changed, what changed about the value, and the connected component that ultimately rendered as a result. When used correctly this can help isolate problem areas and unnecessary renders in the code. To enable this feature, pass `debugSetState: true` to the config and grep JS console logs for `[Onyx-Debug]`.
|
|
@@ -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
|
-
const
|
|
6
|
+
const OnyxKeys_1 = __importDefault(require("../OnyxKeys"));
|
|
7
7
|
const ERROR_LABEL = 'Onyx DevTools - Error: ';
|
|
8
8
|
/**
|
|
9
9
|
* Real implementation of DevTools that connects to Redux DevTools Extension
|
|
@@ -67,7 +67,7 @@ class RealDevTools {
|
|
|
67
67
|
clearState(keysToPreserve = []) {
|
|
68
68
|
const newState = Object.entries(this.state).reduce((obj, [key, value]) => {
|
|
69
69
|
// eslint-disable-next-line no-param-reassign
|
|
70
|
-
obj[key] = keysToPreserve.some((preserveKey) =>
|
|
70
|
+
obj[key] = keysToPreserve.some((preserveKey) => OnyxKeys_1.default.isKeyMatch(preserveKey, key)) ? value : this.defaultState[key];
|
|
71
71
|
return obj;
|
|
72
72
|
}, {});
|
|
73
73
|
this.registerAction('CLEAR', undefined, newState);
|
package/dist/Onyx.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as Logger from './Logger';
|
|
|
2
2
|
import type { CollectionKeyBase, ConnectOptions, InitOptions, OnyxKey, OnyxMergeCollectionInput, OnyxSetCollectionInput, OnyxMergeInput, OnyxMultiSetInput, OnyxSetInput, OnyxUpdate, SetOptions } from './types';
|
|
3
3
|
import type { Connection } from './OnyxConnectionManager';
|
|
4
4
|
/** Initialize the store with actions and listening for storage events */
|
|
5
|
-
declare function init({ keys, initialKeyStates, evictableKeys, maxCachedKeysCount, shouldSyncMultipleInstances,
|
|
5
|
+
declare function init({ keys, initialKeyStates, evictableKeys, maxCachedKeysCount, shouldSyncMultipleInstances, enableDevTools, skippableCollectionMemberIDs, ramOnlyKeys, snapshotMergeKeys, }: InitOptions): void;
|
|
6
6
|
/**
|
|
7
7
|
* Connects to an Onyx key given the options passed and listens to its changes.
|
|
8
8
|
* This method will be deprecated soon. Please use `Onyx.connectWithoutView()` instead.
|
package/dist/Onyx.js
CHANGED
|
@@ -42,35 +42,30 @@ const storage_1 = __importDefault(require("./storage"));
|
|
|
42
42
|
const utils_1 = __importDefault(require("./utils"));
|
|
43
43
|
const DevTools_1 = __importStar(require("./DevTools"));
|
|
44
44
|
const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
|
|
45
|
+
const OnyxKeys_1 = __importDefault(require("./OnyxKeys"));
|
|
45
46
|
const logMessages_1 = __importDefault(require("./logMessages"));
|
|
46
47
|
const OnyxConnectionManager_1 = __importDefault(require("./OnyxConnectionManager"));
|
|
47
|
-
const GlobalSettings = __importStar(require("./GlobalSettings"));
|
|
48
|
-
const metrics_1 = __importDefault(require("./metrics"));
|
|
49
48
|
const OnyxMerge_1 = __importDefault(require("./OnyxMerge"));
|
|
50
49
|
/** Initialize the store with actions and listening for storage events */
|
|
51
|
-
function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = !!global.localStorage,
|
|
50
|
+
function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedKeysCount = 1000, shouldSyncMultipleInstances = !!global.localStorage, enableDevTools = true, skippableCollectionMemberIDs = [], ramOnlyKeys = [], snapshotMergeKeys = [], }) {
|
|
52
51
|
var _a;
|
|
53
|
-
if (enablePerformanceMetrics) {
|
|
54
|
-
GlobalSettings.setPerformanceMetricsEnabled(true);
|
|
55
|
-
applyDecorators();
|
|
56
|
-
}
|
|
57
52
|
(0, DevTools_1.initDevTools)(enableDevTools);
|
|
58
53
|
storage_1.default.init();
|
|
59
54
|
OnyxUtils_1.default.setSkippableCollectionMemberIDs(new Set(skippableCollectionMemberIDs));
|
|
60
55
|
OnyxUtils_1.default.setSnapshotMergeKeys(new Set(snapshotMergeKeys));
|
|
61
|
-
|
|
56
|
+
OnyxKeys_1.default.setRamOnlyKeys(new Set(ramOnlyKeys));
|
|
62
57
|
if (shouldSyncMultipleInstances) {
|
|
63
58
|
(_a = storage_1.default.keepInstancesSync) === null || _a === void 0 ? void 0 : _a.call(storage_1.default, (key, value) => {
|
|
64
59
|
// RAM-only keys should never sync from storage as they may have stale persisted data
|
|
65
60
|
// from before the key was migrated to RAM-only.
|
|
66
|
-
if (
|
|
61
|
+
if (OnyxKeys_1.default.isRamOnlyKey(key)) {
|
|
67
62
|
return;
|
|
68
63
|
}
|
|
69
64
|
OnyxCache_1.default.set(key, value);
|
|
70
65
|
// Check if this is a collection member key to prevent duplicate callbacks
|
|
71
66
|
// When a collection is updated, individual members sync separately to other tabs
|
|
72
67
|
// Setting isProcessingCollectionUpdate=true prevents triggering collection callbacks for each individual update
|
|
73
|
-
const isKeyCollectionMember =
|
|
68
|
+
const isKeyCollectionMember = OnyxKeys_1.default.isCollectionMember(key);
|
|
74
69
|
OnyxUtils_1.default.keyChanged(key, value, undefined, isKeyCollectionMember);
|
|
75
70
|
});
|
|
76
71
|
}
|
|
@@ -83,7 +78,7 @@ function init({ keys = {}, initialKeyStates = {}, evictableKeys = [], maxCachedK
|
|
|
83
78
|
// eager cache loading populates the key index (cache.setAllKeys) inside initializeWithDefaultKeyStates,
|
|
84
79
|
// and the evictable keys list depends on that index being populated.
|
|
85
80
|
OnyxUtils_1.default.initializeWithDefaultKeyStates()
|
|
86
|
-
.then(() => OnyxCache_1.default.addEvictableKeysToRecentlyAccessedList(
|
|
81
|
+
.then(() => OnyxCache_1.default.addEvictableKeysToRecentlyAccessedList(OnyxKeys_1.default.isCollectionKey, OnyxUtils_1.default.getAllKeys))
|
|
87
82
|
.then(OnyxUtils_1.default.getDeferredInitTask().resolve);
|
|
88
83
|
}
|
|
89
84
|
/**
|
|
@@ -194,7 +189,7 @@ function merge(key, changes) {
|
|
|
194
189
|
const skippableCollectionMemberIDs = OnyxUtils_1.default.getSkippableCollectionMemberIDs();
|
|
195
190
|
if (skippableCollectionMemberIDs.size) {
|
|
196
191
|
try {
|
|
197
|
-
const [, collectionMemberID] =
|
|
192
|
+
const [, collectionMemberID] = OnyxKeys_1.default.splitCollectionMemberKey(key);
|
|
198
193
|
if (skippableCollectionMemberIDs.has(collectionMemberID)) {
|
|
199
194
|
// The key is a skippable one, so we set the new changes to undefined.
|
|
200
195
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -322,7 +317,7 @@ function clear(keysToPreserve = []) {
|
|
|
322
317
|
// to null would cause unknown behavior)
|
|
323
318
|
// 2.1 However, if a default key was explicitly set to null, we need to reset it to the default value
|
|
324
319
|
for (const key of allKeys) {
|
|
325
|
-
const isKeyToPreserve = keysToPreserve.some((preserveKey) =>
|
|
320
|
+
const isKeyToPreserve = keysToPreserve.some((preserveKey) => OnyxKeys_1.default.isKeyMatch(preserveKey, key));
|
|
326
321
|
const isDefaultKey = key in defaultKeyStates;
|
|
327
322
|
// If the key is being removed or reset to default:
|
|
328
323
|
// 1. Update it in the cache
|
|
@@ -333,7 +328,7 @@ function clear(keysToPreserve = []) {
|
|
|
333
328
|
const newValue = (_a = defaultKeyStates[key]) !== null && _a !== void 0 ? _a : null;
|
|
334
329
|
if (newValue !== oldValue) {
|
|
335
330
|
OnyxCache_1.default.set(key, newValue);
|
|
336
|
-
const collectionKey =
|
|
331
|
+
const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
|
|
337
332
|
if (collectionKey) {
|
|
338
333
|
if (!keyValuesToResetAsCollection[collectionKey]) {
|
|
339
334
|
keyValuesToResetAsCollection[collectionKey] = { oldValues: {}, newValues: {} };
|
|
@@ -362,7 +357,7 @@ function clear(keysToPreserve = []) {
|
|
|
362
357
|
}
|
|
363
358
|
// Exclude RAM-only keys to prevent them from being saved to storage
|
|
364
359
|
const defaultKeyValuePairs = Object.entries(Object.keys(defaultKeyStates)
|
|
365
|
-
.filter((key) => !keysToPreserve.some((preserveKey) =>
|
|
360
|
+
.filter((key) => !keysToPreserve.some((preserveKey) => OnyxKeys_1.default.isKeyMatch(preserveKey, key)) && !OnyxKeys_1.default.isRamOnlyKey(key))
|
|
366
361
|
.reduce((obj, key) => {
|
|
367
362
|
// eslint-disable-next-line no-param-reassign
|
|
368
363
|
obj[key] = defaultKeyStates[key];
|
|
@@ -459,8 +454,8 @@ function update(data) {
|
|
|
459
454
|
// Group all the collection-related keys and update each collection in a single `mergeCollection` call.
|
|
460
455
|
// This is needed to prevent multiple `mergeCollection` calls for the same collection and `merge` calls for the individual items of the said collection.
|
|
461
456
|
// This way, we ensure there is no race condition in the queued updates of the same key.
|
|
462
|
-
for (const collectionKey of
|
|
463
|
-
const collectionItemKeys = Object.keys(updateQueue).filter((key) =>
|
|
457
|
+
for (const collectionKey of OnyxKeys_1.default.getCollectionKeys()) {
|
|
458
|
+
const collectionItemKeys = Object.keys(updateQueue).filter((key) => OnyxKeys_1.default.isKeyMatch(collectionKey, key));
|
|
464
459
|
if (collectionItemKeys.length <= 1) {
|
|
465
460
|
// If there are no items of this collection in the updateQueue, we should skip it.
|
|
466
461
|
// If there is only one item, we should update it individually, therefore retain it in the updateQueue.
|
|
@@ -548,23 +543,4 @@ const Onyx = {
|
|
|
548
543
|
init,
|
|
549
544
|
registerLogger: Logger.registerLogger,
|
|
550
545
|
};
|
|
551
|
-
function applyDecorators() {
|
|
552
|
-
// We are reassigning the functions directly so that internal function calls are also decorated
|
|
553
|
-
// @ts-expect-error Reassign
|
|
554
|
-
connect = (0, metrics_1.default)(connect, 'Onyx.connect');
|
|
555
|
-
// @ts-expect-error Reassign
|
|
556
|
-
connectWithoutView = (0, metrics_1.default)(connectWithoutView, 'Onyx.connectWithoutView');
|
|
557
|
-
// @ts-expect-error Reassign
|
|
558
|
-
set = (0, metrics_1.default)(set, 'Onyx.set');
|
|
559
|
-
// @ts-expect-error Reassign
|
|
560
|
-
multiSet = (0, metrics_1.default)(multiSet, 'Onyx.multiSet');
|
|
561
|
-
// @ts-expect-error Reassign
|
|
562
|
-
merge = (0, metrics_1.default)(merge, 'Onyx.merge');
|
|
563
|
-
// @ts-expect-error Reassign
|
|
564
|
-
mergeCollection = (0, metrics_1.default)(mergeCollection, 'Onyx.mergeCollection');
|
|
565
|
-
// @ts-expect-error Reassign
|
|
566
|
-
update = (0, metrics_1.default)(update, 'Onyx.update');
|
|
567
|
-
// @ts-expect-error Reassign
|
|
568
|
-
clear = (0, metrics_1.default)(clear, 'Onyx.clear');
|
|
569
|
-
}
|
|
570
546
|
exports.default = Onyx;
|
package/dist/OnyxCache.d.ts
CHANGED
|
@@ -34,10 +34,6 @@ declare class OnyxCache {
|
|
|
34
34
|
private evictionBlocklist;
|
|
35
35
|
/** List of keys that have been directly subscribed to or recently modified from least to most recent */
|
|
36
36
|
private recentlyAccessedKeys;
|
|
37
|
-
/** Set of collection keys for fast lookup */
|
|
38
|
-
private collectionKeys;
|
|
39
|
-
/** Set of RAM-only keys for fast lookup */
|
|
40
|
-
private ramOnlyKeys;
|
|
41
37
|
constructor();
|
|
42
38
|
/** Get all the storage keys */
|
|
43
39
|
getAllKeys(): Set<OnyxKey>;
|
|
@@ -122,12 +118,6 @@ declare class OnyxCache {
|
|
|
122
118
|
* @param testKey - Key to check
|
|
123
119
|
*/
|
|
124
120
|
isEvictableKey(testKey: OnyxKey): boolean;
|
|
125
|
-
/**
|
|
126
|
-
* Check if a given key matches a pattern key
|
|
127
|
-
* @param configKey - Pattern that may contain a wildcard
|
|
128
|
-
* @param key - Key to test against the pattern
|
|
129
|
-
*/
|
|
130
|
-
private isKeyMatch;
|
|
131
121
|
/**
|
|
132
122
|
* Remove a key from the recently accessed key list.
|
|
133
123
|
*/
|
|
@@ -155,26 +145,10 @@ declare class OnyxCache {
|
|
|
155
145
|
* Set the collection keys for optimized storage
|
|
156
146
|
*/
|
|
157
147
|
setCollectionKeys(collectionKeys: Set<OnyxKey>): void;
|
|
158
|
-
/**
|
|
159
|
-
* Check if a key is a collection key
|
|
160
|
-
*/
|
|
161
|
-
isCollectionKey(key: OnyxKey): boolean;
|
|
162
|
-
/**
|
|
163
|
-
* Get the collection key for a given member key
|
|
164
|
-
*/
|
|
165
|
-
getCollectionKey(key: OnyxKey): OnyxKey | undefined;
|
|
166
148
|
/**
|
|
167
149
|
* Get all data for a collection key
|
|
168
150
|
*/
|
|
169
151
|
getCollectionData(collectionKey: OnyxKey): Record<OnyxKey, OnyxValue<OnyxKey>> | undefined;
|
|
170
|
-
/**
|
|
171
|
-
* Set the RAM-only keys for optimized storage
|
|
172
|
-
*/
|
|
173
|
-
setRamOnlyKeys(ramOnlyKeys: Set<OnyxKey>): void;
|
|
174
|
-
/**
|
|
175
|
-
* Check if a key is a RAM-only key
|
|
176
|
-
*/
|
|
177
|
-
isRamOnlyKey(key: OnyxKey): boolean;
|
|
178
152
|
}
|
|
179
153
|
declare const instance: OnyxCache;
|
|
180
154
|
export default instance;
|
package/dist/OnyxCache.js
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
4
|
};
|
|
@@ -40,7 +7,7 @@ exports.TASK = void 0;
|
|
|
40
7
|
const fast_equals_1 = require("fast-equals");
|
|
41
8
|
const bindAll_1 = __importDefault(require("lodash/bindAll"));
|
|
42
9
|
const utils_1 = __importDefault(require("./utils"));
|
|
43
|
-
const
|
|
10
|
+
const OnyxKeys_1 = __importDefault(require("./OnyxKeys"));
|
|
44
11
|
// Task constants
|
|
45
12
|
const TASK = {
|
|
46
13
|
GET: 'get',
|
|
@@ -62,10 +29,6 @@ class OnyxCache {
|
|
|
62
29
|
this.evictionBlocklist = {};
|
|
63
30
|
/** List of keys that have been directly subscribed to or recently modified from least to most recent */
|
|
64
31
|
this.recentlyAccessedKeys = new Set();
|
|
65
|
-
/** Set of collection keys for fast lookup */
|
|
66
|
-
this.collectionKeys = new Set();
|
|
67
|
-
/** Set of RAM-only keys for fast lookup */
|
|
68
|
-
this.ramOnlyKeys = new Set();
|
|
69
32
|
this.storageKeys = new Set();
|
|
70
33
|
this.nullishStorageKeys = new Set();
|
|
71
34
|
this.recentKeys = new Set();
|
|
@@ -73,7 +36,7 @@ class OnyxCache {
|
|
|
73
36
|
this.collectionData = {};
|
|
74
37
|
this.pendingPromises = new Map();
|
|
75
38
|
// bind all public methods to prevent problems with `this`
|
|
76
|
-
(0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction', 'setCollectionKeys', '
|
|
39
|
+
(0, bindAll_1.default)(this, 'getAllKeys', 'get', 'hasCacheForKey', 'addKey', 'addNullishStorageKey', 'hasNullishStorageKey', 'clearNullishStorageKeys', 'set', 'drop', 'merge', 'hasPendingTask', 'getTaskPromise', 'captureTask', 'addToAccessedKeys', 'removeLeastRecentlyUsedKeys', 'setRecentKeysLimit', 'setAllKeys', 'setEvictionAllowList', 'getEvictionBlocklist', 'isEvictableKey', 'removeLastAccessedKey', 'addLastAccessedKey', 'addEvictableKeysToRecentlyAccessedList', 'getKeyForEviction', 'setCollectionKeys', 'getCollectionData', 'hasValueChanged');
|
|
77
40
|
}
|
|
78
41
|
/** Get all the storage keys */
|
|
79
42
|
getAllKeys() {
|
|
@@ -92,12 +55,16 @@ class OnyxCache {
|
|
|
92
55
|
*/
|
|
93
56
|
setAllKeys(keys) {
|
|
94
57
|
this.storageKeys = new Set(keys);
|
|
58
|
+
for (const key of keys) {
|
|
59
|
+
OnyxKeys_1.default.registerMemberKey(key);
|
|
60
|
+
}
|
|
95
61
|
}
|
|
96
62
|
/** Saves a key in the storage keys list
|
|
97
63
|
* Serves to keep the result of `getAllKeys` up to date
|
|
98
64
|
*/
|
|
99
65
|
addKey(key) {
|
|
100
66
|
this.storageKeys.add(key);
|
|
67
|
+
OnyxKeys_1.default.registerMemberKey(key);
|
|
101
68
|
}
|
|
102
69
|
/** Used to set keys that are null/undefined in storage without adding null to the storage map */
|
|
103
70
|
addNullishStorageKey(key) {
|
|
@@ -135,7 +102,7 @@ class OnyxCache {
|
|
|
135
102
|
// When a key is explicitly set in cache, we can remove it from the list of nullish keys,
|
|
136
103
|
// since it will either be set to a non nullish value or removed from the cache completely.
|
|
137
104
|
this.nullishStorageKeys.delete(key);
|
|
138
|
-
const collectionKey =
|
|
105
|
+
const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
|
|
139
106
|
if (value === null || value === undefined) {
|
|
140
107
|
delete this.storageMap[key];
|
|
141
108
|
// Remove from collection data cache if it's a collection member
|
|
@@ -158,16 +125,17 @@ class OnyxCache {
|
|
|
158
125
|
drop(key) {
|
|
159
126
|
delete this.storageMap[key];
|
|
160
127
|
// Remove from collection data cache if this is a collection member
|
|
161
|
-
const collectionKey =
|
|
128
|
+
const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
|
|
162
129
|
if (collectionKey && this.collectionData[collectionKey]) {
|
|
163
130
|
delete this.collectionData[collectionKey][key];
|
|
164
131
|
}
|
|
165
132
|
// If this is a collection key, clear its data
|
|
166
|
-
if (
|
|
133
|
+
if (OnyxKeys_1.default.isCollectionKey(key)) {
|
|
167
134
|
delete this.collectionData[key];
|
|
168
135
|
}
|
|
169
136
|
this.storageKeys.delete(key);
|
|
170
137
|
this.recentKeys.delete(key);
|
|
138
|
+
OnyxKeys_1.default.deregisterMemberKey(key);
|
|
171
139
|
}
|
|
172
140
|
/**
|
|
173
141
|
* Deep merge data to cache, any non existing keys will be created
|
|
@@ -184,7 +152,7 @@ class OnyxCache {
|
|
|
184
152
|
for (const [key, value] of Object.entries(data)) {
|
|
185
153
|
this.addKey(key);
|
|
186
154
|
this.addToAccessedKeys(key);
|
|
187
|
-
const collectionKey =
|
|
155
|
+
const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
|
|
188
156
|
if (value === null || value === undefined) {
|
|
189
157
|
this.addNullishStorageKey(key);
|
|
190
158
|
// Remove from collection data cache if it's a collection member
|
|
@@ -260,7 +228,7 @@ class OnyxCache {
|
|
|
260
228
|
for (const key of keysToRemove) {
|
|
261
229
|
delete this.storageMap[key];
|
|
262
230
|
// Remove from collection data cache if this is a collection member
|
|
263
|
-
const collectionKey =
|
|
231
|
+
const collectionKey = OnyxKeys_1.default.getCollectionKey(key);
|
|
264
232
|
if (collectionKey && this.collectionData[collectionKey]) {
|
|
265
233
|
delete this.collectionData[collectionKey][key];
|
|
266
234
|
}
|
|
@@ -294,16 +262,7 @@ class OnyxCache {
|
|
|
294
262
|
* @param testKey - Key to check
|
|
295
263
|
*/
|
|
296
264
|
isEvictableKey(testKey) {
|
|
297
|
-
return this.evictionAllowList.some((key) =>
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Check if a given key matches a pattern key
|
|
301
|
-
* @param configKey - Pattern that may contain a wildcard
|
|
302
|
-
* @param key - Key to test against the pattern
|
|
303
|
-
*/
|
|
304
|
-
isKeyMatch(configKey, key) {
|
|
305
|
-
const isCollectionKey = configKey.endsWith('_');
|
|
306
|
-
return isCollectionKey ? Str.startsWith(key, configKey) : configKey === key;
|
|
265
|
+
return this.evictionAllowList.some((key) => OnyxKeys_1.default.isKeyMatch(key, testKey));
|
|
307
266
|
}
|
|
308
267
|
/**
|
|
309
268
|
* Remove a key from the recently accessed key list.
|
|
@@ -336,7 +295,7 @@ class OnyxCache {
|
|
|
336
295
|
return getAllKeysFn().then((keys) => {
|
|
337
296
|
for (const evictableKey of this.evictionAllowList) {
|
|
338
297
|
for (const key of keys) {
|
|
339
|
-
if (!
|
|
298
|
+
if (!OnyxKeys_1.default.isKeyMatch(evictableKey, key)) {
|
|
340
299
|
continue;
|
|
341
300
|
}
|
|
342
301
|
this.addLastAccessedKey(key, isCollectionKeyFn(key));
|
|
@@ -359,7 +318,7 @@ class OnyxCache {
|
|
|
359
318
|
* Set the collection keys for optimized storage
|
|
360
319
|
*/
|
|
361
320
|
setCollectionKeys(collectionKeys) {
|
|
362
|
-
|
|
321
|
+
OnyxKeys_1.default.setCollectionKeys(collectionKeys);
|
|
363
322
|
// Initialize collection data for existing collection keys
|
|
364
323
|
for (const collectionKey of collectionKeys) {
|
|
365
324
|
if (this.collectionData[collectionKey]) {
|
|
@@ -368,23 +327,6 @@ class OnyxCache {
|
|
|
368
327
|
this.collectionData[collectionKey] = {};
|
|
369
328
|
}
|
|
370
329
|
}
|
|
371
|
-
/**
|
|
372
|
-
* Check if a key is a collection key
|
|
373
|
-
*/
|
|
374
|
-
isCollectionKey(key) {
|
|
375
|
-
return this.collectionKeys.has(key);
|
|
376
|
-
}
|
|
377
|
-
/**
|
|
378
|
-
* Get the collection key for a given member key
|
|
379
|
-
*/
|
|
380
|
-
getCollectionKey(key) {
|
|
381
|
-
for (const collectionKey of this.collectionKeys) {
|
|
382
|
-
if (key.startsWith(collectionKey) && key.length > collectionKey.length) {
|
|
383
|
-
return collectionKey;
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
return undefined;
|
|
387
|
-
}
|
|
388
330
|
/**
|
|
389
331
|
* Get all data for a collection key
|
|
390
332
|
*/
|
|
@@ -396,18 +338,6 @@ class OnyxCache {
|
|
|
396
338
|
// Return a shallow copy to ensure React detects changes when items are added/removed
|
|
397
339
|
return Object.assign({}, cachedCollection);
|
|
398
340
|
}
|
|
399
|
-
/**
|
|
400
|
-
* Set the RAM-only keys for optimized storage
|
|
401
|
-
*/
|
|
402
|
-
setRamOnlyKeys(ramOnlyKeys) {
|
|
403
|
-
this.ramOnlyKeys = ramOnlyKeys;
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Check if a key is a RAM-only key
|
|
407
|
-
*/
|
|
408
|
-
isRamOnlyKey(key) {
|
|
409
|
-
return this.ramOnlyKeys.has(key);
|
|
410
|
-
}
|
|
411
341
|
}
|
|
412
342
|
const instance = new OnyxCache();
|
|
413
343
|
exports.default = instance;
|
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
const bindAll_1 = __importDefault(require("lodash/bindAll"));
|
|
40
40
|
const Logger = __importStar(require("./Logger"));
|
|
41
41
|
const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
|
|
42
|
+
const OnyxKeys_1 = __importDefault(require("./OnyxKeys"));
|
|
42
43
|
const Str = __importStar(require("./Str"));
|
|
43
44
|
const OnyxCache_1 = __importDefault(require("./OnyxCache"));
|
|
44
45
|
const OnyxSnapshotCache_1 = __importDefault(require("./OnyxSnapshotCache"));
|
|
@@ -71,7 +72,7 @@ class OnyxConnectionManager {
|
|
|
71
72
|
// in order to send all the collection entries, so the connection can't be reused.
|
|
72
73
|
if (reuseConnection === false ||
|
|
73
74
|
initWithStoredValues === false ||
|
|
74
|
-
(
|
|
75
|
+
(OnyxKeys_1.default.isCollectionKey(key) && (waitForCollectionCallback === undefined || waitForCollectionCallback === false))) {
|
|
75
76
|
suffix += `,uniqueID=${Str.guid()}`;
|
|
76
77
|
}
|
|
77
78
|
return `onyxKey=${key},initWithStoredValues=${initWithStoredValues !== null && initWithStoredValues !== void 0 ? initWithStoredValues : true},waitForCollectionCallback=${waitForCollectionCallback !== null && waitForCollectionCallback !== void 0 ? waitForCollectionCallback : false}${suffix}`;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { CollectionKeyBase, CollectionKey, OnyxKey } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Initializes the collection key set. Called once during Onyx.init().
|
|
4
|
+
*/
|
|
5
|
+
declare function setCollectionKeys(keys: Set<OnyxKey>): void;
|
|
6
|
+
/**
|
|
7
|
+
* Returns the set of all registered collection keys.
|
|
8
|
+
*/
|
|
9
|
+
declare function getCollectionKeys(): Set<OnyxKey>;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the given key is a registered collection key (e.g. "report_").
|
|
12
|
+
*/
|
|
13
|
+
declare function isCollectionKey(key: OnyxKey): key is CollectionKeyBase;
|
|
14
|
+
/**
|
|
15
|
+
* Checks if the given key is a member of the specified collection key.
|
|
16
|
+
* e.g. isCollectionMemberKey("report_", "report_123") → true
|
|
17
|
+
*/
|
|
18
|
+
declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>(collectionKey: TCollectionKey, key: string): key is `${TCollectionKey}${string}`;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if a given key is a collection member key (not just a collection key).
|
|
21
|
+
*/
|
|
22
|
+
declare function isCollectionMember(key: OnyxKey): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the provided key matches the config key — either an exact match
|
|
25
|
+
* or a collection prefix match.
|
|
26
|
+
*/
|
|
27
|
+
declare function isKeyMatch(configKey: OnyxKey, key: OnyxKey): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Extracts the collection key from a collection member key.
|
|
30
|
+
*
|
|
31
|
+
* Uses a pre-computed Map for O(1) lookup. Falls back to string parsing
|
|
32
|
+
* for keys not yet in the map (e.g. before they're cached).
|
|
33
|
+
*
|
|
34
|
+
* Examples:
|
|
35
|
+
* - getCollectionKey("report_123") → "report_"
|
|
36
|
+
* - getCollectionKey("report_") → "report_"
|
|
37
|
+
* - getCollectionKey("sharedNVP_user_-1_something") → "sharedNVP_user_"
|
|
38
|
+
*/
|
|
39
|
+
declare function getCollectionKey(key: CollectionKey | OnyxKey): string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* Pre-computes and caches the member → collection key mapping for a given key.
|
|
42
|
+
* Called from OnyxCache.addKey() to ensure the Map stays populated.
|
|
43
|
+
*/
|
|
44
|
+
declare function registerMemberKey(key: OnyxKey): void;
|
|
45
|
+
/**
|
|
46
|
+
* Removes a member key from the reverse lookup map.
|
|
47
|
+
* Called when a key is dropped from cache.
|
|
48
|
+
*/
|
|
49
|
+
declare function deregisterMemberKey(key: OnyxKey): void;
|
|
50
|
+
/**
|
|
51
|
+
* Returns the set of member keys for a given collection key.
|
|
52
|
+
* O(1) lookup using the forward index.
|
|
53
|
+
*/
|
|
54
|
+
declare function getMembersOfCollection(collectionKey: OnyxKey): Set<OnyxKey> | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* Splits a collection member key into the collection key part and the ID part.
|
|
57
|
+
*
|
|
58
|
+
* @param key - The collection member key to split
|
|
59
|
+
* @param collectionKey - Optional pre-resolved collection key for optimization
|
|
60
|
+
* @returns A tuple of [collectionKey, memberId]
|
|
61
|
+
* @throws If the key is not a valid collection member key
|
|
62
|
+
*/
|
|
63
|
+
declare function splitCollectionMemberKey<TKey extends CollectionKey, CollectionKeyType = TKey extends `${infer Prefix}_${string}` ? `${Prefix}_` : never>(key: TKey, collectionKey?: string): [CollectionKeyType, string];
|
|
64
|
+
/**
|
|
65
|
+
* Initializes the RAM-only key set. Called once during Onyx.init().
|
|
66
|
+
*/
|
|
67
|
+
declare function setRamOnlyKeys(keys: Set<OnyxKey>): void;
|
|
68
|
+
/**
|
|
69
|
+
* Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member.
|
|
70
|
+
*
|
|
71
|
+
* For example, given ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]:
|
|
72
|
+
* - isRamOnlyKey("ramOnlyKey") → true
|
|
73
|
+
* - isRamOnlyKey("ramOnlyCollection_") → true
|
|
74
|
+
* - isRamOnlyKey("ramOnlyCollection_1") → true
|
|
75
|
+
* - isRamOnlyKey("someOtherKey") → false
|
|
76
|
+
*/
|
|
77
|
+
declare function isRamOnlyKey(key: OnyxKey): boolean;
|
|
78
|
+
declare const _default: {
|
|
79
|
+
setCollectionKeys: typeof setCollectionKeys;
|
|
80
|
+
getCollectionKeys: typeof getCollectionKeys;
|
|
81
|
+
isCollectionKey: typeof isCollectionKey;
|
|
82
|
+
isCollectionMemberKey: typeof isCollectionMemberKey;
|
|
83
|
+
isCollectionMember: typeof isCollectionMember;
|
|
84
|
+
isKeyMatch: typeof isKeyMatch;
|
|
85
|
+
getCollectionKey: typeof getCollectionKey;
|
|
86
|
+
registerMemberKey: typeof registerMemberKey;
|
|
87
|
+
deregisterMemberKey: typeof deregisterMemberKey;
|
|
88
|
+
getMembersOfCollection: typeof getMembersOfCollection;
|
|
89
|
+
splitCollectionMemberKey: typeof splitCollectionMemberKey;
|
|
90
|
+
setRamOnlyKeys: typeof setRamOnlyKeys;
|
|
91
|
+
isRamOnlyKey: typeof isRamOnlyKey;
|
|
92
|
+
};
|
|
93
|
+
export default _default;
|