mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
[PM-7985] Add & Use InlineDerivedStateProvider (#9131)
* Add & Use InlineDerivedStateProvider * Remove Comment * Delete Foreground & Background Derived State
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import { Subject, firstValueFrom } from "rxjs";
|
||||
|
||||
import { DeriveDefinition } from "../derive-definition";
|
||||
import { StateDefinition } from "../state-definition";
|
||||
|
||||
import { InlineDerivedState } from "./inline-derived-state";
|
||||
|
||||
describe("InlineDerivedState", () => {
|
||||
const syncDeriveDefinition = new DeriveDefinition<boolean, boolean, Record<string, unknown>>(
|
||||
new StateDefinition("test", "disk"),
|
||||
"test",
|
||||
{
|
||||
derive: (value, deps) => !value,
|
||||
deserializer: (value) => value,
|
||||
},
|
||||
);
|
||||
|
||||
const asyncDeriveDefinition = new DeriveDefinition<boolean, boolean, Record<string, unknown>>(
|
||||
new StateDefinition("test", "disk"),
|
||||
"test",
|
||||
{
|
||||
derive: async (value, deps) => Promise.resolve(!value),
|
||||
deserializer: (value) => value,
|
||||
},
|
||||
);
|
||||
|
||||
const parentState = new Subject<boolean>();
|
||||
|
||||
describe("state", () => {
|
||||
const cases = [
|
||||
{
|
||||
it: "works when derive function is sync",
|
||||
definition: syncDeriveDefinition,
|
||||
},
|
||||
{
|
||||
it: "works when derive function is async",
|
||||
definition: asyncDeriveDefinition,
|
||||
},
|
||||
];
|
||||
|
||||
it.each(cases)("$it", async ({ definition }) => {
|
||||
const sut = new InlineDerivedState(parentState.asObservable(), definition, {});
|
||||
|
||||
const valuePromise = firstValueFrom(sut.state$);
|
||||
parentState.next(true);
|
||||
|
||||
const value = await valuePromise;
|
||||
|
||||
expect(value).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("forceValue", () => {
|
||||
it("returns the force value back to the caller", async () => {
|
||||
const sut = new InlineDerivedState(parentState.asObservable(), syncDeriveDefinition, {});
|
||||
|
||||
const value = await sut.forceValue(true);
|
||||
|
||||
expect(value).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Observable, concatMap } from "rxjs";
|
||||
|
||||
import { DerivedStateDependencies } from "../../../types/state";
|
||||
import { DeriveDefinition } from "../derive-definition";
|
||||
import { DerivedState } from "../derived-state";
|
||||
import { DerivedStateProvider } from "../derived-state.provider";
|
||||
|
||||
export class InlineDerivedStateProvider implements DerivedStateProvider {
|
||||
get<TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||
parentState$: Observable<TFrom>,
|
||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||
dependencies: TDeps,
|
||||
): DerivedState<TTo> {
|
||||
return new InlineDerivedState(parentState$, deriveDefinition, dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
export class InlineDerivedState<TFrom, TTo, TDeps extends DerivedStateDependencies>
|
||||
implements DerivedState<TTo>
|
||||
{
|
||||
constructor(
|
||||
parentState$: Observable<TFrom>,
|
||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||
dependencies: TDeps,
|
||||
) {
|
||||
this.state$ = parentState$.pipe(
|
||||
concatMap(async (value) => await deriveDefinition.derive(value, dependencies)),
|
||||
);
|
||||
}
|
||||
|
||||
state$: Observable<TTo>;
|
||||
|
||||
forceValue(value: TTo): Promise<TTo> {
|
||||
// No need to force anything, we don't keep a cache
|
||||
return Promise.resolve(value);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user