UNPKG

@sustain/core

Version:

Sustain is a Framework that is barely used despedcies to make stable and sustainable apps

257 lines 12.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; 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 }); exports.SustainServer = void 0; const dependency_container_1 = require("./di/dependency-container"); const http_1 = require("http"); const constants_1 = require("./constants"); const querystring = __importStar(require("querystring")); const render_error_pages_helper_1 = require("./helpers/render-error-pages.helper"); const route_params_enum_1 = require("./enums/route-params.enum"); const serveStatic = require('@sustain/serve-static'); const yamlconfig = require('@sustain/config'); const { domain = constants_1.DEFAULT_HOST, port = constants_1.DEFAULT_PORT } = yamlconfig; const mode = process.env.NODE_ENV; class SustainServer { constructor(requests, config) { var _a; this.extensions = []; this.staticFolders = []; this.middleswares = []; this.loadedExtensions = []; this.requests = requests; this.config = config; this.port = ((_a = this.config) === null || _a === void 0 ? void 0 : _a.port) || port; const { extensions = [], staticFolders = [], middleswares = [] } = this.config; this.extensions = this.loadInjectedExtension(extensions); this.staticFolders = staticFolders; this.middleswares = middleswares; this.generateOpenApiSchema(); this.create(); } loadInjectedExtension(extensions) { return extensions.map((extension) => dependency_container_1.InjectedContainer.get(extension)); } nextifyMiddleware(middleware, request, responce) { return new Promise(next => { return middleware(request, responce, next); }); } create() { this.server = http_1.createServer((request, response) => __awaiter(this, void 0, void 0, function* () { var _a; try { this.setPoweredByHeader(response); response.on('finish', () => { this.extensions.forEach((extension) => { if (extension.onResponseEndHook) { extension.onResponseEndHook(request, response); } }); }); this.extensions.forEach((extension) => { if (extension.onResquestStartHook) { extension.onResquestStartHook(request, response); } }); for (const middlesware of this.middleswares) { yield this.nextifyMiddleware(middlesware, request, response); } const route = requestSegmentMatch(this.requests, request); if (route) { if (route.interceptors || ((_a = route.objectHanlder) === null || _a === void 0 ? void 0 : _a.config)) { yield this.executeInterceptor(route, request, response); } const routeParamsHandler = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, route.handler) || {}; const methodArgs = fillMethodsArgs(routeParamsHandler, { request, response, body: request.body }); const controllerOutput = route.objectHanlder[route.functionHandler](...methodArgs); yield this.handleControllerOutput(controllerOutput, response); } else { for (const folder of this.staticFolders) { yield this.nextifyMiddleware(serveStatic(folder.path, folder.option), request, response); } response.statusCode = 404; throw new Error('Not Found'); } } catch (error) { // catch all error; render_error_pages_helper_1.renderErrorPage(response, error); console.error(error); } })) .listen(this.port) .on('listening', () => { console.log('\x1b[32m%s\x1b[0m', ' App is running', `at ${domain}:${this.port} in ${yamlconfig.envId} mode`); console.log(' Press CTRL-C to stop\n'); }); } generateOpenApiSchema() { //generateMethodSpec(this.requests, this.config); } handleControllerOutput(controllerOutput, response) { return __awaiter(this, void 0, void 0, function* () { if (controllerOutput instanceof Promise) { const output = yield controllerOutput; if (typeof output == 'object') { response.writeHead(200, { 'Content-Type': 'application/json' }); response.end(JSON.stringify(output)); } else { response.end(yield output); } } else if (typeof controllerOutput == 'object') { response.writeHead(200, { 'Content-Type': 'application/json' }); response.end(JSON.stringify(controllerOutput)); } else { response.end(String(controllerOutput)); } }); } executeInterceptor(route, request, response) { return __awaiter(this, void 0, void 0, function* () { const callstack = []; if (route.objectHanlder.config && route.objectHanlder.config.interceptors && Array.isArray(route.objectHanlder.config.interceptors)) { // TODO: merge the route and controller inteceptor mecanisme for (let controllerInterceptor of route.objectHanlder.config.interceptors) { const interceptor = dependency_container_1.InjectedContainer.get(controllerInterceptor); const routeParamsHandler = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, interceptor.intercept) || {}; const interception = new Promise(resolve => { const methodArgs = fillMethodsArgs(routeParamsHandler, { request, response, resolve }); if (!interceptor.intercept) { throw new Error('Invalid Interceptor : ' + controllerInterceptor.name); } return interceptor.intercept(...methodArgs); }); callstack.push(interception); } } for (let routeInterceptor of route.interceptors || []) { const interceptor = dependency_container_1.InjectedContainer.get(routeInterceptor); const routeParamsHandler = Reflect.getMetadata(constants_1.ROUTE_ARGS_METADATA, interceptor.intercept) || {}; const interception = new Promise(resolve => { const methodArgs = fillMethodsArgs(routeParamsHandler, { request, response, resolve }); if (!interceptor.intercept) { throw new Error('Invalid Interceptor : ' + routeInterceptor.name); } return interceptor.intercept(...methodArgs); }); callstack.push(interception); } return Promise.all(callstack).catch((e) => { response.end(`${e.message}, ${e.stack} `); throw e; }); }); } setPoweredByHeader(response) { response.setHeader('x-powered-by', 'Sustain Server'); response.setHeader('Access-Control-Allow-Origin', '*'); } } exports.SustainServer = SustainServer; function requestSegmentMatch(requests, request) { return requests[request.method].find((route) => { const requestRouteDetails = route.path.match(request.url.split('?')[0]); if (requestRouteDetails) { request.params = requestRouteDetails.params; return true; } }); } function fillMethodsArgs(routeParamsHandler, assets) { const methodArgs = []; Object.keys(routeParamsHandler).forEach(args => { const [arg_type, arg_index] = args.split(':'); const additionalData = routeParamsHandler[args].data; switch (Number(arg_type)) { case route_params_enum_1.RouteParamtypes.REQUEST: methodArgs[Number(arg_index)] = assets.request; break; case route_params_enum_1.RouteParamtypes.RESPONSE: methodArgs[Number(arg_index)] = assets.response; break; case route_params_enum_1.RouteParamtypes.SESSION: methodArgs[Number(arg_index)] = assets.request.session; break; case route_params_enum_1.RouteParamtypes.HEADERS: methodArgs[Number(arg_index)] = assets.request.headers; break; case route_params_enum_1.RouteParamtypes.BODY: let askedBody; if (additionalData) { askedBody = assets.request.body[additionalData]; } else { askedBody = assets.request.body; } methodArgs[Number(arg_index)] = askedBody; break; case route_params_enum_1.RouteParamtypes.HEADER: let askedHeader; if (additionalData) { askedHeader = assets.request.headers[additionalData]; } else { askedHeader = assets.request.headers; } methodArgs[Number(arg_index)] = askedHeader; break; case route_params_enum_1.RouteParamtypes.PARAMS: methodArgs[Number(arg_index)] = assets.request.params; break; case route_params_enum_1.RouteParamtypes.QUERY: const query = querystring.parse(assets.request.url.split('?')[1]); let askedQuery = {}; if (additionalData) { askedQuery = query[additionalData]; } else { askedQuery = Object.assign({}, query); } methodArgs[Number(arg_index)] = askedQuery; break; case route_params_enum_1.RouteParamtypes.PARAM: methodArgs[Number(arg_index)] = assets.request.params[additionalData]; break; case route_params_enum_1.RouteParamtypes.NEXT: methodArgs[Number(arg_index)] = assets.resolve; break; } }); return methodArgs; } //# sourceMappingURL=server.js.map