import { AbstractFactory, Container, DependencyRequirement, PropertyDependency, isInstantiable, DEPENDENCY_KEYS_METADATA_KEY, StaticClass, Instantiable, getPropertyInjectionMetadata, } from '../di' import {Collection, ErrorWithContext} from '../util' import {Logging} from '../service/Logging' import {Config} from '../service/Config' import {ViewEngine} from './ViewEngine' import {PugViewEngine} from './PugViewEngine' /** * Dependency factory whose token matches the abstract ViewEngine class, but produces * a particular ViewEngine implementation based on the configuration. */ export class ViewEngineFactory extends AbstractFactory { protected readonly logging: Logging protected readonly config: Config constructor() { super({}) this.logging = Container.getContainer().make(Logging) this.config = Container.getContainer().make(Config) } produce(): ViewEngine { return new (this.getViewEngineClass())() } match(something: unknown): boolean { return something === ViewEngine } getDependencyKeys(): Collection { const meta = Reflect.getMetadata(DEPENDENCY_KEYS_METADATA_KEY, this.getViewEngineClass()) if ( meta ) { return meta } return new Collection() } getInjectedProperties(): Collection { const meta = new Collection() let currentToken = this.getViewEngineClass() do { const loadedMeta = getPropertyInjectionMetadata(currentToken) if ( loadedMeta ) { meta.concat(loadedMeta) } currentToken = Object.getPrototypeOf(currentToken) } while (Object.getPrototypeOf(currentToken) !== Function.prototype && Object.getPrototypeOf(currentToken) !== Object.prototype) return meta } /** * Using the config, get the implementation of the ViewEngine that should be used in the application. * @protected */ protected getViewEngineClass(): StaticClass> { const ViewEngineClass = this.config.get('server.view_engine.driver', PugViewEngine) if ( !isInstantiable(ViewEngineClass) || !(ViewEngineClass.prototype instanceof ViewEngine) ) { const e = new ErrorWithContext('Provided session class does not extend from @extollo/lib.ViewEngine') e.context = { configKey: 'server.view_engine.driver', class: ViewEngineClass.toString(), } } return ViewEngineClass } }