UNPKG

@lionrockjs/central

Version:

Node.js MVC framework inspire from PHP Kohana Framework

164 lines (163 loc) 6.43 kB
/** * Copyright (c) 2023 Kojin Nakana * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import HelperCache from './helper/central/Cache.mjs'; import HelperBootstrap from './helper/central/Bootstrap.mjs'; import HelperConfig from './helper/central/Config.mjs'; import HelperPath from './helper/central/Path.mjs'; import RuntimeAdapterNode from './adapter/runtime/Node.mjs'; export var CentralEnv; (function (CentralEnv) { CentralEnv["DEVELOPMENT"] = "dev"; CentralEnv["TEST"] = "uat"; CentralEnv["STAGING"] = "stg"; CentralEnv["PRODUCTION"] = "prd"; })(CentralEnv || (CentralEnv = {})); export default class Central { static EXE_PATH = null; static APP_PATH = null; static VIEW_PATH = null; static ENV = ''; static config = { classes: { cache: true }, view: { cache: true }, system: { debug: false } }; static runtime = new RuntimeAdapterNode(); static port = ""; static get modules() { return this.helperPath.modules; } static get classPath() { return this.helperPath.fileList; } static get viewPath() { return this.helperPath.templateList; } static helperPath = new HelperPath(); static async init(opts = {}) { const options = { EXE_PATH: this.runtime.process().cwd(), APP_PATH: null, VIEW_PATH: null, modules: [], ...opts, }; if (!options.EXE_PATH) throw new Error('Central.init requires EXE_PATH option'); Object.keys(this.config).forEach(key => delete this.config[key]); await HelperConfig.init(this.config); this.helperPath.init(options.EXE_PATH, options.APP_PATH, options.VIEW_PATH, options.modules); await HelperCache.init(); await this.applyApplicationConfigs(); await HelperBootstrap.init(this.runtime, this.APP_PATH); await this.helperPath.reloadModuleInit(); await HelperBootstrap.loadRoutes(this.runtime, this.APP_PATH); return Central; } static async applyApplicationConfigs() { //apply application configs await Promise.all(Object.keys(Central.config).map(async (key) => { //fs check file exist in ${APP_PATH}/config/${key}.mjs //if exists, apply to Central.config[key] const source = `${Central.APP_PATH}/config/${key}`; const exist = this.runtime.fileExists(source); if (exist) { const config = await this.runtime.import(source, HelperCache.cacheId); Object.assign(Central.config[key], config); } })); } /** * * @param configMap */ static async initConfig(configMap) { await HelperConfig.addConfig(this.config, configMap); await this.applyApplicationConfigs(); } static async import(pathToFile) { // pathToFile may include file extension; const adjustedPathToFile = /\..*$/.test(pathToFile) ? pathToFile : `${pathToFile}.mjs`; const file = this.helperPath.resolve(adjustedPathToFile); if (!file) { throw new Error(`Resolve path error: path ${adjustedPathToFile}.mjs not found. prefixPath: classes , store: {} `); } if (typeof file !== 'string') return file; return await this.runtime.import(file, HelperCache.cacheId); } static resolveView(pathToFile) { return this.helperPath.resolveView(pathToFile); } static log(args, verbose = true) { if (Central.ENV === CentralEnv.PRODUCTION && Central.config?.system?.debug !== true) return args; if (verbose === false) { console.log(args); return; } console.trace(args); } //add modules to a set of filename, load config, then run init.mjs in each dirname static async addModules(modules) { this.helperPath.addModules(modules); await this.helperPath.reloadModuleInit(); //loop modules, if have it.configs, add them to config for (const it of modules) { if (!it) continue; const configs = it.configs || it.default?.configs; const filename = it.filename || it.default?.filename; if (!filename) continue; const dirname = this.runtime.dirname(filename); if (configs) { const configMap = new Map(); for (const configName of configs) { const configPath = `${dirname}/config/${configName}.mjs`; if (this.runtime.fileExists(configPath)) { const configModule = await this.runtime.import(configPath, HelperCache.cacheId); configMap.set(configName, configModule); } } if (configMap.size > 0) { await HelperConfig.addConfig(this.config, configMap); } } } await this.applyApplicationConfigs(); } //module may add after init, so we need to force reload module init static async reloadModuleInit(force = false) { if (force === false && Central.config.classes.cache) return; await this.helperPath.reloadModuleInit(); } static async reloadConfig() { const configKeys = Object.keys(Central.config); for (let i = 0; i < configKeys.length; i++) { const configKey = configKeys[i]; const packages = [...this.helperPath.modules.keys()]; for (let j = 0; j < packages.length; j++) { const dir = packages[j]; const configFile = `${dir}/config/${configKey}`; const exist = this.runtime.fileExists(configFile); if (exist) { const config = await this.runtime.import(configFile, HelperCache.cacheId); Central[configKey] = Object.assign(Central.config[configKey], config.default || config); } } } await this.applyApplicationConfigs(); } static async flushCache() { HelperCache.clearImportCache(); if (this.config.classes.cache === false) await this.reloadConfig(); } }