mirror of
https://github.com/bitwarden/browser
synced 2025-12-16 16:23:44 +00:00
[PM-14445] TS strict for Key Management Biometrics (#13039)
* PM-14445: TS strict for Key Management Biometrics * formatting * callbacks not null expectations * state nullability expectations updates * unit tests fix * secure channel naming, explicit null check on messageId * revert null for getUser, getGlobal in state.provider.ts * revert null for getUser, getGlobal in state.provider.ts
This commit is contained in:
@@ -18,13 +18,13 @@ export interface GlobalState<T> {
|
||||
* Resolves to the new state. If `shouldUpdate` returns false, the promise will resolve to the current state.
|
||||
*/
|
||||
update: <TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
configureState: (state: T | null, dependency: TCombine) => T | null,
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<T>;
|
||||
) => Promise<T | null>;
|
||||
|
||||
/**
|
||||
* An observable stream of this state, the first emission of this will be the current state on disk
|
||||
* and subsequent updates will be from an update to that state.
|
||||
*/
|
||||
state$: Observable<T>;
|
||||
state$: Observable<T | null>;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ export class DefaultSingleUserState<T>
|
||||
extends StateBase<T, UserKeyDefinition<T>>
|
||||
implements SingleUserState<T>
|
||||
{
|
||||
readonly combinedState$: Observable<CombinedState<T>>;
|
||||
readonly combinedState$: Observable<CombinedState<T | null>>;
|
||||
|
||||
constructor(
|
||||
readonly userId: UserId,
|
||||
|
||||
@@ -54,9 +54,9 @@ export class DefaultStateProvider implements StateProvider {
|
||||
|
||||
async setUserState<T>(
|
||||
userKeyDefinition: UserKeyDefinition<T>,
|
||||
value: T,
|
||||
value: T | null,
|
||||
userId?: UserId,
|
||||
): Promise<[UserId, T]> {
|
||||
): Promise<[UserId, T | null]> {
|
||||
if (userId) {
|
||||
return [userId, await this.getUser<T>(userId, userKeyDefinition).update(() => value)];
|
||||
} else {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
Observable,
|
||||
ReplaySubject,
|
||||
defer,
|
||||
filter,
|
||||
firstValueFrom,
|
||||
merge,
|
||||
Observable,
|
||||
ReplaySubject,
|
||||
share,
|
||||
switchMap,
|
||||
tap,
|
||||
@@ -22,7 +22,7 @@ import {
|
||||
ObservableStorageService,
|
||||
} from "../../abstractions/storage.service";
|
||||
import { DebugOptions } from "../key-definition";
|
||||
import { StateUpdateOptions, populateOptionsWithDefault } from "../state-update-options";
|
||||
import { populateOptionsWithDefault, StateUpdateOptions } from "../state-update-options";
|
||||
|
||||
import { getStoredValue } from "./util";
|
||||
|
||||
@@ -36,7 +36,7 @@ type KeyDefinitionRequirements<T> = {
|
||||
export abstract class StateBase<T, KeyDef extends KeyDefinitionRequirements<T>> {
|
||||
private updatePromise: Promise<T>;
|
||||
|
||||
readonly state$: Observable<T>;
|
||||
readonly state$: Observable<T | null>;
|
||||
|
||||
constructor(
|
||||
protected readonly key: StorageKey,
|
||||
@@ -86,9 +86,9 @@ export abstract class StateBase<T, KeyDef extends KeyDefinitionRequirements<T>>
|
||||
}
|
||||
|
||||
async update<TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
configureState: (state: T | null, dependency: TCombine) => T | null,
|
||||
options: StateUpdateOptions<T, TCombine> = {},
|
||||
): Promise<T> {
|
||||
): Promise<T | null> {
|
||||
options = populateOptionsWithDefault(options);
|
||||
if (this.updatePromise != null) {
|
||||
await this.updatePromise;
|
||||
@@ -96,17 +96,16 @@ export abstract class StateBase<T, KeyDef extends KeyDefinitionRequirements<T>>
|
||||
|
||||
try {
|
||||
this.updatePromise = this.internalUpdate(configureState, options);
|
||||
const newState = await this.updatePromise;
|
||||
return newState;
|
||||
return await this.updatePromise;
|
||||
} finally {
|
||||
this.updatePromise = null;
|
||||
}
|
||||
}
|
||||
|
||||
private async internalUpdate<TCombine>(
|
||||
configureState: (state: T, dependency: TCombine) => T,
|
||||
configureState: (state: T | null, dependency: TCombine) => T | null,
|
||||
options: StateUpdateOptions<T, TCombine>,
|
||||
): Promise<T> {
|
||||
): Promise<T | null> {
|
||||
const currentState = await this.getStateForUpdate();
|
||||
const combinedDependencies =
|
||||
options.combineLatestWith != null
|
||||
@@ -122,7 +121,7 @@ export abstract class StateBase<T, KeyDef extends KeyDefinitionRequirements<T>>
|
||||
return newState;
|
||||
}
|
||||
|
||||
protected async doStorageSave(newState: T, oldState: T) {
|
||||
protected async doStorageSave(newState: T | null, oldState: T) {
|
||||
if (this.keyDefinition.debug.enableUpdateLogging) {
|
||||
this.logService.info(
|
||||
`Updating '${this.key}' from ${oldState == null ? "null" : "non-null"} to ${newState == null ? "null" : "non-null"}`,
|
||||
|
||||
@@ -60,9 +60,9 @@ export abstract class StateProvider {
|
||||
*/
|
||||
abstract setUserState<T>(
|
||||
keyDefinition: UserKeyDefinition<T>,
|
||||
value: T,
|
||||
value: T | null,
|
||||
userId?: UserId,
|
||||
): Promise<[UserId, T]>;
|
||||
): Promise<[UserId, T | null]>;
|
||||
|
||||
/** @see{@link ActiveUserStateProvider.get} */
|
||||
abstract getActive<T>(userKeyDefinition: UserKeyDefinition<T>): ActiveUserState<T>;
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface UserState<T> {
|
||||
readonly state$: Observable<T | null>;
|
||||
|
||||
/** Emits a stream of tuples, with the first element being a user id and the second element being the data for that user. */
|
||||
readonly combinedState$: Observable<CombinedState<T>>;
|
||||
readonly combinedState$: Observable<CombinedState<T | null>>;
|
||||
}
|
||||
|
||||
export const activeMarker: unique symbol = Symbol("active");
|
||||
@@ -38,9 +38,9 @@ export interface ActiveUserState<T> extends UserState<T> {
|
||||
* Resolves to the new state. If `shouldUpdate` returns false, the promise will resolve to the current state.
|
||||
*/
|
||||
readonly update: <TCombine>(
|
||||
configureState: (state: T, dependencies: TCombine) => T,
|
||||
configureState: (state: T | null, dependencies: TCombine) => T | null,
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<[UserId, T]>;
|
||||
) => Promise<[UserId, T | null]>;
|
||||
}
|
||||
|
||||
export interface SingleUserState<T> extends UserState<T> {
|
||||
@@ -58,7 +58,7 @@ export interface SingleUserState<T> extends UserState<T> {
|
||||
* Resolves to the new state. If `shouldUpdate` returns false, the promise will resolve to the current state.
|
||||
*/
|
||||
readonly update: <TCombine>(
|
||||
configureState: (state: T, dependencies: TCombine) => T,
|
||||
configureState: (state: T | null, dependencies: TCombine) => T | null,
|
||||
options?: StateUpdateOptions<T, TCombine>,
|
||||
) => Promise<T>;
|
||||
) => Promise<T | null>;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,11 @@ export class DefaultThemeStateService implements ThemeStateService {
|
||||
map(([theme, isExtensionRefresh]) => {
|
||||
// The extension refresh should not allow for Nord or SolarizedDark
|
||||
// Default the user to their system theme
|
||||
if (isExtensionRefresh && [ThemeType.Nord, ThemeType.SolarizedDark].includes(theme)) {
|
||||
if (
|
||||
isExtensionRefresh &&
|
||||
theme != null &&
|
||||
[ThemeType.Nord, ThemeType.SolarizedDark].includes(theme)
|
||||
) {
|
||||
return ThemeType.System;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user