bitwarden-estensione-browser/apps/browser/src/platform/decorators/session-sync-observable/session-sync.decorator.ts

55 lines
2.0 KiB
TypeScript

import { Jsonify } from "type-fest";
import { SessionStorable } from "./session-storable";
import { InitializeOptions } from "./sync-item-metadata";
class BuildOptions<T, TJson = Jsonify<T>> {
initializer?: (keyValuePair: TJson) => T;
initializeAs?: InitializeOptions;
}
// Used to ensure uniqueness for each synced observable
let index = 0;
/**
* A decorator used to indicate the BehaviorSubject should be synced for this browser session across all contexts.
*
* >**Note** This decorator does nothing if the enclosing class is not decorated with @browserSession.
*
* >**Note** The Behavior subject must be initialized with a default or in the constructor of the class. If it is not, an error will be thrown.
*
* >**!!Warning!!** If the property is overwritten at any time, the new value will not be synced across the browser session.
*
* @param buildOptions
* Builders for the value, requires either a constructor (ctor) for your BehaviorSubject type or an
* initializer function that takes a key value pair representation of the BehaviorSubject data
* and returns your instantiated BehaviorSubject value. `initializeAs can optionally be used to indicate
* the provided initializer function should be used to build an array of values. For example,
* ```ts
* \@sessionSync({ initializer: Foo.fromJSON, initializeAs: 'array' })
* ```
* is equivalent to
* ```
* \@sessionSync({ initializer: (obj: any[]) => obj.map((f) => Foo.fromJSON })
* ```
*
* @returns decorator function
*/
export function sessionSync<T>(buildOptions: BuildOptions<T>) {
return (prototype: unknown, propertyKey: string) => {
// Force prototype into SessionStorable and implement it.
const p = prototype as SessionStorable;
if (p.__syncedItemMetadata == null) {
p.__syncedItemMetadata = [];
}
p.__syncedItemMetadata.push({
propertyKey,
sessionKey: `${propertyKey}_${index++}`,
initializer: buildOptions.initializer,
initializeAs: buildOptions.initializeAs ?? "object",
});
};
}