import {DependencyKey, DependencyRequirement, Instantiable, PropertyDependency} from '../types' import {Collection, logIfDebugging} from '../../util' import {getPropertyInjectionMetadata} from '../decorator/getPropertyInjectionMetadata' /** * Abstract base class for dependency container factories. * @abstract */ export abstract class AbstractFactory { protected constructor( /** * Token that was registered for this factory. In most cases, this is the static * form of the item that is to be produced by this factory. * @var * @protected */ protected token: DependencyKey, ) {} /** * Produce an instance of the token. * @param {Array} dependencies - the resolved dependencies, in order * @param {Array} parameters - the bound constructor parameters, in order */ abstract produce(dependencies: any[], parameters: any[]): T /** * Should return true if the given identifier matches the token for this factory. * @param something * @return boolean */ abstract match(something: unknown): boolean /** * Get the dependency requirements required by this factory's token. * @return Collection */ abstract getDependencyKeys(): Collection /** * Get the property dependencies that should be injected to the created instance. * @return Collection */ abstract getInjectedProperties(): Collection /** Helper method that returns all `@Inject()`'ed properties for a token and its prototypical ancestors. */ protected getInjectedPropertiesForPrototypeChain(token: Instantiable): Collection { const meta = new Collection() do { const loadedMeta = getPropertyInjectionMetadata(token) if ( loadedMeta ) { meta.concat(loadedMeta) } token = Object.getPrototypeOf(token) logIfDebugging('extollo.di.injection', 'next currentToken:', token) } while (token !== Function.prototype && token !== Object.prototype) return meta } /** * Get a human-readable name of the token this factory produces. * This is meant for debugging output only. */ public getTokenName(): string { if ( typeof this.token === 'string' ) { return this.token } return this.token?.name ?? '(unknown token)' } }