shelloid
Version:
Simple and secure Node.js web application server.
221 lines (200 loc) • 6.8 kB
JavaScript
/*
Copyright (c) Shelloid Systems LLP. All rights reserved.
The use and distribution terms for this software are covered by the
GNU Lesser General Public License 3.0 (https://www.gnu.org/licenses/lgpl.html)
which can be found in the file LICENSE at the root of this distribution.
By using this software in any fashion, you are agreeing to be bound by
the terms of this license.
You must not remove this notice, or any other, from this software.
*/
var path = require("path");
var fs = require("fs");
var assert = require("assert");
var utils = lib_require("utils");
var obj = lib_require("obj");
exports.installGlobals = function(){
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
};
String.prototype.startsWith = function (str){
return this.indexOf(str) == 0;
};
global.shelloid = {};
global.sh = shelloid;
shelloid.getDBConfig = function(dbname){
return shelloid.serverCtx.appCtx.config.databases[dbname];
}
obj.installGlobals();
sh.require = require("./lib/sys_require.js");//for app code to require Shelloid's node_modules
}
exports.loadAppConfig = function(appCtx){
var suffix = (!appCtx.env || appCtx.env == "") ? ".json" : "." + appCtx.env + ".json";
var configFile = appCtx.basePath + "/config" + suffix;
if(utils.fileExists(configFile)){
var configTxt = fs.readFileSync(configFile, "utf-8");
try{
var config = JSON.parse(configTxt);
}catch(err){
console.log("Error parsing config.json: " + configFile + " : " + err);
process.exit(0);
}
var config = appCtx.config = utils.merge(appCtx.config, config);
assert(config.dirs.data !== undefined);
config.dirs._data = config.dirs.data;//save for later reference
config.dirs.data = utils.joinIfRelative(appCtx.basePath, config.dirs.data);
utils.mkdirIfNotExists(config.dirs.data,
"Data directory: " + config.dirs._data +
"(" + config.dirs.data+ ") does not exist. Trying to create one.");
config.dirs._uploads = config.dirs.uploads;
config.dirs.uploads = utils.joinIfRelative(config.dirs.data, config.dirs.uploads);
utils.mkdirIfNotExists(config.dirs.uploads,
"Uploads directory: " + config.dirs.uploads +
"(" + config.dirs.uploads+ ") does not exist. Trying to create one.");
config.log._file = config.log.file;
config.log.file = utils.joinIfRelative(config.dirs.data, config.log.file);
config.baseUrl = config.proto + "://" + config.domain;
if(!((config.port == 80 && config.proto == "http") &&
(config.port == 443 && config.proto == "https"))){
config.baseUrl = config.baseUrl + ":" + config.port;
}
var dateFormatInt = {"string": 0, "date": 1, "moment": 2};
config.validate.req.dateFormatInt = dateFormatInt[config.validate.req.dateFormat];
config.validate.res.dateFormatInt = dateFormatInt[config.validate.res.dateFormat];
config.dirs._sim = config.dirs.sim;
config.dirs.sim = utils.joinIfRelative(appCtx.basePath, config.dirs.sim);
}else{
if(appCtx.env && appCtx.env != ""){
console.log("Cannot find the configuration file for the environment: " + appCtx.env + ". Exiting.");
process.exit(0);
}else{
console.log("Application config file does not exist. Using defaults");
}
}
}
exports.serverCtx = function(pathParam, envName){
var appBasePath = checkAppBasePath(pathParam);
var packageJsonPath = path.normalize(path.join(__dirname, "/../package.json"));
var packageJson = utils.readJsonFile(packageJsonPath, "Shelloid package.json");
if(utils.isString(packageJson)){
console.log(packageJson);//this is an error string
process.exit(0);
}
var appPackageJsonPath = path.normalize(path.join(appBasePath, "/package.json"));
var appPackageJson = utils.readJsonFile(appPackageJsonPath, "Application package.json");
if(utils.isString(appPackageJson)){
console.log(appPackageJson);//this is an error string
process.exit(0);
}
var ctx =
{
packageJsonPath : packageJsonPath,
packageJson: packageJson,
basePath: path.normalize(path.join(__dirname, "/..")),
pools:{
},
appCtx :{
env: envName,
hasErrors: false,
basePath: appBasePath,
packageJsonPath: appPackageJsonPath,
packageJson: appPackageJson,
packageJsonModified: false,
routes: [],
authMods : [],
interfaces: {},
app: null,
folders:{
routes: null,
auth: null,
interfaces:null,
sim: null
},
config: {
viewEngine : "ejs",
dirs : {
routes: "src/routes",
auth: "src/auth",
interfaces: "src/interfaces",
pub: "src/public",
views: "src/views",
data: "data",
uploads: "uploads",
init: "src/init.js",
sim: "src/sim"
},
enableCluster: false,
domain: "localhost",
proto: "http",
port: 8080,
baseUrl: null, //computed dynamically
log:{
file : "shelloid.log", //relative to data dir
level: "verbose"
},
validate:{
req:{
dateFormat: "moment",//moment, date, string
dateFormatInt: 2,//int values for faster runtime processing
//0: string, 1: date, 2: moment
safeStrings: true
},
res: {
dateFormat: "string",
dateFormatInt: 0,
safeStrings : true
}
},
auth:{
prefix: "/auth",
successRedirect: "/home",
failureRedirect: "/",
facebook:{
appId: null,
appSecret: null
},
twitter:{
consumerKey: null,
consumerSecret: null
}
},
session:
{
name: "connect.sid",
secret: "secret",
store : null,/*defaults to in-memory store. else give name of the database*/
},
databases:
{
/*database name =>
{type (mongodb, redis, mysql), host, port, username, password, other params}
*/
}
}
},
};
return ctx;
}
exports.appInit = function(done){
var initJs = utils.joinIfRelative(sh.serverCtx.appCtx.basePath, sh.serverCtx.appCtx.config.dirs.init);
sh.routeCtx = {config: sh.serverCtx.appCtx.config, env: sh.serverCtx.appCtx.env};
if(utils.fileExists(initJs)){
var init = require(initJs);
if(utils.isFunction(init)){
init(sh.routeCtx, done);
}else{
sh.error("The init script " + initJs + " must have a function assigned to module.exports");
process.exit(0);
}
}else{
done();
}
}
function checkAppBasePath(pathParam){
var basePath = path.resolve(pathParam);
if(!utils.dirExists(basePath)){
console.log("The provided path: " + pathParam +
" (resolves to " + basePath + ") is not a directory");
process.exit(0);
}
return basePath;
}