|
|
@ -1,18 +1,30 @@ |
|
|
|
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 extends Collection<GlobalRegistrant> { |
|
|
|
constructor() { |
|
|
|
super() |
|
|
|
this.setGlobal('registry_uuid', uuid4()) |
|
|
|
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() |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@ -21,11 +33,11 @@ export class GlobalRegistry extends Collection<GlobalRegistrant> { |
|
|
|
* @param value |
|
|
|
*/ |
|
|
|
public setGlobal(key: string | symbol, value: unknown): this { |
|
|
|
const existing = this.firstWhere('key', '=', key) |
|
|
|
const existing = this.getCollection().firstWhere('key', '=', key) |
|
|
|
if ( existing ) { |
|
|
|
existing.value = value |
|
|
|
} else { |
|
|
|
this.push({ |
|
|
|
this.getCollection().push({ |
|
|
|
key, |
|
|
|
value, |
|
|
|
}) |
|
|
@ -39,7 +51,17 @@ export class GlobalRegistry extends Collection<GlobalRegistrant> { |
|
|
|
* @param key |
|
|
|
*/ |
|
|
|
public getGlobal(key: string | symbol): any { |
|
|
|
return this.firstWhere('key', '=', key)?.value |
|
|
|
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 |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|