DescriptorImpl.ts
83 lines
| 2.6 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r5 | import { Descriptor, ILifetime, ConfigurableKeys, DepsMap, Ref, IActivationContext } from "./interfaces"; | ||
|
|
r1 | import { ActivationContext } from "./ActivationContext"; | ||
|
|
r4 | import { each, isKey, key } from "./traits"; | ||
|
|
r1 | |||
| export type RegistrationOverridesMap<S extends object> = { [k in ConfigurableKeys<S>]?: Descriptor<S, NonNullable<S[k]>> }; | ||||
|
|
r0 | |||
| export interface DescriptorImplArgs<S extends object, T> { | ||||
|
|
r1 | lifetime: ILifetime<T>; | ||
|
|
r0 | |||
|
|
r4 | factory: (refs: Record<key, never>) => T; | ||
|
|
r0 | |||
| cleanup?: (item: T) => void; | ||||
|
|
r1 | overrides?: RegistrationOverridesMap<S>; | ||
|
|
r4 | |||
| dependencies?: DepsMap<key, keyof S>; | ||||
|
|
r0 | } | ||
|
|
r1 | |||
|
|
r0 | export class DescriptorImpl<S extends object, T> implements Descriptor<S, T> { | ||
|
|
r1 | private readonly _overrides?: RegistrationOverridesMap<S>; | ||
|
|
r0 | |||
|
|
r1 | private readonly _lifetime: ILifetime<T>; | ||
|
|
r0 | |||
|
|
r4 | private readonly _factory: (refs: Record<key, never>) => T; | ||
|
|
r0 | |||
| private readonly _cleanup?: (item: T) => void; | ||||
|
|
r4 | private readonly _deps?: DepsMap<key, keyof S>; | ||
| constructor({ lifetime, factory, cleanup, overrides, dependencies }: DescriptorImplArgs<S, T>) { | ||||
| this._lifetime = lifetime; | ||||
| this._factory = factory; | ||||
| if (cleanup) | ||||
| this._cleanup = cleanup; | ||||
| if (overrides) | ||||
| this._overrides = overrides; | ||||
| if (dependencies) | ||||
| this._deps = dependencies; | ||||
|
|
r0 | } | ||
|
|
r5 | activate(context: IActivationContext<S>): T { | ||
|
|
r0 | |||
| if (this._lifetime.has()) | ||||
| return this._lifetime.get(); | ||||
| this._lifetime.initialize(context); | ||||
| if (this._overrides) | ||||
| each(this._overrides, (v, k) => context.register(k, v)); | ||||
|
|
r4 | const resolve = <K extends keyof S, L extends boolean, D = never>({ name, lazy, ...opts }: Ref<K, L, D>) => { | ||
| if (lazy) { | ||||
| return () => "default" in opts ? context.resolve(name, opts.default) : context.resolve(name); | ||||
| } else { | ||||
| return "default" in opts ? context.resolve(name, opts.default) : context.resolve(name); | ||||
| } | ||||
| }; | ||||
|
|
r0 | |||
|
|
r5 | const makeRefs = (deps: typeof this._deps) => deps ? | ||
|
|
r4 | Object.keys(deps) | ||
| .map(k => { | ||||
| const ref = deps[k]; | ||||
| return isKey(ref) ? | ||||
| { [k]: resolve({ name: ref }) } : | ||||
| { [k]: resolve(ref) }; | ||||
| }) | ||||
| .reduce((a, p) => ({ ...a, ...p }), {} ) as Record<key, never>: | ||||
| {} as Record<key, never>; | ||||
|
|
r1 | |||
|
|
r4 | const instance = this._factory.call(undefined, makeRefs(this._deps)); | ||
|
|
r0 | |||
| this._lifetime.store(instance, this._cleanup); | ||||
| return instance; | ||||
| } | ||||
|
|
r1 | |||
|
|
r0 | toString() { | ||
|
|
r1 | return `[object DescriptorImpl, lifetime=${String(this._lifetime)}]`; | ||
|
|
r0 | } | ||
| } | ||||
