import { Observable, ReplaySubject, Subject, concatMap, merge, share, timer } from "rxjs"; import { DeriveDefinition, DerivedState, DerivedStateDependencies } from "@bitwarden/state"; /** * Default derived state */ export class DefaultDerivedState implements DerivedState { private readonly storageKey: string; private forcedValueSubject = new Subject(); state$: Observable; constructor( private parentState$: Observable, protected deriveDefinition: DeriveDefinition, private dependencies: TDeps, ) { this.storageKey = deriveDefinition.storageKey; const derivedState$ = this.parentState$.pipe( concatMap(async (state) => { let derivedStateOrPromise = this.deriveDefinition.derive(state, this.dependencies); if (derivedStateOrPromise instanceof Promise) { derivedStateOrPromise = await derivedStateOrPromise; } const derivedState = derivedStateOrPromise; return derivedState; }), ); this.state$ = merge(this.forcedValueSubject, derivedState$).pipe( share({ connector: () => { return new ReplaySubject(1); }, resetOnRefCountZero: () => timer(this.deriveDefinition.cleanupDelayMs), }), ); } async forceValue(value: TTo) { this.forcedValueSubject.next(value); return value; } }