yahoi
Version:
Yet Another Highly Opinionated Isomorphic Framework
265 lines (208 loc) • 8.79 kB
JavaScript
import './conditional-babel-polyfill';
import express from 'express';
import readdir from 'readdir';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import compression from 'compression';
const ENVIRONMENT_PATH = "Environments/";
const ROUTERS_PATH = "Routing/";
const Controller_PATH = "Controller/";
const Services_PATH = "Services/";
import path from 'path';
import ErrorController from './../Controller/ErrorController';
import TranslationController from './../Controller/TranslationController';
export default class Server {
constructor(props) {
this.__props = props;
this.__environment = this.loadEnvironment(props.env);
this.__services = this.loadServices(props.env);
this.__controller = this.loadController(props.env);
// Default Error Controller
let defaultErrorController = new ErrorController({ app: this } );
defaultErrorController.setViewDirectory(path.resolve(__dirname, '..', 'Views'));
defaultErrorController.setProjectDirectory(path.resolve(__dirname, '..'));
defaultErrorController.setComponentDirectory(path.resolve(__dirname, '..', 'Components'));
defaultErrorController.setContainerDirectory(path.resolve(__dirname, '..', 'Containers'));
this.__controller['__defaultErrorController'] = defaultErrorController;
// Default Translation Controller
let defaultTranslationController = new TranslationController({ app: this } );
defaultTranslationController.setViewDirectory(path.resolve(__dirname, '..', 'Views'));
defaultTranslationController.setProjectDirectory(path.resolve(__dirname, '..'));
defaultTranslationController.setComponentDirectory(path.resolve(__dirname, '..', 'Components'));
defaultTranslationController.setContainerDirectory(path.resolve(__dirname, '..', 'Containers'));
this.__controller['DefaultTranslation'] = defaultTranslationController;
this.__routers = this.loadRouters(props.env);
this.__expressApp = express();
this.__expressApp.use(bodyParser.urlencoded({ extended: true }));
this.__expressApp.use(bodyParser.json())
this.__expressApp.use(cookieParser())
this.getController = this.getController.bind(this);
this.__defaultRouter = new (this.__routers['Default'])({ app: this });
this.__defaultRouter.addRoute({ path: '/Translations', router: 'DefaultTranslation' });
if(typeof(process.env.NODE_ENV)!='undefined' && process.env.NODE_ENV=='development') {
// Development
let enableHmrMidWare = require('./dev/expressMiddleware.js');
enableHmrMidWare(this, this.__expressApp);
} else {
// Production
this.__expressApp.use(compression());
}
}
getDefaultRouter() {
return this.__defaultRouter;
}
getController(name) {
if(typeof(this.__controller[name])=='undefined') {
throw Error(`Controller could not be found: ${name}`);
}
return this.__controller[name];
}
getService(name) {
return this.__services[name];
}
loadRouters() {
try {
let routers = {};
readdir.readSync(`${this.getProjectPath()}/${ROUTERS_PATH}`).map(routerFile => {
if(routerFile.indexOf('.js')>0) {
let routerName = routerFile.substr(0, routerFile.length-9);
routers[routerName] = require(`${this.getProjectPath()}/${ROUTERS_PATH}${routerFile}`).default;
}
});
// build-in
readdir.readSync(`${__dirname}/../Routing`).map(routerFile => {
if(routerFile.indexOf('.js')>0) {
let routerName = routerFile.substr(0, routerFile.length-9);
routers[routerName] = require(`${__dirname}/../Routing/${routerFile}`).default;
}
});
// console.log('initialized routers', routers);
return routers;
} catch(e) {
throw e;
}
}
loadController() {
try {
let controller = {};
readdir.readSync(`${this.getProjectPath()}/${Controller_PATH}`).map(controllerFile => {
if(controllerFile.indexOf('Controller.js')>0) {
let cntrlName = controllerFile.substr(0, controllerFile.length-13);
let controllerObj = new (require(`${this.getProjectPath()}/${Controller_PATH}${controllerFile}`).default)( { app: this });
controllerObj.setViewDirectory(path.resolve(this.getProjectPath(), 'Views'));
controllerObj.setProjectDirectory(this.getProjectPath());
controllerObj.setComponentDirectory(path.resolve(this.getProjectPath(), 'Components'));
controllerObj.setContainerDirectory(path.resolve(this.getProjectPath(), 'Containers'));
controller[cntrlName] = controllerObj
}
});
return controller;
} catch(e) {
throw e;
}
}
loadServices() {
try {
let services = {};
readdir.readSync(`${this.getProjectPath()}/${Services_PATH}`).map(serviceFile => {
if(serviceFile.indexOf('Service.js')>0) {
let serviceName = serviceFile.substr(0, serviceFile.length-10);
let serviceObj = new (require(`${this.getProjectPath()}/${Services_PATH}${serviceFile}`).default)( { app: this });
// controllerObj.setViewDirectory(path.resolve(this.getProjectPath(), 'Views'));
serviceObj.setProjectDirectory(this.getProjectPath());
serviceObj.setComponentDirectory(path.resolve(this.getProjectPath(), 'Components'));
serviceObj.setContainerDirectory(path.resolve(this.getProjectPath(), 'Containers'));
services[serviceName] = serviceObj;
}
});
return services;
} catch(e) {
throw e;
}
}
createRouter(name, props) {
if(typeof(this.__routers[name])=='undefined') {
throw Error(`Router ${name} not found`);
}
return new (this.__routers[name])(props);
}
getProjectPath() {
return this.__props.projectPath;
}
getEnvironment() {
return this.__environment;
}
loadEnvironment(name) {
try {
return require(`${this.getProjectPath()}/${ENVIRONMENT_PATH}${name}`).default;
} catch(e) {
throw e;
}
}
start() {
this.__expressApp.use('/Public', express.static(`${this.getProjectPath()}/Public`))
/*
this.__expressApp.use('/Translations/get', (req, res) => {
this.getController('__defaultTranslationController')
.renderAction('get', req, res)
.then(actionContext => {
try {
actionContext.getResponse().respond(req, res);
} catch(e) {
res.send('[1] Internal Server Error: ' + String(e));
}
})
.catch(e => {
res.send('[2] Internal Server Error: ' + String(e));
})
})
*/
//this.__expressApp.use('/Translations', express.static(`${this.getProjectPath()}/Translations`))
this.__expressApp.all("*", (req, res) => {
let matchResult = this.getDefaultRouter().match(req);
if(matchResult) {
matchResult.route.renderAction(req, res, matchResult).then(actionContext => {
try {
actionContext.getResponse().respond(req, res);
} catch(e) {
res.send('Error: ' + String(e));
}
}).catch(e => {
req.query = {
error: e,
controllerName: matchResult.route.getControllerName(),
actionName: matchResult.route.getActionName()
}
this.getController('__defaultErrorController')
.renderAction('actionError', req, res)
.then(actionContext => {
try {
actionContext.getResponse().respond(req, res);
} catch(e) {
res.send('[1] Internal Server Error: ' + String(e));
}
})
.catch(e => {
res.send('[2] Internal Server Error: ' + String(e));
})
});
} else {
this.getController('__defaultErrorController').renderAction('noRoute', req, res).then(actionContext => {
try {
actionContext.getResponse().respond(req, res);
} catch(e) {
console.log('Internal Server Error:', e);
res.send('Internal Server Error: ' + String(e));
}
}).catch(e => {
console.log('renderedError', e);
});
}
})
this.__expressApp.listen(this.getEnvironment().server.port, () => {
console.log(`Server started: ${process.env.NODE_ENV}`);
console.log('Project Path: ', this.getProjectPath());
console.log('Port: ', this.getEnvironment().server.port);
})
}
}