anchundan
Version:
214 lines (206 loc) • 7.39 kB
JavaScript
const path = require('path');
const fs = require('fs');
const {getController} = require('anchundan/src/core/corecontroller');
const {
setPlugins,
initContextPlugins
} = require('anchundan/src/core/coreplugins');
const KOA = require('koa');
//const initRouter = require('../middleware/main');
const {
setMiddleWares,
initCoreMiddleWares
} = require('anchundan/src/core/coremiddleware');
const novalueproxy = require('anchundan/src/core/utils/novalueproxy');
const publiccom = require('./publiccom');
const hookType = require('anchundan/src/core/hooks/hookType');
const FrameworkType = require('anchundan/src/core/baseStruct/FrameworkType');
// addExtension 装饰器,为Application增加扩展方法
// @addExtension
class Application {
constructor(){
if( Application._instance){
throw new Error('Application could not be recrteated');
}
this.isstart = false;
process.on('uncaughtException',(e)=>{
console.log(`uncaughtException -> ${e.message,e.stack.split('\n')}`);
if(this.config && this.config.handleUncaughtException){
this.config.handleUncaughtException.call(null,this,e);
}
});
process.on('unhandledRejection',(e)=>{
console.log(`unhandledRejection -> ${e.message,e.stack.split('\n')}`);
if(this.config && this.config.handleUnhandledRejection){
this.config.handleUnhandledRejection.call(null,this,e);
}
});
}
static getInstance(){
if(!Application._instance){
Application._instance = new Application();
}
return Application._instance;
}
startApp(){
if(this.isstart) return;
this.setPlugins({});
this.server = new KOA();
this.server.use(async (ctx,next)=>{
ctx.set('Re-Path',ctx.path);
await next();
});
this.middlewares = {};
this.loadConfig();
hookType(path.join(process.getRoot(),'./controller'), FrameworkType.CONTROLLER );
hookType(path.join(process.getRoot(),'./controllers'), FrameworkType.CONTROLLER );
hookType(path.join(__dirname,'./controllers'), FrameworkType.CONTROLLER );
this.controllers = getController(this); //加载controllers
hookType(path.join(__dirname,'./plugins'), FrameworkType.PLUGIN );
hookType(path.join(process.getRoot(),'./plugins'), FrameworkType.PLUGIN );
setPlugins(this); //获取插件
initContextPlugins(this); // 实现context插件挂载
// 挂载核心中间件
hookType(path.join(__dirname,'./middleware'), FrameworkType.CORE_MIDDLEWARE );
hookType(path.join(process.getRoot(),'./middleware'), FrameworkType.MIDDLEWARE);
hookType(path.join(process.getRoot(),'./middlewares'), FrameworkType.MIDDLEWARE);
setMiddleWares(this); //加载中间件
initCoreMiddleWares(this)
this.io = null;
//获取controller
this.server.listen(this.config.port, () => {
console.log(`app run at : http://localhost:${this.config.port}`);
});
/**
* 初始化插件
* 加载plugins
* app/start 是用来增加socket 应用而存在的,可以在app/start中增加 脚本,使整个项目和socket 应用整合。
* PS:socket 应用需要增加单独的端口监听,不能和http 公用一个端口。端口的配置可以在config 中自定义的作出配置
*/
const appfunsPath = path.join(process.getRoot(),'app/start');
if(fs.existsSync(appfunsPath))
{
let list = fs.readdirSync(appfunsPath);
list.forEach(_item => {
let fun = require(path.join(appfunsPath,_item));
this.setInit(fun);
});
}
this.isstart = true;
}
addExtensions(extension) {
const {
controllers,
services,
plugins,
middlewares,
config,
routers
} = extension;
if(config) {
hookType(config, FrameworkType.CONFIG);
}
if(controllers) {
hookType(controllers, FrameworkType.CONTROLLER);
}
if(services) {
hookType(services, FrameworkType.SERVICES);
}
if(plugins) {
hookType(plugins, FrameworkType.PLUGIN);
}
if(middlewares) {
hookType(middlewares, FrameworkType.MIDDLEWARE);
}
if(routers) {
hookType(routers, FrameworkType.ROUTER);
}
}
setPlugins(value){
// plugins 是一个
if(!this.plugins){
this.plugins = new Proxy(value,{
get:(target,key)=>{
return target[key];
},
set:(target,key,val)=>{
target[key] = val;
return true;
}
});
}
}
//
setServices(services){
if(!this.services){
this.services =new Proxy(services,{
get:(target,key)=>{
if(target[key]) return target[key];
else return novalueproxy;
}
});
}
}
//
setControllers(value){
if(!this.controllers){
this.controllers = value;
}
}
loadConfig(){
const extensionsConfig = publiccom.getTarget('types')['config'];
let configs = [];
const template_pool = {};
if(extensionsConfig){
extensionsConfig.forEach(configPath => configs.push(
this.appendConfig(configPath)
))
}
configs.push(this.appendConfig(path.join(process.getRoot(),"config")));
this.config = {};
configs.forEach(conf=>{
Object.keys(this.config).forEach(
key => {
if(Array.isArray(this.config[key])){
if(!template_pool[key]) {
template_pool[key] = [];
}
template_pool[key] = template_pool[key].concat(this.config)
}
}
)
this.config = Object.assign(this.config,conf);
})
}
appendConfig(configPath) {
let env = process.env.NODE_ENV || 'dev';
let baseconfig = require(path.join(configPath,'config.base.js'));
let env_config = fs.existsSync(path.join(configPath,'config.'+env+'.js'))
? require(path.join(configPath,'config.'+env+'.js'))
: {};
return {
...baseconfig,
...env_config
}
}
setInit(func){
func.call(null,this);
}
}
let App = Application.getInstance();
publiccom.regTarget('app',App);
module.exports = new Proxy(App,{
get:(target,key)=>{
return target[key] || undefined;
},
set:(target,key,value) => {
//确保application 的属性值不受污染。
if(target.isstart) {
console.warn('new property is not allowed to set in application');
}else{
target[key] = value;
}
return true;
//throw new Error("new property is not allowed to set in application");
}
});