UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

109 lines (82 loc) 3.18 kB
import { bridgeLogger } from "../../zapp-react-native-bridge/logger"; import { BehaviorSubject } from "rxjs"; import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage"; import { getNamespaceAndKey } from "../appUtils/contextKeysManager/utils"; import { createLogger } from "../logger"; export const { log_verbose, log_debug, log_warning, log_info, log_error } = createLogger({ category: "StorageSingleValueProvider", subsystem: "zapp-react-native-bridge", parent: bridgeLogger, }); export interface SingleValueProvider { getObservable(): BehaviorSubject<string | null>; setValue(value: string): Promise<void>; getValue(): string | null; getValueAsync(): Promise<string | null>; clearValue(): Promise<void>; } interface StorageListenerArgs { value: string | null; } export class StorageSingleValueProvider implements SingleValueProvider { // Static cache of providers by namespace private static singleValueProviders: Record< string, StorageSingleValueProvider > = {}; public static getProvider(keyNamespace: string): SingleValueProvider { if (!this.singleValueProviders[keyNamespace]) { this.singleValueProviders[keyNamespace] = new StorageSingleValueProvider( keyNamespace ); } return this.singleValueProviders[keyNamespace]; } private valueSubject: BehaviorSubject<string | null>; private readonly key: string; private readonly namespace: string; private constructor(keyNamespace: string) { const { namespace, key } = getNamespaceAndKey(keyNamespace); if (!key) { throw new Error("StorageSingleValueProvider: Key is required"); } this.key = key; this.namespace = namespace; localStorage.addListener?.({ key, namespace }, this.reloadValue); this.valueSubject = new BehaviorSubject<string | null>(null); void this.getValueAsync(); log_debug("StorageSingleValueProvider: Initializing"); } private reloadValue = async ({ value }: StorageListenerArgs) => { log_debug(`reloadValue: request to reload value: ${value}`); this.valueSubject.next(value); }; public getObservable = (): BehaviorSubject<string | null> => this.valueSubject; private async updateValueAndNotifyObservers(value: string | null) { if (value === null) { await localStorage.removeItem(this.key, this.namespace); } else { await localStorage.setItem(this.key, value, this.namespace); } this.valueSubject.next(value); } public setValue = async (value: string): Promise<void> => { log_debug(`setValue: Setting new value: ${value}`); await this.updateValueAndNotifyObservers(value); }; public clearValue = async (): Promise<void> => { await localStorage.removeItem(this.key, this.namespace); log_debug("clearValue: Removing value"); this.valueSubject.next(null); }; public getValueAsync = async (): Promise<string | null> => { const value = await localStorage.getItem(this.key, this.namespace); this.valueSubject.next(value); return value; }; public getValue = (): string | null => { return this.valueSubject.getValue(); }; }