UNPKG

jweb

Version:

A typeScript httpServer support annotation

199 lines (198 loc) 7.96 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const Path = require("path"); const jbean_1 = require("jbean"); const application_1 = require("../application"); const base_1 = require("../base"); function Controller(path) { return jbean_1.annotationHelper(arguments, controllerCallback); } exports.Controller = Controller; function Get(path) { return jbean_1.annotationHelper(['GET', path], methodCallback); } exports.Get = Get; function Post(path) { return jbean_1.annotationHelper(['POST', path], methodCallback); } exports.Post = Post; function Put(path) { return jbean_1.annotationHelper(['PUT', path], methodCallback); } exports.Put = Put; function Patch(path) { return jbean_1.annotationHelper(['PATCH', path], methodCallback); } exports.Patch = Patch; function Options(path) { return jbean_1.annotationHelper(['OPTIONS', path], methodCallback); } exports.Options = Options; const controllerCallback = function (annoType, ctor, path) { controllers.push(ctor); addAnno(ctor, path); }; const methodCallback = function (annoType, target, method, descriptor, requestMethod, path) { addAnno(target, path, method, requestMethod, true); }; const URL_PATH_TRIM = /^\/*|\/*$/g; const URL_END_PATH_TRIM = /\/*$/g; const controllerMetas = {}; const controllers = []; const addAnno = function (target, path, method, requestMethod, requestMapping) { let ctor = target; if (typeof target === 'object') { ctor = target.constructor; } let ctorId = ctor[jbean_1.CTOR_ID]; if (typeof controllerMetas[ctorId] === 'undefined') { controllerMetas[ctorId] = { ctor: ctor, methods: [], path: '' }; } let metas = controllerMetas[ctorId]; if (!method) { metas.path = '/' + (path || '').replace(URL_PATH_TRIM, ''); metas.path = (metas.path === '/') ? metas.path : (metas.path + '/'); } else { metas.methods.push({ target: target, method: method, requestMethod: requestMethod, subPath: (path || '').replace(URL_PATH_TRIM, ''), requestMapping: requestMapping }); } }; jbean_1.BeanFactory.registerInitBean(() => { controllers.forEach((controller) => { jbean_1.ReflectHelper.resetClass(controller); }); }); const controllerIns = {}; const TEMPLATE_DIR_NAME = 'template'; const LAYOUT_DIR_NAME = 'layout'; exports.TPL_DIR_KEY = '$__tplDir'; exports.LAYOUT_DIR_KEY = '$__layoutDir'; exports.EXT_KEY = '$__tplExt'; exports.METHOD_KEY = '$__method'; const addTemplateDir = function (ctor, ins) { if (typeof ctor[exports.METHOD_KEY] === 'undefined') { const application = application_1.default.getIns(); let controllerPath = ctor[jbean_1.CTOR_JWEB_FILE_KEY].split(application.controllerDir); let viewDir = application.viewDir; if (!Path.isAbsolute(viewDir)) { viewDir = Path.join(application.root, viewDir); } ctor[exports.TPL_DIR_KEY] = viewDir + Path.sep + TEMPLATE_DIR_NAME + Path.sep + controllerPath.pop().replace(URL_PATH_TRIM, '').slice(0, -3).toLowerCase() + Path.sep; ctor[exports.LAYOUT_DIR_KEY] = viewDir + Path.sep + LAYOUT_DIR_NAME + Path.sep; ctor[exports.EXT_KEY] = application.tplExt; } if (typeof ins === 'object' && typeof ins[exports.TPL_DIR_KEY] === 'undefined') { ins[exports.TPL_DIR_KEY] = ctor[exports.TPL_DIR_KEY]; ins[exports.LAYOUT_DIR_KEY] = ctor[exports.LAYOUT_DIR_KEY]; ins[exports.EXT_KEY] = ctor[exports.EXT_KEY]; } }; jbean_1.BeanFactory.registerStartBean(() => { const app = application_1.default.getIns(); if (app.applicationType !== application_1.ApplicationType.web) { return; } Object.values(controllerMetas).forEach(({ ctor, methods, path }) => { methods.forEach(({ target, method, requestMethod, subPath, requestMapping }) => { if (!requestMapping) { return; } const app = application_1.default.getIns(); const supportCors = app.getAppConfigs().cors; const routePath = (path + subPath).replace(URL_END_PATH_TRIM, '') || '/'; app.route({ method: requestMethod, path: routePath, handler: (request, h) => __awaiter(void 0, void 0, void 0, function* () { return new Promise(function (resolve, reject) { doRequest(ctor, target, app, request, h, supportCors, method); }); }) }); }); }); }); const doRequest = function (ctor, target, app, request, h, supportCors, method) { return __awaiter(this, void 0, void 0, function* () { const req = new base_1.Request(request, h); const res = new base_1.Response(request, h); if (supportCors) { res.setHeader('Access-Control-Allow-Credentials', true); res.setHeader('Access-Control-Allow-Origin', request.headers.origin || '*'); res.setHeader('Access-Control-Allow-Headers', '*, X-Requested-With, Content-Type'); res.setHeader('Access-Control-Allow-Methods', request.method); res.setHeader('Access-Control-Max-Age', 86400); res.setHeader('Access-Control-Expose-Headers', 'WWW-Authenticate,Server-Authorization'); } let ins = target; if (typeof target !== 'function') { if (jbean_1.checkSupportTransition(ctor, method)) { ins = new ctor(); jbean_1.BeanFactory.genRequestId(ins); } else { if (typeof controllerIns[ctor[jbean_1.CTOR_ID]] === 'undefined') { controllerIns[ctor[jbean_1.CTOR_ID]] = new ctor(); } ins = controllerIns[ctor[jbean_1.CTOR_ID]]; } addTemplateDir(ctor, ins); } const requestId = jbean_1.BeanFactory.getRequestId(ins); ins[exports.METHOD_KEY] = method.toLowerCase(); let params = [req, res]; if (request.params && Object.keys(request.params).length > 0) { params.push(request.params); } try { if (requestId) { yield jbean_1.emitBegin(requestId); } res.type('text/html'); const ret = yield ins[method](...params); if (requestId) { yield jbean_1.emitCommit(requestId); } if (ret === null) { /** done nothing, cause res is solved by annotation which returns null*/ res.flush(); } else { res.writeAndFlush(ret); // resolve() } if (requestId) { yield jbean_1.BeanFactory.releaseBeans(requestId); } } catch (e) { if (requestId) { yield jbean_1.emitRollback(requestId); yield jbean_1.BeanFactory.releaseBeans(requestId); } app.emit(application_1.AppErrorEvent.REQUEST, e); res.error('Internal Server Error'); } }); };