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.
@@ -0,0 +1,204 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /** Single source of truth for the set of registered collection keys */
4
+ let collectionKeySet = new Set();
5
+ /** Reverse lookup: member key → collection key for O(1) access */
6
+ const memberToCollectionKeyMap = new Map();
7
+ /** Forward lookup: collection key → set of member keys for O(collectionMembers) iteration */
8
+ const collectionToMembersMap = new Map();
9
+ /** Set of keys that should only be stored in RAM, not persisted to storage */
10
+ let ramOnlyKeySet = new Set();
11
+ /**
12
+ * Initializes the collection key set. Called once during Onyx.init().
13
+ */
14
+ function setCollectionKeys(keys) {
15
+ collectionKeySet = keys;
16
+ }
17
+ /**
18
+ * Returns the set of all registered collection keys.
19
+ */
20
+ function getCollectionKeys() {
21
+ return collectionKeySet;
22
+ }
23
+ /**
24
+ * Checks if the given key is a registered collection key (e.g. "report_").
25
+ */
26
+ function isCollectionKey(key) {
27
+ return collectionKeySet.has(key);
28
+ }
29
+ /**
30
+ * Checks if the given key is a member of the specified collection key.
31
+ * e.g. isCollectionMemberKey("report_", "report_123") → true
32
+ */
33
+ function isCollectionMemberKey(collectionKey, key) {
34
+ return key.startsWith(collectionKey) && key.length > collectionKey.length;
35
+ }
36
+ /**
37
+ * Checks if a given key is a collection member key (not just a collection key).
38
+ */
39
+ function isCollectionMember(key) {
40
+ const collectionKey = getCollectionKey(key);
41
+ return !!collectionKey && key.length > collectionKey.length;
42
+ }
43
+ /**
44
+ * Checks if the provided key matches the config key — either an exact match
45
+ * or a collection prefix match.
46
+ */
47
+ function isKeyMatch(configKey, key) {
48
+ return isCollectionKey(configKey) ? key.startsWith(configKey) : configKey === key;
49
+ }
50
+ /**
51
+ * Extracts the collection key from a collection member key.
52
+ *
53
+ * Uses a pre-computed Map for O(1) lookup. Falls back to string parsing
54
+ * for keys not yet in the map (e.g. before they're cached).
55
+ *
56
+ * Examples:
57
+ * - getCollectionKey("report_123") → "report_"
58
+ * - getCollectionKey("report_") → "report_"
59
+ * - getCollectionKey("sharedNVP_user_-1_something") → "sharedNVP_user_"
60
+ */
61
+ function getCollectionKey(key) {
62
+ // Fast path: O(1) Map lookup for known member keys
63
+ const cached = memberToCollectionKeyMap.get(key);
64
+ if (cached !== undefined) {
65
+ return cached;
66
+ }
67
+ // If the key itself is a collection key, return it directly
68
+ if (isCollectionKey(key)) {
69
+ return key;
70
+ }
71
+ // Slow path: string parsing — use a `string` variable to avoid
72
+ // TypeScript narrowing `key` to `never` after the isCollectionKey guard.
73
+ const keyStr = key;
74
+ let lastUnderscoreIndex = keyStr.lastIndexOf('_');
75
+ while (lastUnderscoreIndex > 0) {
76
+ const possibleKey = keyStr.slice(0, lastUnderscoreIndex + 1);
77
+ if (isCollectionKey(possibleKey)) {
78
+ // Cache for future O(1) lookups
79
+ memberToCollectionKeyMap.set(key, possibleKey);
80
+ return possibleKey;
81
+ }
82
+ lastUnderscoreIndex = keyStr.lastIndexOf('_', lastUnderscoreIndex - 1);
83
+ }
84
+ return undefined;
85
+ }
86
+ /**
87
+ * Pre-computes and caches the member → collection key mapping for a given key.
88
+ * Called from OnyxCache.addKey() to ensure the Map stays populated.
89
+ */
90
+ function registerMemberKey(key) {
91
+ const existingCollectionKey = memberToCollectionKeyMap.get(key);
92
+ if (existingCollectionKey !== undefined) {
93
+ // Already in reverse map — ensure forward map is also populated.
94
+ // getCollectionKey() can populate memberToCollectionKeyMap without
95
+ // updating collectionToMembersMap, so we must sync here.
96
+ let members = collectionToMembersMap.get(existingCollectionKey);
97
+ if (!members) {
98
+ members = new Set();
99
+ collectionToMembersMap.set(existingCollectionKey, members);
100
+ }
101
+ members.add(key);
102
+ return;
103
+ }
104
+ // Find the longest (most specific) matching collection key.
105
+ // e.g. for 'test_level_1', prefer 'test_level_' over 'test_'.
106
+ let matchedCollectionKey;
107
+ for (const collectionKey of collectionKeySet) {
108
+ if (isCollectionMemberKey(collectionKey, key)) {
109
+ if (!matchedCollectionKey || collectionKey.length > matchedCollectionKey.length) {
110
+ matchedCollectionKey = collectionKey;
111
+ }
112
+ }
113
+ }
114
+ if (matchedCollectionKey) {
115
+ memberToCollectionKeyMap.set(key, matchedCollectionKey);
116
+ // Also register in the forward lookup (collection → members)
117
+ let members = collectionToMembersMap.get(matchedCollectionKey);
118
+ if (!members) {
119
+ members = new Set();
120
+ collectionToMembersMap.set(matchedCollectionKey, members);
121
+ }
122
+ members.add(key);
123
+ }
124
+ }
125
+ /**
126
+ * Removes a member key from the reverse lookup map.
127
+ * Called when a key is dropped from cache.
128
+ */
129
+ function deregisterMemberKey(key) {
130
+ const collectionKey = memberToCollectionKeyMap.get(key);
131
+ if (collectionKey) {
132
+ const members = collectionToMembersMap.get(collectionKey);
133
+ if (members) {
134
+ members.delete(key);
135
+ if (members.size === 0) {
136
+ collectionToMembersMap.delete(collectionKey);
137
+ }
138
+ }
139
+ }
140
+ memberToCollectionKeyMap.delete(key);
141
+ }
142
+ /**
143
+ * Returns the set of member keys for a given collection key.
144
+ * O(1) lookup using the forward index.
145
+ */
146
+ function getMembersOfCollection(collectionKey) {
147
+ return collectionToMembersMap.get(collectionKey);
148
+ }
149
+ /**
150
+ * Splits a collection member key into the collection key part and the ID part.
151
+ *
152
+ * @param key - The collection member key to split
153
+ * @param collectionKey - Optional pre-resolved collection key for optimization
154
+ * @returns A tuple of [collectionKey, memberId]
155
+ * @throws If the key is not a valid collection member key
156
+ */
157
+ function splitCollectionMemberKey(key, collectionKey) {
158
+ if (collectionKey && !isCollectionMemberKey(collectionKey, key)) {
159
+ throw new Error(`Invalid '${collectionKey}' collection key provided, it isn't compatible with '${key}' key.`);
160
+ }
161
+ if (!collectionKey) {
162
+ const resolvedKey = getCollectionKey(key);
163
+ if (!resolvedKey) {
164
+ throw new Error(`Invalid '${key}' key provided, only collection keys are allowed.`);
165
+ }
166
+ // eslint-disable-next-line no-param-reassign
167
+ collectionKey = resolvedKey;
168
+ }
169
+ return [collectionKey, key.slice(collectionKey.length)];
170
+ }
171
+ /**
172
+ * Initializes the RAM-only key set. Called once during Onyx.init().
173
+ */
174
+ function setRamOnlyKeys(keys) {
175
+ ramOnlyKeySet = keys;
176
+ }
177
+ /**
178
+ * Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member.
179
+ *
180
+ * For example, given ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]:
181
+ * - isRamOnlyKey("ramOnlyKey") → true
182
+ * - isRamOnlyKey("ramOnlyCollection_") → true
183
+ * - isRamOnlyKey("ramOnlyCollection_1") → true
184
+ * - isRamOnlyKey("someOtherKey") → false
185
+ */
186
+ function isRamOnlyKey(key) {
187
+ var _a;
188
+ return ramOnlyKeySet.has(key) || ramOnlyKeySet.has((_a = getCollectionKey(key)) !== null && _a !== void 0 ? _a : '');
189
+ }
190
+ exports.default = {
191
+ setCollectionKeys,
192
+ getCollectionKeys,
193
+ isCollectionKey,
194
+ isCollectionMemberKey,
195
+ isCollectionMember,
196
+ isKeyMatch,
197
+ getCollectionKey,
198
+ registerMemberKey,
199
+ deregisterMemberKey,
200
+ getMembersOfCollection,
201
+ splitCollectionMemberKey,
202
+ setRamOnlyKeys,
203
+ isRamOnlyKey,
204
+ };
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const OnyxCache_1 = __importDefault(require("../OnyxCache"));
7
+ const OnyxKeys_1 = __importDefault(require("../OnyxKeys"));
7
8
  const OnyxUtils_1 = __importDefault(require("../OnyxUtils"));
8
9
  const storage_1 = __importDefault(require("../storage"));
9
10
  const applyMerge = (key, existingValue, validChanges) => {
@@ -14,7 +15,7 @@ const applyMerge = (key, existingValue, validChanges) => {
14
15
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.MERGE, key, mergedValue, hasChanged);
15
16
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
16
17
  const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
17
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils_1.default.isRamOnlyKey(key);
18
+ const shouldSkipStorageOperations = !hasChanged || OnyxKeys_1.default.isRamOnlyKey(key);
18
19
  // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
19
20
  // If the key is marked as RAM-only, it should not be saved nor updated in the storage.
20
21
  if (shouldSkipStorageOperations) {
@@ -3,6 +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 OnyxKeys_1 = __importDefault(require("../OnyxKeys"));
6
7
  const OnyxUtils_1 = __importDefault(require("../OnyxUtils"));
7
8
  const OnyxCache_1 = __importDefault(require("../OnyxCache"));
8
9
  const storage_1 = __importDefault(require("../storage"));
@@ -20,7 +21,7 @@ const applyMerge = (key, existingValue, validChanges) => {
20
21
  OnyxUtils_1.default.logKeyChanged(OnyxUtils_1.default.METHOD.MERGE, key, mergedValue, hasChanged);
21
22
  // This approach prioritizes fast UI changes without waiting for data to be stored in device storage.
22
23
  const updatePromise = OnyxUtils_1.default.broadcastUpdate(key, mergedValue, hasChanged);
23
- const shouldSkipStorageOperations = !hasChanged || OnyxUtils_1.default.isRamOnlyKey(key);
24
+ const shouldSkipStorageOperations = !hasChanged || OnyxKeys_1.default.isRamOnlyKey(key);
24
25
  // If the value has not changed, calling Storage.setItem() would be redundant and a waste of performance, so return early instead.
25
26
  // If the key is marked as RAM-only, it should not be saved nor updated in the storage.
26
27
  if (shouldSkipStorageOperations) {
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.OnyxSnapshotCache = void 0;
7
- const OnyxUtils_1 = __importDefault(require("./OnyxUtils"));
7
+ const OnyxKeys_1 = __importDefault(require("./OnyxKeys"));
8
8
  /**
9
9
  * Manages snapshot caching for useOnyx hook performance optimization.
10
10
  * Handles selector function tracking and memoized getSnapshot results.
@@ -99,7 +99,7 @@ class OnyxSnapshotCache {
99
99
  // Always invalidate the exact key
100
100
  this.snapshotCache.delete(keyToInvalidate);
101
101
  // Check if the key is a collection member and invalidate the collection base key
102
- const collectionBaseKey = OnyxUtils_1.default.getCollectionKey(keyToInvalidate);
102
+ const collectionBaseKey = OnyxKeys_1.default.getCollectionKey(keyToInvalidate);
103
103
  if (collectionBaseKey) {
104
104
  this.snapshotCache.delete(collectionBaseKey);
105
105
  }
@@ -1,6 +1,6 @@
1
1
  import type { ValueOf } from 'type-fest';
2
2
  import type Onyx from './Onyx';
3
- import type { CollectionKey, CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, CallbackToStateMapping, MultiMergeReplaceNullPatches, OnyxCollection, OnyxEntry, OnyxInput, OnyxKey, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, Selector, MergeCollectionWithPatchesParams, SetCollectionParams, SetParams, OnyxMultiSetInput, RetriableOnyxOperation } from './types';
3
+ import type { CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, CallbackToStateMapping, MultiMergeReplaceNullPatches, OnyxCollection, OnyxEntry, OnyxInput, OnyxKey, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, Selector, MergeCollectionWithPatchesParams, SetCollectionParams, SetParams, OnyxMultiSetInput, RetriableOnyxOperation } from './types';
4
4
  import type { FastMergeResult } from './utils';
5
5
  import type { DeferredTask } from './createDeferredTask';
6
6
  import type { StorageKeyValuePair } from './storage/providers/types';
@@ -106,66 +106,6 @@ declare function storeKeyBySubscriptions(key: OnyxKey, subscriptionID: number):
106
106
  declare function deleteKeyBySubscriptions(subscriptionID: number): void;
107
107
  /** Returns current key names stored in persisted storage */
108
108
  declare function getAllKeys(): Promise<Set<OnyxKey>>;
109
- /**
110
- * Returns set of all registered collection keys
111
- */
112
- declare function getCollectionKeys(): Set<OnyxKey>;
113
- /**
114
- * Checks to see if the subscriber's supplied key
115
- * is associated with a collection of keys.
116
- */
117
- declare function isCollectionKey(key: OnyxKey): key is CollectionKeyBase;
118
- declare function isCollectionMemberKey<TCollectionKey extends CollectionKeyBase>(collectionKey: TCollectionKey, key: string): key is `${TCollectionKey}${string}`;
119
- /**
120
- * Checks if a given key is a collection member key (not just a collection key).
121
- * @param key - The key to check
122
- * @returns true if the key is a collection member, false otherwise
123
- */
124
- declare function isCollectionMember(key: OnyxKey): boolean;
125
- /**
126
- * Checks if a given key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
127
- *
128
- * For example:
129
- *
130
- * For the following Onyx setup
131
- *
132
- * ramOnlyKeys: ["ramOnlyKey", "ramOnlyCollection_"]
133
- *
134
- * - `isRamOnlyKey("ramOnlyKey")` would return true
135
- * - `isRamOnlyKey("ramOnlyCollection_")` would return true
136
- * - `isRamOnlyKey("ramOnlyCollection_1")` would return true
137
- * - `isRamOnlyKey("someOtherKey")` would return false
138
- *
139
- * @param key - The key to check
140
- * @returns true if key is a RAM-only key, RAM-only collection key, or a RAM-only collection member
141
- */
142
- declare function isRamOnlyKey(key: OnyxKey): boolean;
143
- /**
144
- * Splits a collection member key into the collection key part and the ID part.
145
- * @param key - The collection member key to split.
146
- * @param collectionKey - The collection key of the `key` param that can be passed in advance to optimize the function.
147
- * @returns A tuple where the first element is the collection part and the second element is the ID part,
148
- * or throws an Error if the key is not a collection one.
149
- */
150
- declare function splitCollectionMemberKey<TKey extends CollectionKey, CollectionKeyType = TKey extends `${infer Prefix}_${string}` ? `${Prefix}_` : never>(key: TKey, collectionKey?: string): [CollectionKeyType, string];
151
- /**
152
- * Checks to see if a provided key is the exact configured key of our connected subscriber
153
- * or if the provided key is a collection member key (in case our configured key is a "collection key")
154
- */
155
- declare function isKeyMatch(configKey: OnyxKey, key: OnyxKey): boolean;
156
- /**
157
- * Extracts the collection identifier of a given collection member key.
158
- *
159
- * For example:
160
- * - `getCollectionKey("report_123")` would return "report_"
161
- * - `getCollectionKey("report_")` would return "report_"
162
- * - `getCollectionKey("report_-1_something")` would return "report_"
163
- * - `getCollectionKey("sharedNVP_user_-1_something")` would return "sharedNVP_user_"
164
- *
165
- * @param key - The collection key to process.
166
- * @returns The plain collection key or undefined if the key is not a collection one.
167
- */
168
- declare function getCollectionKey(key: CollectionKey): string | undefined;
169
109
  /**
170
110
  * Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
171
111
  * If the requested key is a collection, it will return an object with all the collection members.
@@ -357,18 +297,11 @@ declare const OnyxUtils: {
357
297
  sendActionToDevTools: typeof sendActionToDevTools;
358
298
  get: typeof get;
359
299
  getAllKeys: typeof getAllKeys;
360
- getCollectionKeys: typeof getCollectionKeys;
361
- isCollectionKey: typeof isCollectionKey;
362
- isCollectionMemberKey: typeof isCollectionMemberKey;
363
- isCollectionMember: typeof isCollectionMember;
364
- splitCollectionMemberKey: typeof splitCollectionMemberKey;
365
- isKeyMatch: typeof isKeyMatch;
366
300
  tryGetCachedValue: typeof tryGetCachedValue;
367
301
  getCachedCollection: typeof getCachedCollection;
368
302
  keysChanged: typeof keysChanged;
369
303
  keyChanged: typeof keyChanged;
370
304
  sendDataToConnection: typeof sendDataToConnection;
371
- getCollectionKey: typeof getCollectionKey;
372
305
  getCollectionDataAndSendAsObject: typeof getCollectionDataAndSendAsObject;
373
306
  scheduleSubscriberUpdate: typeof scheduleSubscriberUpdate;
374
307
  scheduleNotifyCollectionSubscribers: typeof scheduleNotifyCollectionSubscribers;
@@ -404,7 +337,6 @@ declare const OnyxUtils: {
404
337
  setWithRetry: typeof setWithRetry;
405
338
  multiSetWithRetry: typeof multiSetWithRetry;
406
339
  setCollectionWithRetry: typeof setCollectionWithRetry;
407
- isRamOnlyKey: typeof isRamOnlyKey;
408
340
  };
409
341
  export type { OnyxMethod };
410
342
  export default OnyxUtils;