thinknode
Version:
A fast, flexible and all-in-one web framework for node.js.
1,714 lines (1,610 loc) • 42.3 kB
JavaScript
;
var _stringify = require('babel-runtime/core-js/json/stringify');
var _stringify2 = _interopRequireDefault(_stringify);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
*
* @author richen
* @copyright Copyright (c) 2017 - <richenlin(at)gmail.com>
* @license MIT
* @version 17/03/13
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var crypto = require('crypto');
var net = require('net');
// var _interopSafeRequire = function (obj) {
// return (obj && obj.__esModule && obj.default) ? obj.default : obj;
// };
var lib = {};
//缓存池
global.THINK_CACHES = {
ALIAS: 'alias',
ALIAS_EXPORT: 'alias_export',
COLLECTION: 'collection',
LIMIT: 'limit',
MODEL: 'alias_model',
GORUP: [],
EXMIDDLEWARE: [],
INSTANCES: { 'CACHE': {}, 'LOG': null, 'AWAIT': null }
};
/**
* console.log 封装
* @param str
*/
global.echo = function (str) {
var date = lib.datetime('', '');
console.log('----------' + date + '----------');
console.log(str);
console.log('----------' + date + '----------');
};
lib.sep = path.sep;
lib.isArray = Array.isArray;
lib.isBuffer = Buffer.isBuffer;
lib.isIP = net.isIP;
lib.isIP4 = net.isIPv4;
lib.isIP6 = net.isIPv6;
lib.isDate = util.isDate;
lib.isRegexp = util.isRegExp;
lib.isSymbol = util.isSymbol;
lib.isError = util.isError;
/**
* 是否是字符串
*
* @param {any} obj
* @returns
*/
lib.isString = function (obj) {
return Object.prototype.toString.call(obj) === '[object String]';
};
/**
* 是否是数值
*
* @param {any} obj
* @returns
*/
lib.isNumber = function (obj) {
return Object.prototype.toString.call(obj) === '[object Number]';
};
/**
*
*
* @param {any} obj
* @returns
*/
lib.isBoolean = function (obj) {
return Object.prototype.toString.call(obj) === '[object Boolean]';
};
/**
* 是否是对象
*
* @param {[type]}
* @return {Boolean}
*/
lib.isObject = function (obj) {
if (Buffer.isBuffer(obj)) {
return false;
}
return Object.prototype.toString.call(obj) === '[object Object]';
};
/**
* 是否是函数
*
* @param {any} obj
* @returns
*/
lib.isFunction = function (obj) {
return typeof obj === 'function';
};
/**
* 是否是个标量
*
* @param {*} obj
* @returns {boolean}
*/
lib.isScalar = function (obj) {
var _obj = Object.prototype.toString.call(obj);
return _obj === '[object Boolean]' || _obj === '[object Number]' || _obj === '[object String]';
};
/**
* 是否是个Promise
*
* @param {*} obj
* @returns {boolean}
*/
lib.isPromise = function (obj) {
return !!(obj && obj.catch && typeof obj.then === 'function');
};
/**
* 是否是仅包含数字的字符串
*
* @param {*} obj
* @returns {boolean}
*/
lib.isNumberString = function (obj) {
var numberReg = /^((\-?\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
return numberReg.test(obj);
};
/**
* 是否是标准JSON对象
* 必须是对象或数组
* @param {*} obj
* @returns {boolean}
*/
lib.isJSONObj = function (obj) {
return lib.isObject(obj) || lib.isArray(obj);
};
/**
* 是否是标准的JSON字符串
* 必须是字符串,且可以被反解为对象或数组
* @param {*} obj
* @returns {boolean}
*/
lib.isJSONStr = function (obj) {
if (!lib.isString(obj)) {
return false;
}
try {
return lib.isJSONObj(JSON.parse(obj));
} catch (e) {
return false;
}
};
/**
* 是否是http对象
*
* @param {*} obj
* @returns {boolean}
*/
lib.isHttp = function (obj) {
return !!(obj && lib.isObject(obj.req) && lib.isObject(obj.res));
};
/**
* 检查对象是否为空
* 不考虑空对象、数组
* @param {*} obj
* @returns {boolean}
*/
lib.isTrueEmpty = function (obj) {
if (obj === undefined || obj === null || obj === '') {
return true;
}
if (lib.isNumber(obj)) {
return isNaN(obj);
}
return false;
};
/**
* 检查对象是否为空
*
* @param {*} obj
* @returns {boolean}
*/
lib.isEmpty = function (obj) {
if (obj === undefined || obj === null || obj === '') {
return true;
} else if (lib.isString(obj)) {
//\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
return obj.replace(/(^\s*)|(\s*$)/g, '').length === 0;
} else if (lib.isNumber(obj)) {
return isNaN(obj);
} else if (lib.isArray(obj)) {
return obj.length === 0;
} else if (lib.isObject(obj)) {
for (var key in obj) {
return !key && !0;
}
return true;
}
return false;
};
/**
* 强制转换为字符串
* 跟.toString不同的是可以转换undefined和null
* @param {*} obj
* @returns {string}
*/
lib.toString = function (obj) {
if (obj === undefined || obj === null) {
return '';
}
return String(obj);
};
/**
* 强制转换为整型
*
* @param {*} obj
* @returns {number}
*/
lib.toInt = function (obj) {
return isNaN(obj) ? 0 : parseInt(obj);
};
/**
* 强制转换为浮点型
*
* @param {*} obj
* @returns {number}
*/
lib.toFloat = function (obj) {
return isNaN(obj) ? 0 : parseFloat(obj);
};
/**
* 强制转换为数值
*
* @param {*} obj
* @returns {number}
*/
lib.toNumber = function (obj) {
return isNaN(obj) ? 0 : Number(obj);
};
/**
* 强制转换为布尔值
*
* @param {*} obj
* @returns {boolean}
*/
lib.toBoolen = function (obj) {
return Boolean(obj);
};
/**
* 大写首字符
*
* @param {string} name
* @returns {string}
*/
lib.ucFirst = function (name) {
name = (name || '') + '';
return name.slice(0, 1).toUpperCase() + name.slice(1).toLowerCase();
};
var htmlMaps = {
'<': '<',
'>': '>',
'"': '"e;',
'\'': '''
};
/**
* 字符转义实体
*
* @param {string} str
* @returns {string}
*/
lib.escapeHtml = function (str) {
return (str + '').replace(/[<>'"]/g, function (a) {
return htmlMaps[a];
});
};
/**
* 实体转义字符
*
* @param {string} str
* @returns {string}
*/
lib.escapeSpecial = function (str) {
var specialMaps = {
'<': '<',
'>': '>',
'"e;': '"',
''': '\''
};
for (var n in specialMaps) {
str = str.replace(new RegExp(n, 'g'), specialMaps[n]);
}
return str;
};
/**
* md5
*
* @param {string} str
* @returns {string}
*/
lib.md5 = function (str) {
var ins = crypto.createHash('md5');
ins.update(str + '', 'utf8');
return ins.digest('hex');
};
/**
* hash
*
* @param {string} str
* @returns {string}
*/
lib.hash = function (str) {
var _hash = 5381;
var I64BIT_TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-'.split('');
var i = str.length - 1;
if (typeof str === 'string') {
for (; i > -1; i--) {
_hash += (_hash << 5) + str.charCodeAt(i);
}
} else {
for (; i > -1; i--) {
_hash += (_hash << 5) + str[i];
}
}
var value = _hash & 0x7FFFFFFF;
var retValue = '';
do {
retValue += I64BIT_TABLE[value & 0x3F];
} while (value >>= 6);
return retValue;
};
/**
* rand
*
* @param {number} min
* @param {number} max
* @returns {number}
*/
lib.rand = function (min, max) {
return Math.floor(min + Math.random() * (max - min + 1));
};
/**
* AES字符串加密
*
* @param {string} data 需要加密的字符串
* @param {string} key 密钥 (必须为16位字符串)
* @returns {string}
*/
lib.encryption = function (data, key) {
try {
var iv = '0000000000000000';
// let clearEncoding = 'utf8';
// let cipherEncoding = 'base64';
var cipherChunks = [];
var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
cipher.setAutoPadding(true);
cipherChunks.push(cipher.update(data, 'utf8', 'base64'));
cipherChunks.push(cipher.final('base64'));
return encodeURIComponent(cipherChunks.join(''));
} catch (e) {
return '';
}
};
/**
* AES字符串解密
*
* @param {string} data 需要解密的字符串
* @param {string} key 密钥 (必须为16位字符串)
* @returns {string}
*/
lib.decryption = function (data, key) {
try {
var iv = '0000000000000000';
// let clearEncoding = 'utf8';
// let cipherEncoding = 'base64';
var cipherChunks = [];
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
decipher.setAutoPadding(true);
cipherChunks.push(decipher.update(decodeURIComponent(data), 'base64', 'utf8'));
cipherChunks.push(decipher.final('utf8'));
return cipherChunks.join('');
} catch (e) {
return '';
}
};
/**
* 日期时间戳及格式化
*
* @param {any} date
* @param {any} format
* @returns
*/
lib.datetime = function (date, format) {
if (format === undefined) {
//datetime() => now timestamp
if (date === undefined) {
return Math.floor(Date.now() / 1000);
} else if (lib.isString(date)) {
//datetime('2017-01-01') => timestamp
date = date || new Date();
return Math.floor(new Date(date).getTime() / 1000);
}
return NaN;
} else {
format = format || 'yyyy-mm-dd hh:mi:ss';
var fn = function fn(d, f) {
var Week = ['日', '一', '二', '三', '四', '五', '六'];
f = f.replace(/yyyy|YYYY/, d.getFullYear());
f = f.replace(/yy|YY/, d.getYear() % 100 > 9 ? (d.getYear() % 100).toString() : '0' + d.getYear() % 100);
f = f.replace(/mi|MI/, d.getMinutes() > 9 ? d.getMinutes().toString() : '0' + d.getMinutes());
f = f.replace(/mm|MM/, d.getMonth() + 1 > 9 ? (d.getMonth() + 1).toString() : '0' + (d.getMonth() + 1));
f = f.replace(/m|M/g, d.getMonth() + 1);
f = f.replace(/w|W/g, Week[d.getDay()]);
f = f.replace(/dd|DD/, d.getDate() > 9 ? d.getDate().toString() : '0' + d.getDate());
f = f.replace(/d|D/g, d.getDate());
f = f.replace(/hh|HH/, d.getHours() > 9 ? d.getHours().toString() : '0' + d.getHours());
f = f.replace(/h|H/g, d.getHours());
f = f.replace(/ss|SS/, d.getSeconds() > 9 ? d.getSeconds().toString() : '0' + d.getSeconds());
return f;
};
if (date && lib.isNumber(date)) {
var newDate = new Date();
newDate.setTime(date * 1000);
return fn(newDate, format);
}
if (date && lib.isString(date)) {
return fn(new Date(Date.parse(date)), format);
}
return fn(new Date(), format);
}
};
/**
* 快速生成一个object
*
* @param {*} key
* @param {*} value
* @returns {object}
*/
lib.getObject = function (key, value) {
var obj = {};
if (!lib.isArray(key)) {
obj[key] = value;
return obj;
}
key.forEach(function (item, i) {
obj[item] = value[i];
});
return obj;
};
/**
* 生成一个Promise
* 如果传入的参数是Promise则直接返回
* @template T
* @param {*} obj
* @param {boolean} reject
* @returns {*}
*/
lib.getPromise = function (obj, reject) {
if (lib.isPromise(obj)) {
return obj;
}
if (reject) {
return _promise2.default.reject(obj);
} else {
return _promise2.default.resolve(obj);
}
};
/**
* 生成一个defer对象
*
* @returns {*}
*/
lib.getDefer = function () {
var defer = {};
defer.promise = new _promise2.default(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
});
return defer;
};
/**
* 将callback风格的函数转换为Promise
*
* @param {Function} fn
* @param {object} receiver
* @returns {*}
*/
lib.promisify = function (fn, receiver) {
return function () {
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return new _promise2.default(function (resolve, reject) {
fn.apply(receiver, [].concat(args, [function (err, res) {
return err ? reject(err) : resolve(res);
}]));
});
};
};
/**
* 判断值是否为数组的元素
* 非严格匹配
* @param {*} value
* @param {any[]} arr
* @returns {boolean}
*/
lib.inArray = function (value, arr) {
var len = arr.length;
for (var i = 0; i < len; i++) {
if (arr[i] == value) {
return true;
}
}
return false;
};
/**
* 将数组变成对象
*
* @param {any[]} arr
* @param {*} key
* @param {*} valueKey
* @returns {*}
*/
lib.arrToObj = function (arr, key, valueKey) {
var res = {},
arrRes = [],
keyValue = void 0;
arr.forEach(function (item) {
keyValue = item[key];
if (valueKey === null) {
arrRes.push(keyValue);
} else if (valueKey) {
res[keyValue] = item[valueKey];
} else {
res[keyValue] = item;
}
});
return valueKey === null ? arrRes : res;
};
/**
* 数组去重
*
* @param {any[]} arr
* @returns {*}
*/
lib.arrUnique = function (arr) {
var ret = [],
json = {},
len = arr.length,
val = void 0;
for (var i = 0; i < len; i++) {
val = arr[i];
if (!json[val]) {
json[val] = 1;
ret.push(val);
}
}
return ret;
};
/**
* 数组删除元素
* indexs为需要删除的下标数组
* @param {any[]} arr
* @param {any[]} indexs
* @returns {*}
*/
lib.arrRemove = function (arr, indexs) {
var result = [],
len = arr.length,
need = void 0;
for (var i = 0; i < len; i++) {
need = false;
for (var j = 0; j < indexs.length; j++) {
if (i == indexs[j]) {
need = true;
break;
}
}
if (!need) {
result.push(arr[i]);
}
}
return result;
};
/**
* 是否是个文件
*
* @param {string} p
* @returns {boolean}
*/
lib.isFile = function (p) {
if (!fs.existsSync(p)) {
return false;
}
try {
var stats = fs.statSync(p);
return stats.isFile();
} catch (e) {
return false;
}
};
/**
* 是否是个目录
*
* @param {string} p
* @returns {boolean}
*/
lib.isDir = function (p) {
if (!fs.existsSync(p)) {
return false;
}
try {
var stats = fs.statSync(p);
return stats.isDirectory();
} catch (e) {
return false;
}
};
/**
* 判断一个文件或者目录是否可写
*
* @param {string} p
* @returns {boolean}
*/
lib.isWritable = function (p) {
if (!fs.existsSync(p)) {
return false;
}
var stats = fs.statSync(p);
var mode = stats.mode;
var uid = process.getuid ? process.getuid() : 0;
var gid = process.getgid ? process.getgid() : 0;
var owner = uid === stats.uid;
var group = gid === stats.gid;
return !!(owner && mode & parseInt('00200', 8) || group && mode & parseInt('00020', 8) || mode & parseInt('00002', 8));
};
/**
* 修改目录或者文件权限
* 同步模式
* @param {string} p
* @param {string} mode
* @returns {*}
*/
lib.chmod = function (p, mode) {
mode = mode || '0777';
if (!fs.existsSync(p)) {
return true;
}
return fs.chmodSync(p, mode);
};
/**
* 递归创建目录
* 同步模式
* @param {string} p
* @param {string} mode
* @returns {*}
*/
lib.mkDir = function (p, mode) {
mode = mode || '0777';
if (fs.existsSync(p)) {
fs.chmodSync(p, mode);
return true;
}
var pp = path.dirname(p);
if (fs.existsSync(pp)) {
fs.mkdirSync(p, mode);
} else {
lib.mkDir(pp, mode);
lib.mkDir(p, mode);
}
return true;
};
/**
* 递归的删除目录
* 返回Promise
* @template T
* @param {string} p
* @param {boolean} reserve
* @returns {*}
*/
lib.rmDir = function (p, reserve) {
if (!lib.isDir) {
return _promise2.default.resolve(null);
}
var deferred = lib.getDefer();
fs.readdir(p, function (err, files) {
if (err) {
return deferred.reject(err);
}
var spromise = _promise2.default.resolve(null);
if (files.length > 0) {
var promises = files.map(function (item) {
var filePath = path.normalize('' + p + path.sep + item);
if (lib.isDir(filePath)) {
return lib.rmDir(filePath, false);
} else {
var defer = lib.getDefer();
fs.unlink(filePath, function (er) {
return er ? defer.reject(er) : defer.resolve();
});
return defer.promise;
}
});
spromise = _promise2.default.all(promises);
}
return spromise.then(function () {
if (!reserve) {
var deferr = lib.getDefer();
fs.rmdir(p, function (e) {
return e ? deferr.reject(e) : deferr.resolve();
});
return deferr.promise;
}
return _promise2.default.resolve();
}).then(function () {
deferred.resolve();
}).catch(function (e) {
deferred.reject(e);
});
});
return deferred.promise;
};
/**
* 读取文件
* 返回Promise
* @param {string} filename 文件物理路径
* @param {*} enc 为空返回Buffer类型,'utf8'返回String类型
* @returns {*}
*/
lib.mReadFile = function (filename, enc) {
return new _promise2.default(function (fulfill, reject) {
fs.readFile(filename, enc || 'utf8', function (err, res) {
return err ? reject(err) : fulfill(res);
});
});
};
/**
* 写入文件
* 返回Promise
* @param {string} filename
* @param {*} data
* @returns {*}
*/
lib.mWriteFile = function (filename, data) {
return new _promise2.default(function (fulfill, reject) {
fs.writeFile(filename, data, function (err, res) {
return err ? reject(err) : fulfill(res);
});
});
};
/**
* 修改文件名
* 支持移动
* @param {string} filename
* @param {string} nfilename
* @returns {*}
*/
lib.mReName = function (filename, nfilename) {
return new _promise2.default(function (fulfill, reject) {
fs.rename(filename, nfilename, function (err) {
return err ? reject(err) : fulfill();
});
});
};
/**
* 读取文件
* 同步模式
* @param {string} file
* @param {*} encoding
* @returns {*}
*/
lib.getFileContent = function (file, encoding) {
if (!fs.existsSync(file)) {
return '';
}
return fs.readFileSync(file, encoding || 'utf8');
};
/**
* 写入文件
* 同步模式
* @param {string} file
* @param {*} data
* @returns {*}
*/
lib.setFileContent = function (file, data) {
var filePath = path.dirname(file);
lib.mkDir(filePath);
return fs.writeFileSync(file, data);
};
/*#################################################system function lib#####################################################*/
/**
* 继承
* from jquery.具有深度克隆
* @returns {*}
*/
lib.extend = function () {
var args = [].slice.call(arguments),
deep = true,
target = void 0;
if (lib.isBoolean(args[0])) {
deep = args.shift();
}
if (deep) {
target = lib.isArray(args[0]) ? [] : {};
} else {
target = args.shift();
}
target = target || {};
var i = 0,
length = args.length,
options = void 0,
name = void 0,
src = void 0,
copy = void 0;
for (; i < length; i++) {
options = args[i];
if (!options) {
continue;
}
for (name in options) {
src = target[name];
copy = options[name];
if (src && src === copy) {
continue;
}
if (deep) {
if (lib.isObject(copy)) {
target[name] = lib.extend(src && lib.isObject(src) ? src : {}, copy);
} else if (lib.isArray(copy)) {
target[name] = lib.extend([], copy);
} else {
target[name] = copy;
}
} else {
target[name] = copy;
}
}
}
return target;
};
/**
* 加载文件
* 自动缓存并拦截错误
* @param {string} file
* @returns {*}
*/
lib.safeRequire = function (file) {
try {
var obj = require(file);
return obj && obj.__esModule && obj.default ? obj.default : obj;
} catch (e) {
return null;
}
};
/**
* 参数缓存池
*
* @param {string} type
* @param {*} [name]
* @param {*} [value]
* @returns {*}
*/
lib.loadCache = function (type, name, value) {
if (!(type in THINK_CACHES)) {
THINK_CACHES[type] = {};
}
// get cache
if (name === undefined) {
return THINK_CACHES[type];
} else if (name === null) {
//remove cache
THINK_CACHES[type] = {};
return null;
} else if (value === undefined) {
// get cache
if (lib.isString(name)) {
return THINK_CACHES[type][name];
}
THINK_CACHES[type] = name;
return null;
} else if (value === null) {
//remove cache
delete THINK_CACHES[type][name];
return null;
}
//set cache
THINK_CACHES[type][name] = value;
return null;
};
/**
* 自定义require
* 具备别名加载功能
* @param {*} name
* @param {*} [type]
* @returns {*}
*/
lib.require = function (name, type) {
if (lib.isObject(name)) {
return name;
}
var cls = lib.loadCache(type || THINK_CACHES.ALIAS_EXPORT, name);
if (!lib.isEmpty(cls)) {
return cls;
}
var load = function load(na, filepath) {
var obj = lib.safeRequire(filepath);
if (lib.isFunction(obj)) {
obj.prototype.__filename = filepath;
}
if (obj) {
lib.loadCache(type || THINK_CACHES.ALIAS_EXPORT, na, obj);
}
return obj;
};
try {
var filepath = type ? lib.loadCache(THINK_CACHES.ALIAS, type)[name] : lib.loadCache(THINK_CACHES.ALIAS, name);
if (filepath) {
return load(name, path.normalize(filepath));
}
filepath = require.resolve(name);
return load(name, filepath);
} catch (e) {
return null;
}
};
/*#################################################app function lib#####################################################*/
/**
* 调用执行Group/Controller/Action
* THINK.action('Home/Index', this.http), THINK.action('Admin/Index/test', this.http)
* @param {string} name
* @param {THINK.HttpObject} http
* @param {string} suffix
* @returns {*}
*/
lib.action = function (name, http, suffix) {
var app = new THINK.App();
http = app.getController(http, name);
//controller instance
var controller = void 0;
try {
var instance = lib.controller(http.group + '/' + http.controller);
controller = new instance(http);
} catch (e) {
return lib.statusAction(http, 404, 'Controller ' + http.group + '/' + http.controller + ' not found.');
}
http.actionSuffix = suffix;
return app.execAction(http, controller);
};
/**
* 加载/实例化一个Adapter
*
* @param {(string | object)} name
* @param {EmptyObject} [options]
* @returns {*}
*/
lib.adapter = function (name, options) {
try {
var cls = void 0;
if (!lib.isString(name) && name.__filename) {
cls = lib.require(name.__filename, 'Adapter');
} else {
cls = lib.require(name, 'Adapter');
}
if (!cls) {
return lib.error('Adapter ' + name + ' is undefined');
}
if (options !== undefined) {
return new cls(options);
}
return cls;
} catch (e) {
return lib.error(e);
}
};
/**
* 自定义日志记录
*
* @param {string} name
* @param {*} context
* @returns {*}
*/
lib.addLogs = function (name, context) {
try {
if (!lib.isString(context)) {
context = (0, _stringify2.default)(context);
}
if (!THINK_CACHES.INSTANCES.LOG) {
THINK_CACHES.INSTANCES.LOG = lib.adapter(THINK_CACHES.CONF.log_type + 'Logs');
}
return new THINK_CACHES.INSTANCES.LOG({ log_itemtype: 'custom' }).logCustom(name, context);
} catch (e) {
return lib.error(e, false);
}
};
/**
* 执行等待,避免一个耗时的操作多次被执行
* callback 需要返回一个 Promise
* @param {string} key
* @param {Function} callback
* @returns {*}
*/
lib.await = function (key, callback) {
if (!THINK_CACHES.INSTANCES.AWAIT) {
THINK_CACHES.INSTANCES.AWAIT = new (lib.require('Await'))();
}
return THINK_CACHES.INSTANCES.AWAIT.run(key, callback);
};
/**
* 缓存的设置和读取
*
* @param {string} name
* @param {*} [value]
* @param {*} [options]
* @returns {*}
*/
lib.cache = function (name, value, options) {
try {
if (lib.isNumber(options)) {
options = { cache_timeout: options };
} else if (options === null) {
options = { cache_timeout: null };
}
options = options || {};
options.cache_key_prefix = ~lib.config('cache_key_prefix').indexOf(':') ? lib.config('cache_key_prefix') + 'Cache:' : lib.config('cache_key_prefix') + ':Cache:';
var cls = lib.adapter((lib.config('cache_type') || 'File') + 'Cache');
var instance = new cls(options);
if (value === undefined) {
return instance.get(name).then(function (val) {
return lib.isJSONStr(val) ? JSON.parse(val) : val;
});
} else if (value === null) {
return instance.rm(name);
} else {
return instance.set(name, lib.isScalar(value) ? value : (0, _stringify2.default)(value), options.cache_timeout);
}
} catch (e) {
return lib.error(e);
}
};
/**
* 配置读取
*
* @param {string} name
* @returns {*}
*/
lib.config = function (name) {
if (name === undefined) {
return THINK_CACHES.CONF;
}
if (lib.isString(name)) {
//name不含. 一级
if (name.indexOf('.') === -1) {
return THINK_CACHES.CONF[name];
} else {
//name包含. 二级
var keys = name.split('.');
var value = THINK_CACHES.CONF[keys[0]] || {};
return value[keys[1]];
}
} else {
return THINK_CACHES.CONF[name];
}
};
/**
* 加载/实例化一个Controller
*
* @param {*} name
* @param {THINK.HttpObject} [http]
* @returns {*}
*/
lib.controller = function (name, http) {
try {
if (!name && !http) {
return THINK.Controller;
}
var cls = void 0;
if (!lib.isString(name) && name.__filename) {
cls = lib.require(name.__filename, 'Controller');
} else {
cls = lib.require(name, 'Controller');
}
if (!cls) {
return lib.error('Controller ' + name + ' is undefined');
}
if (http && lib.isHttp(http)) {
return new cls(http);
}
return cls;
} catch (e) {
return lib.error(e);
}
};
/**
* 文件缓存读取和写入
* 默认写入到App/Runtime/Data目录下
* @param {string} name
* @param {*} [value]
* @param {string} [rootPaht]
* @returns {*}
*/
lib.data = function (name, value, rootPaht) {
try {
rootPaht = rootPaht || THINK.DATA_PATH;
var filePath = '' + rootPaht + path.sep + name + '.json';
if (value === undefined) {
if (lib.isFile(filePath)) {
return lib.getFileContent(filePath);
}
} else {
return lib.setFileContent(filePath, value);
}
return null;
} catch (e) {
return lib.error(e);
}
};
/**
* 抛出异常
* 当isbreak为true时返回reject,否则仅记录日志
* @param {*} msg
* @param {boolean} [isbreak]
* @returns {*}
*/
lib.error = function (msg, isbreak) {
if (lib.isPromise(msg)) {
return msg.catch(function (e) {
return lib.error(e);
});
}
if (isbreak === undefined || isbreak === true) {
isbreak = true;
} else {
isbreak = false;
}
msg = msg || '';
if (!lib.isError(msg)) {
if (!lib.isScalar(msg)) {
msg = (0, _stringify2.default)(msg);
}
msg = new Error(msg);
}
if (isbreak === true) {
return _promise2.default.reject(msg);
} else {
//console print
lib.log(msg);
return msg;
}
};
/**
* 加载框架扩展类
*
* @param {*} name
* @param {string} [type='Controller']
* @returns {*}
*/
lib.ext = function (name) {
var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Controller';
return lib.require(name, type);
};
/**
* 中间件挂载机制
*
* @param {...any[]} args
* @returns {*}
*/
lib.hook = function () {
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = arguments[_key2];
}
var name = args[0],
type = args[1],
append = args[2];
if (!name || !type) {
return null;
}
THINK_CACHES.EXMIDDLEWARE || (THINK_CACHES.EXMIDDLEWARE = []);
THINK_CACHES.EXMIDDLEWARE.push({
name: name,
type: type,
append: append || 'append'
});
return null;
};
/**
* 多语言读取
*
* @param {string} [name]
* @returns {*}
*/
lib.lang = function (name) {
var langConfig = THINK_CACHES.CONF.language || 'en';
if (name === undefined) {
return THINK_CACHES.LANGUAGE[langConfig];
}
if (lib.isString(name)) {
//name不含. 一级
if (name.indexOf('.') === -1) {
return THINK_CACHES.LANGUAGE[langConfig][name];
} else {
//name包含. 二级
var keys = name.split('.');
var value = THINK_CACHES.LANGUAGE[langConfig][keys[0]] || {};
return value[keys[1]];
}
} else {
return THINK_CACHES.LANGUAGE[langConfig][name];
}
};
/**
* 日志记录及打印
*
* @param {*} msg
* @param {string} [type]
* @param {number} [showTime]
* @returns {void}
*/
lib.log = function (msg, type, showTime) {
var dateTime = '[' + lib.datetime('', '') + '] ';
var message = msg;
if (lib.isError(msg)) {
type = 'ERROR';
message = msg.stack;
console.error(msg.stack);
} else if (type === 'ERROR') {
type = 'ERROR';
if (!lib.isString(msg)) {
message = (0, _stringify2.default)(msg);
}
console.error(message);
} else if (type === 'WARNING') {
type = 'WARNING';
if (!lib.isString(msg)) {
message = (0, _stringify2.default)(msg);
}
console.warn(message);
} else {
if (!lib.isString(msg)) {
message = (0, _stringify2.default)(msg);
}
if (lib.isNumber(showTime)) {
var _time = Date.now() - showTime;
message += ' ' + (_time + 'ms');
}
type = type || 'INFO';
//判断console.info是否被重写
'prototype' in console.info && console.info(message);
}
(THINK.APP_DEBUG || type === 'THINK') && console.log(dateTime + '[' + type + '] ' + message);
};
/**
* 加载/挂载/运行一个Middleware
*
* @param {*} [name]
* @param {*} [type]
* @param {*} [append]
* @returns {*}
*/
lib.middleware = function (name, type, append) {
try {
if (!name && !type) {
return THINK.Middleware;
}
if (type !== undefined) {
if (lib.isHttp(type)) {
return lib.use(name, type, append);
} else {
return lib.hook(name, type, append);
}
} else {
var cls = void 0;
if (!lib.isString(name) && name.__filename) {
cls = lib.require(name.__filename, 'Middleware');
} else {
cls = lib.require(name, 'Middleware');
}
if (!cls) {
return lib.error('Middleware ' + name + ' is undefined');
}
return cls;
}
} catch (e) {
return lib.error(e);
}
};
/**
* 加载/实例化一个Model
*
* @param {*} name
* @param {EmptyObject} [config]
* @returns {*}
*/
lib.model = function (name, config) {
try {
if (!name && !config) {
return THINK.Model;
}
var cls = void 0;
if (!lib.isString(name) && name.__filename) {
cls = lib.require(name.__filename, 'Model');
name = name.modelName;
} else {
cls = lib.require(name, 'Model');
var tempName = name.split('/');
tempName[1] ? name = tempName[1] : name = tempName[0];
}
if (!cls) {
return lib.error('Model ' + name + ' is undefined');
}
if (config === undefined) {
return cls;
}
config = lib.extend(false, {
db_type: lib.config('db_type'),
db_host: lib.config('db_host'),
db_port: lib.config('db_port'),
db_name: lib.config('db_name'),
db_user: lib.config('db_user'),
db_pwd: lib.config('db_pwd'),
db_prefix: lib.config('db_prefix'),
db_charset: lib.config('db_charset'),
db_ext_config: lib.config('db_ext_config') || {}
}, config);
config.db_ext_config.db_log_sql = THINK.APP_DEBUG;
return new cls(config);
} catch (e) {
return lib.error(e);
}
};
/**
* 并行处理
*
* @param {*} [key]
* @param {*} [data]
* @param {*} [callback]
* @param {any} [options={}]
* @returns
*/
lib.parallelLimit = function (key, data, callback) {
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
if (!lib.isString(key) || lib.isFunction(data)) {
options = callback || {};
callback = data;
data = key;
key = '';
}
if (!lib.isFunction(callback)) {
options = callback || {};
callback = undefined;
}
if (lib.isNumber(options)) {
options = { limit: options };
}
var flag = !lib.isArray(data) || options.array;
if (!flag) {
key = '';
}
//get parallel limit class
var Limit = lib.loadCache(THINK_CACHES.COLLECTION, 'limit');
if (!Limit) {
Limit = lib.require('ParallelLimit');
lib.loadCache(THINK_CACHES.COLLECTION, 'limit', Limit);
}
var instance = void 0;
if (key) {
instance = lib.loadCache(THINK_CACHES.LIMIT, key);
if (!instance) {
instance = new Limit(options.limit, callback);
lib.loadCache(THINK_CACHES.LIMIT, key, instance);
}
} else {
instance = new Limit(options.limit, callback);
}
if (flag) {
return instance.add(data);
}
return instance.addMany(data, options.ignoreError);
};
/**
* prevent next process
* @return {*} []
*/
var preventMessage = 'PREVENT_NEXT_PROCESS';
lib.prevent = function () {
return lib.error(preventMessage);
};
lib.isPrevent = function (err) {
return lib.isError(err) && err.message === preventMessage;
};
/**
* 运行挂载点挂载的中间件链
*
* @param {*} name
* @param {THINK.HttpObject} http
* @param {*} [data]
* @returns {*}
*/
lib.run = function (name, http, data) {
var list = THINK_CACHES.HOOK[name] || [];
var runItemMiddleware = function runItemMiddleware(ls, index, ht, da) {
var item = ls[index];
if (!item) {
return _promise2.default.resolve(da);
}
return lib.use(item, ht, da).then(function (result) {
if (result === null) {
return _promise2.default.resolve(da);
} else if (result !== undefined) {
da = result;
}
return runItemMiddleware(ls, index + 1, ht, da);
}).catch(function (err) {
return lib.error(err);
});
};
if (!list || list.length === 0) {
return _promise2.default.resolve(data);
}
return runItemMiddleware(list, 0, http, data);
};
/**
* 加载/实例化一个Service
*
* @param {*} name
* @param {*} [arg]
* @param {*} [config]
* @returns {*}
*/
lib.service = function (name, arg, config) {
try {
if (!name && !arg && !config) {
return THINK.Service;
}
var cls = void 0;
if (!lib.isString(name) && name.__filename) {
cls = lib.require(name.__filename, 'Service');
} else {
cls = lib.require(name, 'Service');
}
if (!cls) {
return lib.error('Service ' + name + ' is undefined');
}
if (arg !== undefined || config !== undefined) {
return new cls(arg, config);
}
return cls;
} catch (e) {
return lib.error(e);
}
};
/**
* 系统异常页面输出
*
* @param {THINK.HttpObject} http
* @param {number} [status=200]
* @param {string} [msg='']
* @returns
*/
lib.statusAction = function (http) {
var status = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 200;
var msg = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
if (lib.isPrevent(msg)) {
return lib.getDefer().promise;
}
if (!lib.isHttp(http)) {
//错误输出
msg && lib.error(msg, false);
return lib.prevent();
}
http.status(status);
//自定义错误模板输出
if (status > 399) {
if (lib.isError(msg)) {
http._endError = msg;
} else {
http._endError = msg ? new Error(msg) : lib.lang(status);
}
var controller = void 0;
if (http.isStatusAction) {
controller = lib.controller('Status', http);
} else {
try {
var instance = lib.controller(lib.config('status_controller'));
http.isStatusAction = true;
controller = new instance(http);
} catch (e) {
controller = lib.controller('Status', http);
}
}
if (controller) {
var app = new THINK.App();
return app.execAction(http, controller, '_' + status).catch(function (err) {
return http.afterEnd(500, err);
});
}
}
return http.afterEnd(status);
};
/**
* 中间件执行机制
*
* @param {...any[]} args
* @returns {*}
*/
lib.use = function () {
for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
args[_key3] = arguments[_key3];
}
var name = args[0],
http = args[1],
data = args[2];
if (lib.isString(name)) {
if (lib.isEmpty(name)) {
return data;
}
var fn = lib.middleware(name);
if (!fn) {
return lib.error('Middlewate ' + name + ' is undefined');
}
if (fn.prototype.run) {
var cls = new fn(http);
return cls.run(data);
} else {
return fn(http, data);
}
}
return name(http, data);
};
/**
* URL格式化 输出带伪静态支持的标准url
*
* @param {*} urls URL表达式,格式:'模块[/控制器/操作]'
* @param {THINK.HttpObject} http http对象
* @param {string} [vars=''] 传入的参数,支持对象和字符串 {var1: "aa", var2: "bb"}
* @returns {string}
*/
lib.url = function (urls, http) {
var vars = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
if (!urls) {
return '';
}
var bCamelReg = function bCamelReg(s) {
s = s.slice(0, 1).toLowerCase() + s.slice(1);
return s.replace(/([A-Z])/g, '_$1').toLowerCase();
};
if (urls.indexOf('/') === 0) {
urls = urls.slice(1);
}
var temp = urls.split('/');
var retUrl = '';
if (temp[0]) {
retUrl = bCamelReg(temp[0]);
} else {
retUrl = bCamelReg(http.group || lib.config('default_group'));
}
if (temp[1]) {
retUrl = retUrl + '/' + bCamelReg(temp[1]);
} else {
retUrl = retUrl + '/' + bCamelReg(http.controller || lib.config('default_controller'));
}
if (temp[2]) {
retUrl = retUrl + '/' + bCamelReg(temp[2]);
} else {
retUrl = retUrl + '/' + bCamelReg(http.action || lib.config('default_action'));
}
retUrl = '' + retUrl + lib.config('url_pathname_suffix');
if (!lib.isEmpty(vars)) {
if (lib.isString(vars)) {
retUrl = retUrl + '?' + vars;
} else if (lib.isObject(vars)) {
var querystring = require('querystring');
retUrl = retUrl + '?' + querystring.stringify(vars);
}
}
return retUrl;
};
/**
* 值循环过滤
* 深度过滤
* @param {*} object 数组或对象(对象属性值可以为字符串或数组)
* @returns {*}
*/
lib.walkFilter = function (object) {
if (object === null || object === undefined) {
return '';
}
if (lib.isString(object)) {
return lib.escapeHtml(object);
}
if (lib.isObject(object) || lib.isArray(object)) {
for (var n in object) {
object[n] = lib.walkFilter(object[n]);
}
}
return object;
};
/**
* v8引擎优化
*
* @param {object} obj
*/
lib.toFastProperties = function (obj) {
var f = function f() {};
f.prototype = obj;
/*eslint-disable no-new*/
new f();
};
module.exports = lib;