import { Observable } from "rxjs"; import { DeriveDefinition, DerivedState, DerivedStateDependencies, DerivedStateProvider, } from "@bitwarden/state"; import { DefaultDerivedState } from "./default-derived-state"; export class DefaultDerivedStateProvider implements DerivedStateProvider { /** * The cache uses a WeakMap to maintain separate derived states per user. * Each user's state Observable acts as a unique key, without needing to * pass around `userId`. Also, when a user's state Observable is cleaned up * (like during an account swap) their cache is automatically garbage * collected. */ private cache = new WeakMap, Record>>(); constructor() {} get( parentState$: Observable, deriveDefinition: DeriveDefinition, dependencies: TDeps, ): DerivedState { let stateCache = this.cache.get(parentState$); if (!stateCache) { stateCache = {}; this.cache.set(parentState$, stateCache); } const cacheKey = deriveDefinition.buildCacheKey(); const existingDerivedState = stateCache[cacheKey]; if (existingDerivedState != null) { // I have to cast out of the unknown generic but this should be safe if rules // around domain token are made return existingDerivedState as DefaultDerivedState; } const newDerivedState = this.buildDerivedState(parentState$, deriveDefinition, dependencies); stateCache[cacheKey] = newDerivedState; return newDerivedState; } protected buildDerivedState( parentState$: Observable, deriveDefinition: DeriveDefinition, dependencies: TDeps, ): DerivedState { return new DefaultDerivedState(parentState$, deriveDefinition, dependencies); } }