astroboy
Version:
Astroboy(阿童木)is a Nodejs SFB(Separation of Front and Back ends) framework, built on koa2.
146 lines • 5.75 kB
JavaScript
;
const glob = require("fast-glob");
const http_1 = require("http");
const lodash = require("lodash");
const Loader_1 = require("../core/Loader");
const Ajv = require('ajv');
const ajv = new Ajv({
coerceTypes: true,
});
function check(data) {
return Object.prototype.toString.call(data) === '[object Object]' && Object.keys(data).length > 0;
}
/**
* 加载所有路由文件
*/
async function loadRouters(rootPath, pattern) {
let routerArr = [];
try {
// 如果通过 ts-node 启动会 resolve index.ts
const indexFile = require.resolve(`${rootPath}/app/routers/index`);
const content = require(indexFile);
if (Array.isArray(content)) {
routerArr = content;
}
}
catch (_err) {
const entries = await glob([`${rootPath}${pattern}`], {
dot: true,
});
entries.forEach(entry => {
routerArr = routerArr.concat(require(entry));
});
}
return routerArr;
}
/**
* 解析老的路由写法
*/
function parseOldRouter(router) {
// 如果第一个参数不是 routerName,则添加空参数名
if (http_1.METHODS.indexOf(router[0].toUpperCase()) > -1) {
router.unshift('');
}
return {
name: router[0],
description: '',
method: Array.isArray(router[1]) ? router[1] : [router[1]],
path: Array.isArray(router[2]) ? router[2] : [router[2]],
controllerName: router[3],
controllerMethods: Array.isArray(router[4]) ? router[4] : [router[4]],
schema: {},
middleware: [],
};
}
/**
* 解析新的路由写法
*/
function parseNewRouter(router) {
const controllerMethods = router.preHandler || [];
if (!router.handler) {
throw new Error(`注册路由失败,handler 不能为空`);
}
const splitArr = router.handler.split(':');
controllerMethods.push(splitArr[1]);
if (!router.method) {
throw new Error(`注册路由失败,method 不能为空`);
}
if (!router.path) {
throw new Error(`注册路由失败,path 不能为空`);
}
return {
name: router.name,
description: router.description || '',
method: Array.isArray(router.method) ? router.method : [router.method],
path: Array.isArray(router.path) ? router.path : [router.path],
controllerName: splitArr[0],
controllerMethods,
schema: router.schema || {},
middleware: router.middleware || [],
};
}
class AstroboyRouterLoader extends Loader_1.Loader {
async load() {
const routerArr = await loadRouters(this.app.ROOT_PATH, this.config.pattern);
const controllers = this.app.controllers;
const middlewares = this.app.middlewares;
const middlewareConfig = this.app.middlewareConfig;
const routers = [];
routerArr.forEach(item => {
const router = Array.isArray(item) ? parseOldRouter(item) : parseNewRouter(item);
router.controller = controllers[router.controllerName];
router.method.forEach((method) => {
if (http_1.METHODS.indexOf(method.toUpperCase()) === -1) {
throw new Error(`注册路由失败,请求方法 ${method} 不是一个标准的 HTTP 请求方法!`);
}
});
for (let i = 0; i < router.middleware.length; i++) {
const middlewareKey = router.middleware[i];
if (!middlewares[middlewareKey]) {
throw new Error(`注册路由失败,中间件 ${middlewareKey} 不存在`);
}
else {
const middlewareOptions = middlewareConfig[middlewareKey] && middlewareConfig[middlewareKey].options;
router.middleware[i] = middlewares[middlewareKey](middlewareOptions, this.app);
}
}
if (!router.controller) {
throw new Error(`注册路由失败,控制器 ${router.controllerName} 未找到!`);
}
if (!lodash.isFunction(router.controller)) {
throw new Error(`注册路由失败,${router.controllerName} 必须是一个类`);
}
const newControllerMethods = [];
if (router.controller.prototype['init']) {
newControllerMethods.push('init');
}
router.controllerMethods.forEach((method) => {
if (!router.controller.prototype[method]) {
throw new Error(`注册路由失败,控制器类 ${router.controllerName} 不存在方法名为 ${method} 的方法!`);
}
else {
const beforeMethod = 'before' + method.slice(0, 1).toUpperCase() + method.slice(1);
if (router.controller.prototype[beforeMethod]) {
newControllerMethods.push(beforeMethod);
}
newControllerMethods.push(method);
}
});
router.controllerMethods = newControllerMethods;
router.compiledSchema = {};
if (check(router.schema.header)) {
router.compiledSchema.header = ajv.compile(router.schema.header);
}
if (check(router.schema.query)) {
router.compiledSchema.query = ajv.compile(router.schema.query);
}
if (check(router.schema.body)) {
router.compiledSchema.body = ajv.compile(router.schema.body);
}
routers.push(router);
});
this.app.routers = routers;
}
}
module.exports = AstroboyRouterLoader;
//# sourceMappingURL=AstroboyRouterLoader.js.map