UNPKG

thinknode

Version:

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

734 lines (607 loc) 26.4 kB
'use strict'; 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;