mirror of
https://github.com/bitwarden/browser
synced 2026-02-18 18:33:50 +00:00
wip: working in vscode, but broken when testing types
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import {
|
||||
COLLECTION_DATA,
|
||||
DeriveDefinition,
|
||||
@@ -15,7 +13,7 @@ export const ENCRYPTED_COLLECTION_DATA_KEY = UserKeyDefinition.record<Collection
|
||||
COLLECTION_DATA,
|
||||
"collections",
|
||||
{
|
||||
deserializer: (jsonData: Jsonify<CollectionData>) => CollectionData.fromJSON(jsonData),
|
||||
deserializer: (jsonData) => CollectionData.fromJSON(jsonData!),
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -16,11 +16,11 @@ import {
|
||||
import { LoginEmailServiceAbstraction } from "../../abstractions/login-email.service";
|
||||
|
||||
export const LOGIN_EMAIL = new KeyDefinition<string>(LOGIN_EMAIL_MEMORY, "loginEmail", {
|
||||
deserializer: (value: string) => value,
|
||||
deserializer: (value: string | null) => value,
|
||||
});
|
||||
|
||||
export const STORED_EMAIL = new KeyDefinition<string>(LOGIN_EMAIL_DISK, "storedEmail", {
|
||||
deserializer: (value: string) => value,
|
||||
deserializer: (value: string | null) => value,
|
||||
});
|
||||
|
||||
export class LoginEmailService implements LoginEmailServiceAbstraction {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { map } from "rxjs";
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import {
|
||||
ORGANIZATION_MANAGEMENT_PREFERENCES_DISK,
|
||||
@@ -20,7 +19,7 @@ import {
|
||||
*/
|
||||
function buildKeyDefinition<T>(key: string): UserKeyDefinition<T> {
|
||||
return new UserKeyDefinition<T>(ORGANIZATION_MANAGEMENT_PREFERENCES_DISK, key, {
|
||||
deserializer: (obj: Jsonify<T>) => obj as T,
|
||||
deserializer: (obj) => obj! as T,
|
||||
clearOn: ["logout"],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { ORGANIZATIONS_DISK, UserKeyDefinition } from "../../../platform/state";
|
||||
import { OrganizationData } from "../../models/data/organization.data";
|
||||
|
||||
@@ -13,7 +11,7 @@ export const ORGANIZATIONS = UserKeyDefinition.record<OrganizationData>(
|
||||
ORGANIZATIONS_DISK,
|
||||
"organizations",
|
||||
{
|
||||
deserializer: (obj: Jsonify<OrganizationData>) => OrganizationData.fromJSON(obj),
|
||||
deserializer: (obj) => OrganizationData.fromJSON(obj!),
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -122,7 +122,7 @@ export class SymmetricCryptoKey {
|
||||
return new SymmetricCryptoKey(arrayBuffer);
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<SymmetricCryptoKey>): SymmetricCryptoKey {
|
||||
static fromJSON(obj: Jsonify<SymmetricCryptoKey> | null): SymmetricCryptoKey {
|
||||
return SymmetricCryptoKey.fromString(obj?.keyB64);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import { Jsonify } from "type-fest";
|
||||
* @returns
|
||||
*/
|
||||
export function array<T>(
|
||||
elementDeserializer: (element: Jsonify<T>) => T,
|
||||
): (array: Jsonify<T[]>) => T[] {
|
||||
elementDeserializer: (element: Jsonify<T> | null) => T | null,
|
||||
): (array: Jsonify<T[]> | null) => T[] | null {
|
||||
return (array) => {
|
||||
if (array == null) {
|
||||
return null;
|
||||
@@ -24,9 +24,9 @@ export function array<T>(
|
||||
* @param valueDeserializer
|
||||
*/
|
||||
export function record<T, TKey extends string | number = string>(
|
||||
valueDeserializer: (value: Jsonify<T>) => T,
|
||||
): (record: Jsonify<Record<TKey, T>>) => Record<TKey, T> {
|
||||
return (jsonValue: Jsonify<Record<TKey, T> | null>) => {
|
||||
valueDeserializer: (value: Jsonify<T> | null) => T | null,
|
||||
): (record: Jsonify<Record<TKey, T>> | null) => Record<TKey, T> | null {
|
||||
return (jsonValue: Jsonify<Record<TKey, T>> | null) => {
|
||||
if (jsonValue == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { mergeOptions, OptionsWithDefaultsDeep } from "../../types/options";
|
||||
import { StorageKey } from "../../types/state";
|
||||
|
||||
import { array, record } from "./deserialization-helpers";
|
||||
@@ -42,7 +41,7 @@ export type KeyDefinitionOptions<T> = {
|
||||
* @param jsonValue The JSON object representation of your state.
|
||||
* @returns The fully typed version of your state.
|
||||
*/
|
||||
readonly deserializer: (jsonValue: Jsonify<T>) => T | null;
|
||||
readonly deserializer: (jsonValue: Jsonify<T> | null) => T | null;
|
||||
/**
|
||||
* The number of milliseconds to wait before cleaning up the state after the last subscriber has unsubscribed.
|
||||
* Defaults to 1000ms.
|
||||
@@ -55,13 +54,27 @@ export type KeyDefinitionOptions<T> = {
|
||||
readonly debug?: DebugOptions;
|
||||
};
|
||||
|
||||
const DEFAULT_KEY_DEFINITION_OPTIONS = Object.freeze({
|
||||
cleanupDelayMs: 1000 as number,
|
||||
debug: {
|
||||
enableUpdateLogging: false,
|
||||
enableRetrievalLogging: false,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* KeyDefinitions describe the precise location to store data for a given piece of state.
|
||||
* The StateDefinition is used to describe the domain of the state, and the KeyDefinition
|
||||
* sub-divides that domain into specific keys.
|
||||
*/
|
||||
export class KeyDefinition<T> {
|
||||
readonly debug: Required<DebugOptions>;
|
||||
private readonly options: OptionsWithDefaultsDeep<
|
||||
KeyDefinitionOptions<T>,
|
||||
typeof DEFAULT_KEY_DEFINITION_OPTIONS
|
||||
>;
|
||||
get debug() {
|
||||
return Object.freeze({ ...this.options.debug });
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of a KeyDefinition
|
||||
@@ -75,24 +88,19 @@ export class KeyDefinition<T> {
|
||||
constructor(
|
||||
readonly stateDefinition: StateDefinition,
|
||||
readonly key: string,
|
||||
private readonly options: KeyDefinitionOptions<T>,
|
||||
options: KeyDefinitionOptions<T>,
|
||||
) {
|
||||
if (options.deserializer == null) {
|
||||
throw new Error(`'deserializer' is a required property on key ${this.errorKeyName}`);
|
||||
}
|
||||
|
||||
if (options.cleanupDelayMs < 0) {
|
||||
this.options = mergeOptions(options, DEFAULT_KEY_DEFINITION_OPTIONS);
|
||||
|
||||
if (this.options.cleanupDelayMs < 0) {
|
||||
throw new Error(
|
||||
`'cleanupDelayMs' must be greater than or equal to 0. Value of ${options.cleanupDelayMs} passed to key ${this.errorKeyName} `,
|
||||
`'cleanupDelayMs' must be greater than or equal to 0. Value of ${this.options.cleanupDelayMs} passed to key ${this.errorKeyName} `,
|
||||
);
|
||||
}
|
||||
|
||||
// Normalize optional debug options
|
||||
const { enableUpdateLogging = false, enableRetrievalLogging = false } = options.debug ?? {};
|
||||
this.debug = {
|
||||
enableUpdateLogging,
|
||||
enableRetrievalLogging,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +114,7 @@ export class KeyDefinition<T> {
|
||||
* Gets the number of milliseconds to wait before cleaning up the state after the last subscriber has unsubscribed.
|
||||
*/
|
||||
get cleanupDelayMs() {
|
||||
return this.options.cleanupDelayMs < 0 ? 0 : (this.options.cleanupDelayMs ?? 1000);
|
||||
return this.options.cleanupDelayMs;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@ export const EVENT_COLLECTION = UserKeyDefinition.array<EventData>(
|
||||
EVENT_COLLECTION_DISK,
|
||||
"events",
|
||||
{
|
||||
deserializer: (s) => EventData.fromJSON(s),
|
||||
deserializer: (s) => EventData.fromJSON(s!),
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ export const SEND_USER_ENCRYPTED = UserKeyDefinition.record<SendData>(
|
||||
SEND_DISK,
|
||||
"sendUserEncrypted",
|
||||
{
|
||||
deserializer: (obj: SendData) => obj,
|
||||
deserializer: (obj) => obj,
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
|
||||
0
libs/common/src/types/merge-deep.ts
Normal file
0
libs/common/src/types/merge-deep.ts
Normal file
100
libs/common/src/types/options.spec.ts
Normal file
100
libs/common/src/types/options.spec.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { mergeOptions } from "./options";
|
||||
|
||||
type ExampleOptions = {
|
||||
readonly a?: number;
|
||||
readonly required_func: () => void;
|
||||
readonly optional_func?: () => void;
|
||||
readonly b: string;
|
||||
readonly c?: {
|
||||
readonly d?: number;
|
||||
readonly e: string;
|
||||
};
|
||||
};
|
||||
|
||||
const EXAMPLE_DEFAULTS = Object.freeze({
|
||||
a: 0,
|
||||
optional_func: () => {},
|
||||
c: {
|
||||
d: 1,
|
||||
},
|
||||
f: {
|
||||
h: 1,
|
||||
},
|
||||
});
|
||||
|
||||
describe("mergeOptions", () => {
|
||||
it("merges options with defaults", () => {
|
||||
const options: ExampleOptions = {
|
||||
required_func: () => {},
|
||||
b: "test",
|
||||
};
|
||||
|
||||
const merged = mergeOptions(options, EXAMPLE_DEFAULTS);
|
||||
|
||||
// can access properties
|
||||
expect(merged.a).toBe(42);
|
||||
|
||||
expect(merged).toEqual({
|
||||
a: 0,
|
||||
b: "test",
|
||||
});
|
||||
});
|
||||
|
||||
it("overrides defaults with options", () => {
|
||||
const options: ExampleOptions = {
|
||||
a: 42,
|
||||
b: "test",
|
||||
f: {
|
||||
i: "example",
|
||||
},
|
||||
required_func: () => {},
|
||||
};
|
||||
|
||||
const merged = mergeOptions(options, EXAMPLE_DEFAULTS);
|
||||
|
||||
// can access properties
|
||||
expect(merged.a).toBe(42);
|
||||
|
||||
expect(merged).toEqual({
|
||||
a: 42,
|
||||
b: "test",
|
||||
});
|
||||
});
|
||||
|
||||
//Defaults has a required property 'a', but options does not provide it. Not an error
|
||||
mergeOptions({ b: "test" } as { b: string }, { a: 0 });
|
||||
//Defaults provides a required function, but options does not provide it. Not an error
|
||||
mergeOptions({ b: "test" } as { b: string }, { required_func: () => {} });
|
||||
//Defaults provides a required property of the wrong type. Not an error because default will never be used
|
||||
mergeOptions({ a: "test" } as { a: string }, { a: 0 });
|
||||
//Defaults provides a required function of the wrong type. Not an error because default will never be used
|
||||
mergeOptions({ required_func: () => "" } as { required_func: () => string }, {
|
||||
required_func: () => {},
|
||||
});
|
||||
|
||||
//@ts-expect-error -- Defaults provides an optional property of the wrong type
|
||||
mergeOptions({} as { a?: string }, { a: 0 });
|
||||
//@ts-expect-error -- Defaults provides an optional function of the wrong type
|
||||
mergeOptions({} as { optional_func?: () => string }, { optional_func: () => {} });
|
||||
|
||||
//@ts-expect-error -- defaults missing an property optional in options
|
||||
mergeOptions({ a: 42 } as { a?: number }, {});
|
||||
//@ts-expect-error -- defaults missing an method optional in options
|
||||
mergeOptions({ f: () => {} } as { f?: () => void }, {});
|
||||
|
||||
//@ts-expect-error -- defaults missing a deep optional property defined in options
|
||||
mergeOptions({ a: { required_func: () => {} } } as { a?: { required_func: () => void } }, {});
|
||||
//@ts-expect-error -- defaults missing a deep optional property defined in options
|
||||
mergeOptions({ a: { required_func: () => {} } } as { a: { required_func?: () => void } }, {});
|
||||
|
||||
//@ts-expect-error -- defaults missing a optional object defined in options
|
||||
mergeOptions({} as { a?: { b: number } }, {});
|
||||
|
||||
//@ts-expect-error -- defaults missing a deep optional property defined in required option
|
||||
mergeOptions({ a: {} } as { a: { b?: number } }, {});
|
||||
|
||||
//@ts-expect-error -- defaults missing a deep optional property defined in optional option
|
||||
mergeOptions({ a: {} } as { a?: { b?: number } }, {});
|
||||
//@ts-expect-error -- defaults missing a deep optional property defined in optional option
|
||||
mergeOptions({ a: {} } as { a?: { b?: number } }, { a: {} });
|
||||
});
|
||||
186
libs/common/src/types/options.ts
Normal file
186
libs/common/src/types/options.ts
Normal file
@@ -0,0 +1,186 @@
|
||||
/* eslint-disable @typescript-eslint/no-empty-object-type -- used in type-fest's code*/
|
||||
import { RequiredKeysOf, Simplify, Primitive } from "type-fest";
|
||||
|
||||
type Function = (...args: any[]) => any;
|
||||
|
||||
/** FIXME: this is pulled from type-fest-v4. remove when we update package */
|
||||
export type ConditionalSimplifyDeep<
|
||||
Type,
|
||||
ExcludeType = never,
|
||||
IncludeType = unknown,
|
||||
> = Type extends ExcludeType
|
||||
? Type
|
||||
: Type extends IncludeType
|
||||
? { [TypeKey in keyof Type]: ConditionalSimplifyDeep<Type[TypeKey], ExcludeType, IncludeType> }
|
||||
: Type;
|
||||
export type BuiltIns = Primitive | void | Date | RegExp;
|
||||
export type NonRecursiveType = BuiltIns | Function | (new (...arguments_: any[]) => unknown);
|
||||
export type SimplifyDeep<Type, ExcludeType = never> = ConditionalSimplifyDeep<
|
||||
Type,
|
||||
ExcludeType | NonRecursiveType | Set<unknown> | Map<unknown, unknown>,
|
||||
object
|
||||
>;
|
||||
|
||||
type SimplifyDeepExcludeArray<T> = SimplifyDeep<T, UnknownArray>;
|
||||
export type UnknownArray = readonly unknown[];
|
||||
export type UnknownRecord = Record<PropertyKey, unknown>;
|
||||
export type UnknownArrayOrTuple = readonly [...unknown[]];
|
||||
export type OmitIndexSignature<ObjectType> = {
|
||||
[KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
|
||||
? never
|
||||
: KeyType]: ObjectType[KeyType];
|
||||
};
|
||||
export type PickIndexSignature<ObjectType> = {
|
||||
[KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
|
||||
? KeyType
|
||||
: never]: ObjectType[KeyType];
|
||||
};
|
||||
|
||||
type MergeDeepRecordProperty<Destination, Source> = undefined extends Source
|
||||
?
|
||||
| MergeDeepOrReturn<Source, Exclude<Destination, undefined>, Exclude<Source, undefined>>
|
||||
| undefined
|
||||
: MergeDeepOrReturn<Source, Destination, Source>;
|
||||
type RequiredFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
|
||||
? Type[Key] extends undefined
|
||||
? Key
|
||||
: never
|
||||
: Key;
|
||||
|
||||
// Returns `never` if the key is required otherwise return the key type.
|
||||
type OptionalFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
|
||||
? Type[Key] extends undefined
|
||||
? never
|
||||
: Key
|
||||
: never;
|
||||
|
||||
export type EnforceOptional<ObjectType> = Simplify<
|
||||
{
|
||||
[Key in keyof ObjectType as RequiredFilter<ObjectType, Key>]: ObjectType[Key];
|
||||
} & {
|
||||
[Key in keyof ObjectType as OptionalFilter<ObjectType, Key>]?: Exclude<
|
||||
ObjectType[Key],
|
||||
undefined
|
||||
>;
|
||||
}
|
||||
>;
|
||||
|
||||
type MergeDeepOrReturn<DefaultType, Destination, Source> = SimplifyDeepExcludeArray<
|
||||
[undefined] extends [Destination | Source]
|
||||
? DefaultType
|
||||
: Destination extends UnknownRecord
|
||||
? Source extends UnknownRecord
|
||||
? MergeDeepRecord<Destination, Source>
|
||||
: DefaultType
|
||||
: Destination extends UnknownArrayOrTuple
|
||||
? Source extends UnknownArrayOrTuple
|
||||
? MergeDeepArrayOrTuple<Destination, Source>
|
||||
: DefaultType
|
||||
: DefaultType
|
||||
>;
|
||||
|
||||
type MergeDeepArrayOrTuple<
|
||||
Destination extends UnknownArrayOrTuple,
|
||||
Source extends UnknownArrayOrTuple,
|
||||
> = Array<Exclude<Destination, undefined>[number] | Exclude<Source, undefined>[number]>;
|
||||
|
||||
type MergeDeepRecord<
|
||||
Destination extends UnknownRecord,
|
||||
Source extends UnknownRecord,
|
||||
> = DoMergeDeepRecord<OmitIndexSignature<Destination>, OmitIndexSignature<Source>> &
|
||||
Merge<PickIndexSignature<Destination>, PickIndexSignature<Source>>;
|
||||
|
||||
type DoMergeDeepRecord<Destination extends UnknownRecord, Source extends UnknownRecord> =
|
||||
// Case in rule 1: The destination contains the key but the source doesn't.
|
||||
{
|
||||
[Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key];
|
||||
} & {
|
||||
// Case in rule 2: The source contains the key but the destination doesn't.
|
||||
[Key in keyof Source as Key extends keyof Destination ? never : Key]: Source[Key];
|
||||
} & {
|
||||
// Case in rule 3: Both the source and the destination contain the key.
|
||||
[Key in keyof Source as Key extends keyof Destination ? Key : never]: MergeDeepRecordProperty<
|
||||
Destination[Key],
|
||||
Source[Key]
|
||||
>;
|
||||
};
|
||||
type SimpleMerge<Destination, Source> = {
|
||||
[Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key];
|
||||
} & Source;
|
||||
|
||||
export type Merge<Destination, Source> = Simplify<
|
||||
SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>> &
|
||||
SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
|
||||
>;
|
||||
export type IfNever<T, TypeIfNever = true, TypeIfNotNever = false> =
|
||||
IsNever<T> extends true ? TypeIfNever : TypeIfNotNever;
|
||||
export type IsNever<T> = [T] extends [never] ? true : false;
|
||||
|
||||
type MergeDeep<Destination, Source> = SimplifyDeepExcludeArray<
|
||||
[undefined] extends [Destination | Source]
|
||||
? never
|
||||
: Destination extends UnknownRecord
|
||||
? Source extends UnknownRecord
|
||||
? MergeDeepRecord<Destination, Source>
|
||||
: never
|
||||
: Destination extends UnknownArrayOrTuple
|
||||
? Source extends UnknownArrayOrTuple
|
||||
? MergeDeepArrayOrTuple<Destination, Source>
|
||||
: never
|
||||
: never
|
||||
>;
|
||||
export type ConditionalKeys<Base, Condition> = {
|
||||
// Map through all the keys of the given base type.
|
||||
[Key in keyof Base]-?: Base[Key] extends Condition // Pick only keys with types extending the given `Condition` type.
|
||||
? // Retain this key
|
||||
// If the value for the key extends never, only include it if `Condition` also extends never
|
||||
IfNever<Base[Key], IfNever<Condition, Key, never>, Key>
|
||||
: // Discard this key since the condition fails.
|
||||
never;
|
||||
// Convert the produced object into a union type of the keys which passed the conditional test.
|
||||
}[keyof Base];
|
||||
|
||||
/** END FIXME: this is pulled from type-fest-v4. remove when we update package */
|
||||
|
||||
export type OptionsWithDefaultsDeep<Options, Defaults> =
|
||||
// FIXME: replace with MergeDeep<Options, Defaults> when type-fest is updated to v4+
|
||||
MergeDeep<Options, Defaults>;
|
||||
|
||||
type DefaultsForDeep<Options extends object> = Simplify<
|
||||
Omit<
|
||||
Required<{
|
||||
[K in keyof Options]: Required<Options>[K] extends Primitive | Function
|
||||
? Options[K]
|
||||
: Required<Options>[K] extends object
|
||||
? DefaultsForDeep<Required<Options>[K]>
|
||||
: never; // should only ever be primitive, function, or object
|
||||
}>,
|
||||
RequiredPrimitiveKeysOf<Options> | RequiredMethodKeysOf<Options>
|
||||
>
|
||||
>;
|
||||
|
||||
// Returns only the keys of `Obj` that are required and not records
|
||||
type RequiredPrimitiveKeysOf<Obj extends object> = RequiredKeysOf<
|
||||
Omit<Obj, ConditionalKeys<Obj, object>>
|
||||
>;
|
||||
|
||||
// Returns only the keys of `Obj` that are required and are functions
|
||||
type RequiredMethodKeysOf<Obj extends object> = RequiredKeysOf<
|
||||
Pick<Obj, ConditionalKeys<Obj, Function>>
|
||||
>;
|
||||
|
||||
export function mergeOptions<
|
||||
Options extends object,
|
||||
const Defaults extends DefaultsForDeep<Options>,
|
||||
>(
|
||||
options: Options,
|
||||
defaults: Defaults,
|
||||
): OptionsWithDefaultsDeep<Options, DefaultsForDeep<Options>> {
|
||||
const result = { ...options } as any;
|
||||
for (const key in defaults) {
|
||||
if (result[key] == null) {
|
||||
result[key] = (defaults as any)[key];
|
||||
}
|
||||
}
|
||||
return result as OptionsWithDefaultsDeep<Options, DefaultsForDeep<Options>>;
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { NOTIFICATION_DISK, UserKeyDefinition } from "@bitwarden/common/platform/state";
|
||||
|
||||
import { NotificationViewData } from "../models";
|
||||
@@ -8,8 +6,7 @@ export const NOTIFICATIONS = UserKeyDefinition.array<NotificationViewData>(
|
||||
NOTIFICATION_DISK,
|
||||
"notifications",
|
||||
{
|
||||
deserializer: (notification: Jsonify<NotificationViewData>) =>
|
||||
NotificationViewData.fromJSON(notification),
|
||||
deserializer: (notification) => NotificationViewData.fromJSON(notification!),
|
||||
clearOn: ["logout", "lock"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { FOLDER_DISK, FOLDER_MEMORY, UserKeyDefinition } from "../../../platform/state";
|
||||
import { FolderData } from "../../models/data/folder.data";
|
||||
import { FolderView } from "../../models/view/folder.view";
|
||||
@@ -8,7 +6,7 @@ export const FOLDER_ENCRYPTED_FOLDERS = UserKeyDefinition.record<FolderData>(
|
||||
FOLDER_DISK,
|
||||
"folders",
|
||||
{
|
||||
deserializer: (obj: Jsonify<FolderData>) => FolderData.fromJSON(obj),
|
||||
deserializer: (obj) => FolderData.fromJSON(obj!),
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
@@ -17,7 +15,7 @@ export const FOLDER_DECRYPTED_FOLDERS = new UserKeyDefinition<FolderView[]>(
|
||||
FOLDER_MEMORY,
|
||||
"decryptedFolders",
|
||||
{
|
||||
deserializer: (obj: Jsonify<FolderView[]>) => obj?.map((f) => FolderView.fromJSON(f)) ?? [],
|
||||
deserializer: (obj) => obj?.map((f) => FolderView.fromJSON(f)) ?? [],
|
||||
clearOn: ["logout", "lock"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SECURITY_TASKS_DISK, UserKeyDefinition } from "@bitwarden/common/platform/state";
|
||||
|
||||
import { SecurityTaskData } from "../models/security-task.data";
|
||||
@@ -8,7 +6,7 @@ export const SECURITY_TASKS = UserKeyDefinition.array<SecurityTaskData>(
|
||||
SECURITY_TASKS_DISK,
|
||||
"securityTasks",
|
||||
{
|
||||
deserializer: (task: Jsonify<SecurityTaskData>) => SecurityTaskData.fromJSON(task),
|
||||
deserializer: (task) => SecurityTaskData.fromJSON(task!),
|
||||
clearOn: ["logout", "lock"],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -103,6 +103,6 @@ export const LAST_PROCESS_RELOAD = new KeyDefinition<Date>(
|
||||
BIOMETRIC_SETTINGS_DISK,
|
||||
"lastProcessReload",
|
||||
{
|
||||
deserializer: (obj) => new Date(obj),
|
||||
deserializer: (obj) => new Date(obj!),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -13,7 +13,7 @@ import { KdfType } from "./enums/kdf-type.enum";
|
||||
import { Argon2KdfConfig, KdfConfig, PBKDF2KdfConfig } from "./models/kdf-config";
|
||||
|
||||
export const KDF_CONFIG = new UserKeyDefinition<KdfConfig>(KDF_CONFIG_DISK, "kdfConfig", {
|
||||
deserializer: (kdfConfig: Jsonify<KdfConfig>) => {
|
||||
deserializer: (kdfConfig: Jsonify<KdfConfig> | null) => {
|
||||
if (kdfConfig == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const GENERATOR_HISTORY = SecretKeyDefinition.array(
|
||||
"localGeneratorHistory",
|
||||
SecretClassifier.allSecret<GeneratedCredential>(),
|
||||
{
|
||||
deserializer: GeneratedCredential.fromJSON,
|
||||
deserializer: (obj) => GeneratedCredential.fromJSON(obj!),
|
||||
clearOn: ["logout"],
|
||||
},
|
||||
);
|
||||
|
||||
15
package-lock.json
generated
15
package-lock.json
generated
@@ -179,6 +179,7 @@
|
||||
"ts-loader": "9.5.2",
|
||||
"tsconfig-paths-webpack-plugin": "4.2.0",
|
||||
"type-fest": "2.19.0",
|
||||
"type-fest-v4": "npm:type-fest@4.41.0",
|
||||
"typescript": "5.5.4",
|
||||
"typescript-eslint": "8.31.0",
|
||||
"typescript-strict-plugin": "2.4.4",
|
||||
@@ -37241,6 +37242,20 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/type-fest-v4": {
|
||||
"name": "type-fest",
|
||||
"version": "4.41.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz",
|
||||
"integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR CC0-1.0)",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
"ts-loader": "9.5.2",
|
||||
"tsconfig-paths-webpack-plugin": "4.2.0",
|
||||
"type-fest": "2.19.0",
|
||||
"type-fest-v4": "npm:type-fest@4.41.0",
|
||||
"typescript": "5.5.4",
|
||||
"typescript-eslint": "8.31.0",
|
||||
"typescript-strict-plugin": "2.4.4",
|
||||
|
||||
Reference in New Issue
Block a user