<commit_before>/**
 * Module dependencies.
 */
var express = require('express');
var View = require('express/lib/view');
var routes = require('../routes');
var path = require('path');
var swig = require('swig');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var models = require('../models');
var _ = require('underscore');
var configloader = require('./config');
var utils = require('./utils');
var namedroutes = require('./namedroutes');
var util = require('util');
var crypto = require('crypto');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session      = require('express-session');
var morgan = require('morgan'); //formerly known as express.logger()
var errorhandler = require('errorhandler');
var path  = require('path');
var assert = require('assert');

/*
Allow views to search a unix-like path for file resolution
*/
function AppView(name, options) {
  View.call(this, name, options);
}
util.inherits(AppView, View);

AppView.prototype.lookup = function(locate) {
  //rely on template engine loader to resolve relative path
  return locate;

  //note: this logic isn't important since views are internally specified
  // var ext = this.ext;
  // // <path>.<engine>
  // var resolved = utils.searchPath(this.root, locate);
  // if (resolved)
  //   return resolved;
  //
  // // <path>/index.<engine>
  // locate = path.join(path.dirname(locate), path.basename(locate, ext), 'index' + ext);
  // resolved = utils.searchPath(this.root, locate);
  // if (resolved)
  //   return resolved;
}

var STOP_APP_TIMEOUT = 30*1000;

var appmethods = {

updateNamedRoutes: function(routes) {
  var namedRoutes = this.get("namedRoutes") || {};
  namedroutes.update(this, namedRoutes, routes);
  return namedRoutes;
},

stop: function(closeCallback, forcequit) {
  var onclose = function() {
    mongoose.connection.close(closeCallback);
  };
  this.gracefullyExiting = true;
  var server = this.get("server");
  if (server)
    server.close(onclose)
  else
    onclose();

  if (forcequit) {
    var timeout = typeof forcequit == "number" ? forcequit : STOP_APP_TIMEOUT;
    setTimeout( function () {
      console.error("Could not close connections in time, forcefully shutting down");
      process.exit(1);
    }, timeout);
  }
},

/*
@param ready function called
if ready is defined it is the responsibility of that function to start listening (if desired) by calling the supplied listen function.
e.g.:
function ready(listen) {
   //do more stuff
   //if you want to initiate listening:
   listen(function(server) { //optional listen callback
   })
}
if ready is not defined, the server will start listening
@param closeCallback invoked when app is terminated, see app.stop()
*/
start: function(ready, closeCallback) {
  var app = this;
  namedroutes.apply(app.get("namedRoutes"));

  //app.startstack = new Error().stack;
  //set up clean shutdown on sigterm
  //see http://blog.argteam.com/coding/hardening-node-js-for-production-part-3-zero-downtime-deployments-with-nginx/
  //and https://github.com/visionmedia/express/issues/1366
  process.on( 'SIGTERM', function() {app.stop(closeCallback,true);});
  //XXX what about SIGINT (ctrl-c)? closeCallback needs to call process.exit(1) in that case
  var onready = function() {
    if (ready) {
       ready(function(onlisten) {
         var server = app.listen(app.get('port'), 'localhost', function() {
           console.log('Express server listening on port %d', server.address().port);
           if (onlisten) onlisten(server);
         });
         app.set('server', server);
       });
    } else {
      var server = app.listen(app.get('port'), 'localhost', function() {
        console.log('Express server listening on port %d',server.address().port);
      });
      app.set('server', server);
    }
  };

  var dburl  = app.get("dburl");
  mongoose.connect(dburl, function(err) {
    if (err)
      throw err;
    else
      console.log("connecting to database", dburl);

    // optionally apply data migrations in /updates folder before starting server.
    if(app.set('autoUpdates')) {
      console.log("checking for autoupdates to apply...");
      require('keystone').connect(mongoose); // need to do this for updates to work.
      var updates = require('keystone/lib/updates');
      updates.apply(function(){
        onready()
      });
    } else  {
      onready();
    }
  });
},

getUrl: function() {
  var server = this.get("server");
  if (!server)
    return null;
  var address = server.address();
  //XXX support https
  return util.format("http://%s:%d", address.address, address.port);
}

};

/*
usage:

app = base.createApp(__dirname);
app.get(...); //add routes, etc.
app.start()
*/
function createApp(root, options) {
  root = root || '';
  options = _.defaults(options || {}, {
    views: path.join(root, 'views', path.sep),
    public: path.join(root, 'public'),
    configdir: root,
    cacheviews: false
  });
  var app = express();
  app.loadConfig = configloader(path.resolve(options.configdir), path.join(__dirname, '..'));
  var config = app.loadConfig('app')
  require('../config/passport')(passport); // pass passport for configuration

  // all environments
  app.set('view', AppView);
  //'..' cause we're in lib
  var baseviewpath = path.normalize(path.join(__dirname, '..', 'views', path.sep));
  var viewpath = options.views ?
      [path.normalize(path.join(options.views,path.sep)), baseviewpath]
      : [baseviewpath];
  app.set('views', viewpath);
  require('./swigextensions')(swig, {
   loaderPath: viewpath,
   cache: config.cacheviews !== undefined ? config.cacheviews : options.cacheviews,
  });
  app.engine('html', swig.renderFile);
  app.set('view engine', 'html');

  //see http://blog.argteam.com/coding/hardening-node-js-for-production-part-3-zero-downtime-deployments-with-nginx/
  app.gracefullyExiting = false;
  app.use(function(req, res, next) {
    if (!app.gracefullyExiting)
      return next();
    res.setHeader ("Connection", "close")
    res.send (502, "Server is in the process of restarting. [stopApp]")
  });

  if (typeof config.request_logger == 'undefined') {
    //use it twice in order to log both initial request and response
    app.use(morgan({format: 'dev', immediate: true }));
    app.use(morgan({format: 'dev'}));
  } else if (typeof config.request_logger == 'function') {
    config.request_logger(app);<commit_msg>support true as valid cacheview value<commit_after>/**
 * Module dependencies.
 */
var express = require('express');
var View = require('express/lib/view');
var routes = require('../routes');
var path = require('path');
var swig = require('swig');
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');
var models = require('../models');
var _ = require('underscore');
var configloader = require('./config');
var utils = require('./utils');
var namedroutes = require('./namedroutes');
var util = require('util');
var crypto = require('crypto');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session      = require('express-session');
var morgan = require('morgan'); //formerly known as express.logger()
var errorhandler = require('errorhandler');
var path  = require('path');
var assert = require('assert');

/*
Allow views to search a unix-like path for file resolution
*/
function AppView(name, options) {
  View.call(this, name, options);
}
util.inherits(AppView, View);

AppView.prototype.lookup = function(locate) {
  //rely on template engine loader to resolve relative path
  return locate;

  //note: this logic isn't important since views are internally specified
  // var ext = this.ext;
  // // <path>.<engine>
  // var resolved = utils.searchPath(this.root, locate);
  // if (resolved)
  //   return resolved;
  //
  // // <path>/index.<engine>
  // locate = path.join(path.dirname(locate), path.basename(locate, ext), 'index' + ext);
  // resolved = utils.searchPath(this.root, locate);
  // if (resolved)
  //   return resolved;
}

var STOP_APP_TIMEOUT = 30*1000;

var appmethods = {

updateNamedRoutes: function(routes) {
  var namedRoutes = this.get("namedRoutes") || {};
  namedroutes.update(this, namedRoutes, routes);
  return namedRoutes;
},

stop: function(closeCallback, forcequit) {
  var onclose = function() {
    mongoose.connection.close(closeCallback);
  };
  this.gracefullyExiting = true;
  var server = this.get("server");
  if (server)
    server.close(onclose)
  else
    onclose();

  if (forcequit) {
    var timeout = typeof forcequit == "number" ? forcequit : STOP_APP_TIMEOUT;
    setTimeout( function () {
      console.error("Could not close connections in time, forcefully shutting down");
      process.exit(1);
    }, timeout);
  }
},

/*
@param ready function called
if ready is defined it is the responsibility of that function to start listening (if desired) by calling the supplied listen function.
e.g.:
function ready(listen) {
   //do more stuff
   //if you want to initiate listening:
   listen(function(server) { //optional listen callback
   })
}
if ready is not defined, the server will start listening
@param closeCallback invoked when app is terminated, see app.stop()
*/
start: function(ready, closeCallback) {
  var app = this;
  namedroutes.apply(app.get("namedRoutes"));

  //app.startstack = new Error().stack;
  //set up clean shutdown on sigterm
  //see http://blog.argteam.com/coding/hardening-node-js-for-production-part-3-zero-downtime-deployments-with-nginx/
  //and https://github.com/visionmedia/express/issues/1366
  process.on( 'SIGTERM', function() {app.stop(closeCallback,true);});
  //XXX what about SIGINT (ctrl-c)? closeCallback needs to call process.exit(1) in that case
  var onready = function() {
    if (ready) {
       ready(function(onlisten) {
         var server = app.listen(app.get('port'), 'localhost', function() {
           console.log('Express server listening on port %d', server.address().port);
           if (onlisten) onlisten(server);
         });
         app.set('server', server);
       });
    } else {
      var server = app.listen(app.get('port'), 'localhost', function() {
        console.log('Express server listening on port %d',server.address().port);
      });
      app.set('server', server);
    }
  };

  var dburl  = app.get("dburl");
  mongoose.connect(dburl, function(err) {
    if (err)
      throw err;
    else
      console.log("connecting to database", dburl);

    // optionally apply data migrations in /updates folder before starting server.
    if(app.set('autoUpdates')) {
      console.log("checking for autoupdates to apply...");
      require('keystone').connect(mongoose); // need to do this for updates to work.
      var updates = require('keystone/lib/updates');
      updates.apply(function(){
        onready()
      });
    } else  {
      onready();
    }
  });
},

getUrl: function() {
  var server = this.get("server");
  if (!server)
    return null;
  var address = server.address();
  //XXX support https
  return util.format("http://%s:%d", address.address, address.port);
}

};

/*
usage:

app = base.createApp(__dirname);
app.get(...); //add routes, etc.
app.start()
*/
function createApp(root, options) {
  root = root || '';
  options = _.defaults(options || {}, {
    views: path.join(root, 'views', path.sep),
    public: path.join(root, 'public'),
    configdir: root,
    cacheviews: false
  });
  var app = express();
  app.loadConfig = configloader(path.resolve(options.configdir), path.join(__dirname, '..'));
  var config = app.loadConfig('app')
  require('../config/passport')(passport); // pass passport for configuration

  // all environments
  app.set('view', AppView);
  //'..' cause we're in lib
  var baseviewpath = path.normalize(path.join(__dirname, '..', 'views', path.sep));
  var viewpath = options.views ?
      [path.normalize(path.join(options.views,path.sep)), baseviewpath]
      : [baseviewpath];
  app.set('views', viewpath);
  var cacheviews = config.cacheviews !== undefined ? config.cacheviews : options.cacheviews;
  if (cacheviews && typeof cacheviews === 'boolean')
    cacheviews = 'memory';
  require('./swigextensions')(swig, {
   loaderPath: viewpath,
   cache: cacheviews,
  });
  app.engine('html', swig.renderFile);
  app.set('view engine', 'html');

  //see http://blog.argteam.com/coding/hardening-node-js-for-production-part-3-zero-downtime-deployments-with-nginx/
  app.gracefullyExiting = false;
  app.use(function(req, res, next) {
    if (!app.gracefullyExiting)
      return next();
    res.setHeader ("Connection", "close")
    res.send (502, "Server is in the process of restarting. [stopApp]")
  });

  if (typeof config.request_logger == 'undefined') {
    //use it twice in order to log both initial request and response
    app.use(morgan({format: 'dev', immediate: true }));
    app.use(morgan({format: 'dev'}));
  } else if (typeof config.request_logger == 'function') {
    config.request_logger(app);
{'fraction_non_alphanumeric': 0.15808795411089865, 'fraction_numerical': 0.00260038240917782, 'mean_word_length': 3.617231638418079, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2579230', 'n_tokens_mistral': 4028, 'n_tokens_neox': 3975, 'n_words': 1052}