tsunamy
Version:
A new typesript framework
229 lines (228 loc) • 12.1 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());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var Router_1 = require("./Router");
var Log_1 = require("./Log");
var fs_1 = __importDefault(require("fs"));
var https_1 = __importDefault(require("https"));
var http_1 = __importDefault(require("http"));
var http_status_1 = require("./http-status");
var MimeTypes = {
html: 'text/html',
jpeg: 'image/jpeg',
jpg: 'image/jpeg',
png: 'image/png',
js: 'text/javascript',
css: 'text/css'
};
var Server = /** @class */ (function () {
function Server() {
}
Server.prototype.bootstrapModule = function (module, CONFIGURATION) {
if (!CONFIGURATION.locale) {
CONFIGURATION.locale = 'en-US';
}
function originIsAuthorized(originsAllowed, originToCheck) {
if (typeof originToCheck === 'string') {
return originsAllowed.includes(originToCheck);
}
else {
for (var _i = 0, originToCheck_1 = originToCheck; _i < originToCheck_1.length; _i++) {
var origin_1 = originToCheck_1[_i];
if (originsAllowed.includes(origin_1)) {
return true;
}
}
return false;
}
}
function app(req, res) {
var _this = this;
var bodyChunk = [];
var body;
req.on('error', function (err) {
console.error(err);
}).on('data', function (chunk) {
bodyChunk.push(chunk);
}).on('end', function () { return __awaiter(_this, void 0, void 0, function () {
var originsAllowed, originHeader, isAuthorized, methods, headers, methodsAllowed, headersAllowed, route, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
originsAllowed = CONFIGURATION.allowOrigins || [];
originHeader = req.headers.origin;
isAuthorized = originHeader && originIsAuthorized(originsAllowed, originHeader);
if (originHeader && isAuthorized) {
res.setHeader('Access-Control-Allow-Origin', originHeader);
}
if (!(req.method === 'OPTIONS')) return [3 /*break*/, 1];
// Safari (and potentially other browsers) need content-length 0,
// for 204 or they just hang waiting for a body
Log_1.Log.info('(Pre-flight request) Call : ' + req.method + ' ' + req.url);
if (isAuthorized) {
methods = CONFIGURATION.allowMethods || [];
headers = CONFIGURATION.allowHeaders || [];
methodsAllowed = 'PUT,GET,POST,DELETE' + (methods.length > 0 ? ',' + methods.toString() : '');
headersAllowed = headers.length > 0 ? headers.toString() : '*';
res.setHeader('Access-Control-Allow-Methods', methodsAllowed);
res.setHeader('Access-Control-Allow-Headers', headersAllowed);
res.setHeader('Content-Length', '0');
res.statusCode = http_status_1.HttpStatus.OK.getCode();
res.end();
}
else {
Log_1.Log.err('(Pre-flight request) Origin ' + originHeader + ' unknown');
res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode();
res.end();
}
return [3 /*break*/, 4];
case 1:
body = JSON.parse(Buffer.concat(bodyChunk).toString() || '{}');
route = Router_1.Router.resolve(req.url, req.method);
if (!!route.error) return [3 /*break*/, 3];
if (route.isStaticFile) { // If static files
serveStaticFiles(req, res);
return [2 /*return*/];
}
Log_1.Log.info('Call : ' + req.method + ' ' + req.url);
return [4 /*yield*/, Router_1.Router.executeRouteFunction(req, res, route.urlParam, route.queryParam, body, route.function, route.controllerInstance)];
case 2:
result = _a.sent();
serveResponse(result, res);
return [2 /*return*/];
case 3:
backError(route, res);
_a.label = 4;
case 4: return [2 /*return*/];
}
});
}); });
}
function backError(route, res) {
var error = route.error;
if (error) {
if (route.message) {
if (typeof error === 'number') {
res.statusCode = error;
res.end(error + ' ' + route.message);
}
else {
Log_1.Log.err('Status code type is incorrect');
res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode();
Log_1.Log.info('Response Code : ' + res.statusCode);
res.end(http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
}
}
else {
Log_1.Log.info('Response Code : ' + error);
var httpStatus = http_status_1.HttpStatus.getValueOf(error);
if (httpStatus) {
res.statusCode = httpStatus.getCode();
res.end(httpStatus.getReasonPhrase());
}
else {
res.statusCode = error;
res.end(error + ' Error');
}
}
}
}
function serveStaticFiles(req, res) {
var urlDecoded = decodeURIComponent(req.url);
if (urlDecoded === '/') { // default index.html
urlDecoded = '/index.html';
}
var extension = urlDecoded.substring(urlDecoded.lastIndexOf('.') + 1);
if (extension) {
extension = extension.toLowerCase();
}
var mimeType = MimeTypes[extension];
var filename = CONFIGURATION.projectDirectory + '/public' + urlDecoded;
Log_1.Log.info('Serve static files : file name : ' + filename + ' mime type ' + mimeType);
var readStream = fs_1.default.createReadStream(filename);
readStream.on('open', function () {
res.writeHead(http_status_1.HttpStatus.OK.getCode(), mimeType);
readStream.pipe(res);
});
readStream.on('error', function (err) {
if (err.code === 'ENOENT') {
res.statusCode = http_status_1.HttpStatus.NOT_FOUND.getCode();
res.end(http_status_1.HttpStatus.NOT_FOUND.getReasonPhrase());
}
else {
res.statusCode = http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getCode();
res.end(http_status_1.HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
}
});
}
/**
* Fill ServerResponse value from application's returned value
*
* @param result route's returned value
* @param res server response
*/
function serveResponse(result, res) {
Log_1.Log.info('Server result', result);
res.setHeader('Content-Type', 'application/json');
res.statusCode = result.getCode();
res.end(JSON.stringify(result.getBody()));
}
Log_1.Log.setLocale(CONFIGURATION);
Log_1.Log.initLog(CONFIGURATION);
Router_1.Router.setConfig(CONFIGURATION);
if (CONFIGURATION.http) {
this.currentServerHttp = http_1.default.createServer(app);
this.currentServerHttp.listen(CONFIGURATION.httpPort, CONFIGURATION.hostname, function () {
Log_1.Log.info("Tsunamy server running at http://" + CONFIGURATION.hostname + ":" + CONFIGURATION.httpPort + "/");
});
}
if (CONFIGURATION.https) {
var privatekey = fs_1.default.readFileSync(CONFIGURATION.projectDirectory + '/certificate/key.pem', 'utf-8');
var certificate = fs_1.default.readFileSync(CONFIGURATION.projectDirectory + '/certificate/certificate.pem', 'utf-8');
this.currentServerHttps = https_1.default.createServer({ key: privatekey, cert: certificate }, app);
this.currentServerHttps.listen(CONFIGURATION.httpsPort, CONFIGURATION.hostname, function () {
Log_1.Log.info("Tsunamy https server running at https://" + CONFIGURATION.hostname + ":" + CONFIGURATION.httpsPort + "/");
});
}
Log_1.Log.blue(Log_1.Log.logoWithColor());
};
return Server;
}());
exports.Server = Server;