mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 02:03:39 +00:00
[PM-7289] implement generator libraries (#9549)
This is a copy of the files. The source in `@bitwarden/common` will be deleted once all of the applications have been ported to the library.
This commit is contained in:
@@ -4,9 +4,9 @@ import { PolicyService } from "../../../admin-console/abstractions/policy/policy
|
||||
import { PolicyType } from "../../../admin-console/enums";
|
||||
import { StateProvider } from "../../../platform/state";
|
||||
import { UserId } from "../../../types/guid";
|
||||
import { distinctIfShallowMatch, reduceCollection } from "../../rx";
|
||||
import { GeneratorNavigationService } from "../abstractions/generator-navigation.service.abstraction";
|
||||
import { GENERATOR_SETTINGS } from "../key-definitions";
|
||||
import { distinctIfShallowMatch, reduceCollection } from "../rx-operators";
|
||||
|
||||
import { DefaultGeneratorNavigation, GeneratorNavigation } from "./generator-navigation";
|
||||
import { GeneratorNavigationEvaluator } from "./generator-navigation-evaluator";
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
/**
|
||||
* include structuredClone in test environment.
|
||||
* @jest-environment ../../../../shared/test.environment.ts
|
||||
*/
|
||||
|
||||
import { of, firstValueFrom } from "rxjs";
|
||||
|
||||
import { awaitAsync, trackEmissions } from "../../../spec";
|
||||
|
||||
import { distinctIfShallowMatch, reduceCollection } from "./rx-operators";
|
||||
|
||||
describe("reduceCollection", () => {
|
||||
it.each([[null], [undefined], [[]]])(
|
||||
"should return the default value when the collection is %p",
|
||||
async (value: number[]) => {
|
||||
const reduce = (acc: number, value: number) => acc + value;
|
||||
const source$ = of(value);
|
||||
|
||||
const result$ = source$.pipe(reduceCollection(reduce, 100));
|
||||
const result = await firstValueFrom(result$);
|
||||
|
||||
expect(result).toEqual(100);
|
||||
},
|
||||
);
|
||||
|
||||
it("should reduce the collection to a single value", async () => {
|
||||
const reduce = (acc: number, value: number) => acc + value;
|
||||
const source$ = of([1, 2, 3]);
|
||||
|
||||
const result$ = source$.pipe(reduceCollection(reduce, 0));
|
||||
const result = await firstValueFrom(result$);
|
||||
|
||||
expect(result).toEqual(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("distinctIfShallowMatch", () => {
|
||||
it("emits a single value", async () => {
|
||||
const source$ = of({ foo: true });
|
||||
const pipe$ = source$.pipe(distinctIfShallowMatch());
|
||||
|
||||
const result = trackEmissions(pipe$);
|
||||
await awaitAsync();
|
||||
|
||||
expect(result).toEqual([{ foo: true }]);
|
||||
});
|
||||
|
||||
it("emits different values", async () => {
|
||||
const source$ = of({ foo: true }, { foo: false });
|
||||
const pipe$ = source$.pipe(distinctIfShallowMatch());
|
||||
|
||||
const result = trackEmissions(pipe$);
|
||||
await awaitAsync();
|
||||
|
||||
expect(result).toEqual([{ foo: true }, { foo: false }]);
|
||||
});
|
||||
|
||||
it("emits new keys", async () => {
|
||||
const source$ = of({ foo: true }, { foo: true, bar: true });
|
||||
const pipe$ = source$.pipe(distinctIfShallowMatch());
|
||||
|
||||
const result = trackEmissions(pipe$);
|
||||
await awaitAsync();
|
||||
|
||||
expect(result).toEqual([{ foo: true }, { foo: true, bar: true }]);
|
||||
});
|
||||
|
||||
it("suppresses identical values", async () => {
|
||||
const source$ = of({ foo: true }, { foo: true });
|
||||
const pipe$ = source$.pipe(distinctIfShallowMatch());
|
||||
|
||||
const result = trackEmissions(pipe$);
|
||||
await awaitAsync();
|
||||
|
||||
expect(result).toEqual([{ foo: true }]);
|
||||
});
|
||||
|
||||
it("suppresses removed keys", async () => {
|
||||
const source$ = of({ foo: true, bar: true }, { foo: true });
|
||||
const pipe$ = source$.pipe(distinctIfShallowMatch());
|
||||
|
||||
const result = trackEmissions(pipe$);
|
||||
await awaitAsync();
|
||||
|
||||
expect(result).toEqual([{ foo: true, bar: true }]);
|
||||
});
|
||||
});
|
||||
@@ -1,45 +1,10 @@
|
||||
import { distinctUntilChanged, map, OperatorFunction, pipe } from "rxjs";
|
||||
import { map, pipe } from "rxjs";
|
||||
|
||||
import { reduceCollection, distinctIfShallowMatch } from "@bitwarden/common/tools/rx";
|
||||
|
||||
import { DefaultPolicyEvaluator } from "./default-policy-evaluator";
|
||||
import { PolicyConfiguration } from "./policies";
|
||||
|
||||
/**
|
||||
* An observable operator that reduces an emitted collection to a single object,
|
||||
* returning a default if all items are ignored.
|
||||
* @param reduce The reduce function to apply to the filtered collection. The
|
||||
* first argument is the accumulator, and the second is the current item. The
|
||||
* return value is the new accumulator.
|
||||
* @param defaultValue The default value to return if the collection is empty. The
|
||||
* default value is also the initial value of the accumulator.
|
||||
*/
|
||||
export function reduceCollection<Item, Accumulator>(
|
||||
reduce: (acc: Accumulator, value: Item) => Accumulator,
|
||||
defaultValue: Accumulator,
|
||||
): OperatorFunction<Item[], Accumulator> {
|
||||
return map((values: Item[]) => {
|
||||
const reduced = (values ?? []).reduce(reduce, structuredClone(defaultValue));
|
||||
return reduced;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An observable operator that emits distinct values by checking that all
|
||||
* values in the previous entry match the next entry. This method emits
|
||||
* when a key is added and does not when a key is removed.
|
||||
* @remarks This method checks objects. It does not check items in arrays.
|
||||
*/
|
||||
export function distinctIfShallowMatch<Item>(): OperatorFunction<Item, Item> {
|
||||
return distinctUntilChanged((previous, current) => {
|
||||
let isDistinct = true;
|
||||
|
||||
for (const key in current) {
|
||||
isDistinct &&= previous[key] === current[key];
|
||||
}
|
||||
|
||||
return isDistinct;
|
||||
});
|
||||
}
|
||||
|
||||
/** Maps an administrative console policy to a policy evaluator using the provided configuration.
|
||||
* @param configuration the configuration that constructs the evaluator.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user