// FIXME: Update this file to be type safe and remove this and next line // @ts-strict-ignore import { Observable, map, switchMap, firstValueFrom, timeout, throwError, NEVER } from "rxjs"; import { activeMarker, ActiveUserState, CombinedState, SingleUserStateProvider, StateUpdateOptions, UserKeyDefinition, } from "@bitwarden/state"; import { UserId } from "@bitwarden/user-core"; export class DefaultActiveUserState implements ActiveUserState { [activeMarker]: true; combinedState$: Observable>; state$: Observable; constructor( protected keyDefinition: UserKeyDefinition, private activeUserId$: Observable, private singleUserStateProvider: SingleUserStateProvider, ) { this.combinedState$ = this.activeUserId$.pipe( switchMap((userId) => userId != null ? this.singleUserStateProvider.get(userId, this.keyDefinition).combinedState$ : NEVER, ), ); // State should just be combined state without the user id this.state$ = this.combinedState$.pipe(map(([_userId, state]) => state)); } async update( configureState: (state: T, dependency: TCombine) => T, options: Partial> = {}, ): Promise<[UserId, T]> { const userId = await firstValueFrom( this.activeUserId$.pipe( timeout({ first: 1000, with: () => throwError( () => new Error( `Timeout while retrieving active user for key ${this.keyDefinition.fullName}.`, ), ), }), ), ); if (userId == null) { throw new Error( `Error storing ${this.keyDefinition.fullName} for the active user: No active user at this time.`, ); } return [ userId, await this.singleUserStateProvider .get(userId, this.keyDefinition) .update(configureState, options), ]; } }