ckn.backend
Version:
CKN Framework for Backend
114 lines (105 loc) • 4.86 kB
JavaScript
import {Middleware} from "../core/Middleware.js";
import {File} from "ckn.stream";
import {Controller} from "./Controller.js";
import fs from "fs";
import path from "path";
class ModuleMiddleware extends Middleware {
constructor() {
super();
this.priority = 1;
this.modulesFolder = 'modules';
}
async #loadModules(backend) {
let modulesDirectoryPath = File.join(this.modulesFolder);
let modules = [];
let modulesDirectory = modulesDirectoryPath.toDirectory();
if (modulesDirectory.isExist) {
for (let directory of modulesDirectory.directories) {
let moduleName = directory.path.replace(this.modulesFolder, "").match(/^[\/\\]?(\w+)/)[1];
let moduleConfigFile = File.join(directory.path, "module.js").toFile();
if (moduleConfigFile.isExist) {
modules[moduleName] = await import("file://"+moduleConfigFile.fullPath);
let appClassName = Object.keys(modules[moduleName])[0];
modules[moduleName] = new modules[moduleName][appClassName]();
modules[moduleName].name = moduleName;
modules[moduleName].directory = directory;
this.log.info("[OK]", `Module ${moduleName} has been loaded with configuration in ${moduleConfigFile.fullPath}`);
}
}
}
return modules;
}
async #loadController(backend, module, controllerClass) {
let controller = new controllerClass();
controller.name = controller.constructor.name;
this.log.info(`[OK] Controller '${controller.constructor.name}' is loading.`)
let serviceNames = Object.keys(controller);
for (let serviceName of serviceNames) {
let service = controller[serviceName];
if (service.process && typeof service === "object") {
service.name = serviceName;
await this.#loadService(backend, module, controller, service);
}
}
return controller;
}
async #loadService(backend, module, controller, service) {
let method = service.method ? service.method : Controller.Method.GET;
let url = service.url != null ? service.url : service.name;
url = File.join(module.url, controller.url, url);
if (url == ".") url = "";
let process = service.process;
this.log.info(`[OK] Service '${url}' is loading.`)
switch (method) {
case Controller.Method.GET:
this.log.info(`GET: URL: ${"/" + url}`);
backend.get("/" + url, process);
break;
case Controller.Method.POST:
this.log.info(`POST: URL: ${"/" + url}`);
backend.post("/" + url, process);
break;
case Controller.Method.PUT:
this.log.info(`PUT: URL: ${"/" + url}`);
backend.put("/" + url, process);
break;
case Controller.Method.PATCH:
this.log.info(`PATCH: URL: ${"/" + url}`);
backend.patch("/" + url, process);
break;
case Controller.Method.DELETE:
this.log.info(`DELETE: URL: ${"/" + url}`);
backend.delete("/" + url, process);
break;
}
}
async #loadView(backend, module) {
let path = File.join(module.directory.path, "views");
if (path.toDirectory().isExist) {
module.views.push(File.join(module.directory.path, "views"));
}
}
async onStartingServer(backend, next) {
if (!fs.existsSync(path.resolve(process.cwd(), this.modulesFolder))) {
fs.mkdirSync(path.resolve(process.cwd(), this.modulesFolder));
}
let modules = await this.#loadModules(backend);
for (let module of modules.values()) {
this.log.info(`[OK] Module '${module.name}' is loading.`)
let controllerDirectoryPath = File.join(this.modulesFolder, module.name, "controllers");
for (let controllerFilePath of controllerDirectoryPath.toDirectory().allFiles) {
let controllerClasses = await import("file://"+path.resolve(controllerFilePath.fullPath));
let items = Object.values(controllerClasses);
for (let controllerClass of items) {
let controller = await this.#loadController(backend, module, controllerClass);
module.controllers[controller.constructor.name] = controller;
}
}
await this.#loadView(backend, module);
}
backend.modules = modules;
this.log.info(`[OK] Modules have been loaded.`);
next();
}
}
export {ModuleMiddleware}