@sustain/core
Version:
Sustain is a Framework that is barely used despedcies to make stable and sustainable apps
257 lines • 12.4 kB
JavaScript
;
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