插件系统
=====

为什么koa那么火爆，那么完美？

就是因为他强大的中间件功能。中间件实际上就可以算做一款最简单的插件。我们通过这些一个个的插件，使得我们应用得到**高度定制化**。

因为我们的框架已经进行了一系列的定制化，完成了一些核心功能，那什么东西值得我们用插件来实现呢？


- orm

orm版本很多，各种各样，以及各种乱七八糟的数据库，这些玩意儿一般来说是随着开发人员和项目走的。

所以orm比较适合做成插件


- log日志系统
同样如此，种类繁多的日志系统



类似的，有着各种个样、根据项目不同需求而不同的东西，我们都应该做成插件。


插件实现
===

第一步，在config文件中，新建一个plugin.ts文件
====

```
.
├── dist
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│   ├── app.ts
│   ├── blueprint.ts
│   ├── config
│   │   ├── config.default.ts
│   │   ├── config.dev.ts
│   │   ├── config.pro.ts
│   │   └── plugin.ts    ------->新增
│   ├── controller
│   │   ├── base.ts
│   │   └── user.ts
│   ├── loader.ts
│   └── service
│       └── check.ts
└── tsconfig.json

```


在文件中写上:
```ts
export const orm = {
    enable: true, //用于表示开启和关闭，提供热拔插功能
    packagePath: '../extends/orm' // 插件的路径

}

```

第二步，新建一个extends文件夹，文件夹里新建一个orm.ts
====
```
.
├── dist
├── nodemon.json
├── package-lock.json
├── package.json
├── src
│   ├── app.ts
│   ├── blueprint.ts
│   ├── config
│   │   ├── config.default.ts
│   │   ├── config.dev.ts
│   │   ├── config.pro.ts
│   │   └── plugin.ts
│   ├── controller
│   │   ├── base.ts
│   │   └── user.ts
│   ├── extends   ----->插件目录
│   │   └── orm.ts   ----->第一个插件
│   ├── loader.ts
│   └── service
│       └── check.ts
└── tsconfig.json

```


orm.ts文件中
````ts
export default (app: any) => {

}
````
插件的实现一定要非常切合我们的框架设计，在整个应用生命周期中，我们的插件应该绑定在一个全局唯一，并且哪里都可以用到的实例上，那就是框架的app实例了。


也就是：
```ts
const app = new burn;
```

在这个实例上，我们可以
- 挂载，拓展app实例
- 拓展请求级别context对象

所以，我们传给插件的就是全局唯一的app对象


第三步，实现一个loadplugin
====

```ts
//loader.ts

  loadPlugin() {
        const pluginModule = require(__dirname + '/config/plugin.js');
        Object.keys(pluginModule).forEach((key) => {
            pluginModule[key];
            if (pluginModule[key].enable) { //判断是否开启
                const plugin = require(pluginModule[key].packagePath);
                plugin(this.app);
            }
        })
    }

```

在这里我们讲插件导出，然后执行导出的插件，至于插件到底干什么，我们就完全不care了。


第四步，实现plugin的逻辑
=====
回到/extends/orm.ts文件

我们使用Sequelize来作为我们的orm，mysql作为我们的数据库

```
npm install --save sequelize

```

```ts
///extends/orm.ts
import { Sequelize } from 'sequelize';

export default (app: any) => {
    app.Sequelize = new Sequelize(...,....);
}

```

通过这样我们就可以绑定Sequelize实例，在app上了。


第五步，愉快的使用Sequelize
====

在我们的service和controller中，我们这么去使用

````ts
class One extends Controller{
    async index(){
        this.app.Sequelize.define(...)......
    }

}

class Svs extends Service{
    async index(){
        this.app.Sequelize.define(...)......
    }

}

````



