<commit_before>"use strict";

/**
 * Module Dependencies
 */
var EventEmitter = require('events').EventEmitter;
var only = require('only');
var Logger = require('./log/Logger');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var co = require('co');
const Context = require('./Context');
const Util = require('./Util');

/**
 * Initialize a new `Application`.
 *
 * @api public
 */
class Application extends EventEmitter {
  constructor(config) {
    super();

    this.config = 'object' === typeof config ? config : {};
    this.env = this.config.env || process.env.NODE_ENV || 'development';
    var appPath = process.env.SAND_APP_PATH || this.config.appPath || path.dirname(require.main.filename);
    this.appPath = fs.realpathSync(appPath);
    this.configPath = this.appPath + '/config';   // location for config packaged with the app
    this.extConfigPath = this.config.configPath || process.env.SAND_CONFIG_PATH || this.configPath;   // location for config external to the app
    this.loadConfig();
    this.modules = [];

    let slogger = (new Logger('Sand'));
    this._log = slogger.log;
    this._error = slogger.error;
    this._warn = slogger.warn;

    this.initCalled = false;
    this.initCallback = null;

    try {
      this.appName = require(this.appPath + '/package').name;
      let logger = (new Logger(this.appName, true));
      this.log = logger.log;
      this.warn = logger.warn;
      this.error = logger.error;
      Logger.setupDebug(this);
    } catch(e) {
      this._warn(this.appPath + ' is not the correct AppPath');
    }

    // Set PS Title
    this.executable = path.basename(process.argv[0]);
    process.title = `${this.executable} ${this.appName}`;

    // Load package.json
    var p = require('../package.json');
    this.version = p.version;

    // this._boundShutdown = this.shutdown.bind(this);
    this._boundShutdown = this.shutdown.bind(this, process.exit);

    global.sand = this;
  }

  /**
   * Converts Sand into a nice
   * descriptive object
   * @returns {*}
   */
  inspect() {
    return only(this, [
      'env',
      'version',
      'modules'
    ]);
  }

  /**
   * Registers for process exit and initializes
   * each module
   *
   * @returns {Application}
   */
  start(cb) {
    this.logStart();

    let self = this;
    co(function *() {
      yield runFunctionOnModules.call(self, self.modules, 'init', function (module) {
        return [module.config];
      }, function(module) {
        module.module.log('Version: ' + module.module.version);
      }, self.initCallback);

      yield runFunctionOnModules.call(self, self.modules, 'start', null, null, cb);

      // Lets overwrite all debugs
      Logger.overwriteDebug(self);
    }).catch(function(e) {
      self._error(e);
      self._boundShutdown();
    });


    // Listens
    process.on('message', function(msg) {
      if ('shutdown' == msg) {
        self._boundShutdown();
      }
    });

    process.on("exit", this._boundShutdown);
    process.on("SIGINT", this._boundShutdown);
    process.on("SIGTERM", this._boundShutdown);
    process.on("uncaughtException", function(err) {
      self._error(err.stack || err.message || err);
      self._boundShutdown();
    });

    return this;
  }

  /**
   * Calls init on each module then calls
   * your callback, can be a generator or regular function
   *
   * @param {GeneratorFunction|Function} cb
   */
  init(cb) {
    this.initCalled = true;
    this.initCallback = cb;

    return this;
  }

  /**
   * Calls shutdown on each module
   */
  shutdown(cb) {
    if (this.isShuttingDown) {
      return;
    }

    this.isShuttingDown = true;
    this.emit('shutdown');

    this._log('Shutting down...');
    var shutdownCount = 0;
    var timer = this._waitTimer(this.config.shutdownTimeout, 'Could not shutdown in ' + this.config.shutdownTimeout + ' milliseconds, hard shutting down...');
    this.modules.forEach(function(v) {
      v.module.shutdown(function() {
        shutdownCount++;
        if (shutdownCount >= this.modules.length) {
          clearTimeout(timer);
          if ('function' === typeof cb) {
            cb();
          }
        }
      }.bind(this));
    }.bind(this));

    if (!this.modules.length) {
      if ('function' === typeof cb) {
        cb();
      }
    }
  }

  /**
   * Configures sand to use {SandGrain}
   *
   * @param {SandGrain} module the {SandGrain} to load
   * @param {JSON} [config] the config to override
   * @param {string} [name=moduleName] the variable name to use, by default uses module name
   *
   * @returns {Application}
   */
  use(module, config, name) {
    if (typeof module === 'function') {
      // Not an instance, lets instantiate it
      module = new module();
    }

    if ('function' !== typeof module.shutdown && 'function' !== typeof module.init) {
      this._log(`${module.name} module is not an instance of SandGrain. Therefore it is invalid.`, JSON.stringify(module));
      this.shutdown(process.exit.bind(null, 1));
      return this;
    }

    var appConfig = {};
    var extConfig = {};

    if (typeof config === 'undefined') {
      config = {
        all: {}
      };
    }<commit_msg>add support for module to accept name<commit_after>"use strict";

/**
 * Module Dependencies
 */
var EventEmitter = require('events').EventEmitter;
var only = require('only');
var Logger = require('./log/Logger');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');
var co = require('co');
const Context = require('./Context');
const Util = require('./Util');

/**
 * Initialize a new `Application`.
 *
 * @api public
 */
class Application extends EventEmitter {
  constructor(config) {
    super();

    this.config = 'object' === typeof config ? config : {};
    this.env = this.config.env || process.env.NODE_ENV || 'development';
    var appPath = process.env.SAND_APP_PATH || this.config.appPath || path.dirname(require.main.filename);
    this.appPath = fs.realpathSync(appPath);
    this.configPath = this.appPath + '/config';   // location for config packaged with the app
    this.extConfigPath = this.config.configPath || process.env.SAND_CONFIG_PATH || this.configPath;   // location for config external to the app
    this.loadConfig();
    this.modules = [];

    let slogger = (new Logger('Sand'));
    this._log = slogger.log;
    this._error = slogger.error;
    this._warn = slogger.warn;

    this.initCalled = false;
    this.initCallback = null;

    try {
      this.appName = require(this.appPath + '/package').name;
      let logger = (new Logger(this.appName, true));
      this.log = logger.log;
      this.warn = logger.warn;
      this.error = logger.error;
      Logger.setupDebug(this);
    } catch(e) {
      this._warn(this.appPath + ' is not the correct AppPath');
    }

    // Set PS Title
    this.executable = path.basename(process.argv[0]);
    process.title = `${this.executable} ${this.appName}`;

    // Load package.json
    var p = require('../package.json');
    this.version = p.version;

    // this._boundShutdown = this.shutdown.bind(this);
    this._boundShutdown = this.shutdown.bind(this, process.exit);

    global.sand = this;
  }

  /**
   * Converts Sand into a nice
   * descriptive object
   * @returns {*}
   */
  inspect() {
    return only(this, [
      'env',
      'version',
      'modules'
    ]);
  }

  /**
   * Registers for process exit and initializes
   * each module
   *
   * @returns {Application}
   */
  start(cb) {
    this.logStart();

    let self = this;
    co(function *() {
      yield runFunctionOnModules.call(self, self.modules, 'init', function (module) {
        return [module.config];
      }, function(module) {
        module.module.log('Version: ' + module.module.version);
      }, self.initCallback);

      yield runFunctionOnModules.call(self, self.modules, 'start', null, null, cb);

      // Lets overwrite all debugs
      Logger.overwriteDebug(self);
    }).catch(function(e) {
      self._error(e);
      self._boundShutdown();
    });


    // Listens
    process.on('message', function(msg) {
      if ('shutdown' == msg) {
        self._boundShutdown();
      }
    });

    process.on("exit", this._boundShutdown);
    process.on("SIGINT", this._boundShutdown);
    process.on("SIGTERM", this._boundShutdown);
    process.on("uncaughtException", function(err) {
      self._error(err.stack || err.message || err);
      self._boundShutdown();
    });

    return this;
  }

  /**
   * Calls init on each module then calls
   * your callback, can be a generator or regular function
   *
   * @param {GeneratorFunction|Function} cb
   */
  init(cb) {
    this.initCalled = true;
    this.initCallback = cb;

    return this;
  }

  /**
   * Calls shutdown on each module
   */
  shutdown(cb) {
    if (this.isShuttingDown) {
      return;
    }

    this.isShuttingDown = true;
    this.emit('shutdown');

    this._log('Shutting down...');
    var shutdownCount = 0;
    var timer = this._waitTimer(this.config.shutdownTimeout, 'Could not shutdown in ' + this.config.shutdownTimeout + ' milliseconds, hard shutting down...');
    this.modules.forEach(function(v) {
      v.module.shutdown(function() {
        shutdownCount++;
        if (shutdownCount >= this.modules.length) {
          clearTimeout(timer);
          if ('function' === typeof cb) {
            cb();
          }
        }
      }.bind(this));
    }.bind(this));

    if (!this.modules.length) {
      if ('function' === typeof cb) {
        cb();
      }
    }
  }

  /**
   * Configures sand to use {SandGrain}
   *
   * @param {SandGrain} module the {SandGrain} to load
   * @param {JSON} [config] the config to override
   * @param {string} [name=moduleName] the variable name to use, by default uses module name
   *
   * @returns {Application}
   */
  use(module, config, name) {
    if (typeof module === 'function') {
      // Not an instance, lets instantiate it
      module = new module(name);
    }

    if ('function' !== typeof module.shutdown && 'function' !== typeof module.init) {
      this._log(`${module.name} module is not an instance of SandGrain. Therefore it is invalid.`, JSON.stringify(module));
      this.shutdown(process.exit.bind(null, 1));
      return this;
    }

    var appConfig = {};
    var extConfig = {};

    if (typeof config === 'undefined') {
      config = {
        all: {}
      };
    }
{'fraction_non_alphanumeric': 0.15079517148879096, 'fraction_numerical': 0.0005748227629814141, 'mean_word_length': 2.613361024575978, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, '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': '1830141', 'n_tokens_mistral': 3277, 'n_tokens_neox': 3187, 'n_words': 762}