2.0.7 • Published 3 years ago

anchundan v2.0.7

Weekly downloads
148
License
ISC
Repository
github
Last release
3 years ago

鹌鹑蛋 🥚

使用方式 和 eggjs 类似
区别在于插件的设置,简化了插件的配置和使用。 进程管理交给 pm2 .管理 如果你具备一些eggjs ,koa ,的开发经验,以及对sequelize 有相对的了解,可以很轻松的看懂这个份readme 这个框架诞生的目的是为了简化初始化的过程,精简eggjs

npm install anchundan

or

yarn add anchundan

or 
yarn add https://github.com/shinku/anchundan

toc

项目初始化

anchundan-init

目录
├─ src
│ ├─ app
│ ├─ config
│ │ ├─ config.base.js
│ │ ├─ config.dev.js
│ │ ├─ config.pro.js
│ │ ├─ config.uat.js
│ ├─ middleware
│ ├─ modules
│ ├─ plugins
│ ├─ routers
│ │ ├─ index.js
│ ├─ static
│ ├─ controller
│ └─ index.js
├─ application.dev.config.js
├─ application.uat.config.js
├─ application.pro.config.js

启动应用:

yarn start
or
yarn start_uat
or
yarn start_prod

配置文件

/config/config.base.js

这个文件存储基本的配置信息。 其次,dev对应开发环境。uat 对应预发,pro对应 生产环境的配置 配置的相关过程跟eggjs类似。 application.{env}.config.js 对应的是pm2 启动项的配置

监听端口设置

/src/config/config.base.js

module.exports = {
  port:9000
}

新建 controller

//方式与eggjs 一致
/src/controller/index.js

const Controller = require('anchundan').Controller;
class Index extends Controller{
    async start(ctx){
        this.send("hello~",{
          "Content-Type":"text/plain"
        });    
    }
    
}
module.exports = Index;

同时 anchundan.Controller内置了其他一些方法,方便某些场景的调用

  • get/set context 获取/设置 当前的上下文对象,context 是一个KOA 的context 对象。
    this.context.set("X-PATH",this.context.path);
  • send(content,option?)
    this.send("hello~")
  • get request 获取当前的request对象,post的场景下使用
    /// postdata  为 : {userid:"123"}
    let {userid} = this.request.body;
  • get query 获取当前的 query 对象,get 的场景下使用
     /// postdata  为 : {userid:"123"}
    let {userid} = this.query;
  • get params 路由格式类似为 /path/:id/:pagenum 使用
     /// postdata  为 : {userid:"123"}
    let {id,pagenum} = this.params;
  • get services 获取当前应用的所有service 组件时使用
    let userdata = this.services.userdata;
    let result = await userdata.find({where:{userid}});
  • get plugins 获取当前应用的所有application 插件

路由

//结合controller
/src/routers/index.js
module.exports = (router,app)=>{
    let {
        index,
    } = app.controllers;
    router.get(vpath+'/test',index.start);
    router.post(vpath+'/test',index.start);
}

路由增加中间件

const mid = async (ctx,next)=>{
  //do something
  await next();
}
module.exports = (router,app)=>{
    let {
        index,
    } = app.controllers;
    router.get(vpath+'/test',mid,index.start);
    router.post(vpath+'/test',mid,index.start);
}

中间件

  •  创建中间件
    /src/middleware/apiproxy.js
    module.exports =  (config,app)=>{
        return async (ctx,next)=>{
            //console.log("api proxy");
            //dosomething
            //这里可以使用 app 参数获取到 controllers,services,plugins
            let {index} = app.controllers;
            let {plugins,services} = app;
            //
            index.context = ctx;
            await index.start();
            await next();
        }
      }
  •  配置中间件 与eggjs 一致

    /src/config/config.base.js
    
    module.exports = {
      port:9000,
      middlewares:['apiproxy'],
      apiproxy:{
        abc:"test"
      }
    }

    插件

    • context 插件,挂载在context上下文
    • 插件可以是 一个Object 或者一个function
    • PS:如果想通过插件访问到 具体的 context 或者application 内部数据,定义函数插件的时候用 function(){}定义,而不() =>{}

      /src/plugins/sendresult/context.js
      //使用 function abc(){}  的方式新建函数,可以直接使用this 操作当前上下文
      //使用箭头函数无法操作,application 插件类似。
      module.exports =  function (result){
        this.body = result;
        this.set('Content-Type',"html/text");
      }
    • application 插件,挂载在application
      /src/plugins/getfile/application.js
      //使用 function abc(){}  的方式新建函数,可以直接使用this 操作当前上下文
      //使用箭头函数无法操作,application 插件类似。
      module.exports =  function (filepath){
        return fs.readFileSync(filepath);
      }
    • sample
      //方式与eggjs 一致
      /src/controller/index.js
    
      const Controller = require('anchundan').Controller;
      class Index extends Controller{
          async start(ctx){
              let file = this.app.plugins.getfile("/static/index.html");
              this.context.plugins.sendresult(file);
          }
          
      }
      module.exports = Index;

sequelize

anchundan 默认集成 sequelize,并在此基础上做了封装

  • 初始化sequelize 在配置文件中,配置sequelize 关键字

    /src/config/config.base.js
    
    let config  ={
      sequelize:{
          /** 基本配置*/
          host:"localhost",
          username:"root",
          password:"**********",
          database:'DATA_BASE',
          dialect:"mysql",
          port:'3306',
          /**其他配置 */
          options:{
              //开启连接池
              pool:{
                  //开启10个连接池
                  max: 10,
                  idle: 30000
              }
          }
      }
    }
    module.exports = config;
  • 新建module

    /src/modules/user.js
    const { Sequelize, DataTypes, Model } = require('sequelize');
    const SequelizeOperate = require('anchundan').Sequelize;
    class users extends SequelizeOperate{
        init(){
            this.define('users',{
                id:{
                    type:DataTypes.INTEGER,
                    autoIncrement:true,
                    primaryKey:true,
                    allowNull: false,
                    comment:"自增ID"
                },
                userid:{
                    type:DataTypes.STRING(50),
                    comment:"用户ID",
                    allowNull: false,
                },
                pwd:{
                    type:DataTypes.STRING(100),
                    comment:"密码",
                    allowNull: false,
                },
            },{
                comment:"是否有效",
                //增加索引
                indexes:[{
                    unique:true,
                    fields:['userid']
                }]
            });
            this.sync({force:false}).then(_res=>{})
        }
    }
    module.exports = users

    该module 将以插件的形式挂载在application中,如下方式可直接使用,已封装了常规的sequelize 方法 find,count,update,query

    // 在controller 中使用:
    let userdatatable =  this.plugins.sequelize.DB.users;
    let result = await userdatatable.find({where:{userid}});
    result = await userdatatable.count({where:{userid}});
    result = await userdatatable.query("select * from users");
  • module 结合services 使用

    /src/services/users.js
    const ADbService = require("anchundan").Services;
    class users extends ADbService{
       constructor(app) {
          super(app);
          //绑定 users module
          this.tableName = 'users';
      }
      getInfo(userid,...params){
        return this.table.find({where:{userid}},...params)
      }
    }
    module.exports = users;

    之后在controller 中使用services

    let users = this.services.users;
    let data = await users.getInfo(userid);

    通过 service 操作数据的方式更加安全,也存在更好的可读性,并且可以集成除了操作数据库意外的其他方法。
    通过 this.plugins.sequelize.DB[{MODULENAME}] 的方式直接操作sequelize对象,可以更加灵活的操作数据

数据库事务

以在controller中使用为例子

//假设建两个 module,users 和infos,需要通过数据库事务处理数据,并已经通过anchuandan.Services 实例做了绑定
let users =this.services.users;
let infos = this.service.infos;
let sequelize = this.plugins.sequelize.sequelize;
//以plugins.sequelize.sequelize; 获取数据库链接实例
let transaction = await  sequelize.transaction();
try{

  await users.addData({userid},{transaction});
  await infos.addData({userid},{transaction});
  //提交事务
  await transaction.commit();
  //something else
}
catch(e){
  //遇到报错,关闭事务
  await transaction.rollback();
}

跨域

在config 中配置cors属性

/src/config/config.dev.js
let base = require('./config.base')
let config = {
    ...base,
    port:9000,
    
    middlewares:['apiproxy']
    cors:{
        //允许你的域名,http和https需要分别设置
        origins:["http://test.local.com","https://www.anchundan.com"],
        //针对于headers中的:Access-Control-Allow-Headers 字段,已包含:Content-Type,Cookie,Content-Length, Authorization, Accept, X-Requested-With,如想设置允许所有的字段,则 headers为 ”*“,多过定向规定一些其他字段,则用逗号分割,例如:BIZ,Connection,
        headers:"",
        //针对于headers中的 Access-Control-Allow-Methods 字段,默认为 DELETE,PUT,POST,GET,OPTIONS,
        methods:"DELETE,PUT,POST,GET,OPTIONS",
        // 针对于headers中的 Access-Control-Allow-Credentials 字段,默认未空
        credentials:true,

    }
}
module.exports  = config;

启动其他应用

全局的application 中可以捆绑其他服务,比如性能的监听,socket服务等。

src/app/start/ {newapp}.js

module.exports = (application)=>{
    //console.log(application);
    let {config,server} = application;
    //获取到了当前应用的 config 和 koa 应用
    //server 为koa的一个实例,可以直接用server.use(XXX)的方式增加一个新的中间件,但不建议这么处理,
    //中间件的使用方式按照框架约定的方式处理最为安全
    
}

全局错误捕获

全局的报错由 processunhandledRejectionuncaughtException 捕获,并由config.js 配置 handleUncaughtExceptionhandleUncaughtException 配合业务做报错处理

../config.base.js
const config = {

    ....,
   handleUncaughtException:(app,error)=>{
        
        
        //全局未捕获的报错
        //app 为当前application 实例,可以在此调用 applicaation 的插件,例如注册的 log 插件,以下类似
        // app.plugins.logger().info('xxxxx');
    },
    handleUnhandledRejection:(app,error)=>{
       //app 为当前application 实例,可以在此调用 app 的插件。
        //全局未处理的Promise 的rejection 的报错处理
    }
}

增加扩展

// 首先安装扩展
app.addExtension({
  controllers:path.join(__dirname,'./controllers'),
  middlewares:path.join(__dirname,'./middlewares'),
  services:path.join(__dirname,'./services'),
  plugins:path.join(__dirname,'./plugins'),
})
// 启动app
app.startApp();

宏函数

  • getAppPlugins (): Object< string, Object | Function > 获取全局的app 插件
  • getAppPluginByName( pluginname ): Object | Function 根据插件名字获取插件内容
  • getAppConfig(): Object <string, any> 获取当前的应用配置信息
  • getControllers(): Object <string, anchuandan.Controller> 获取所有挂载的Controller字典
  • getServices() : Object <string, anchuandan.Service> 获取所有挂载的Service
2.0.7

3 years ago

2.0.6

3 years ago

2.0.5

3 years ago

2.0.4

3 years ago

2.0.3

3 years ago

2.0.2

3 years ago

2.0.1

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.2

3 years ago

1.0.1

4 years ago

1.0.0

4 years ago