mirror of
https://github.com/bitwarden/browser
synced 2025-12-18 17:23:37 +00:00
[PM-5533] Migrate Asymmetric User Keys to State Providers (#7665)
This commit is contained in:
42
libs/common/src/platform/state/derive-definition.spec.ts
Normal file
42
libs/common/src/platform/state/derive-definition.spec.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { DeriveDefinition } from "./derive-definition";
|
||||
import { KeyDefinition } from "./key-definition";
|
||||
import { StateDefinition } from "./state-definition";
|
||||
|
||||
const derive: () => any = () => null;
|
||||
const deserializer: any = (obj: any) => obj;
|
||||
|
||||
const STATE_DEFINITION = new StateDefinition("test", "disk");
|
||||
const TEST_KEY = new KeyDefinition(STATE_DEFINITION, "test", {
|
||||
deserializer,
|
||||
});
|
||||
const TEST_DERIVE = new DeriveDefinition(STATE_DEFINITION, "test", {
|
||||
derive,
|
||||
deserializer,
|
||||
});
|
||||
|
||||
describe("DeriveDefinition", () => {
|
||||
describe("from", () => {
|
||||
it("should create a new DeriveDefinition from a KeyDefinition", () => {
|
||||
const result = DeriveDefinition.from(TEST_KEY, {
|
||||
derive,
|
||||
deserializer,
|
||||
});
|
||||
|
||||
expect(result).toEqual(TEST_DERIVE);
|
||||
});
|
||||
|
||||
it("should create a new DeriveDefinition from a DeriveDefinition", () => {
|
||||
const result = DeriveDefinition.from([TEST_DERIVE, "newDerive"], {
|
||||
derive,
|
||||
deserializer,
|
||||
});
|
||||
|
||||
expect(result).toEqual(
|
||||
new DeriveDefinition(STATE_DEFINITION, "newDerive", {
|
||||
derive,
|
||||
deserializer,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { UserId } from "../../types/guid";
|
||||
import { DerivedStateDependencies, StorageKey } from "../../types/state";
|
||||
|
||||
import { KeyDefinition } from "./key-definition";
|
||||
@@ -95,18 +96,60 @@ export class DeriveDefinition<TFrom, TTo, TDeps extends DerivedStateDependencies
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Factory that produces a {@link DeriveDefinition} from a {@link KeyDefinition} and a set of options. The returned
|
||||
* definition will have the same key as the given key definition, but will not collide with it in storage, even if
|
||||
* they both reside in memory.
|
||||
* @param keyDefinition
|
||||
* Factory that produces a {@link DeriveDefinition} from a {@link KeyDefinition} or {@link DeriveDefinition} and new name.
|
||||
*
|
||||
* If a `KeyDefinition` is passed in, the returned definition will have the same key as the given key definition, but
|
||||
* will not collide with it in storage, even if they both reside in memory.
|
||||
*
|
||||
* If a `DeriveDefinition` is passed in, the returned definition will instead use the name given in the second position
|
||||
* of the tuple. It is up to you to ensure this is unique within the domain of derived state.
|
||||
*
|
||||
* @param options A set of options to customize the behavior of {@link DeriveDefinition}.
|
||||
* @param options.derive A function to use to convert values from TFrom to TTo. This is called on each emit of the parent state observable
|
||||
* and the resulting value will be emitted from the derived state observable.
|
||||
* @param options.cleanupDelayMs The number of milliseconds to wait before cleaning up the state after the last subscriber has unsubscribed.
|
||||
* Defaults to 1000ms.
|
||||
* @param options.dependencyShape An object defining the dependencies of the derive function. The keys of the object are the names of the dependencies
|
||||
* and the values are the types of the dependencies.
|
||||
* for example:
|
||||
* ```
|
||||
* {
|
||||
* myService: MyService,
|
||||
* myOtherService: MyOtherService,
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param options.deserializer A function to use to safely convert your type from json to your expected type.
|
||||
* Your data may be serialized/deserialized at any time and this needs callback needs to be able to faithfully re-initialize
|
||||
* from the JSON object representation of your type.
|
||||
* @param definition
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
static from<TFrom, TTo, TDeps extends DerivedStateDependencies = never>(
|
||||
keyDefinition: KeyDefinition<TFrom>,
|
||||
definition:
|
||||
| KeyDefinition<TFrom>
|
||||
| [DeriveDefinition<unknown, TFrom, DerivedStateDependencies>, string],
|
||||
options: DeriveDefinitionOptions<TFrom, TTo, TDeps>,
|
||||
) {
|
||||
return new DeriveDefinition(keyDefinition.stateDefinition, keyDefinition.key, options);
|
||||
if (isKeyDefinition(definition)) {
|
||||
return new DeriveDefinition(definition.stateDefinition, definition.key, options);
|
||||
} else {
|
||||
return new DeriveDefinition(definition[0].stateDefinition, definition[1], options);
|
||||
}
|
||||
}
|
||||
|
||||
static fromWithUserId<TKeyDef, TTo, TDeps extends DerivedStateDependencies = never>(
|
||||
definition:
|
||||
| KeyDefinition<TKeyDef>
|
||||
| [DeriveDefinition<unknown, TKeyDef, DerivedStateDependencies>, string],
|
||||
options: DeriveDefinitionOptions<[UserId, TKeyDef], TTo, TDeps>,
|
||||
) {
|
||||
if (isKeyDefinition(definition)) {
|
||||
return new DeriveDefinition(definition.stateDefinition, definition.key, options);
|
||||
} else {
|
||||
return new DeriveDefinition(definition[0].stateDefinition, definition[1], options);
|
||||
}
|
||||
}
|
||||
|
||||
get derive() {
|
||||
@@ -137,3 +180,11 @@ export class DeriveDefinition<TFrom, TTo, TDeps extends DerivedStateDependencies
|
||||
return `derived_${this.stateDefinition.name}_${this.uniqueDerivationName}` as StorageKey;
|
||||
}
|
||||
}
|
||||
|
||||
function isKeyDefinition(
|
||||
definition:
|
||||
| KeyDefinition<unknown>
|
||||
| [DeriveDefinition<unknown, unknown, DerivedStateDependencies>, string],
|
||||
): definition is KeyDefinition<unknown> {
|
||||
return Object.prototype.hasOwnProperty.call(definition, "key");
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export abstract class StateProvider {
|
||||
getGlobal: <T>(keyDefinition: KeyDefinition<T>) => GlobalState<T>;
|
||||
getDerived: <TFrom, TTo, TDeps extends DerivedStateDependencies>(
|
||||
parentState$: Observable<TFrom>,
|
||||
deriveDefinition: DeriveDefinition<unknown, TTo, TDeps>,
|
||||
deriveDefinition: DeriveDefinition<TFrom, TTo, TDeps>,
|
||||
dependencies: TDeps,
|
||||
) => DerivedState<TTo>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user