You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
lib/src/util/support/global.ts

74 lines
2.1 KiB

import {Collection} from '../collection/Collection'
import {uuid4} from './data'
import {AsyncLocalStorage} from 'async_hooks'
/**
* Type structure for a single item in the global registry.
*/
export type GlobalRegistrant = { key: string | symbol, value: any }
export class AccessGlobalRegistryOutsideAsyncLifecycleError extends Error {
constructor() {
super('Attempted to access global registry outside of an async context.')
}
}
/**
* A convenient class to manage global variables.
*/
export class GlobalRegistry {
protected readonly storage: AsyncLocalStorage<Collection<GlobalRegistrant>> = new AsyncLocalStorage<Collection<GlobalRegistrant>>()
/** Run a closure with a global registry. */
public run<T>(closure: () => T): T {
return this.storage.run(new Collection<GlobalRegistrant>(), (): T => {
this.setGlobal('registry_uuid', uuid4())
return closure()
})
}
/**
* Store the given `value` associated by `key`.
* @param key
* @param value
*/
public setGlobal(key: string | symbol, value: unknown): this {
const existing = this.getCollection().firstWhere('key', '=', key)
if ( existing ) {
existing.value = value
} else {
this.getCollection().push({
key,
value,
})
}
return this
}
/**
* Retrieve the value of the given `key`, if it exists in the store.
* @param key
*/
public getGlobal(key: string | symbol): any {
return this.getCollection().firstWhere('key', '=', key)?.value
}
/** Get the globals collection or throw an error if outside async context. */
protected getCollection(): Collection<GlobalRegistrant> {
const coll = this.storage.getStore()
if ( !coll ) {
throw new AccessGlobalRegistryOutsideAsyncLifecycleError()
}
return coll
}
}
/**
* Export a singleton global registry for all code to share.
*
* Exporting an instance here guarantees that all code that import it will get the same instance.
*/
export const globalRegistry = new GlobalRegistry()