UNPKG

thinknode

Version:

A fast, flexible and all-in-one web framework for node.js.

1,714 lines (1,610 loc) 42.3 kB
'use strict'; 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 = { '<': '&lt;', '>': '&gt;', '"': '&quote;', '\'': '&#39;' }; /** * 字符转义实体 * * @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 = { '&lt;': '<', '&gt;': '>', '&quote;': '"', '&#39;': '\'' }; 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;