UNPKG

kcola

Version:

一个基于koa2,小而美的RESTful API+MVC的web开发框架!

142 lines (127 loc) 3.6 kB
const Koa = require('koa'); const onerror = require('koa-onerror'); const lib = require('./lib'); const isGeneratorFunction = require('is-generator-function'); const convert = require('koa-convert'); const defaultConfig = { publicDir: '', // 访问静态资源目录 routeDir: '', // 存放route文件目录 ctrlDir: '', // 存放controller文件目录 appConfigPath: '', // 框架配置文件地址 middlewareOpts: {}, // 中间件配置参数 }; const coreMiddlewarePosTable = { 'koa-sslify': '0', 'spa': '1', 'koa-static': '2', 'koa-body': '3', 'koa-router': '-1', 'koa-router-allowed-methods': '-2', 'koa-json': '-3', }; /** * * * @class Kcola * @extends {Koa} */ class Kcola extends Koa { /** *Creates an instance of Kcola. * @param {*} workDir 工程启动目录 * @param {*} config * @memberof Kcola */ constructor(workDir, config = {}) { global.__kcola_workdir = workDir; super(); this.mwCount = 0; this.mwPosTable = []; this.mwScope = { start: null, end: null, }; config = Object.assign(defaultConfig, config); lib(config, this); onerror(this); this.use(require('koa-json')(), 'koa-json'); } /** * 重写koa use方法 * 保证中间件的顺序 * @param {function} fn * @param {number} pos 指定中间件的位置 * @return {Kcola} * @memberof Kcola */ use(fn, pos) { if (typeof fn !== 'function') throw new TypeError('middleware must be a function!'); if (isGeneratorFunction(fn)) { fn = convert(fn); } let mwname = ''; // 处理内部核心中间件,减少外部修改参数的可能 if (typeof pos === 'string') { mwname = pos; let cpos = coreMiddlewarePosTable[mwname]; if (!cpos) { throw new Error('Invalid parameter: type check failed for parameter "pos". Expected Number'); } cpos = parseInt(cpos, 10); // pos为undefined时插入到最后 // 还有pos为负数的情况也需要放置到最后 // 因为可以配置一些系统的中间件是可以跳过,故需要处理pos值进行重新赋值 if (cpos < 0 || this.middleware.length < cpos + 1) { pos = this.middleware.length; } else { pos = cpos; } if (this.mwScope.start === null) { this.mwScope.start = pos; } // cpos < 0 表示找到最后一个节点标志 if (cpos < 0 && this.mwScope.end === null) { this.mwScope.end = pos; } } else { // 非系统组件做索引转换,使调用无感知 // 确定范围,在范围内增删 const startIndex = this.mwScope.start || 0; const endIndex = this.mwScope.end || this.middleware.length; if (typeof pos === 'undefined') { pos = endIndex; } if (pos < startIndex) { pos = startIndex + pos; } if (pos > endIndex) { pos = endIndex - 1; } if (this.mwScope.end !== null) { this.mwScope.end++; } } this.middleware.splice(pos, 0, fn); fn['mwname'] = mwname || `mw-${pos}`; console.log('middleware record:', this.middleware.map((mw) => mw.mwname)); return this; } /** * * 加载中间件 * @param { Object } middleware * @memberof Kcola */ loadMiddleware(middleware) { const middlewares = []; if (!Array.isArray(middleware)) { middlewares.push(middleware); } middlewares.forEach((m, i) => { if (typeof m.fn === 'function') { this.use(m.fn(m.opts)); } }); } } module.exports = Kcola;