mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
Use union type to limit initialize options
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { SessionStorable } from "./session-storable";
|
||||
import { InitializeOptions } from "./sync-item-metadata";
|
||||
|
||||
class BuildOptions<T, TJson = Jsonify<T>> {
|
||||
ctor?: new () => T;
|
||||
initializer?: (keyValuePair: TJson) => T;
|
||||
initializeAsArray? = false;
|
||||
initializeAsRecord? = false;
|
||||
initializeAs?: InitializeOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,8 +47,7 @@ export function sessionSync<T>(buildOptions: BuildOptions<T>) {
|
||||
sessionKey: `${prototype.constructor.name}_${propertyKey}`,
|
||||
ctor: buildOptions.ctor,
|
||||
initializer: buildOptions.initializer,
|
||||
initializeAsArray: buildOptions.initializeAsArray,
|
||||
initializeAsRecord: buildOptions.initializeAsRecord,
|
||||
initializeAs: buildOptions.initializeAs ?? "object",
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
export type InitializeOptions = "array" | "record" | "object";
|
||||
|
||||
export class SyncedItemMetadata {
|
||||
propertyKey: string;
|
||||
sessionKey: string;
|
||||
ctor?: new () => any;
|
||||
initializer?: (keyValuePair: any) => any;
|
||||
initializeAsArray?: boolean;
|
||||
initializeAsRecord?: boolean;
|
||||
initializeAs: InitializeOptions;
|
||||
|
||||
static builder(metadata: SyncedItemMetadata): (o: any) => any {
|
||||
if (metadata.initializeAsArray && metadata.initializeAsRecord) {
|
||||
throw new Error("initializeAsArray and initializeAsRecord cannot both be true");
|
||||
}
|
||||
|
||||
const itemBuilder =
|
||||
metadata.initializer != null
|
||||
? metadata.initializer
|
||||
: (o: any) => Object.assign(new metadata.ctor(), o);
|
||||
if (metadata.initializeAsArray) {
|
||||
if (metadata.initializeAs === "array") {
|
||||
return (keyValuePair: any) => keyValuePair.map((o: any) => itemBuilder(o));
|
||||
} else if (metadata.initializeAsRecord) {
|
||||
} else if (metadata.initializeAs === "record") {
|
||||
return (keyValuePair: any) => {
|
||||
const record: Record<any, any> = {};
|
||||
for (const key in keyValuePair) {
|
||||
|
||||
@@ -8,29 +8,40 @@ describe("builder", () => {
|
||||
const ctor = TestClass;
|
||||
|
||||
it("should use initializer if provided", () => {
|
||||
const metadata = { propertyKey, sessionKey: key, initializer };
|
||||
const metadata: SyncedItemMetadata = {
|
||||
propertyKey,
|
||||
sessionKey: key,
|
||||
initializer,
|
||||
initializeAs: "object",
|
||||
};
|
||||
const builder = SyncedItemMetadata.builder(metadata);
|
||||
expect(builder({})).toBe("used initializer");
|
||||
});
|
||||
|
||||
it("should use ctor if initializer is not provided", () => {
|
||||
const metadata = { propertyKey, sessionKey: key, ctor };
|
||||
const metadata: SyncedItemMetadata = { propertyKey, sessionKey: key, ctor };
|
||||
const builder = SyncedItemMetadata.builder(metadata);
|
||||
expect(builder({})).toBeInstanceOf(TestClass);
|
||||
});
|
||||
|
||||
it("should prefer initializer over ctor", () => {
|
||||
const metadata = { propertyKey, sessionKey: key, ctor, initializer };
|
||||
const metadata: SyncedItemMetadata = {
|
||||
propertyKey,
|
||||
sessionKey: key,
|
||||
ctor,
|
||||
initializer,
|
||||
initializeAs: "object",
|
||||
};
|
||||
const builder = SyncedItemMetadata.builder(metadata);
|
||||
expect(builder({})).toBe("used initializer");
|
||||
});
|
||||
|
||||
it("should honor initialize as array", () => {
|
||||
const metadata = {
|
||||
const metadata: SyncedItemMetadata = {
|
||||
propertyKey,
|
||||
sessionKey: key,
|
||||
initializer: initializer,
|
||||
initializeAsArray: true,
|
||||
initializeAs: "array",
|
||||
};
|
||||
const builder = SyncedItemMetadata.builder(metadata);
|
||||
expect(builder([{}])).toBeInstanceOf(Array);
|
||||
@@ -38,11 +49,11 @@ describe("builder", () => {
|
||||
});
|
||||
|
||||
it("should honor initialize as record", () => {
|
||||
const metadata = {
|
||||
const metadata: SyncedItemMetadata = {
|
||||
propertyKey,
|
||||
sessionKey: key,
|
||||
initializer: initializer,
|
||||
initializeAsRecord: true,
|
||||
initializeAs: "record",
|
||||
};
|
||||
const builder = SyncedItemMetadata.builder(metadata);
|
||||
expect(builder({ key: "" })).toBeInstanceOf(Object);
|
||||
|
||||
@@ -8,8 +8,8 @@ import { browserSession, sessionSync } from "../decorators/session-sync-observab
|
||||
|
||||
@browserSession
|
||||
export class BrowserFolderService extends BaseFolderService {
|
||||
@sessionSync({ initializer: Folder.fromJSON, initializeAsArray: true })
|
||||
@sessionSync({ initializer: Folder.fromJSON, initializeAs: "array" })
|
||||
protected _folders: BehaviorSubject<Folder[]>;
|
||||
@sessionSync({ initializer: FolderView.fromJSON, initializeAsArray: true })
|
||||
@sessionSync({ initializer: FolderView.fromJSON, initializeAs: "array" })
|
||||
protected _folderViews: BehaviorSubject<FolderView[]>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user