thinknode
Version:
A fast, flexible and all-in-one web framework for node.js.
734 lines (607 loc) • 26.4 kB
JavaScript
;
exports.__esModule = true;
var _regenerator = require('babel-runtime/regenerator');
var _regenerator2 = _interopRequireDefault(_regenerator);
var _freeze = require('babel-runtime/core-js/object/freeze');
var _freeze2 = _interopRequireDefault(_freeze);
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);
var _promise = require('babel-runtime/core-js/promise');
var _promise2 = _interopRequireDefault(_promise);
var _from = require('babel-runtime/core-js/array/from');
var _from2 = _interopRequireDefault(_from);
var _set = require('babel-runtime/core-js/set');
var _set2 = _interopRequireDefault(_set);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _fs = require('fs');
var _fs2 = _interopRequireDefault(_fs);
var _path = require('path');
var _path2 = _interopRequireDefault(_path);
var _thinkorm = require('thinkorm');
var _thinkorm2 = _interopRequireDefault(_thinkorm);
var _Base = require('./Base');
var _Base2 = _interopRequireDefault(_Base);
var _App = require('./Core/App');
var _App2 = _interopRequireDefault(_App);
var _Http = require('./Core/Http');
var _Http2 = _interopRequireDefault(_Http);
var _Base3 = require('./Extension/Controller/Base');
var _Base4 = _interopRequireDefault(_Base3);
var _Base5 = require('./Extension/Middleware/Base');
var _Base6 = _interopRequireDefault(_Base5);
var _Base7 = require('./Extension/Service/Base');
var _Base8 = _interopRequireDefault(_Base7);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _class = function () {
function _class() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
(0, _classCallCheck3.default)(this, _class);
//初始化
this.initialize(options);
//运行环境检测
this.checkEnv();
//加载框架文件
this.loadFramework();
//挂载核心类
THINK.App = _App2.default;
THINK.Base = _Base2.default;
THINK.Controller = _Base4.default;
THINK.Middleware = _Base6.default;
THINK.Model = _thinkorm2.default;
THINK.Service = _Base8.default;
THINK.Http = _Http2.default;
}
/**
* check node env
* @return {Boolean} []
*/
_class.prototype.checkEnv = function checkEnv() {
this.checkNodeVersion();
THINK.log('Check Node Version: success', 'THINK');
this.checkDependencies();
THINK.log('Check Dependencies: success', 'THINK');
};
/**
* init
* @param options
*/
_class.prototype.initialize = function initialize(options) {
THINK.ROOT_PATH = options.ROOT_PATH;
THINK.APP_PATH = options.APP_PATH;
THINK.RESOURCE_PATH = options.RESOURCE_PATH;
THINK.RUNTIME_PATH = options.RUNTIME_PATH;
THINK.THINK_PATH = _path2.default.dirname(__dirname);
THINK.APP_DEBUG = options.APP_DEBUG;
THINK.log('====================================', 'THINK');
//项目根目录
if (!THINK.ROOT_PATH) {
THINK.log('global.THINK.ROOT_PATH must be defined', 'ERROR');
process.exit();
}
//静态资源目录
if (!THINK.RESOURCE_PATH) {
THINK.RESOURCE_PATH = '' + THINK.ROOT_PATH + THINK.sep + 'www';
}
//应用目录
if (!THINK.APP_PATH) {
THINK.APP_PATH = '' + THINK.ROOT_PATH + THINK.sep + 'App';
}
//DEBUG模式
if (THINK.APP_DEBUG !== true) {
THINK.APP_DEBUG = false;
}
//运行缓存目录
if (!THINK.RUNTIME_PATH) {
THINK.RUNTIME_PATH = '' + THINK.ROOT_PATH + THINK.sep + 'Runtime';
}
//日志目录
if (THINK.LOG_PATH === undefined) {
THINK.LOG_PATH = '' + THINK.RUNTIME_PATH + THINK.sep + 'Logs';
}
//缓存目录
if (THINK.TEMP_PATH === undefined) {
THINK.TEMP_PATH = '' + THINK.RUNTIME_PATH + THINK.sep + 'Temp';
}
//数据文件目录
if (THINK.DATA_PATH === undefined) {
THINK.DATA_PATH = '' + THINK.RUNTIME_PATH + THINK.sep + 'Data';
}
//文件缓存目录
if (THINK.CACHE_PATH === undefined) {
THINK.CACHE_PATH = '' + THINK.RUNTIME_PATH + THINK.sep + 'Cache';
}
//框架版本
try {
var pkgPath = '' + THINK.THINK_PATH + THINK.sep + 'package.json';
var packages = JSON.parse(_fs2.default.readFileSync(pkgPath, 'utf8'));
THINK.THINK_ENGINES = packages.engines;
THINK.THINK_VERSION = packages.version;
} catch (e) {
THINK.THINK_ENGINES = { node: '>4.0.0' };
THINK.THINK_VERSION = '4.x.x';
}
//debug模式 node --debug index.js
if (THINK.APP_DEBUG || process.execArgv.indexOf('--debug') > -1) {
THINK.APP_DEBUG = true;
}
//生产环境
if (process.execArgv.indexOf('--production') > -1 || process.env.NODE_ENV === 'production') {
THINK.APP_DEBUG = false;
}
//Cache定时器
THINK_CACHES.GC = {};
THINK_CACHES.GCTIMER = function (instance) {
if (THINK_CACHES.GC[instance.options.gctype]) {
return;
}
THINK_CACHES.GC[instance.options.gctype] = setInterval(function () {
var hour = new Date().getHours();
if (THINK.config('cache_gc_hour').indexOf(hour) === -1) {
return null;
}
return instance.gc && instance.gc(Date.now());
}, 3600 * 1000);
};
THINK.log('Initialize: success', 'THINK');
};
/**
* check node version
* @return {} []
*/
_class.prototype.checkNodeVersion = function checkNodeVersion() {
var engines = THINK.THINK_ENGINES;
var needVersion = engines.node.slice(1);
var nodeVersion = process.version;
if (nodeVersion[0] === 'v') {
nodeVersion = nodeVersion.slice(1);
}
if (needVersion > nodeVersion) {
THINK.log('ThinkNode need node version >= ' + needVersion + ', current version is ' + nodeVersion + ', please upgrade it.', 'ERROR');
process.exit();
}
};
/**
* check dependencies is installed before server start
* @return {} []
*/
_class.prototype.checkDependencies = function checkDependencies() {
var packageFile = '' + THINK.ROOT_PATH + THINK.sep + 'package.json';
if (!THINK.isFile(packageFile)) {
return;
}
var dependencies = {};
try {
var data = JSON.parse(_fs2.default.readFileSync(packageFile, 'utf8'));
dependencies = data.dependencies;
} catch (e) {
THINK.log(e);
}
for (var pkg in dependencies) {
if (!THINK.isDir('' + THINK.ROOT_PATH + THINK.sep + 'node_modules' + THINK.sep + pkg)) {
THINK.log(' package `' + pkg + '` is not installed. please run \'npm install\' command before start server.', 'ERROR');
process.exit();
}
}
};
/**
* load alias
* @param alias
* @param g
*/
_class.prototype.loadAlias = function loadAlias(alias, g) {
THINK_CACHES[THINK_CACHES.ALIAS] || (THINK_CACHES[THINK_CACHES.ALIAS] = {});
for (var v in alias) {
if (THINK.isObject(alias[v])) {
this.loadAlias(alias[v], v);
} else {
if (g) {
var _Object$assign2;
THINK_CACHES[THINK_CACHES.ALIAS][g] || (THINK_CACHES[THINK_CACHES.ALIAS][g] = {});
(0, _assign2.default)(THINK_CACHES[THINK_CACHES.ALIAS][g], (_Object$assign2 = {}, _Object$assign2[v] = alias[v], _Object$assign2));
} else {
var _Object$assign3;
(0, _assign2.default)(THINK_CACHES[THINK_CACHES.ALIAS], (_Object$assign3 = {}, _Object$assign3[v] = alias[v], _Object$assign3));
}
}
}
};
/**
* load alias module export
* @param alias
* @param exp
*/
_class.prototype.loadAliasExport = function loadAliasExport(alias) {
var exp = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : THINK_CACHES.ALIAS_EXPORT;
alias = alias || THINK.loadCache(THINK_CACHES.ALIAS);
for (var key in alias) {
if (THINK.loadCache(exp, key)) {
continue;
}
if (THINK.isObject(alias[key])) {
this.loadAliasExport(alias[key], key);
} else {
THINK.loadCache(exp, key, THINK.safeRequire(alias[key]));
}
}
};
/**
* load alias model export
*/
_class.prototype.loadAliasModel = function loadAliasModel(alias) {
THINK.loadCache(THINK_CACHES.MODEL, alias, 1);
};
/**
* load external middleware
*/
_class.prototype.loadExMiddleware = function loadExMiddleware() {
THINK_CACHES.EXMIDDLEWARE.forEach(function (item) {
var tempName = void 0,
cls = void 0;
//挂载第三方中间件
if (THINK.isFunction(item.name)) {
tempName = THINK.hash(item.name);
cls = item.name;
THINK_CACHES.Middleware[tempName] = item.name;
} else {
//内部中间件
tempName = item.name;
cls = item.name;
}
//挂载中间件链
if (cls) {
THINK_CACHES.HOOK[item.type] || (THINK_CACHES.HOOK[item.type] = []);
var oriHooks = [].push(tempName);
if (item.append === 'prepend') {
THINK_CACHES.HOOK[item.type] = oriHooks.concat(THINK_CACHES.HOOK[item.type]);
} else {
THINK_CACHES.HOOK[item.type].push(tempName);
}
}
});
};
/**
* flush alias module export
*/
_class.prototype.flushAliasExport = function flushAliasExport(g, type, file) {
g = g || THINK_CACHES.ALIAS_EXPORT;
file && require.cache[file] && delete require.cache[file];
THINK.loadCache(g, type, null);
};
/**
* load files
* @param ext
* @param callback
* @param g
*/
_class.prototype.loadFiles = function loadFiles(ext, callback) {
var g = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
var _ref = [[], [], '', '', ''],
tempDir = _ref[0],
tempType = _ref[1],
tempName = _ref[2],
tempFile = _ref[3];
var _loop = function _loop(type) {
/*eslint-disable no-loop-func */
(function (t) {
ext[t] = ext[t] || [];
ext[t].forEach(function (v) {
if (THINK.isDir(v)) {
try {
tempDir = _fs2.default.readdirSync(v);
} catch (e) {
tempDir = [];
}
tempDir.forEach(function (f) {
tempFile = v + f;
if (THINK.isFile(tempFile) && tempFile.indexOf('.js') === tempFile.length - 3) {
tempName = _path2.default.basename(f, '.js');
tempType = g === '' ? tempName : g + '/' + tempName;
callback(tempType, v + f, type);
}
});
}
});
})(type);
};
for (var type in ext) {
_loop(type);
}
var _ref2 = [null, null, null, null, null];
tempDir = _ref2[0];
tempType = _ref2[1];
tempName = _ref2[2];
tempFile = _ref2[3];
};
/**
* 自动加载框架文件
*/
_class.prototype.loadFramework = function loadFramework() {
var _this = this;
//加载配置
THINK_CACHES.CONF = null; //移除之前的所有配置
THINK_CACHES.CONF = THINK.safeRequire('' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'config.js');
//别名文件
if (THINK.isFile('' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'alias.js')) {
this.loadAlias(THINK.safeRequire('' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'alias.js'));
}
//加载中间件
THINK_CACHES.HOOK || (THINK_CACHES.HOOK = []);
if (THINK.isFile('' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'hook.js')) {
THINK_CACHES.HOOK = THINK.safeRequire('' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'hook.js');
}
//加载多语言
THINK_CACHES.LANGUAGE = {};
this.loadFiles({
'Lang': ['' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Conf' + THINK.sep + 'Lang' + THINK.sep]
}, function (t, f) {
THINK_CACHES.LANGUAGE[t] = THINK_CACHES.LANGUAGE[t] || {};
THINK_CACHES.LANGUAGE[t] = THINK.extend(false, THINK_CACHES.LANGUAGE[t], THINK.safeRequire(f));
});
//加载框架类
this.loadFiles({
'Adapter': ['' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Adapter' + THINK.sep + 'Cache' + THINK.sep, '' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Adapter' + THINK.sep + 'Logs' + THINK.sep, '' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Adapter' + THINK.sep + 'Session' + THINK.sep, '' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Adapter' + THINK.sep + 'Socket' + THINK.sep, '' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Adapter' + THINK.sep + 'Template' + THINK.sep],
'Controller': ['' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Controller' + THINK.sep],
'Middleware': ['' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Middleware' + THINK.sep],
'Service': ['' + THINK.THINK_PATH + THINK.sep + 'lib' + THINK.sep + 'Extension' + THINK.sep + 'Service' + THINK.sep]
}, function (t, f, g) {
var _g, _this$loadAlias;
_this.loadAlias((_this$loadAlias = {}, _this$loadAlias[g] = (_g = {}, _g[t] = f, _g), _this$loadAlias));
});
THINK.log('Load ThinkNode Framework: success', 'THINK');
};
/**
* 加载应用
*/
_class.prototype.loadApp = function loadApp() {
//加载应用函数库
// if (THINK.isFile(`${THINK.APP_PATH}${THINK.sep}Common${THINK.sep}Util${THINK.sep}function.js`)) {
// THINK.safeRequire(`${THINK.APP_PATH}${THINK.sep}Common${THINK.sep}Util${THINK.sep}function.js`);
// }
//加载应用配置
if (THINK.isFile('' + THINK.APP_PATH + THINK.sep + 'Common' + THINK.sep + 'Conf' + THINK.sep + 'config.js')) {
THINK_CACHES.CONF = THINK.extend(false, THINK_CACHES.CONF, THINK.safeRequire('' + THINK.APP_PATH + THINK.sep + 'Common' + THINK.sep + 'Conf' + THINK.sep + 'config.js'));
}
//加载应用自定义路由
if (THINK_CACHES.CONF.url_route_on && THINK.isFile('' + THINK.APP_PATH + THINK.sep + 'Common' + THINK.sep + 'Conf' + THINK.sep + 'route.js')) {
THINK_CACHES.CONF.url_route_rules = THINK.safeRequire('' + THINK.APP_PATH + THINK.sep + 'Common' + THINK.sep + 'Conf' + THINK.sep + 'route.js');
}
//加载应用别名文件
// if (THINK.isFile(`${ THINK.APP_PATH }${THINK.sep}Common${THINK.sep}Conf${THINK.sep}alias.js`)) {
// let appAlias = THINK.safeRequire(`${ THINK.APP_PATH }${THINK.sep}Common${THINK.sep}Conf${THINK.sep}alias.js`);
// for (let n in appAlias) {
// if (THINK.loadCache(THINK_CACHES.ALIAS, n)) {
// THINK.log(`App alias ${appAlias[n]} definition contains a reserved keyword`, 'WARNING');
// delete appAlias[n];
// } else {
// this.flushAliasExport('', n, appAlias[n]);
// }
// }
// this.loadAlias(appAlias);
// }
//加载应用多语言
this.loadFiles({
'Lang': ['' + THINK.APP_PATH + THINK.sep + 'Common' + THINK.sep + 'Conf' + THINK.sep + 'Lang' + THINK.sep]
}, function (t, f) {
THINK_CACHES.LANGUAGE[t] = THINK_CACHES.LANGUAGE[t] || {};
THINK_CACHES.LANGUAGE[t] = THINK.extend(false, THINK_CACHES.LANGUAGE[t], THINK.safeRequire(f));
});
//解析应用模块列表
this.parseMoudleList();
};
/**
* 解析应用模块列表
*/
_class.prototype.parseMoudleList = function parseMoudleList() {
var _this2 = this;
//禁止访问的分组
var denyDirs = THINK_CACHES.CONF.deny_group_list || [];
var groupList = THINK_CACHES.GROUP || [];
var dirs = [],
dList = [];
try {
dirs = _fs2.default.readdirSync(THINK.APP_PATH);
} catch (e) {
dirs = [];
}
if (dirs.length > groupList.length) {
dirs.forEach(function (dir) {
dList.push(dir);
});
}
if (dList.length > 0) {
//并集并去重
var unionSet = new _set2.default([].concat(groupList, dList));
groupList = (0, _from2.default)(unionSet);
}
THINK_CACHES.GROUP = groupList;
//加载模块文件
groupList.map(function (item) {
_this2.loadMoudleFiles(item);
});
//差集
THINK_CACHES.CONF.app_group_list = [].concat(groupList).filter(function (x) {
return denyDirs.indexOf(x) === -1;
}).map(function (s) {
return s.toLowerCase();
});
};
/**
* 加载模块文件
* @param group
*/
_class.prototype.loadMoudleFiles = function loadMoudleFiles(group) {
var _this3 = this;
var list = {
'Controller': ['' + THINK.APP_PATH + THINK.sep + group + THINK.sep + 'Controller' + THINK.sep],
'Middleware': ['' + THINK.APP_PATH + THINK.sep + group + THINK.sep + 'Middleware' + THINK.sep],
'Model': ['' + THINK.APP_PATH + THINK.sep + group + THINK.sep + 'Model' + THINK.sep],
'Service': ['' + THINK.APP_PATH + THINK.sep + group + THINK.sep + 'Service' + THINK.sep]
};
if (group === 'Common') {
list.Adapter = ['' + THINK.APP_PATH + THINK.sep + group + THINK.sep + 'Adapter' + THINK.sep];
}
//加载模块类
this.loadFiles(list, function (t, f, g) {
var _g2, _this3$loadAlias;
_this3.flushAliasExport(g, t, f);
_this3.loadAlias((_this3$loadAlias = {}, _this3$loadAlias[g] = (_g2 = {}, _g2[t] = f, _g2), _this3$loadAlias));
if (g === 'Model') {
_this3.loadAliasModel(t);
}
}, group);
};
/**
* 初始化应用数据模型
*/
_class.prototype.initModel = function initModel() {
var modelCache = THINK.loadCache(THINK_CACHES.MODEL);
if (!THINK.isEmpty(modelCache)) {
var config = {
db_type: THINK_CACHES.CONF.db_type, // 数据库类型,支持mysql,mongo,postgressql
db_host: THINK_CACHES.CONF.db_host, // 服务器地址
db_port: THINK_CACHES.CONF.db_port, // 端口
db_name: THINK_CACHES.CONF.db_name, // 数据库名
db_user: THINK_CACHES.CONF.db_user, // 用户名
db_pwd: THINK_CACHES.CONF.db_pwd, // 密码
db_prefix: THINK_CACHES.CONF.db_prefix, // 数据库表前缀
db_charset: THINK_CACHES.CONF.db_charset, // 数据库编码默认采用utf8
db_nums_per_page: THINK_CACHES.CONF.db_nums_per_page, //查询分页每页显示的条数
db_ext_config: THINK_CACHES.CONF.db_ext_config || {} };
//非调试模式下关闭sql日志
if (!THINK.APP_DEBUG) {
config.db_ext_config.db_log_sql = false;
}
//循环加载模型到collections
var ps = [];
for (var v in modelCache) {
var k = v.endsWith('/') ? null : v;
if (k) {
ps.push(_thinkorm2.default.setCollection(THINK.require(k, 'Model'), config));
}
}
return _promise2.default.all(ps);
}
return _promise2.default.resolve();
};
/**
* debug模式文件重载
*/
_class.prototype.autoReload = function autoReload() {
var _this4 = this;
setInterval(function () {
_this4.loadApp();
}, 2000);
};
/**
* 注册异常处理
*/
_class.prototype.captureError = function captureError() {
process.on('uncaughtException', function (err) {
var msg = err.message;
THINK.log(err, 'ERROR');
if (/EADDRINUSE/.test(msg)) {
process.exit();
}
});
process.on('unhandledRejection', function (err) {
if (THINK.isPrevent(err)) {
return null;
}
if (THINK.isPromise(err)) {
return err.catch(function (e) {
THINK.log(e, 'ERROR');
});
} else {
THINK.log(err, 'ERROR');
return null;
}
});
};
/**
* 运行
*/
_class.prototype.run = function () {
var _ref3 = (0, _asyncToGenerator3.default)(_regenerator2.default.mark(function _callee() {
return _regenerator2.default.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.next = 2;
return this.loadApp();
case 2:
THINK.log('Load App Moudle: success', 'THINK');
//初始化应用模型
_context.next = 5;
return this.initModel().catch(function (e) {
THINK.log('Initialize App Model error: ' + e.stack, 'ERROR');
process.exit();
});
case 5:
THINK.log('Initialize App Model: success', 'THINK');
/***根据配置挂载中间件 start***/
//日志监听
if (THINK.config('log_loged')) {
THINK.middleware('Logs', 'bootstrap');
}
//WebSocket服务
if (THINK.config('use_websocket')) {
THINK.middleware('WebSocket', 'bootstrap');
}
//自定义路由解析
if (THINK.config('url_route_on')) {
THINK.middleware('ParseRoute', 'route_parse');
}
//二级域名路由
if (!THINK.isEmpty(THINK.config('sub_domain'))) {
THINK.middleware('SubDomain', 'route_parse');
}
//多语言url识别
if (THINK.config('multi_lang')) {
THINK.middleware('MultiLang', 'route_parse');
}
//Token表单令牌
if (THINK.config('token_on')) {
THINK.middleware('Token', 'view_filter');
}
/***根据配置挂载中间件 end***/
if (THINK.APP_DEBUG) {
//debug模式
this.autoReload();
} else {
//缓存对象
this.loadAliasExport();
//异常拦截
this.captureError();
}
//加载挂载的中间件
this.loadExMiddleware();
//v8优化
THINK.toFastProperties(THINK);
(0, _freeze2.default)(THINK);
!THINK.APP_DEBUG && THINK.toFastProperties(THINK_CACHES);
//运行应用
return _context.abrupt('return', THINK.App.run());
case 18:
case 'end':
return _context.stop();
}
}
}, _callee, this);
}));
function run() {
return _ref3.apply(this, arguments);
}
return run;
}();
return _class;
}(); /**
*
* @author richen
* @copyright Copyright (c) 2015 - <richenlin(at)gmail.com>
* @license MIT
* @version 15/11/19
*/
exports.default = _class;