koa-springboot
Version:
springboot-like koa
138 lines (137 loc) • 5.73 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const errors_1 = require("./errors");
const constants_1 = require("./constants");
function prefixSlash(str) {
return str.startsWith('/') ? str : `/${str}`;
}
function getParams(actionParams, ctx) {
const ret = [];
(actionParams || []).forEach(actionParam => {
if (actionParam.type === 'PathVariable') {
ret[actionParam.index] = ctx.params[actionParam.name];
}
else if (actionParam.type === 'RequestParam') {
ret[actionParam.index] = ctx.query[actionParam.name];
}
else if (actionParam.type === 'RequestBody') {
ret[actionParam.index] = ctx.request.body || ctx.body;
}
if (actionParam.defaultValue !== undefined) {
ret[actionParam.index] = ret[actionParam.index] || actionParam.defaultValue;
}
if (actionParam.required && ret[actionParam.index] === undefined) {
throw new errors_1.ParamError(`param ${actionParam.name} is required`);
}
});
ret.push(ctx);
return ret;
}
function paramsMiddleWare(actionParams, responseType, responseStatus, viewPath) {
return (ctx, next) => __awaiter(this, void 0, void 0, function* () {
try {
ctx.actionParams = getParams(actionParams, ctx);
}
catch (error) {
if (error instanceof errors_1.ParamError) {
ctx.body = JSON.stringify({
code: error.code,
data: error.message
});
return;
}
else {
throw error;
}
}
const ret = yield next();
ctx.status = responseStatus;
if (ret && typeof ret === 'object') {
if (responseType === 'json') {
ctx.set('Content-Type', 'application/json');
ctx.body = JSON.stringify(ret);
}
else {
yield ctx.render(viewPath, ret);
}
}
});
}
function mountSingleRoute(router, baseUrl, routerConfig, controllerInstance, baseResponseType) {
const { method, action, pattern, actionParams, responseType, responseStatus } = routerConfig;
let path = baseUrl === '/' ? pattern : baseUrl + pattern;
if (path.length > 1) {
path = path.replace(/\/$/, '');
}
const rResponseType = responseType || baseResponseType;
const viewPath = `${controllerInstance.constructor.name.toLowerCase()}/${action}`;
router[method](path, paramsMiddleWare(actionParams, rResponseType, responseStatus || constants_1.HttpStatus.OK, viewPath), (ctx) => controllerInstance[action].call(controllerInstance, ...ctx.actionParams));
}
class RouterManager {
constructor() {
this.config = new Map();
}
setRouteConfig(controller, routeConfig) {
const preRouteConfig = this.getRouteConfig(controller, routeConfig.action);
routeConfig.pattern = prefixSlash(routeConfig.pattern || preRouteConfig.pattern || '');
Object.assign(preRouteConfig, routeConfig);
}
setParamVariable(controller, action, config) {
const preRouteConfig = this.getRouteConfig(controller, action);
preRouteConfig.actionParams.push(config);
}
setInjectModel(controller, name, propertyKey) {
const preRouteConfig = this.getControllerConfig(controller);
preRouteConfig.injectModels = preRouteConfig.injectModels || new Map();
preRouteConfig.injectModels.set(propertyKey, name);
}
setControllerConfig(controller, config) {
const controllerConfig = this.getControllerConfig(controller);
Object.assign(controllerConfig, config);
}
getControllerConfig(controller) {
if (!this.config.has(controller)) {
const controllerConfig = {
controller,
baseUrl: '',
routes: [],
responseType: 'template'
};
this.config.set(controller, controllerConfig);
}
return this.config.get(controller);
}
getRouteConfig(controller, action) {
const controllerConfig = this.getControllerConfig(controller);
let ret = controllerConfig.routes.find(r => r.action === action);
if (!ret) {
ret = {
method: constants_1.RequestMethod.ALL,
action,
actionParams: []
};
controllerConfig.routes.push(ret);
}
return ret;
}
mountRoutes(router, models = {}) {
this.config.forEach(({ baseUrl, controller, routes, responseType, injectModels }) => {
const cInstance = new controller();
if (injectModels && injectModels.size > 0) {
injectModels.forEach((propName, modelName) => {
cInstance[propName] = models[modelName];
});
}
routes.forEach(routerConfig => mountSingleRoute(router, baseUrl, routerConfig, cInstance, responseType));
});
}
}
exports.default = new RouterManager();
;