1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-13 06:43:35 +00:00
Files
browser/libs/state-internal/src/default-state.provider.ts
Justin Baur 5f7f1d1924 Resolve state <-> state-test-utils circular dependency (#16093)
* Resolve state <-> state-test-utils circular dependency

* Fix type errors
2025-08-25 12:38:28 -04:00

83 lines
2.9 KiB
TypeScript

// FIXME: Update this file to be type safe and remove this and next line
// @ts-strict-ignore
import { Observable, filter, of, switchMap, take } from "rxjs";
import {
ActiveUserStateProvider,
DeriveDefinition,
DerivedState,
DerivedStateDependencies,
DerivedStateProvider,
GlobalStateProvider,
SingleUserStateProvider,
StateProvider,
UserKeyDefinition,
} from "@bitwarden/state";
import { UserId } from "@bitwarden/user-core";
export class DefaultStateProvider implements StateProvider {
activeUserId$: Observable<UserId>;
constructor(
private readonly activeUserStateProvider: ActiveUserStateProvider,
private readonly singleUserStateProvider: SingleUserStateProvider,
private readonly globalStateProvider: GlobalStateProvider,
private readonly derivedStateProvider: DerivedStateProvider,
) {
this.activeUserId$ = this.activeUserStateProvider.activeUserId$;
}
getUserState$<T>(userKeyDefinition: UserKeyDefinition<T>, userId?: UserId): Observable<T> {
if (userId) {
return this.getUser<T>(userId, userKeyDefinition).state$;
} else {
return this.activeUserId$.pipe(
filter((userId) => userId != null), // Filter out null-ish user ids since we can't get state for a null user id
take(1),
switchMap((userId) => this.getUser<T>(userId, userKeyDefinition).state$),
);
}
}
getUserStateOrDefault$<T>(
userKeyDefinition: UserKeyDefinition<T>,
config: { userId: UserId | undefined; defaultValue?: T },
): Observable<T> {
const { userId, defaultValue = null } = config;
if (userId) {
return this.getUser<T>(userId, userKeyDefinition).state$;
} else {
return this.activeUserId$.pipe(
take(1),
switchMap((userId) =>
userId != null ? this.getUser<T>(userId, userKeyDefinition).state$ : of(defaultValue),
),
);
}
}
async setUserState<T>(
userKeyDefinition: UserKeyDefinition<T>,
value: T | null,
userId?: UserId,
): Promise<[UserId, T | null]> {
if (userId) {
return [userId, await this.getUser<T>(userId, userKeyDefinition).update(() => value)];
} else {
return await this.getActive<T>(userKeyDefinition).update(() => value);
}
}
getActive: InstanceType<typeof ActiveUserStateProvider>["get"] =
this.activeUserStateProvider.get.bind(this.activeUserStateProvider);
getUser: InstanceType<typeof SingleUserStateProvider>["get"] =
this.singleUserStateProvider.get.bind(this.singleUserStateProvider);
getGlobal: InstanceType<typeof GlobalStateProvider>["get"] = this.globalStateProvider.get.bind(
this.globalStateProvider,
);
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
parentState$: Observable<TFrom>,
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
dependencies: TDeps,
) => DerivedState<TTo> = this.derivedStateProvider.get.bind(this.derivedStateProvider);
}