UNPKG

@glandjs/core

Version:

Glands is a web framework for Node.js (@core)

114 lines (113 loc) 4.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Container = void 0; const common_1 = require("@glandjs/common"); const module_1 = require("../module"); const graph_1 = require("../graph"); const module_container_1 = require("./module-container"); class Container { constructor(logger) { this._modules = new module_container_1.ModulesContainer(); this.instances = new Map(); this.graph = new graph_1.DependencyGraph(); this.logger = logger?.child('Container'); } get modules() { return this._modules; } async register(module, parentModuleId) { const { module: moduleClass, metadata } = this.normalizeModule(module); const moduleId = this.getId(moduleClass); const existingModule = this._modules.getByToken(moduleId); if (existingModule) { return existingModule; } this.logger?.debug(`Registering module: ${moduleId}`); const moduleRef = this.createModule(moduleId, moduleClass); this.graph.addNode(moduleId, 'module', parentModuleId, metadata); await this.processImports(moduleRef, metadata.imports || [], moduleId); this.processControllers(moduleRef, metadata.controllers || [], moduleId); this.processChannels(moduleRef, metadata.channels || [], moduleId); this.logger?.debug(`- Done.`); return moduleRef; } normalizeModule(module) { if ((0, common_1.isDynamicModule)(module)) { return { module: module.module, metadata: { imports: module.imports || [], controllers: module.controllers || [], channels: module.channels || [], }, }; } return { module, metadata: Reflect.getMetadata(common_1.MODULE_METADATA, module) || { imports: [], controllers: [], channels: [], }, }; } getId(token) { if (typeof token === 'string') return token; if (typeof token === 'symbol') return token.description || token.toString(); return token.name; } createModule(token, module) { const moduleRef = new module_1.Module(token, module); this._modules.set(token, moduleRef); return moduleRef; } async processImports(module, imports, moduleId) { const importedModules = []; for (const imported of imports) { const importedModule = await this.register(imported instanceof Promise ? await imported : imported, moduleId); importedModules.push(importedModule); } module.addImports(importedModules); } processControllers(module, controllers, moduleId) { controllers.forEach((controller) => { const controllerId = this.getId(controller); this.graph.addNode(controllerId, 'controller', moduleId); const instance = this.resolve(controller); module.addController(controller, instance); const controllerNode = this.graph.getNode(controllerId); if (controllerNode) { controllerNode.instance = instance; } this.logger?.debug(`Registered controller: ${controllerId}`); }); } processChannels(module, channels, moduleId) { channels.forEach((channel) => { const channelId = this.getId(channel); this.graph.addNode(channelId, 'channel', moduleId); const instance = this.resolve(channel); module.addChannel(channel, instance); const node = this.graph.getNode(channelId); if (node) { node.instance = instance; } this.logger?.debug(`Registered channel: ${channelId}`); }); } resolve(token) { if (this.instances.has(token)) { return this.instances.get(token); } const constructor = token; const paramTypes = Reflect.getMetadata('design:paramtypes', constructor) || []; const dependencies = paramTypes.map((param) => this.resolve(param)); const instance = new constructor(...dependencies); this.instances.set(token, instance); this.logger?.debug(`Resolved instance: ${this.getId(token)}`); return instance; } } exports.Container = Container;