UNPKG

vesh

Version:

码农nodejs版本VESH框架,使用函数责任链模式 实现了 默认文件跳转,自定义错误页,空文件处理,URL解析,Querystring与Form参数解析,PostFiles解析,MVC自动映射,SQL自动服务化,可继承页面,静态文件,json,tjson,jsonp,tjsonp,string,void,xjson,xjosnp等等6种JSON格式,http与https等等操作

1,059 lines (1,002 loc) 27.3 kB
import V, { finalC } from "gcl/com/coooders/common/tool"; import N from "gcl/com/coooders/db/ni"; import I from "gcl/com/coooders/io/tool"; import { parse, resolve, normalize } from "path"; import { exists } from "fs"; import { AModuler } from "./app"; /** * AAction基类 用于完成Controler操作 */ export const AAction = class { constructor() { const { _, __ } = pri(this); _.isStatic = true; } preload(req, rep, session) { return false; } unload(req, rep, session) { return false; } }; export const LoadModuler = class extends AModuler { constructor(base, src, debug = false, isRestful = false) { super("LoadModuler"); const { _, __ } = pri(this, { base: base ? base .trim("/") .trim("\\") .replace(/[\\\/]/g, ".") : "", src: src ? "/" + src.replace(/^[\\\/]/g, "") : "", actions: {}, debug, isRestful, pathregex: /([/\\][^/\\]+)+[/\\]/g, }); } async onrequest(req, rep, session, call) { const { _, __ } = pri(this); //todo src=>dist的 es7编译 let query = (session.url.pathname.match(__.pathregex) || "/")[0]; session.classtype = `${__.src}${query}action`.toLowerCase(); session.methodname = `${__.base}${query}${session.status}` .replace(/[\\\/]/g, ".") .toLowerCase(); let action = __.actions[session.classtype]; if (typeof action == "undefined") { let base = parse(resolve(normalize(process.mainModule.filename))).dir; if ("windows".eq(V.environment.os || "")) { //windows base = base.replace(/\//g, "\\"); } else { //linux base = base.replace(/\\\\/g, "/"); } let ist = await V.callback((call) => exists(base + session.classtype + ".njs", (ist) => call(null, ist)), ); // console.log(35, base + session.classtype + ".njs", ist); action = !ist ? false : (function () { try { const classname = require(base + session.classtype + ".njs"); //console.log(56, base + session.classtype + '.njs', classname); let action = classname && classname.Action ? V.create2(classname.Action, []) : false; if (action) { let proto = action.__proto__; //遍历所有父类方法 while (proto) { const names = Reflect.ownKeys(proto); names.forEach((k) => { if ( k != k.toLowerCase() && k != "constructor" && k.indexOf("__") < 0 && typeof action[k] == "function" ) action[k.toLowerCase()] = action[k]; }); proto = proto.__proto__; } } return action; } catch (e) { session.Log.error("VESH:" + e.stack); //__.debug && console.log(e.stack); } })(); if (__.isRestful && !ist) { let split = "windows".eq(V.environment.os || "") ? "\\" : "/"; let bases = query.toLowerCase().split(split); let params = []; bases.pop(); while (bases.length && !ist) { ist = await V.callback((call) => exists( `${base}${__.src}${bases.join(split)}${split}action.njs`, (ist) => call(null, ist), ), ); // console.log( // 103, // `${base}${__.src}${bases.join(split)}${split}action.njs`, // ist, // ); if (!ist) params.unshift(bases.pop()); else { action = __.actions[`${__.src}${bases.join(split)}${split}action.njs`]; if (!action) try { // console.log( // 117, // `${base}${__.src}${bases.join(split)}${split}action.njs`, // ); const classname = require( `${base}${__.src}${bases.join(split)}${split}action.njs`, ); //console.log(56, base + session.classtype + '.njs', classname); // 保证是唯一的一个对象 action = classname && classname.Action ? V.create2(classname.Action, []) : false; if (action) { let proto = action.__proto__; //遍历所有父类方法 while (proto) { const names = Reflect.ownKeys(proto); names.forEach((k) => { if ( k != k.toLowerCase() && k != "constructor" && k.indexOf("__") < 0 && typeof action[k] == "function" ) action[k.toLowerCase()] = action[k]; }); proto = proto.__proto__; } //`${base}${__.src}${bases.join(split)}${split}action.njs`, //`${__.src}${query}action`.toLowerCase(); if (action.isStatic) __.actions[ `${__.src}${bases.join(split)}${split}action.njs` ] = action; } session.querystring.params = params; } catch (e) { session.Log.error("VESH:" + e.stack); //__.debug && console.log(e.stack); } } } } } if (action) { if (action.isStatic) __.actions[session.classtype] = action; session.action = action; //先调用preload方法 return ( (await V.callback2(action.preload, action, req, rep, session)) || false ); } else { __.actions[session.classtype] = false; return false; } } async onresponse(req, rep, session, call) { if (session.action && session.action.unload) { //先调用preload方法 return ( (await V.callback2( session.action.unload, session.action, req, rep, session, )) || false ); } return false; } }; /** * 用于自动填充ni对象的方法 */ export const AFilter = class { constructor() {} fill(req, rep, session, form) { return false; } }; /** * 用户Form参数填充 */ export const FormFilter = class extends AFilter { constructor() { super(); } fill(req, rep, session, form = {}) { V.merge(form, session.querystring, true); if (session.form) V.merge(form, session.form, true); return false; } }; /** * ;号分割的sessionNames):AFilter子类,使用Session数据填充form的值 */ export const SessionFilter = class extends AFilter { constructor(sessionNames) { super(); const { _, __ } = pri(this, { sessionNames: (sessionNames + "").split(";").filter((v) => V.isValid(v)), }); } async fill(req, rep, session, form) { const { _, __ } = pri(this); await V.each(__.sessionNames, async (v) => { const data = await session.data(v); if (data) { const strf = data.Name.replace(/\./g, "_") + "_"; await V.forC(data.serialize(), (key, value) => { form[strf + key.replace(/\./g, "_")] = value; return false; }); } return false; }); return false; } }; /** * 设定可以参数化的AppSetting * @param {string} sessionNames */ export const AppSettingFilter = class extends AFilter { constructor(sessionNames) { super(); const { _, __ } = pri(this, { sessionNames: (sessionNames + "").split(";").filter((v) => V.isValid(v)), }); } async fill(req, rep, session, form) { const { _, __ } = pri(this); await V.each(__.sessionNames, (v) => { const data = session.AppSettings(v); data && (form[v.replace(/\./g, "_")] = data); return false; }); return false; } }; /** * NiModuler(filters,middler[,appname:"Ni"]):Ni处理器Moduler,主要识别query中的_n参数,并对数据集进行填充和请求 */ export const NiModuler = class extends AModuler { constructor(filter = [], middler, appname = "Ni", strict = false) { super("NiModuler"); const { _, __ } = pri(this, { filter: filter.length > 0 ? filter : (function () { throw new Error("必须定义数据填充逻辑数组filter"); })(), middler: middler, ni: middler ? new N.NiTemplateManager(middler, appname) : (function () { throw new Error("必须定义中介者middler对象"); })(), strict: !!strict, }); } async onrequest(req, rep, session) { const { _, __ } = pri(this); session.dbresult = session.dbresult || []; const templatename = session.param("_n"); if (templatename) { await V.next( (data) => { data.params = {}; return V.each(__.filter, (v, call) => v.fill(req, rep, session, data.params, call), ); }, async (data) => { const cmd = await __.ni.getCommand(templatename, session.methodname); if (cmd && cmd.params) { if (cmd.params["_TestPermission"]) { let pers = (cmd.params["_TestPermission"].value || "") .split(",") .filter((v) => v.length > 0); let hasRight = false; await V.each( pers, async (v, call) => { if (await session.hasRight(v)) hasRight = true; return false; }, true, ); if (pers.length > 0 && !hasRight) throw new Error( `${session.methodname}执行需要${cmd.params["_TestPermission"].value}权限!`, ); } if ( (cmd.params["_TestLogin"] || cmd.params["_User_UID"]) && !session.User.Login ) { throw new Error(`${session.methodname}执行需要登录执行!`); } } else if (__.strict) throw new Error(`没有找到对应的模板命令:${session.methodname}。`); return false; }, async (data) => { try { session.dbparams = data.params; const result = await __.ni.excute( templatename, session.methodname, data.params, ); if (result.hasData && result.hasData()) { session.dbresult.push(result.last()); } return false; } catch (e) { console.log(e.stack); throw e; } }, ); return false; } else return false; } onresponse1(req, rep, session) { delete session.dbparams; delete session.dbresult; return false; } }; /** * ActionModuler:Action处理器Moduler并根据返回值决定是否请求页面 */ export const ActionModuler = class extends AModuler { constructor() { super("ActionModuler"); pri(this); } async onrequest(req, rep, session) { const status = (session.status || "").toLowerCase(); if (session.action && session.action[status]) { const _ac = session.action[status]; let ret = false; if (_ac["needs"]) { _ac["needs"].forEach((n) => { const need = n(req, rep, session); if (need) { session.end(401, need); ret = true; return true; } }); } if (!ret) return ( (await V.callback2( session.action[status], session.action, req, rep, session, )) || false ); } return false; } }; /** * * @param {*} 分号隔开的命令类型 */ export const NeedMethod = (methods = "GET") => { const method = {}; methods = methods.toUpperCase(); methods.split(";").forEach((v) => (method[v.toLowerCase()] = true)); return (target) => V.prop(target, "needs", function (req, rep, session) { return method[req.method] ? false : "限制的Method为" + methods; }); }; /** * * @param {*} 分号隔开的命令类型 */ export const TestMethod = (paras, methods = "GET") => { const session = paras[2]; return session.testMethod(methods); }; /** * 限制方法为Get访问 */ export const NeedGet = () => NeedMethod("get"); /** * 限制方法为Get访问 */ export const TestGet = (paras) => { const session = paras[2]; return session.testGet(); }; /** * 限制方法为Post访问 */ export const NeedPost = () => NeedMethod("post"); /** * 限制方法为POST访问 */ export const TestPost = (paras) => { const session = paras[2]; return session.testPost(); }; /** * 限制方法为Restful访问 */ export const NeedRestful = () => NeedMethod("get;post;put;patch;delete"); /** * 限制方法为Get访问 */ export const TestRestful = (paras) => { const session = paras[2]; return session.testRestful(); }; /** * 限制参数满足条件 * @param {要判断的参数} key * @param {正则} regex * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedRegex = (key, regex, error, isRequire = false) => { regex = regex.test ? regex : new RegExp(regex, "i"); return (target) => V.prop(target, "needs", function (req, rep, session) { const value = session.param(key); return typeof value != "undefined" && value != null && ("" + value).length ? regex.test(value) ? false : error || ` 限制$ { key } 参数需满足正则表达式要求: $ { regex } ` : isRequire ? ` 限制$ { key } 参数为必填 ` : false; }); }; /** * 限制参数满足条件 * @param {要判断的参数} key * @param {正则} regex * @param {错误说明} error * @param {是否必填} isRequire */ export const TestRegex = (paras, key, regex, error, isRequire = false) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testRegex(key, regex, error, isRequire); }; /** * 限制参数满足是数字 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedNumber = (key, error, isRequire) => NeedRegex( key, /^([0-9]+\.{0,1}[0-9]{0,2})$/g, error || ` 限制$ { key } 要求是数字 `, isRequire, ); /** * 限制参数满足是数字 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestNumber = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testNumber(key, error, isRequire); }; /** * 限制参数满足是整数 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedInt = (key, error, isRequire) => NeedRegex( key, /^([0-9]+)$/g, error || ` 限制$ { key } 要求是正整数 `, isRequire, ); /** * 限制参数满足是数字 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestInt = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testInt(key, error, isRequire); }; /** * 限制参数满足是连续字母 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedLetter = (key, error, isRequire) => NeedRegex( key, /^([A-Za-z]+)$/g, error || ` 限制$ { key } 要求是连续字母 `, isRequire, ); /** * 限制参数满足是数字 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestLetter = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testLetter(key, error, isRequire); }; /** * 限制参数满足是密码规范 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedPassword = (key, error, isRequire) => NeedRegex( key, /^(([a-zA-Z]|\w){5,17})$/g, error || ` 限制$ { key } 要求满足密码要求 `, isRequire, ); /** * 限制参数满足是数字 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestPassword = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testPassword(key, error, isRequire); }; /** * 限制参数满足是非空必填 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedRequired = (key, error) => { const regex = /^(\s*\S\s*)+$/g; return (target) => V.prop(target, "needs", function (req, rep, session) { const value = session.param(key); return V.isValid(value) ? regex.test(value) ? false : error || ` 限制$ { key } 要求满足非空要求 ` : error; }); }; /** * 限制参数满足是非空必填 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestRequired = (paras, key, error) => { const req = paras[0], rep = paras[1], session = paras[2]; return session.testRequired(key, error); }; /** * 限制参数满足是身份证 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedCard = (key, error, isRequire) => NeedRegex( key, /^((\d{14}|\d{17})(\d|[a-zA-Z]))$/g, error || ` 限制$ { key } 要求身份证 `, isRequire, ); /** * 限制参数满足是身份证 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestCard = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testCard(key, error, isRequire); }; /** * 限制参数满足是手机号 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedMobile = (key, error, isRequire) => NeedRegex( key, /^(1[3|4|5|6|7|8][0-9]\d{8})$/g, error || ` 限制$ { key } 要求是手机号 `, isRequire, ); /** * 限制参数满足是手机号 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestMobile = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testMobile(key, error, isRequire); }; /** * 限制参数满足是座机 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedPhone = (key, error, isRequire) => NeedRegex( key, /^(\d{3}-\d{8}|\d{4}-\d{7})$/g, error || ` 限制$ { key } 要求是座机号 `, isRequire, ); /** * 限制参数满足是座机 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestPhone = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testPhone(key, error, isRequire); }; /** * 限制参数满足是网络地址 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedUrl = (key, error, isRequire) => NeedRegex( key, /^((http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)$/g, error || ` 限制$ { key } 要求是URL `, isRequire, ); /** * 限制参数满足是网络地址 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestUrl = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testUrl(key, error, isRequire); }; /** * 限制参数满足是电子邮箱 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedEmail = (key, error, isRequire) => NeedRegex( key, /^(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)$/g, error || ` 限制$ { key } 要求是邮箱 `, isRequire, ); /** * 限制参数满足是电子邮箱 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestEmail = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testEmail(key, error, isRequire); }; /** * 限制参数满足是中文 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedChinese = (key, error, isRequire) => NeedRegex( key, /^([\u4e00-\u9fa5]{0,})$/g, error || ` 限制$ { key } 要求是中文 `, isRequire, ); /** * 限制参数满足是中文 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestChinese = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testChinese(key, error, isRequire); }; /** * 限制参数满足是QQ * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedQQ = (key, error, isRequire) => NeedRegex( key, /^([1-9]\d{4,12})$/g, error || ` 限制$ { key } 要求是QQ号 `, isRequire, ); /** * 限制参数满足是QQ * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestQQ = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testQQ(key, error, isRequire); }; /** * 限制参数满足是邮政编码 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedZipCode = (key, error, isRequire) => NeedRegex( key, /^([1-9]\d{5}(?!\d))$/g, error || ` 限制$ { key } 要求是邮编 `, isRequire, ); /** * 限制参数满足是邮政编码 * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestZipCode = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testZipCode(key, error, isRequire); }; /** * 限制参数满足是IP * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedIP = (key, error, isRequire) => NeedRegex( key, /^(([\d+\.]{3}|[\d+\.]{5})\d+)$/g, error || ` 限制$ { key } 要求是IP `, isRequire, ); /** * 限制参数满足是IP * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestIP = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testIP(key, error, isRequire); }; /** * 限制参数满足是金额(2位小数) * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedCurreny = (key, error, isRequire) => NeedRegex( key, /^(\d+\.\d{2})$/g, error || ` 限制$ { key } 要求是金额 `, isRequire, ); /** * 限制参数满足是金额(2位小数) * @param {要判断的参数} key * @param {错误说明} error * @param {是否必填} isRequire */ export const TestCurreny = (paras, key, error, isRequire) => { const req = paras[0], rep = paras[1], session = paras[2]; session.testCurreny(key, error, isRequire); }; /** * 限制操作所需权限 * @param {要判断的参数} key * @param {正则} regex * @param {错误说明} error * @param {是否必填} isRequire */ export const NeedPermission = (key, error) => { return (target) => V.prop(target, "needs", async function (req, rep, session) { let val = false; await V.each( key.split(","), async (v) => { val = val || (await session.hasRight(v)) ? false : error || `该操作需要${v}权限 `; }, true, ); if (!!val) { const e = new Error(val); e.status = 401; throw e; } return false; }); }; /** * 限制操作所需权限 * @param {要判断的参数} key * @param {正则} regex * @param {错误说明} error * @param {是否必填} isRequire */ export const TestPermission = async (paras, key, error) => { const req = paras[0], rep = paras[1], session = paras[2]; return await session.testPermission(key, error); }; export default { AAction, LoadModuler, AFilter, SessionFilter, FormFilter, AppSettingFilter, NiModuler, NeedCard, NeedChinese, NeedCurreny, NeedEmail, NeedGet, NeedIP, NeedInt, NeedLetter, NeedMethod, NeedMobile, NeedNumber, NeedPassword, NeedPhone, NeedPost, NeedQQ, NeedRegex, NeedRequired, NeedRestful, NeedUrl, NeedZipCode, TestCard, TestChinese, TestCurreny, TestEmail, TestGet, TestIP, TestInt, TestLetter, TestMethod, TestMobile, TestNumber, TestPassword, TestPhone, TestPost, TestQQ, TestRegex, TestRequired, TestRestful, TestUrl, TestZipCode, NeedPermission, TestPermission, }; const pri = V.pris();