react-native-onyx
Version:
State management for React Native
327 lines (326 loc) • 18.4 kB
TypeScript
import type { ValueOf } from 'type-fest';
import type Onyx from './Onyx';
import type { CollectionKeyBase, ConnectOptions, DeepRecord, KeyValueMapping, CallbackToStateMapping, MultiMergeReplaceNullPatches, OnyxCollection, OnyxEntry, OnyxInput, OnyxKey, OnyxMergeCollectionInput, OnyxUpdate, OnyxValue, Selector, MergeCollectionWithPatchesParams, SetCollectionParams, SetParams, OnyxMultiSetInput, RetriableOnyxOperation } from './types';
import type { FastMergeResult } from './utils';
import type { DeferredTask } from './createDeferredTask';
import type { StorageKeyValuePair } from './storage/providers/types';
declare const METHOD: {
readonly SET: "set";
readonly MERGE: "merge";
readonly MERGE_COLLECTION: "mergecollection";
readonly SET_COLLECTION: "setcollection";
readonly MULTI_SET: "multiset";
readonly CLEAR: "clear";
};
type OnyxMethod = ValueOf<typeof METHOD>;
declare function getSnapshotKey(): OnyxKey | null;
/**
* Getter - returns the merge queue.
*/
declare function getMergeQueue(): Record<OnyxKey, Array<OnyxValue<OnyxKey>>>;
/**
* Getter - returns the merge queue promise.
*/
declare function getMergeQueuePromise(): Record<OnyxKey, Promise<void>>;
/**
* Getter - returns the default key states.
*/
declare function getDefaultKeyStates(): Record<OnyxKey, OnyxValue<OnyxKey>>;
/**
* Getter - returns the deffered init task.
*/
declare function getDeferredInitTask(): DeferredTask;
/**
* Executes an action after Onyx has been initialized.
* If Onyx is already initialized, the action is executed immediately.
* Otherwise, it waits for initialization to complete before executing.
*
* @param action The action to execute after initialization
* @returns The result of the action
*/
declare function afterInit<T>(action: () => Promise<T>): Promise<T>;
/**
* Getter - returns the skippable collection member IDs.
*/
declare function getSkippableCollectionMemberIDs(): Set<string>;
/**
* Getter - returns the snapshot merge keys allowlist.
*/
declare function getSnapshotMergeKeys(): Set<string>;
/**
* Setter - sets the skippable collection member IDs.
*/
declare function setSkippableCollectionMemberIDs(ids: Set<string>): void;
/**
* Setter - sets the snapshot merge keys allowlist.
*/
declare function setSnapshotMergeKeys(keys: Set<string>): void;
/**
* Sets the initial values for the Onyx store
*
* @param keys - `ONYXKEYS` constants object from Onyx.init()
* @param initialKeyStates - initial data to set when `init()` and `clear()` are called
* @param evictableKeys - This is an array of keys (individual or collection patterns) that when provided to Onyx are flagged as "safe" for removal.
*/
declare function initStoreValues(keys: DeepRecord<string, OnyxKey>, initialKeyStates: Partial<KeyValueMapping>, evictableKeys: OnyxKey[]): void;
/**
* Sends an action to DevTools extension
*
* @param method - Onyx method from METHOD
* @param key - Onyx key that was changed
* @param value - contains the change that was made by the method
* @param mergedValue - (optional) value that was written in the storage after a merge method was executed.
*/
declare function sendActionToDevTools(method: typeof METHOD.MERGE_COLLECTION | typeof METHOD.MULTI_SET | typeof METHOD.SET_COLLECTION, key: undefined, value: OnyxCollection<KeyValueMapping[OnyxKey]>, mergedValue?: undefined): void;
declare function sendActionToDevTools(method: Exclude<OnyxMethod, typeof METHOD.MERGE_COLLECTION | typeof METHOD.MULTI_SET | typeof METHOD.SET_COLLECTION>, key: OnyxKey, value: OnyxEntry<KeyValueMapping[OnyxKey]>, mergedValue?: OnyxEntry<KeyValueMapping[OnyxKey]>): void;
/**
* Takes a collection of items (eg. {testKey_1:{a:'a'}, testKey_2:{b:'b'}})
* and runs it through a reducer function to return a subset of the data according to a selector.
* The resulting collection will only contain items that are returned by the selector.
*/
declare function reduceCollectionWithSelector<TKey extends CollectionKeyBase, TReturn>(collection: OnyxCollection<KeyValueMapping[TKey]>, selector: Selector<TKey, TReturn>): Record<string, TReturn>;
/** Get some data from the store */
declare function get<TKey extends OnyxKey, TValue extends OnyxValue<TKey>>(key: TKey): Promise<TValue>;
declare function multiGet<TKey extends OnyxKey>(keys: CollectionKeyBase[]): Promise<Map<OnyxKey, OnyxValue<TKey>>>;
/**
* This helper exists to map an array of Onyx keys such as `['report_', 'conciergeReportID']`
* to the values for those keys (correctly typed) such as `[OnyxCollection<Report>, OnyxEntry<string>]`
*
* Note: just using `.map`, you'd end up with `Array<OnyxCollection<Report>|OnyxEntry<string>>`, which is not what we want. This preserves the order of the keys provided.
*/
declare function tupleGet<Keys extends readonly OnyxKey[]>(keys: Keys): Promise<{
[Index in keyof Keys]: OnyxValue<Keys[Index]>;
}>;
/**
* Stores a subscription ID associated with a given key.
*
* @param subscriptionID - A subscription ID of the subscriber.
* @param key - A key that the subscriber is subscribed to.
*/
declare function storeKeyBySubscriptions(key: OnyxKey, subscriptionID: number): void;
/**
* Deletes a subscription ID associated with its corresponding key.
*
* @param subscriptionID - The subscription ID to be deleted.
*/
declare function deleteKeyBySubscriptions(subscriptionID: number): void;
/** Returns current key names stored in persisted storage */
declare function getAllKeys(): Promise<Set<OnyxKey>>;
/**
* Tries to get a value from the cache. If the value is not present in cache it will return the default value or undefined.
* If the requested key is a collection, it will return an object with all the collection members.
*/
declare function tryGetCachedValue<TKey extends OnyxKey>(key: TKey): OnyxValue<OnyxKey>;
declare function getCachedCollection<TKey extends CollectionKeyBase>(collectionKey: TKey, collectionMemberKeys?: string[]): NonNullable<OnyxCollection<KeyValueMapping[TKey]>>;
/**
* When a collection of keys change, search for any callbacks matching the collection key and trigger those callbacks
*/
declare function keysChanged<TKey extends CollectionKeyBase>(collectionKey: TKey, partialCollection: OnyxCollection<KeyValueMapping[TKey]>, partialPreviousCollection: OnyxCollection<KeyValueMapping[TKey]> | undefined): void;
/**
* When a key change happens, search for any callbacks matching the key or collection key and trigger those callbacks
*/
declare function keyChanged<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, canUpdateSubscriber?: (subscriber?: CallbackToStateMapping<OnyxKey>) => boolean, isProcessingCollectionUpdate?: boolean): void;
/**
* Sends the data obtained from the keys to the connection.
*/
declare function sendDataToConnection<TKey extends OnyxKey>(mapping: CallbackToStateMapping<TKey>, matchedKey: TKey | undefined): void;
/**
* Gets the data for a given an array of matching keys, combines them into an object, and sends the result back to the subscriber.
*/
declare function getCollectionDataAndSendAsObject<TKey extends OnyxKey>(matchingKeys: CollectionKeyBase[], mapping: CallbackToStateMapping<TKey>): void;
/**
* Remove a key from Onyx and update the subscribers
*/
declare function remove<TKey extends OnyxKey>(key: TKey, isProcessingCollectionUpdate?: boolean): Promise<void>;
declare function reportStorageQuota(error?: Error): Promise<void>;
/**
* Handles storage operation failures based on the error class (see lib/storage/errors.ts).
* The connection layer (createStore) owns connection/transport recovery; this operation layer owns
* capacity recovery (eviction) so that a given failure is retried by exactly one layer:
* - INVALID_DATA: logs an alert and throws (the same data will always fail).
* - TRANSIENT / FATAL: the connection layer already retried (transient) or exhausted its heal budget
* and alerted (fatal). Retrying here would only re-amplify, so we skip the write quietly.
* - CAPACITY: evicts the least recently accessed evictable key and retries, under a session-level
* circuit breaker (see lib/StorageCircuitBreaker.ts) that halts the loop once eviction stops making
* progress or failures storm — the per-operation budget alone cannot stop a session-wide storm.
* - UNKNOWN: the provider couldn't classify it — log the full error shape (name + message +
* provider) once so it's visible, then bounded retry without eviction.
*/
declare function retryOperation<TMethod extends RetriableOnyxOperation>(error: Error, onyxMethod: TMethod, defaultParams: Parameters<TMethod>[0], retryAttempt: number | undefined, inFlightKeys?: Set<OnyxKey>): Promise<void>;
/**
* Notifies subscribers and writes current value to cache
*/
declare function broadcastUpdate<TKey extends OnyxKey>(key: TKey, value: OnyxValue<TKey>, hasChanged?: boolean): void;
declare function hasPendingMergeForKey(key: OnyxKey): boolean;
/**
* Storage expects array like: [["@MyApp_user", value_1], ["@MyApp_key", value_2]]
* This method transforms an object like {'@MyApp_user': myUserValue, '@MyApp_key': myKeyValue}
* to an array of key-value pairs in the above format and removes key-value pairs that are being set to null
*
* @return an array of key - value pairs <[key, value]>
*/
declare function prepareKeyValuePairsForStorage(data: Record<OnyxKey, OnyxInput<OnyxKey>>, shouldRemoveNestedNulls?: boolean, replaceNullPatches?: MultiMergeReplaceNullPatches, isProcessingCollectionUpdate?: boolean): StorageKeyValuePair[];
/**
* Merges an array of changes with an existing value or creates a single change.
*
* @param changes Array of changes that should be merged
* @param existingValue The existing value that should be merged with the changes
*/
declare function mergeChanges<TValue extends OnyxInput<OnyxKey> | undefined, TChange extends OnyxInput<OnyxKey> | undefined>(changes: TChange[], existingValue?: TValue): FastMergeResult<TChange>;
/**
* Merges an array of changes with an existing value or creates a single change.
* It will also mark deep nested objects that need to be entirely replaced during the merge.
*
* @param changes Array of changes that should be merged
* @param existingValue The existing value that should be merged with the changes
*/
declare function mergeAndMarkChanges<TValue extends OnyxInput<OnyxKey> | undefined, TChange extends OnyxInput<OnyxKey> | undefined>(changes: TChange[], existingValue?: TValue): FastMergeResult<TChange>;
/**
* Merge user provided default key value pairs.
*/
declare function initializeWithDefaultKeyStates(): Promise<void>;
/**
* Validate the collection is not empty and has a correct type before applying mergeCollection()
*/
declare function isValidNonEmptyCollectionForMerge<TKey extends CollectionKeyBase>(collection: OnyxMergeCollectionInput<TKey>): boolean;
/**
* Verify if all the collection keys belong to the same parent
*/
declare function doAllCollectionItemsBelongToSameParent<TKey extends CollectionKeyBase>(collectionKey: TKey, collectionKeys: string[]): boolean;
/**
* Subscribes to an Onyx key and listens to its changes.
*
* @param connectOptions The options object that will define the behavior of the connection.
* @returns The subscription ID to use when calling `OnyxUtils.unsubscribeFromKey()`.
*/
declare function subscribeToKey<TKey extends OnyxKey>(connectOptions: ConnectOptions<TKey>): number;
/**
* Disconnects and removes the listener from the Onyx key.
*
* @param subscriptionID Subscription ID returned by calling `OnyxUtils.subscribeToKey()`.
*/
declare function unsubscribeFromKey(subscriptionID: number): void;
declare function updateSnapshots<TKey extends OnyxKey>(data: Array<OnyxUpdate<TKey>>, mergeFn: typeof Onyx.merge): Array<() => Promise<void>>;
/**
* Writes a value to our store with the given key.
* Serves as core implementation for `Onyx.set()` public function, the difference being
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
*
* @param params - set parameters
* @param params.key ONYXKEY to set
* @param params.value value to store
* @param params.options optional configuration object
* @param retryAttempt retry attempt
*/
declare function setWithRetry<TKey extends OnyxKey>({ key, value, options }: SetParams<TKey>, retryAttempt?: number): Promise<void>;
/**
* Sets multiple keys and values.
* Serves as core implementation for `Onyx.multiSet()` public function, the difference being
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
*
* @param data object keyed by ONYXKEYS and the values to set
* @param retryAttempt retry attempt
*/
declare function multiSetWithRetry(data: OnyxMultiSetInput, retryAttempt?: number): Promise<void>;
/**
* Sets a collection by replacing all existing collection members with new values.
* Any existing collection members not included in the new data will be removed.
* Serves as core implementation for `Onyx.setCollection()` public function, the difference being
* that this internal function allows passing an additional `retryAttempt` parameter to retry on failure.
*
* @param params - collection parameters
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
* @param params.collection Object collection keyed by individual collection member keys and values
* @param retryAttempt retry attempt
*/
declare function setCollectionWithRetry<TKey extends CollectionKeyBase>({ collectionKey, collection }: SetCollectionParams<TKey>, retryAttempt?: number): Promise<void>;
/**
* Merges a collection based on their keys.
* Serves as core implementation for `Onyx.mergeCollection()` public function, the difference being
* that this internal function allows passing an additional `mergeReplaceNullPatches` parameter and retries on failure.
*
* @param params - mergeCollection parameters
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
* @param params.collection Object collection keyed by individual collection member keys and values
* @param params.mergeReplaceNullPatches Record where the key is a collection member key and the value is a list of
* tuples that we'll use to replace the nested objects of that collection member record with something else.
* @param params.isProcessingCollectionUpdate whether this is part of a collection update operation.
* @param retryAttempt retry attempt
*/
declare function mergeCollectionWithPatches<TKey extends CollectionKeyBase>({ collectionKey, collection, mergeReplaceNullPatches, isProcessingCollectionUpdate }: MergeCollectionWithPatchesParams<TKey>, retryAttempt?: number): Promise<void>;
/**
* Sets keys in a collection by replacing all targeted collection members with new values.
* Any existing collection members not included in the new data will not be removed.
* Retries on failure.
*
* @param params - collection parameters
* @param params.collectionKey e.g. `ONYXKEYS.COLLECTION.REPORT`
* @param params.collection Object collection keyed by individual collection member keys and values
* @param retryAttempt retry attempt
*/
declare function partialSetCollection<TKey extends CollectionKeyBase>({ collectionKey, collection }: SetCollectionParams<TKey>, retryAttempt?: number): Promise<void>;
declare function logKeyChanged(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey, value: unknown, hasChanged: boolean): void;
declare function logKeyRemoved(onyxMethod: Extract<OnyxMethod, 'set' | 'merge'>, key: OnyxKey): void;
/**
* Clear internal variables used in this file, useful in test environments.
*/
declare function clearOnyxUtilsInternals(): void;
declare const OnyxUtils: {
METHOD: {
readonly SET: "set";
readonly MERGE: "merge";
readonly MERGE_COLLECTION: "mergecollection";
readonly SET_COLLECTION: "setcollection";
readonly MULTI_SET: "multiset";
readonly CLEAR: "clear";
};
getMergeQueue: typeof getMergeQueue;
getMergeQueuePromise: typeof getMergeQueuePromise;
getDefaultKeyStates: typeof getDefaultKeyStates;
getDeferredInitTask: typeof getDeferredInitTask;
afterInit: typeof afterInit;
initStoreValues: typeof initStoreValues;
sendActionToDevTools: typeof sendActionToDevTools;
get: typeof get;
getAllKeys: typeof getAllKeys;
tryGetCachedValue: typeof tryGetCachedValue;
getCachedCollection: typeof getCachedCollection;
keysChanged: typeof keysChanged;
keyChanged: typeof keyChanged;
sendDataToConnection: typeof sendDataToConnection;
getCollectionDataAndSendAsObject: typeof getCollectionDataAndSendAsObject;
remove: typeof remove;
reportStorageQuota: typeof reportStorageQuota;
retryOperation: typeof retryOperation;
broadcastUpdate: typeof broadcastUpdate;
hasPendingMergeForKey: typeof hasPendingMergeForKey;
prepareKeyValuePairsForStorage: typeof prepareKeyValuePairsForStorage;
mergeChanges: typeof mergeChanges;
mergeAndMarkChanges: typeof mergeAndMarkChanges;
initializeWithDefaultKeyStates: typeof initializeWithDefaultKeyStates;
getSnapshotKey: typeof getSnapshotKey;
multiGet: typeof multiGet;
tupleGet: typeof tupleGet;
isValidNonEmptyCollectionForMerge: typeof isValidNonEmptyCollectionForMerge;
doAllCollectionItemsBelongToSameParent: typeof doAllCollectionItemsBelongToSameParent;
subscribeToKey: typeof subscribeToKey;
unsubscribeFromKey: typeof unsubscribeFromKey;
getSkippableCollectionMemberIDs: typeof getSkippableCollectionMemberIDs;
setSkippableCollectionMemberIDs: typeof setSkippableCollectionMemberIDs;
getSnapshotMergeKeys: typeof getSnapshotMergeKeys;
setSnapshotMergeKeys: typeof setSnapshotMergeKeys;
storeKeyBySubscriptions: typeof storeKeyBySubscriptions;
deleteKeyBySubscriptions: typeof deleteKeyBySubscriptions;
reduceCollectionWithSelector: typeof reduceCollectionWithSelector;
updateSnapshots: typeof updateSnapshots;
mergeCollectionWithPatches: typeof mergeCollectionWithPatches;
partialSetCollection: typeof partialSetCollection;
logKeyChanged: typeof logKeyChanged;
logKeyRemoved: typeof logKeyRemoved;
setWithRetry: typeof setWithRetry;
multiSetWithRetry: typeof multiSetWithRetry;
setCollectionWithRetry: typeof setCollectionWithRetry;
};
export type { OnyxMethod };
export default OnyxUtils;
export { clearOnyxUtilsInternals };