UNPKG

vesh

Version:

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

1,219 lines (1,184 loc) 35.3 kB
import V from "gcl/com/coooders/common/tool"; import N from "gcl/com/coooders/db/ni"; import { AModuler } from "./app"; import Q from "querystring"; import createError from "http-errors"; import { ArrayStream } from "gcl/com/coooders/collection/arraystream"; import iconv from "iconv-lite"; import U from "url"; import Z from "zlib"; import C from "gcl/com/coooders/net/cookie"; import { MIME, get } from "gcl/com/coooders/net/mime"; import I from "gcl/com/coooders/io/tool"; import F from "fs"; import P from "path"; /** * ViewModuler调用的Controler基类,用于处理View文件解析 需要实现output(req,rep,session)方法 */ export const AViewControler = class { constructor() {} output(req, rep, session) { return false; } }; /** * ViewModuler(basename,controler):主要用于根据session数据调用不同的Controller处理数据 */ export const ViewModuler = class extends AModuler { constructor(src, controler) { super("ViewModuler"); const { _, __ } = pri(this, { src: src ? src.trim(V.environment.splitChar) : "", controler, controlers: {}, basedir: P.parse(P.resolve(P.normalize(process.mainModule.filename))).dir, inputControlers: {}, hasInput: false, regex: /\.[^/\\\.]+$/g, pathregex: /([/\\][^/\\]+)+[/\\]/g, }); } setControler(name, controler) { const { __ } = pri(this); __.controlers[name.toLowerCase()] = controler; if (typeof controler.input == "function") { __.hasInput = true; __.inputControlers[name.toLowerCase()] = controler; } } /** * 核心思想 session 提前返回,其它的内容 继续执行但是插入redis * @param {*} req * @param {*} rep * @param {*} session */ async onrequest(req, rep, session) { try { const { __ } = pri(this); //需要兼容 无后缀名和多点的情况 session.extend = session.url.pathname.match(__.regex); session.extend = session.extend && session.extend[0].substr(1); if (!__.hasInput) return false; const controler = __.inputControlers[session.extend]; controler && (await V.callback2((call) => controler.input(req, rep, session, call))); } catch (e) { console.log(e.stack); throw e; } return false; } async onresponse(req, rep, session) { try { const { __ } = pri(this); if (!"200".eq(session.Response.statusCode)) return false; let query = (session.url.pathname.match(__.pathregex) || "/")[0]; // console.log(84, session.extend, session.filename); // session.filename && session.filename.eq(session.status) //需要兼容 无后缀名和多点的情况 if ( !session.extend && "undefined".eq(typeof rep.getHeader("content-type")) ) { session.extend = "string"; } const controler = __.controlers[session.extend] || __.controler; session.pathname = `${__.basedir}/${__.src}${query}${session.status}.${session.extend}`.toLowerCase(); await V.callback2((call) => controler.output(req, rep, session, call)); } catch (e) { console.log(e.stack); throw e; } return false; } onresponse1(req, rep, session) { delete session.extend; delete session.basedir; delete session.formatPath; delete session.pathname; return false; } }; /** * StaticControler:静态文件控制器,允许用户下载具体文件,但是文件类型受限制于;号隔开的文件类型 */ export const StaticControler = class extends AViewControler { constructor( list = "htm;css;js;jpg;jpeg;png;gif;xml;ico;swf;eot;svg;ttf;woff", regex = "(^\\S+\\/action\\.js$)|(^\\/logic\\/\\S+$)", ) { super(); const { __ } = pri(this, { list: {}, regex: new RegExp(regex), }); list .split(";") .filter((v) => V.isValid(v)) .forEach((k) => (__.list[k.toLowerCase()] = true)); } async output(req, rep, session) { const { __ } = pri(this); const ist = await V.callback((call) => F.exists(session.pathname, (ist) => call(null, ist)), ); if ( ist && __.list[session.extend.toLowerCase()] && !(session.url.pathname || "").toLowerCase().match(__.regex) ) { try { const stat = await V.callback(F.stat, F, session.pathname); const contenttype = get(session.extend); rep.setHeader( "Content-Type", contenttype + ("text/html,application/javascript,application/json,text/css,text/plain,application/xml,text/xml".indexOf( contenttype, ) >= 0 ? ";charset=utf-8" : ""), ); rep.setHeader("Date", stat.ctime.toUTCString()); rep.setHeader("Last-Modified", stat.mtime.toDateString()); session.isStatic = true; session.writeStream(F.createReadStream(session.pathname)); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } } else session.end(404, "no1 such file:" + session.url.pathname); return true; } }; /** * 使用querystring和raw-body完成SessionDataManager.QueryString,Form的管理和设置 */ export const JsonControler = class extends AViewControler { constructor(isOri = false) { super(); pri(this, { isOri }); } stringfy(array) { if (pri(this).__.isOri) return V.toJsonString(array); if (V.isArray(array)) { if (array.length == 0) return "[]"; let sb = V.sb(); sb.append("["); for (let i = 0; i < array.length; i++) { sb.append(this.stringfy(array[i])); if (i != array.length - 1) sb.append(","); } sb.append("]"); return sb.clear(); } else { for (let k in array) array[k] = typeof array[k] == "number" || array[k] ? "" + array[k] : array[k] || ""; return V.toJsonString(array); } } output(req, rep, session) { //处理JSON数组的stringfy rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { if (session.dbresult.length > 0 && session.dbresult[0].length > 0) { session.dbresult[0].forEach((v, i) => { session.dbresult[0][i] = v && v.length && (v[0].length == 0 || v[0]._nodata) ? [] : v; }); //(session.dbresult[0][0][0].length == 0 || session.dbresult[0][0][0]._nodata)) session.dbresult[0][0] = []; } session.write( session.dbresult.length > 0 ? this.stringfy(session.dbresult[0]) : "[]", ); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } return true; } }; /** * TJsonControler:TJson格式控制器 将session.dbresult中的第一个数据 */ export const TJsonControler = class extends JsonControler { constructor() { super(); const { __ } = pri(this, { stringfy: (array) => { if (V.isArray(array)) { if (array.length == 0) return ""; let sb = V.sb(); sb.append("["); for (let i = 0; i < array.length; i++) { sb.append(__.stringfy(array[i])); if (i != array.length - 1) sb.append(","); } sb.append("]"); return sb.clear(); } else return array == null ? "" : array; }, }); } stringfy(array) { const { __ } = pri(this); array = V.toTJson(array); return "[" + __.stringfy(array) + "]"; } }; export const XExcelControler = class extends AViewControler { constructor(paramsname = "_name") { super(); pri(this, { paramsname }); } async output(req, rep, session) { //处理JSON数组的stringfy const { _, __ } = pri(this); try { var array = session.dbresult && session.dbresult.length > 0 ? V.toTJson(session.dbresult[0])[0] : []; // console.log(226,"("+V.toJsonString(array).replace(/(\\")/g,'')+")"); !!array.length && (array = eval("(" + V.toJsonString(array).replace(/(\\")/g, "") + ")")); //去除"号 await session.exportExcel( array, session.param(__.paramsname) || session.status + ".xlsx", ); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } return true; } }; /** * JsonPControler(bk:"_bk"):JsonP格式控制器允许 */ export const JsonPControler = class extends JsonControler { constructor(bk = "_bk") { super(); pri(this, { bk }); } output(req, rep, session) { const { __ } = pri(this); //处理JSON数组的stringfy const bk = session.param(__.bk); if (bk) { rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { const json = session.dbresult.length > 0 ? this.stringfy(session.dbresult[0]) : "[]"; session.write(`${bk}(${json});`); } catch (e) { console.log(e.stack); session.write(bk + "([False]);"); session.Log.error("VESH:" + e.stack); } } else session.end(500, `JsonP need ${__.bk} as callback-function name.`); return true; } }; /** * TJsonPControler:TJsonP格式控制器 将session.dbresult中的第一个数据 */ export const TJsonPControler = class extends TJsonControler { constructor(bk = "_bk") { super(); pri(this, { bk }); } output(req, rep, session) { const { __ } = pri(this); //处理JSON数组的stringfy const bk = session.param(__.bk); if (bk) { rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { const json = session.dbresult.length > 0 ? this.stringfy(session.dbresult[0]) : "[]"; session.write(`${bk}(${json});`); } catch (e) { console.log(e.stack); session.write(bk + "([False]);"); session.Log.error("VESH:" + e.stack); } } else session.end(500, `TJsonP need ${__.bk} as callback-function name.`); return true; } }; /** * XJsonControler:XJson格式控制器 将session.dbresult中的第一个数据 */ export const XJsonControler = class extends JsonControler { constructor() { super(); const { __ } = pri(this); } output(req, rep, session) { //处理JSON数组的stringfy rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { if (session.dbresult) { let data = session.dbresult; while (data.length) data = data[0]; session.write( V.toJsonString({ success: true, Msg: "", data: data, code: 0, }), ); } else session.write( V.toJsonString({ success: true, Msg: "", data: {}, code: 0, }), ); } catch (e) { console.log(e.stack); session.write( V.toJsonString({ success: false, Msg: e.message, data: "", code: e.code || 500, }), ); session.Log.error("VESH:" + e.stack); } return true; } }; /** * XJsonPControler:XJson格式控制器 将session.dbresult中的第一个数据 */ export const XJsonPControler = class extends XJsonControler { constructor(bk = "_bk") { super(); pri(this, { bk }); } output(req, rep, session) { const { __ } = pri(this); //处理JSON数组的stringfy const bk = session.param(__.bk); if (bk) { rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { let json = V.toJsonString({ success: true, Msg: "", data: {}, code: 0, }); if (session.dbresult) { let data = session.dbresult; while (data.length) data = data[0]; json = V.toJsonString({ success: true, Msg: "", data: data, code: 0, }); } session.write(`${bk}(${json});`); } catch (e) { console.log(e.stack); session.write( bk + "(" + V.toJsonString({ success: false, Msg: e.message, data: "", code: e.code || 500, }) + ");", ); session.Log.error("VESH:" + e.stack); } } else session.end(500, `TJsonP need ${__.bk} as callback-function name.`); return true; } }; /** * VoidControler:无值返回值 */ export const VoidControler = class extends AViewControler { constructor() { super(); pri(this); } output(req, rep, session) { //处理JSON数组的stringfy rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); session.write("[[1]]"); return true; } }; /** * XControler:完全由Action处理的返回值 */ export const XControler = class extends AViewControler { constructor() { super(); pri(this); } output() { return true; } }; /** * StringControler:status作为返回值返回值 */ export const StringControler = class extends AViewControler { constructor() { super(); pri(this); } output(req, rep, session) { //处理JSON数组的stringfy rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); session.write(session.returnValue || session.status); return true; } }; /** * FormatPageControler:格式化页面 */ export const FormatPageControler = class extends AViewControler { constructor(extend = "html") { super(); pri(this, { extend }); } async output(req, rep, session) { const { _, __ } = pri(this); await V.next( async (data) => { let pathname = session.pathname.substr( 0, session.pathname.length - session.extend.length, ) + __.extend; const ist = await V.callback((call) => F.exists(pathname, (ist) => call(null, ist)), ); if (ist) { const text = await V.callback(F.readFile, F, pathname); data.text = Buffer.from(text).toString("utf-8") + ""; return false; } else { session.end(404, "no such file:" + session.url.pathname); return true; } }, async (data) => { data.text = await _.format(data.text, req, rep, session); return false; }, async (data) => { data.parent = {}; //不支持方法执行 只能实现数据<%=%>填充 循环一般不执行 继承需要实现 而且应该定义在<html inherit="具体的父类文件" >元素中 说明其继承的json文件并且直接进入 会话信息 let matchs = data.text.match(/<[hH][tT][mM][lL][^>]+inherit=[^>]+>/); if (matchs) { let parent = matchs[0] .match(/inherit=[\"'][^\"']+[\"']/)[0] .split(/['"]/)[1]; try { data.parent = await V.include(parent).output(req, rep, session); data.text = data.text .replace( /<\/[hH][eE][aA][dD]>/, (word) => (data.parent["HeaderScript"] || "") + word, ) .replace( /<[bB][oO][dD][yY][^>]*>/, (word) => word + (data.parent["Header"] || "") + (data.parent["Menu"] || ""), ) .replace( /<\/[bB][oO][dD][yY]>/, (word) => (data.parent["Footer"] || "") + (data.parent["FooterScript"] || "") + word, ); return false; } catch (e) { session.end(500, "VESH:" + e.stack); return true; } } else return false; }, (data) => { rep.setHeader("Content-Type", MIME.html + ";charset=utf-8"); //替换可能的引用页面里面的设置 session.write(data.text); return false; }, ); return true; } async funrep(s, o) { let reg = /<%=(.+?)%>/gi; let pros = []; s = s.replace(reg, function (word = "") { let prop = word.replace(/<%=/g, "").replace(/%>/g, ""); let ret = o(prop); if (ret.then && ret.catch) { pros.push(ret); return word; } return ret; }); if (pros.length > 0) { pros = await Promise.all(pros); s = s.replace(reg, function (word = "") { return pros.shift(); }); } return s; } getvalue(obj, name) { const matchs = name.match(/\([^\)]+\)/g); let params = []; if (matchs && matchs.length > 0) { name = name.substr(0, name.indexOf("(")); params = matchs[0].replace(/[\(\)\'\"]/g, "").split(","); } if (typeof obj[name] == "function") return obj[name].apply(obj, params); else if (obj.__proto__ && obj.__proto__[name]) return obj.__proto__[name].apply(obj, params); else return obj[name]; } async format(text, req, rep, session) { const { _, __ } = pri(this); return _.funrep(text, async (data) => { let map = data.split(/(?:[\.\[\]])/); let obj = null; for (let i = 0; i < map.length; i++) if (map[i]) { let v = map[i]; if (i == 0) obj = _.getvalue(session, v) || (session.dbresult && _.getvalue(session.dbresult, v)) || session.param(v); else if (obj) obj = _.getvalue(obj, v); if (obj && obj.then && obj.catch) obj = await obj; } obj = typeof (obj || "") == "string" ? obj : obj.toString ? obj.toString() : V.toJsonString(obj); return obj || ""; }); } }; export const FormatPageAScriptPage = class { constructor( dirs, HeaderScriptPath = "HeaderScript.htm", FooterScriptPath = "FooterScript.htm", ) { this.formater = new FormatPageControler(); this.dirs = dirs; pri(this, { HeaderScriptPath: I.formatPath( this.dirs + V.environment.splitChar + HeaderScriptPath, ), FooterScriptPath: I.formatPath( this.dirs + V.environment.splitChar + FooterScriptPath, ), }); } async output(req, rep, session) { const { _, __ } = pri(this); return { HeaderScript: await _.formater.format( Buffer.from( await V.callback(F.readFile, F, __.HeaderScriptPath), ).toString("utf-8"), req, rep, session, ), FooterScript: await _.formater.format( Buffer.from( await V.callback(F.readFile, F, __.FooterScriptPath), ).toString("utf-8"), req, rep, session, ), }; } }; export const FormatPageAPage = class extends FormatPageAScriptPage { constructor( dirs, HeaderScriptPath, FooterScriptPath, HeaderPath = "Header.htm", FooterPath = "Footer.htm", ) { super(dirs, HeaderScriptPath, FooterScriptPath); pri(this, { HeaderPath: I.formatPath( this.dirs + V.environment.splitChar + HeaderPath, ), FooterPath: I.formatPath( this.dirs + V.environment.splitChar + FooterPath, ), }); } async output(req, rep, session) { const { _, __ } = pri(this); return V.merge(await super.output(req, rep, session), { Header: await _.formater.format( Buffer.from(await V.callback(F.readFile, F, __.HeaderPath)).toString( "utf-8", ), req, rep, session, ), Footer: await _.formater.format( Buffer.from(await V.callback(F.readFile, F, __.FooterPath)).toString( "utf-8", ), req, rep, session, ), }); } }; export const FormatPageAContentPage = class extends FormatPageAPage { constructor( dirs, HeaderScriptPath, FooterScriptPath, HeaderPath, FooterPath, MenuPath = "Menu.htm", ) { super(dirs, HeaderScriptPath, FooterScriptPath, HeaderPath, FooterPath); pri(this, { MenuPath: I.formatPath(this.dirs + V.environment.splitChar + MenuPath), }); } async output(req, rep, session) { const { _, __ } = pri(this); return V.merge(await super.output(req, rep, session), { Menu: await _.formater.format( Buffer.from(await V.callback(F.readFile, F, __.MenuPath)).toString( "utf-8", ), req, rep, session, ), }); } }; /** * JsonPageControler:根据Json结果进行print操作 */ export const JsonPageControler = class extends AViewControler { constructor(extend = "html") { super(); const { _, __ } = pri(this, { extend, idic: {}, element: class { constructor(name) { const { _, __ } = pri(this, { name, data: {}, children: [] }); } parse(json) { const { _, __ } = pri(this); if (V.isArray(json)) __.children = json; else __.data = json; } push(data) { pri(this).__.children.push(data); } unshift(data) { pri(this).__.children.unshift(data); } toString() { const { _, __ } = pri(this); let sb = V.sb(); sb.append("<").append(__.name); for (let k in __.data) { let v = __.data[k]; sb.append(" " + k + '="') .append(v) .append('"'); } sb.append(">"); __.children.forEach((v) => { sb.append(v.toString()); }); sb.append("</" + __.name + ">"); const ret = sb.clear(); sb = null; return ret; } }, }); V.merge( __, { htmlEle: class extends __.element { constructor(json) { super("html"); pri(this); this.parse(json); } parse(json) { if (json.head) { const ele = __.headEle; this.push(new ele(json.head)); } if (json.body) { const ele = __.bodyEle; this.push(new ele("body", json.body)); } delete json.head; delete json.body; super.parse(json); } toString() { return ( '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' + super.toString() ); } }, headEle: class extends __.element { constructor(json) { super("head"); pri(this); this.parse(json); } parse(json) { for (let k in json) { let v = json[k]; switch (k.toLowerCase()) { case "content-type": case "x-ua-compatible": case "expires": case "pragma": case "refresh": case "set-cookie": case "window-target": case "pics-label": case "page-Enter": case "page-exit": case "cache-control": case "keywords": case "description": this.push(`<meta http-equiv="${k}" content="${v}">`); break; case "title": this.push("<title>" + v + "</title>"); break; case "js": { const ele = __.jsEle; this.push(new ele(json.js)); } break; case "css": { const ele = __.cssEle; this.push(new ele(json.css)); } break; default: this.push(`V.format('<meta name="${k}" content="${v}">`); break; } } } }, jsEle: class extends __.element { constructor(json) { super("js"); pri(this); this.parse(V.isArray(json) ? json : [json]); } parse(json) { const { _ } = pri(this); json.forEach((v) => { if (typeof v == "string") push(v); else if (v.child) { const elem = __.element; let ele = new elem("script"); ele.push(v.child); delete v.child; v = V.merge({ type: "text/javascript" }, v); ele.parse(v); _.push(ele); } else { const elem = __.element; let ele = new elem("script"); v = V.merge({ type: "text/javascript" }, v); ele.parse(v); _.push(ele); } }); } toString() { return super.toString().trim("<js>").trim("</js>"); } }, cssEle: class extends __.element { constructor(json) { super("css"); pri(this); this.parse(V.isArray(json) ? json : [json]); } parse(json) { const { _ } = pri(this); json.forEach((v) => { if (typeof v == "string") _.push(v); else if (v.child) { const elem = __.element; let ele = new elem("style"); ele.push(v.child); delete v.child; v = V.merge({ type: "text/css", rel: "stylesheet" }, v); ele.parse(v); _.push(ele); } else { const elem = __.element; let ele = new elem("style"); v = V.merge({ type: "text/css", rel: "stylesheet" }, v); ele.parse(v); _.push(ele); } }); } toString() { return super.toString().trim("<css>").trim("</css>"); } }, bodyEle: class extends __.element { constructor(name, json) { super(name); pri(this); this.parse(V.isArray(json) ? { child: json } : json); } parse(json) { const { _ } = pri(this); if (json.child) { json.child.forEach((v) => { let name = v.name || "div"; delete v.name; const elem = __.bodyEle; let ele = new elem(name, v); _.push(ele); }); delete json.child; } super.parse(json); } }, }, true, ); } parse(json) { const ele = pri(this).__.htmlEle; return new ele(json.html || json); } format(json) { return this.parse(json).toString(); } merge(...args) { //totest V.merge(...args); } getvalue(obj, name) { const matchs = name.match(/\([^)]+\)/g); let params = []; if (matchs && matchs.length > 0) { name = name.substr(0, name.indexOf("(")); params = matchs[0].replace(/[\(\)\'\"]/g, "").split(","); } if (typeof obj[name] == "function") return obj[name].apply(obj, params); else if (obj.__proto__ && obj.__proto__[name]) return obj.__proto__[name].apply(obj, params); else return obj[name]; } values(session, data) { const _ = this; let map = data.split(/(?:[\.\[\]])/); let obj = null; for (let i = 0; i < map.length; i++) if (map[i]) { let v = map[i]; if (i == 0) obj = _.getvalue(session, v) || (session.dbresult && _.getvalue(session.dbresult, v)) || session.param(v); else if (obj) obj = _.getvalue(obj, v); } return obj || ""; } async output(req, rep, session) { const { _, __ } = pri(this); const val = (data) => _.values(session, data); try { await V.next( async (data) => { let pathname = session.pathname.substr( 0, session.pathname.length - session.extend.length, ) + __.extend; data.pathname = pathname; const ist = await V.callback((call) => F.exists(pathname, (ist) => call(null, ist)), ); if (ist) { const stat = await V.callback(F.stat, F, pathname); if (__.idic[pathname]) { //todo getvalue无值? if (__.idic[pathname].size == stat.size) { data.text = __.idic[pathname].text; return false; } else { delete __.idic[pathname]; //todo 需要有机制保证父类文件和本文件都更新时更新缓存 } } __.idic[pathname] = { size: stat.size, text: await V.callback(F.readFile, F, pathname), }; data.text = __.idic[pathname].text; return false; } else { session.end(404, "no such file:" + session.url.pathname); return true; } }, (data) => { _.format(data); return false; }, async (data) => { data.text = eval("(" + data.text + ")"); data.parent = {}; if (data.text.html.parent) try { data.parent = await V.include(data.text.html.parent).output( req, rep, session, ); data.text = _.merge(data.text, data.parent); return false; } catch (e) { console.log(e.stack); session.end(500, "VESH:" + e.stack); return true; } else return false; }, (data) => { rep.setHeader("Content-Type", MIME.html + ";charset=utf-8"); const text = data.text; session.write(text); return false; }, ); } catch (e) { console.log(e.stack); session.end(500, e.stack); } return true; } }; /** * 处理当session.dbresult有数据的情况下按照data方式返回的API接口的情况 */ export const SingleControler = class extends JsonControler { constructor() { super(); pri(this); } output(req, rep, session) { const { __ } = pri(this); rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { if (session.dbresult) { let data = session.dbresult; while (data.length) data = data[0]; session.write(`[${V.toJsonString(data)}]`); } else session.write(`[]`); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } return true; } }; /** * 处理当有数据的情况下只返回第一个值的情况 */ export const SinglePControler = class extends SingleControler { constructor(bk = "_bk") { super(); pri(this, { bk }); } output(req, rep, session) { const { __ } = pri(this); const bk = session.param(__.bk); if (bk) { rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { if (session.dbresult) { let data = session.dbresult; while (data.length) data = data[0]; session.write(`${bk}(${V.toJsonString(data)})`); } else session.write(`${bk}({})`); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } } else session.end(500, `SingleP need ${__.bk} as callback-function name.`); return true; } }; /** * 处理当session.dbresult || session.status 有数据的情况下按照data方式返回的API接口的情况 */ export const MSocketControler = class extends JsonControler { constructor(insql, outsql) { super(); pri(this, { insql, outsql }); } async input(req, rep, session) { const { __ } = pri(this); rep.setHeader("Content-Type", MIME.js + ";charset=utf-8"); rep.setHeader("Expires", new Date().toUTCString()); try { let res = await session.Ni.execute("MT", __.outsql, { key: session.User.UserID || session.User.SessionID, }); session.write( res.hasData() ? V.toJsonString(res.last()[0].map((v) => V.json(v.value))) : "[]", ); //console.log('input 读取', res.hasData() ? V.toJsonString(res.last()[0]) : "[]"); } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } session.Response.statusCode = 200; session._status = session.status; await session.update(); if (!!session._status) { //console.log(919, '中断,继续进行下面的操作,存入List'); await session.flush(); await session.interrupt(); } else { //终止 //console.log(924, 'return true'); return true; } return false; } async output(req, rep, session) { const { __ } = pri(this); try { //保证数据有效 if (!!session._status) { // console.log('output 写入', session._status, session.User.SessionID, { // key: session.param('_id') || session._status, // value: session.dbresult && session.dbresult.length > 0 && session.dbresult[0] || session.status // }); await session.Ni.execute("MT", __.insql, { key: session.User.UserID || session.User.SessionID, value: V.toJsonString({ key: session.param("_id") || session._status, value: (session.dbresult && session.dbresult.length > 0 && session.dbresult[0]) || session.status, }), }); //session.clearWrite(); //session.clearStream(); } } catch (e) { console.log(e.stack); session.write("[False]"); session.Log.error("VESH:" + e.stack); } return true; } }; export default { FormatPageControler, JsonPageControler, JsonControler, JsonPControler, TJsonControler, TJsonPControler, VoidControler, XControler, StringControler, AViewControler, ViewModuler, StaticControler, XJsonControler, XJsonPControler, FormatPageAScriptPage, FormatPageAPage, FormatPageAContentPage, SingleControler, SinglePControler, MSocketControler, XExcelControler, }; const pri = V.pris();