@wocker/core
Version:
Core of the Wocker
148 lines (147 loc) • 5.98 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Scanner = void 0;
require("reflect-metadata");
const cli_1 = require("@kearisp/cli");
const Container_1 = require("./Container");
const ModuleWrapper_1 = require("./ModuleWrapper");
const env_1 = require("../env");
class Scanner {
constructor() {
this.container = new Container_1.Container();
}
scan(moduleType) {
return __awaiter(this, void 0, void 0, function* () {
this.scanModule(moduleType);
yield this.scanDynamicModules();
this.scanRoutes();
});
}
scanModule(moduleType) {
let module = this.container.hasModule(moduleType)
? this.container.getModule(moduleType)
: null;
if (!module) {
module = new ModuleWrapper_1.ModuleWrapper(this.container, moduleType);
this.container.addModule(moduleType, module);
this.scanImports(module);
this.scanControllers(module);
this.scanProviders(module);
this.scanExports(module);
}
return module;
}
scanControllers(module) {
const controllers = Reflect.getMetadata(env_1.MODULE_METADATA.CONTROLLERS, module.type) || [];
controllers.forEach((controller) => {
module.addController(controller);
});
}
scanProviders(module) {
const providers = Reflect.getMetadata(env_1.MODULE_METADATA.PROVIDERS, module.type) || [];
providers.forEach((provider) => {
module.addProvider(provider);
});
}
scanImports(module) {
const imports = Reflect.getMetadata(env_1.MODULE_METADATA.IMPORTS, module.type) || [];
imports.forEach((importType) => {
const subModule = this.scanModule(importType);
subModule.exports.forEach((type) => {
const provider = subModule.providers.get(type);
if (!provider) {
return;
}
module.providers.set(type, provider);
});
});
}
scanExports(module) {
const exports = Reflect.getMetadata(env_1.MODULE_METADATA.EXPORTS, module.type) || [];
const isGlobal = Reflect.getMetadata(env_1.IS_GLOBAL_METADATA, module.type) || false;
exports.forEach((type) => {
module.addExport(type);
if (isGlobal) {
const wrapper = module.getWrapper(type);
if (wrapper) {
this.container.addProvider(type, wrapper);
}
}
});
}
scanRoutes() {
const cliWrapper = this.container.globalProviders.get(cli_1.Cli);
if (!cliWrapper) {
return;
}
const cli = cliWrapper.instance;
for (const [, module] of this.container.modules) {
for (const [, controller] of module.controllers) {
if (!controller.instance) {
continue;
}
this.scanControllerRoutes(cli, controller);
}
}
}
scanControllerRoutes(cli, wrapper) {
for (const route of wrapper.commands) {
for (const commandName of route.commandNames) {
const command = cli.command(commandName);
if (route.description) {
command.help({
description: route.description
});
}
command.action((input) => {
return wrapper.run(route, input);
});
for (const arg of route.args) {
if (arg.type === "option") {
command.option(arg.name, arg.params);
}
command.completion(arg.name, (input) => {
const [completion] = wrapper.getCompletionCommands(arg.name, commandName);
if (!completion) {
return [];
}
return wrapper.run(completion, input);
});
}
}
}
}
scanDynamicModules() {
return __awaiter(this, void 0, void 0, function* () {
const promises = ([...this.container.modules.keys()]).map((type) => __awaiter(this, void 0, void 0, function* () {
if (!type.prototype.load) {
return;
}
const parentModule = this.container.modules.get(type);
const { [env_1.MODULE_METADATA.IMPORTS]: imports = [] } = yield type.prototype.load(this.container);
for (const subModuleType of imports) {
const module = this.scanModule(subModuleType);
module.exports.forEach((type) => {
const provider = module.getWrapper(type);
if (!provider) {
return;
}
// @ts-ignore
parentModule.providers.set(type, provider);
});
}
}));
yield Promise.all(promises);
});
}
}
exports.Scanner = Scanner;