import 'reflect-metadata'; import { Type } from './Util'; import { FrontworkComponent } from '../Types/FrontworkComponent'; /** * The Injector stores services and resolves requested instances. */ export const Injector = new class { injectionQueue :any[] = [] rootInterface : Type root : Type rootModules: Type[] = [] modules : {implements?: Type, implementation: Type}[] = [] moduleObjs : {[key in string] : FrontworkComponent} = {} /** * Resolves instances by injecting required services * @param {Type} target * @returns {T} */ resolve(target: Type): T { // tokens are required dependencies, while injections are resolved tokens from the Injector if(this.moduleObjs[target.name]) return this.moduleObjs[target.name] as any if(target.name === this.rootInterface.name || target.name === this.root.name){ let modules = this.modules.map(m => { const module = new m.implementation() if(m.implements) this.moduleObjs[m.implements.name] = module this.moduleObjs[m.implementation.name] = module return module }) const rootobj = new this.root(modules); this.moduleObjs[this.rootInterface.name] = rootobj this.moduleObjs[target.name] = rootobj while(this.injectionQueue.length > 0){ const i = this.injectionQueue.shift() if(this.moduleObjs[i.what.name]) i.target[i.where] = this.moduleObjs[i.what.name] else this.injectionQueue.push(i) } return rootobj } this.moduleObjs[target.name] = new target() return this.moduleObjs[target.name] as any } };