UNPKG

@unblocks/registry

Version:

All-purpose map data structure on steroids. Successor of @encodable/registry

211 lines (204 loc) 6.36 kB
/** Union types of all values from a map type */ type ValueOf<T> = T[keyof T]; declare const OverwritePolicy: { readonly ALLOW: "ALLOW"; readonly PROHIBIT: "PROHIBIT"; readonly WARN: "WARN"; }; type OverwritePolicy = ValueOf<typeof OverwritePolicy>; interface ItemWithValue<V> { /** item value */ value: V; } interface ItemWithLoader<L> { /** function that returns value */ loader: () => L; } interface RegistryState<V, L extends V | Promise<V>> { /** * If this is a global registry, it will be defined. */ globalId?: string; /** name of this registry */ name?: string; /** schema version, can be used to check compatibility */ version: string; /** * fallback key to use if `.get()` was called without a key * This was the initial value when the registry was created. */ initialDefaultKey?: string; /** * fallback key to use if `.get()` was called without a key * This is the current default key. */ defaultKey?: string; /** set the first item registered as the default */ setFirstItemAsDefault: boolean; /** define if registering with an existing key is allowed, prohibited or warned */ overwritePolicy: OverwritePolicy; /** map to lookup items by key */ items: { [key: string]: ItemWithValue<V> | ItemWithLoader<L>; }; /** map to lookup promises by key */ promises: { [key: string]: Promise<V>; }; } interface RegistryConfig { /** * Set this value to define a global registry. * This will make it a true singleton and accessible via this `globalId` from any package. */ globalId?: string; /** schema version, can be used to check compatibility */ version?: string; /** name of this registry */ name?: string; /** fallback key to use if `.get()` was called without a key */ defaultKey?: string; /** set the first item registered as the default */ setFirstItemAsDefault?: boolean; /** define if registering with an existing key is allowed, prohibited or warned */ overwritePolicy?: OverwritePolicy; } /** * Registry class * * Can use generic to specify type of item in the registry * @type V Type of value * @type L Type of value returned from loader function when using `registerLoader()`. * `L` can be either `V`, `Promise<V>` or `V | Promise<V>` * Set `L=V` when does not support asynchronous loader. * By default `L` is set to `V | Promise<V>` to support * both synchronous and asynchronous loaders. */ declare class Registry<V, L extends V | Promise<V> = V | Promise<V>> { readonly state: RegistryState<V, L>; constructor(config?: RegistryConfig); /** * Clear all item in the registry. * Reset default key to initial default key (if any) * @returns the registry itself */ clear(): this; /** * Apply a function to this registry. * @param func Function that takes this registry as an argument * @returns the registry itself */ apply(func: (registry: this) => void): this; /** * Check if item with the given key exists * @param key the key to look for * @returns true if the item exists, false otherwise */ has(key: string): boolean; /** * Register key with a value * @param key * @param value * @returns the registry itself */ registerValue(key: string, value: V): this; /** * Register key with a loader, a function that returns a value. * @param key * @param loader * @returns the registry itself */ registerLoader(key: string, loader: () => L): this; /** * Get value from the specified key. * If the item contains a loader, invoke the loader and return its output. * @param key */ get(key?: string): V | L | undefined; /** * Similar to `.get()` but wrap results in a `Promise`. * This is useful when some items are async loaders to provide uniform output. * @param key */ getAsPromise(key: string): Promise<V>; /** * Return the current default key. * Default key is a fallback key to use if `.get()` was called without a key. */ getDefaultKey(): string | undefined; /** * Set default key to the specified key * Default key is a fallback key to use if `.get()` was called without a key. * @param key */ setDefaultKey(key: string): this; /** * Remove default key. * Default key is a fallback key to use if `.get()` was called without a key. */ clearDefaultKey(): this; /** * Return a map of all key-values in this registry. */ getMap(): { [key: string]: V | L | undefined; }; /** * Same with `.getMap()` but return a `Promise` that resolves when all values are resolved. */ getMapAsPromise(): Promise<{ [key: string]: V; }>; /** * Return all keys in this registry. */ keys(): string[]; /** * Return all values in this registry. * For loaders, they are invoked and their outputs are returned. */ values(): (V | L | undefined)[]; /** * Same with `.values()` but return a `Promise` that resolves when all values are resolved. */ valuesAsPromise(): Promise<V[]>; /** * Return all key-value entries in this registry. */ entries(): { key: string; value: V | L | undefined; }[]; /** * Same with `.entries()` but return a `Promise` that resolves when all values are resolved. */ entriesAsPromise(): Promise<{ key: string; value: V; }[]>; /** * Remove the item with the specified key. * Do nothing if an item with the given key does not exist. * @param key */ remove(key: string): this; /** * Get number of items in the registry */ size(): number; /** * Returns true if there is no item in the registry */ isEmpty(): boolean; } /** * Synchronous registry */ declare class SyncRegistry<V> extends Registry<V, V> { } /** * Helper function for creating a singleton * @param create factory function */ declare function makeSingleton<T>(create: () => T): () => T; export { OverwritePolicy, Registry, type RegistryConfig, type RegistryState, SyncRegistry, makeSingleton };