// 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 { UserId } from "../../../types/guid"; import { StateUpdateOptions } from "../state-update-options"; import { UserKeyDefinition } from "../user-key-definition"; import { ActiveUserState, CombinedState, activeMarker } from "../user-state"; import { SingleUserStateProvider } from "../user-state.provider"; 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: StateUpdateOptions = {}, ): 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), ]; } }