vesh
Version:
码农nodejs版本VESH框架,使用函数责任链模式 实现了 默认文件跳转,自定义错误页,空文件处理,URL解析,Querystring与Form参数解析,PostFiles解析,MVC自动映射,SQL自动服务化,可继承页面,静态文件,json,tjson,jsonp,tjsonp,string,void,xjson,xjosnp等等6种JSON格式,http与https等等操作
1,210 lines (1,175 loc) • 34.9 kB
JavaScript
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];
//需要兼容 无后缀名和多点的情况
if (
!session.extend &&
session.filename &&
!session.filename.eq(session.status) &&
"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);
rep.setHeader("Content-Type", get(session.extend) + ";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, "no 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();