# Koa-quick-service

快速搭建您的KOA网站，帮您管理您的数据库等引擎，同时提供缓存通用规则。

# Files Constructor

- `/src/index.js` 入口文件
- `/src/routes/index.js` 路由首页
- `/configs/dev.js` 配置文件

## Methods

这样调用

```javascript
import {...args} from 'koa-quick-service';
````

`args`参数列表

- `ReDIS` redis引擎类
- `MySQL` mysql引擎类
- `URI` 自定义路由规则对象
- `CACHE` 自定义缓存规则对象
- `EngineProcess` 运行进程引擎类
- `Convert` koa-convert对象
- `Secret` 加密算法类
- `Dictionary` 字典类
- `App` 全局应用对象
- `PostBody` koa-better-body组件中间件
- `LOG` console变形 属性有：`error` `success` `info` `warn` `notice` `send`

## /src/index.js

```javascript
import { App } from 'koa-quick-service';
import RoutePage from './routes';
import * as DEV from '../configs/dev';

App.setNativeConfigs('dev', DEV);
App.createNativeService(RoutePage);
```

## /src/routes/index.js

```javascript
import Router from 'koa-router';
const route = new Router();
export default route;

route.get('/', async ctx => {
    ctx.cast(200);
});
```

## /configs/dev.js

```javascript
import { ReDIS, MySQL } from 'koa-quick-service';
import path from 'path';

export default {
    "ip": "0.0.0.0",
    "port": 8271,
    "logger": true,
    "cors": true,
    "secret": "root",
    "db": {
        "mysql": {
            "constructor": MySQL,
            "namespace": {
                "local": {
                    "host": "127.0.0.1",
                    "user": "root",
                    "password": "123456",
                    "database": "database"
                }
            }
        },
        "redis": {
            "constructor": ReDIS,
            "default": "redis:local",
            "namespace": {
                "local": {}
            }
        }
    },
    "static": {
        "/web": path.resolve(__dirname, '..', 'web')
    },
    "cookie": {
        "key": "web",
        "value": "component"
    }
}
```

# Package.json 

增加：

```json
"scripts": {
   "dev": "NODE_ENV=dev babel-node src/index.js",
   "build": "rm -rf build/ && babel src -d build",
   "start": "NODE_ENV=production pm2 start build/index.js -i max",
   "stop": "pm2 stop build/index.js",
   "restart": "NODE_ENV=production pm2 restart build/index.js"
}
```

# .babelrc

生成一个这样的文件

```json
{
    "presets": ["es2015", "stage-0" ],
    "plugins": [ "add-module-exports", "transform-runtime" ]
}
```

# EngineProcess

```javascript
import Router from 'koa-router';
import { EngineProcess, PostBody } from 'koa-quick-service';
const route = new Router();
export default route;

route.post('/', PostBody(), async ctx => {
    const engine = new EngineProcess();
    const name = ctx.form.name;
    
    engine.on('error', err => {
        console.log(err);
    });
    
    const engines = await engine.create('mysql:local', 'redis:local');
    ctx.cast(await engine.tryCatch(async (mysql, redis) => {
        const result = await mysql.query(`Select * from member`);
        await redis.hmset(name, result);
        return result;
    }, engines));
});
```

或者你可以这样用：

```javascript
import Router from 'koa-router';
import { EngineProcess, PostBody } from 'koa-quick-service';
const route = new Router();
export default route;

route.post('/', PostBody(), async ctx => {
    const name = ctx.form.name;
    ctx.cast(await EngineProcess.create(['mysql:local', 'redis:local'], async (mysql, redis) => {
        const result = await mysql.query(`Select * from member`);
        await redis.hmset(name, result);
        return result;
    }));
});
```

# Cache

定义一个缓存

```javascript
// cache.js
import { CACHE, URI } from 'koa-quick-service';
URI.setDomain('Web', 'http://u51.com');
URI.set('Web:UserInfo', '/user/:id(\\d+)');

// 缓存名必须与资源名相同
CACHE.define('Web:UserInfo', async (CREATE, params) => {
    const mysql = CREATE('mysql:local');
    return await mysql.query(`Select * from member where uid=?`, [params.uid]);
});
```

然后在启动文件中应用即可

```javascript
import { App } from 'koa-quick-service';
import RoutePage from './routes';
import * as DEV from '../configs/dev';
import './cache'; // 注册这个文件

App.setNativeConfigs('dev', DEV);
App.createNativeService(RoutePage);
```

调用这个缓存

```javascript
import Router from 'koa-router';
import { EngineProcess, PostBody, CACHE } from 'koa-quick-service';
const route = new Router();
export default route;

route.post('/', PostBody(), async ctx => {
    // 使用CACHE与EngineProcess相连
    const engine = new EngineProcess(CACHE);
    const id = ctx.form.id;
    
    engine.on('error', err => {
        console.log(err);
    });
    
    ctx.cast(await engine.tryCatch(async () => {
        return await CACHE.load('Web:UserInfo', {
            uid: id
        });
    }));
});
```

重新编译这个缓存

```javascript
import Router from 'koa-router';
import { EngineProcess, PostBody, CACHE } from 'koa-quick-service';
const route = new Router();
export default route;

route.post('/', PostBody(), async ctx => {
    // 使用CACHE与EngineProcess相连
    const engine = new EngineProcess(CACHE);
    const id = ctx.form.id;
    
    engine.on('error', err => {
        console.log(err);
    });
    
    ctx.cast(await engine.tryCatch(async () => {
        return await CACHE.build('Web:UserInfo', {
            uid: id
        });
    }));
});
```

# Events

框架具有非常多的事件来分配处理各个阶段，下面我将按照执行顺序逐个介绍。

> 需要注意的是，App这个对象的emit已成为一个可以async化的异步转同步方法，即 `await App.emit(event)`;

## Event:error

错误处理事件。

如果预先定义了错误处理事件，那么将替换掉系统的错误处理方法。

```javascript
App.on('error', async (err, ctx) => {
    // do something else.
})
```

## Event:beforeSetNativeDatabase

在框架将数据库类或者基础类注入到内部前执行。

```javascript
App.on('beforeSetNativeDatabase', async () => {
    // do something else.
})
```

## Event:beforeSetStaticResource

在路由对静态资源配置前执行。

```javascript
App.on('beforeSetStaticResource', async () => {
    // do something else.
})
```

## Event:beforeSetLoggerAndCors

在处理是否允许logger和跨域前执行。

```javascript
App.on('beforeSetLoggerAndCors', async () => {
    // do something else.
})
```

## Event:beforeSetCookie

在进行cookie模式开启前执行。

```javascript
App.on('beforeSetCookie', async () => {
    // do something else.
})
```

## Event:beforeSetNativeMiddleWares

在设置路由通用中间件前执行。

```javascript
App.on('beforeSetNativeMiddleWares', async () => {
    // do something else.
})
```

## Event:beforeStartInjectRouters

在设定业务路由前执行。

```javascript
App.on('beforeStartInjectRouters', async () => {
    // do something else.
})
```

## Event:beforeCreateService

在服务启动前执行。

```javascript
App.on('beforeCreateService', async () => {
    // do something else.
})
```

## Event:afterCreateService

在服务启动后执行。

```javascript
App.on('afterCreateService', async () => {
    // do something else.
})
```

# LOG

框架分装类一套带色彩描述的，类似`NPM`的console模式。

## LOG.change(name)

更换基础显示名，基于第一个单词。

```javascript
LOG.change('test');
```

## LOG.[params](...args)

具体输出方法。有这么几种`error` `success` `info` `warn` `notice`

```javascript
LOG.warn('1111', {}, 2, new Date, new Buffer());
```

## LOG.send(type, color, args)

- `type` {String} 第二个单词名
- `color` {Number} 色值，基于`cli-color`组件的色值
- `args` {Array} 输出参数集合

```javascript
LOG.send('miox', 32, ['a', 1, 2, {}]);
```