@glandjs/core
Version:
Glands is a web framework for Node.js (@core)
114 lines (113 loc) • 4.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DependenciesScanner = void 0;
const common_1 = require("@glandjs/common");
const container_1 = require("../container");
class DependenciesScanner {
constructor(logger) {
this.container = new container_1.Container(logger);
this.logger = logger?.child('Scanner');
}
get modules() {
return this.container.modules;
}
async scan(rootModule) {
this.logger?.debug('Starting full module scan');
await this.scanForModules(rootModule);
this.logger?.debug('Completed scanning module structure, scanning dependencies');
await this.scanModulesForDependencies();
this.logger?.debug('- Done.');
}
async scanForModules(rootModule) {
const moduleRef = await this.container.register(rootModule);
this.logger?.debug(`Registered module: ${moduleRef.token}`);
this.modules.set(moduleRef.token, moduleRef);
for (const importedModule of moduleRef.imports) {
if (!this.modules.has(importedModule.token)) {
this.modules.set(importedModule.token, importedModule);
const moduleType = this.getModuleByToken(importedModule.token);
if (moduleType) {
await this.scanForModules(moduleType);
}
}
}
}
async scanModulesForDependencies() {
for (const [_, moduleRef] of this.modules.entries()) {
await this.scanModuleDependencies(moduleRef);
}
}
async scanModuleDependencies(moduleRef) {
const token = moduleRef.token;
const moduleType = this.getModuleByToken(token);
if (!moduleType) {
throw new Error(`Could not find module type for token: ${token}`);
}
const metadata = this.extractModuleMetadata(moduleType);
this.logger?.debug(`Scanning dependencies for module: ${token}`);
if (metadata.imports && metadata.imports.length > 0) {
this.logger?.debug(` - Imports found: ${metadata.imports.length}`);
await this.scanModuleImports(metadata.imports, moduleRef);
}
if (metadata.controllers && metadata.controllers.length > 0) {
this.logger?.debug(` - Controllers found: ${metadata.controllers.map((c) => c.name).join(', ')}`);
this.scanControllers(metadata.controllers, moduleRef);
}
if (metadata.channels && metadata.channels.length > 0) {
this.logger?.debug(` - Channels found: ${metadata.channels.map((c) => c.name).join(', ')}`);
this.scanChannels(metadata.channels, moduleRef);
}
}
getModuleByToken(token) {
const moduleRef = this.modules.getByToken(token);
return moduleRef ? moduleRef.metatype : undefined;
}
extractModuleMetadata(moduleType) {
return (Reflect.getMetadata(common_1.MODULE_METADATA, moduleType) ?? {
imports: [],
controllers: [],
channels: [],
});
}
async getModuleType(moduleDefinition) {
if ((0, common_1.isDynamicModule)(moduleDefinition)) {
return moduleDefinition.module;
}
if (moduleDefinition instanceof Promise) {
const resolvedModule = await moduleDefinition;
return (0, common_1.isDynamicModule)(resolvedModule) ? resolvedModule.module : resolvedModule;
}
return moduleDefinition;
}
async getModuleToken(moduleDefinition) {
const moduleType = await this.getModuleType(moduleDefinition);
return moduleType.name;
}
async scanModuleImports(imports, moduleRef) {
for (const importedModule of imports) {
const token = await this.getModuleToken(importedModule);
const importedRef = this.modules.getByToken(token);
if (importedRef) {
moduleRef.addImports([importedRef]);
}
else {
this.logger?.warn(`Could not find imported module with token: ${token}`);
}
}
}
scanControllers(controllers, moduleRef) {
controllers.forEach((controller) => {
const instance = this.container.resolve(controller);
moduleRef.addController(controller, instance);
this.logger?.debug(`Added controller: ${controller.name} to module: ${moduleRef.token}`);
});
}
scanChannels(channels, moduleRef) {
channels.forEach((channel) => {
const instance = this.container.resolve(channel);
moduleRef.addChannel(channel, instance);
this.logger?.debug(`Added channel: ${channel.name} to module: ${moduleRef.token}`);
});
}
}
exports.DependenciesScanner = DependenciesScanner;