1
0
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:
Justin Baur
2024-05-13 07:42:29 -04:00
committed by GitHub
parent c0216e191a
commit 657807c96a
11 changed files with 108 additions and 462 deletions

View File

@@ -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);
});
});
});

View File

@@ -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);
}
}