@glandjs/core
Version:
Glands is a web framework for Node.js (@core)
114 lines (113 loc) • 4.49 kB
JavaScript
"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;