UNPKG

mm_machine

Version:

这是超级美眉框架机制构建辅助模块,用于快速构建一个机制

560 lines (529 loc) 12.2 kB
/** * @fileOverview 机制构建帮助类函数 * @author <a href="http://qww.elins.cn">邱文武</a> * @version 1.5 */ const util = require('util'); const ph = require('path'); const Item = require('./item.js'); /** * @class Index索引类 */ class Index { /** * 构造函数 * @param {Object} scope 作用域 * @param {String} dir_base 模块目录 * @constructor */ constructor(scope, dir_base) { // 作用域(同时作为检索的后缀名) this.scope; if (scope) { this.scope = scope; } else { this.scope = $.val.scope + ''; } // Index接口列表 this.list = []; /** * 机制类型 */ this.type = ""; /** * 排序项 */ this.sort_key = "sort"; /** * 模块目录 */ this.dir_base = dir_base; /** * 模式 * 1.生产模式,改变文件不会重新加载 * 2.热更新模式,改变配置文件会重新加载配置,不重新加载脚本 * 3.热重载模式,改变配置文件都会加载配置和脚本 * 4.重载模式,执行完后重新加载脚本,避免变量污染 * 5.热更新+重载模式,改变配置文件重新加载配置和脚本,执行完后重新加载脚本 */ this.mode = 1; } } /** * 清除接口缓存 */ Index.prototype.clear = function() { this.list = []; }; /** * 默认驱动 */ Index.prototype.Drive = Item; /** * 加载项 * @param {String} dir 文件路径 * @param {Object} cg 配置参数 * @param {String} file 配置文件 */ Index.prototype.load_item = async function(dir, cg, file) { if (this.Drive) { var drive = new this.Drive(dir, this.dir_base.fullname()); drive.mode = this.mode; if (cg) { await drive.exec('load_config', file, cg.name); await drive.exec('set_config', cg); } else { await drive.exec('load_config', file); } this.list.push(drive); return drive; } else { var json = file.loadJson(); if (!json) { var fl = this.dir_base + "/config.tpl.json"; if (fl.hasFile()) { fl.copyFile(file); json = file.loadJson(); } } if (json) { this.list.push(json); } return json; } }; /** * 加载列表 * @param {Array} list 文件列表 */ Index.prototype.load_list = async function(list) { // 遍历文件路径 for (var i = 0; i < list.length; i++) { var file = list[i]; await this.load_file(file, true); } }; /** * 排序 */ Index.prototype.sort = function() { var _this = this; this.list.sort(function(o1, o2) { var p1 = o1.config[_this.sort_key]; var p2 = o2.config[_this.sort_key]; return p2 - p1; }); }; /** * 更新前 */ Index.prototype.update_before = async function(dir) { // console.log("更新前") } /** * 更新后 */ Index.prototype.update_after = async function(dir) { // console.log("更新后") } /** * 更新所有配置 * @param {String} path 检索路径 * @param {Boolean} accurate 精准路径,默认为false */ Index.prototype.update_config_all = async function(path, accurate) { if (path) { if (!ph.isAbsolute(path)) { path = ph.join('app', path); } } else { path = './app/'; } var list_scope = []; try { if (!accurate) { // 获取所有应用路径 var search_dir; if (this.scope && this.scope !== $.val.scope) { search_dir = this.type + '_' + this.scope; } else { search_dir = this.type; } list_scope = $.dir.getAll(path, search_dir); } else { list_scope = $.dir.getAll(path); } } catch (err) { console.error("检索目录失败!", err); } for (var i = 0; i < list_scope.length; i++) { var f = list_scope[i]; // 获取所有配置文件 var list_file = $.file.getAll(f, "*" + this.type + ".json"); await this.load_list(list_file); } }; /** * 更新配置 * @param {Object} dir */ Index.prototype.update_config_have = async function(dir) { var list = this.list; for (var i = 0; i < list.length; i++) { var o = list[i]; var file = o.filename; if (file) { var config = file.loadJson(); if (config) { if (Array.isArray(config)) { var lt = config; for (var n = 0; n < lt.length; n++) { var cg = lt[n]; if (cg.name == o.config.name) { await o.exec('set_config', cg); continue; } } } else { await o.exec('set_config', config); } } } } } /** * 更新配置 * @param {Object} dir */ Index.prototype.update_config = async function(dir, accurate = false, clear = false) { if (clear) { this.clear(); await this.update_config_all(dir, accurate); } else { // 如果没有指定目录,则更新已有的配置文件 await this.update_config_have(); } this.sort(); } /** * 更新JS */ Index.prototype.update_script = async function() { var list = this.list; for (var i = 0; i < list.length; i++) { var o = list[i]; if (o.config.state === 1) { await o.exec('load'); } } } /** * 更新 * @param {String} dir 检索的路径 * @param {Boolean} loadJS 是否加载JS */ Index.prototype.update_main = async function(dir, accurate = false, loadJS = true, clear = true) { await this.update_config(dir, accurate, clear); if (loadJS) { await this.update_script(); } } /** * 更新配置 * @param {String} dir 检索的路径 * @param {Boolean} loadJS 是否加载JS */ Index.prototype.update = async function(dir, accurate = false, loadJS = true, clear = true) { await this.update_before(dir); await this.update_main(dir, accurate, loadJS, clear); await this.update_after(dir); }; /** * 查询配置项 * @param {String} name 名称 * @return {Object} 返回单项配置 */ Index.prototype.get = function(name) { var obj; var lt = this.list; var len = lt.length; for (var i = 0; i < len; i++) { var o = lt[i]; if (name === o.config.name) { obj = o; break; } } return obj; }; /** * 查询配置项 * @param {String} name 名称 * @return {Object} 返回单项配置 */ Index.prototype.set = function(cg) { var bl = false; var lt = this.list; var len = lt.length; for (var i = 0; i < len; i++) { var o = lt[i]; if (cg.name === o.config.name) { $.push(lt[i].config, cg); bl = true; break; } } return bl; }; /** * 保存配置 * @param {String} name 保存的配置 */ Index.prototype.save = function(name) { var item = this.get(name); if (item) { item.save(); return true; } else { return false; } }; /** * 添加 * @param {Object} obj 配置参数 * @return {String} 失败返回错误提示,成功返回null */ Index.prototype.add = async function(obj) { var f = obj.filename; if (!f) { return "文件保存路径不能为空"; } var name = obj.config.name; var item = this.get(name); if (item) { return "配置已存在"; } if (f.hasFile()) { var jobj = f.loadJson(obj.dir); if (jobj) { if (jobj.constructor == Array) { var has = false; for (var i = 0; i < jobj.length; i++) { var o = jobj[i]; if (o.name === name) { has = true; break; } } if (has) { return "配置文件已存在"; } else { jobj.push(obj.config); f.saveText(JSON.stringify(jobj, null, 4)); } } else { var list = []; list.push(jobj); list.push(obj.config); f.saveText(JSON.stringify(list, null, 4)); } } else { f.saveText(JSON.stringify(obj.config, null, 4)); } } else { await this.load_item(f.dirname(), obj.config, f); this.save(name); } return null; }; /** * 删除 * @param {String} name 保存的配置名 * @param {Boolean} remove 是否删除配置文件 * @return {String} 失败返回null,成功返回文件路径 */ Index.prototype.del = function(name, remove) { var lt = this.list; var obj = null; var len = lt.length; for (var i = 0; i < len; i++) { var o = lt[i]; if (name === o.config.name) { obj = o; // 删除成员 lt.splice(i, 1); break; } } return obj; }; /** * 加载模块 * @param {String} name 模块名称 * @return {String} 失败返回null,成功返回文件路径 */ Index.prototype.load = async function(name) { var o = this.get(name); var file = null; if (o) { await o.exec('load'); file = o.filename; } return file; } /** * 卸载模块 * @param {String} name 模块名称 * @param {Boolean} remove 是否删除配置文件 * @return {String} 失败返回null,成功返回文件路径 */ Index.prototype.unload = async function(name, remove) { var o = this.del(name, remove); var file = null; if (o) { await o.exec('unload', remove); file = o.filename; } return file; } /** * 重载脚本和配置 * @param {String} file 文件名 * @return {String} 重载失败返回错误提示,重载成功返回null */ Index.prototype.reload = async function(name) { var o = this.get(name); if (o) { await o.exec('reload'); return o.filename; } return '没有找到模块'; } /** * 通过文件加载配置 * @param {String} file 文件名 * @param {Boolean} create 不存在则进行创建 * @return {String} 加载失败返回错误提示,加载成功返回null */ Index.prototype.load_file = async function(file, create = false) { var _this = this; var dir = file.dirname(); // 载入文件 var obj = file.loadJson(); if (obj) { if (obj.constructor == Array) { for (var i = 0; i < obj.length; i++) { var o = obj[i]; // 实例化一个驱动 await _this.load_item(dir, o, file); } } else { return await _this.load_item(dir, null, file); } } else if (create) { return await _this.load_item(dir, null, file); } else { return file + "文件不存在"; } return null; }; /** * 调用函数 * @param {String} name 模块名 * @param {String} method 函数名 * @param {Object} params 参数集合 * @return {Object} 执行结果 */ Index.prototype.run = async function(name, method, ...params) { var result; if (name) { var o = await this.get(name); if (o && o.config.state === 1) { if (!o.complete) { await o.exec('load'); } var ret = o.exec(method, ...params); if (util.types.isPromise(ret)) { result = await ret; } else { result = ret; } if (this.mode >= 4) { o.exec('reload'); } } } else if (name === null) { var lt = this.list; for (var i = 0; i < lt.length; i++) { var o = lt[i]; if (o.config.state === 1) { if (!o.complete) { await o.exec('load'); } var ret = o.exec(method, ...params); if (util.types.isPromise(ret)) { result = await ret; } else { result = ret; } if (this.mode >= 4) { o.exec('reload'); } if (result && o.config.end) { break; } } } } return result; }; /** * 执行方法 * @param {String} name 插件名称 * @param {String} method 方法名称 * @param {Object} option 配置参数 * @return {String} 执行结果 */ Index.prototype.exec = async function(name, method, ...params) { var result; if (name) { var o = await this.get(name); if (o) { if (!o.complete) { await o.exec('load'); } var ret = o.exec(method, ...params); if (util.types.isPromise(ret)) { result = await ret; } else { result = ret; } if (this.mode >= 4) { await o.exec('reload'); } } } else if (name === null) { var lt = this.list; for (var i = 0; i < lt.length; i++) { var o = lt[i]; if (!o.complete) { await o.exec('load'); } var ret = o.exec(method, ...params); if (util.types.isPromise(ret)) { result = await ret; } else { result = ret; } if (this.mode >= 4) { await o.exec('reload'); } } } return result; }; /** * @module 导出Index类 */ exports.Index = Index; exports.Item = Item;