import { AbstractFactory, Container, DependencyRequirement, PropertyDependency, isInstantiable, DEPENDENCY_KEYS_METADATA_KEY, DEPENDENCY_KEYS_PROPERTY_METADATA_KEY } from "@extollo/di" import {Collection, ErrorWithContext} from "@extollo/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(dependencies: any[], parameters: any[]): ViewEngine { return new (this.getViewEngineClass()) } match(something: any) { 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 = Reflect.getMetadata(DEPENDENCY_KEYS_PROPERTY_METADATA_KEY, 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() { 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 = { config_key: 'server.view_engine.driver', class: ViewEngineClass.toString(), } } return ViewEngineClass } }