<commit_before>const fs = require('../core/fs.js');
const async = require('async');
const ProcessLauncher = require('../process/processLauncher');
const utils = require('../utils/utils.js');
const constants = require('../constants');

require("babel-preset-react");
require("babel-preset-es2015");
require("babel-preset-es2016");
require("babel-preset-es2017");

class Pipeline {

  constructor(options) {
    this.env = options.env;
    this.buildDir = options.buildDir;
    this.contractsFiles = options.contractsFiles;
    this.assetFiles = options.assetFiles;
    this.events = options.events;
    this.logger = options.logger;
    this.plugins = options.plugins;
    this.pipelinePlugins = this.plugins.getPluginsFor('pipeline');
  }

  build(abi, contractsJSON, path, callback) {
    let self = this;
    const importsList = {};
    let placeholderPage;

    if (!this.assetFiles || !Object.keys(this.assetFiles).length) {
      return callback();
    }

    async.waterfall([
      function createPlaceholderPage(next){
        self.events.request('embark-building-placeholder', (html) => {
          fs.mkdirpSync(self.buildDir); // create dist/ folder if not already exists
          fs.writeFile(self.buildDir + 'index.html', html, next);
        });
      },
      function buildTheContracts(next) {
        self.buildContracts(next);
      },
      function buildWeb3(next) {
        self.buildWeb3JS(next);
      },
      function createImportList(next) {
        importsList["Embark/EmbarkJS"] = fs.dappPath(".embark", 'embark.js');
        importsList["Embark/web3"] = fs.dappPath(".embark", 'web3_instance.js');
        importsList["Embark/contracts"] = fs.dappPath(".embark/contracts", '');

        self.plugins.getPluginsProperty('imports', 'imports').forEach(function (importObject) {
          let [importName, importLocation] = importObject;
          importsList[importName] = importLocation;
        });

        next();
      },
      function writeContracts(next) {
        self.events.request('contracts:list', (_err, contracts) => {
          // ensure the .embark/contracts directory exists (create if not exists)
          fs.mkdirp(fs.dappPath(".embark/contracts", ''), (err) => {
            if(err) return next(err);

            // Create a file .embark/contracts/index.js that requires all contract files
            // Used to enable alternate import syntax:
            // e.g. import {Token} from 'Embark/contracts'
            // e.g. import * as Contracts from 'Embark/contracts'
            let importsHelperFile = fs.createWriteStream(fs.dappPath(".embark/contracts", 'index.js'));
            importsHelperFile.write('module.exports = {\n');

            async.eachOf(contracts, (contract, idx, eachCb) => {
              self.events.request('code-generator:contract', contract.className, (contractCode) => {
                let filePath = fs.dappPath(".embark/contracts", contract.className + '.js');
                importsList["Embark/contracts/" + contract.className] = filePath;
                fs.writeFile(filePath, contractCode, eachCb);

                // add the contract to the exports list to support alternate import syntax
                importsHelperFile.write(`"${contract.className}": require('./${contract.className}').default`);
                if(idx < contracts.length - 1) importsHelperFile.write(',\n'); // add a comma if we have more contracts to add
              });
            }, function(){
              importsHelperFile.write('\n}'); // close the module.exports = {}
              importsHelperFile.close(next); // close the write stream
            });
          });
        });
      },
      function assetFileWrite(next) {
        async.eachOf(self.assetFiles, function (files, targetFile, cb) {
            async.map(files,
              function (file, fileCb) {
                self.logger.trace("reading " + file.filename);

                // Not a JS file
                if (file.filename.indexOf('.js') < 0) {
                  return file.content(function (fileContent) {
                    self.runPlugins(file, fileContent, fileCb);
                  });
                }

                // JS files
                async.waterfall([
                  function runWebpack(next) {
                    let built = false;
                    const webpackProcess = new ProcessLauncher({
                      env: self.env,
                      modulePath: utils.joinPath(__dirname, 'webpackProcess.js'),
                      logger: self.logger,
                      events: self.events,
                      exitCallback: function (code) {
                        if (!built) {
                          return next(`File building of ${file.filename} exited with code ${code} before the process finished`);
                        }
                        if (code) {
                          self.logger(__('File building process exited with code ', code));
                        }
                      }
                    });
                    webpackProcess.send({action: constants.pipeline.init, options: {env: self.env}});
                    webpackProcess.send({action: constants.pipeline.build, file, importsList});

                    webpackProcess.once('result', constants.pipeline.built, (msg) => {
                      built = true;
                      webpackProcess.kill();
                      return next(msg.error);
                    });
                  },

                  function readFile(next) {
                    fs.readFile('./.embark/' + file.filename, (err, data) => {
                      if (err) {
                        return next(err);
                      }
                      next(null, data.toString());
                    });
                  },

                  function runPluginsOnContent(fileContent, next) {
                    self.runPlugins(file, fileContent, next);
                  }

                ], function (err, contentFile) {
                  if (err) {
                    self.logger.error(err);
                    return fileCb(err);
                  }

                  fileCb(null, contentFile);
                });
              },
              function (err, contentFiles) {
                if (err) {
                  self.logger.error(__('errors found while generating') + ' ' + targetFile);
                }
                let dir = targetFile.split('/').slice(0, -1).join('/');
                self.logger.trace("creating dir " + self.buildDir + dir);
                fs.mkdirpSync(self.buildDir + dir);

                // if it's a directory
                if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
                  let targetDir = targetFile;

                  if (targetDir.slice(-1) !== '/') {
                    targetDir = targetDir + '/';
                  }

                  async.each(contentFiles, function (file, mapCb) {
                    let filename = file.filename.replace(file.basedir + '/', '');
                    self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);

                    fs.copy(file.path, self.buildDir + targetDir + filename, {overwrite: true}, mapCb);
                  }, cb);
                  return;
                }

                let content = contentFiles.map(function (file) {
                  if (file === undefined) {
                    return "";
                  }
                  return file.content;
                }).join("\n");

                self.logger.info(__("writing file") + " " + (self.buildDir + targetFile).bold.dim);
                if(new RegExp(/^index.html?/i).test(targetFile)){
                  targetFile = targetFile.replace('index', 'index-temp');
                  placeholderPage = targetFile;
                }
                fs.writeFile(self.buildDir + targetFile, content, cb);
              }
            );
          },
          next);
      },
      function removePlaceholderPage(next){
        let placeholderFile = self.buildDir + placeholderPage;
        fs.access(self.buildDir + placeholderPage, (err) => {
          if (err) return next(); // index-temp doesn't exist, do nothing

          // rename index-temp.htm/l to index.htm/l, effectively replacing our placeholder page
          // with the contents of the built index.html page
          fs.move(placeholderFile, placeholderFile.replace('index-temp', 'index'), {overwrite: true}, next);
        });
      }
    ], callback);
  }

  runPlugins(file, fileContent, fileCb) {
    const self = this;
    if (self.pipelinePlugins.length <= 0) {
      return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
    }
    async.eachSeries(self.pipelinePlugins,
      function(plugin, pluginCB) {
        if (file.options && file.options.skipPipeline) {
          return pluginCB();
        }

        fileContent = plugin.runPipeline({targetFile: file.filename, source: fileContent});
        file.modified = true;
        pluginCB();
      },
      function (err) {
        if (err) {
          self.logger.error(err.message);
        }
        return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
      }
    );
  }

  buildContracts(cb) {
    const self = this;

    async.waterfall([
      function makeDirectory(next) {
        fs.mkdirp(fs.dappPath(self.buildDir, 'contracts'), (err, _result) => {
          next(err);
        });
      },
      function getContracts(next) {
        self.events.request('contracts:list', (err, contracts) => {
          next(err, contracts);
        });
      },
      function writeContractsJSON(contracts, next) {
        async.each(contracts, (contract, eachCb) => {
          fs.writeJson(fs.dappPath(self.buildDir, 'contracts', contract.className + ".json"), contract, {spaces: 2}, eachCb);
        }, () => { next(); });
      }
    ], cb);
  }

  buildWeb3JS(cb) {
    const self = this;
    async.waterfall([
      function makeDirectory(next) {
        fs.mkdirp(fs.dappPath(".embark"), (err, _result) => {
          next(err);
        });
      },
      function getWeb3Code(next) {
        self.events.request('code-generator:web3js', next);
      },
      function writeFile(code, next) {
        fs.writeFile(fs.dappPath(".embark", 'web3_instance.js'), code, next);
      }
    ], cb);
  }
}

module.exports = Pipeline;
<commit_msg>rm unnecessary requires<commit_after>const fs = require('../core/fs.js');
const async = require('async');
const ProcessLauncher = require('../process/processLauncher');
const utils = require('../utils/utils.js');
const constants = require('../constants');

// require("babel-preset-react");
// require("babel-preset-es2015");
// require("babel-preset-es2016");
// require("babel-preset-es2017");

class Pipeline {

  constructor(options) {
    this.env = options.env;
    this.buildDir = options.buildDir;
    this.contractsFiles = options.contractsFiles;
    this.assetFiles = options.assetFiles;
    this.events = options.events;
    this.logger = options.logger;
    this.plugins = options.plugins;
    this.pipelinePlugins = this.plugins.getPluginsFor('pipeline');
  }

  build(abi, contractsJSON, path, callback) {
    let self = this;
    const importsList = {};
    let placeholderPage;

    if (!this.assetFiles || !Object.keys(this.assetFiles).length) {
      return callback();
    }

    async.waterfall([
      function createPlaceholderPage(next){
        self.events.request('embark-building-placeholder', (html) => {
          fs.mkdirpSync(self.buildDir); // create dist/ folder if not already exists
          fs.writeFile(self.buildDir + 'index.html', html, next);
        });
      },
      function buildTheContracts(next) {
        self.buildContracts(next);
      },
      function buildWeb3(next) {
        self.buildWeb3JS(next);
      },
      function createImportList(next) {
        importsList["Embark/EmbarkJS"] = fs.dappPath(".embark", 'embark.js');
        importsList["Embark/web3"] = fs.dappPath(".embark", 'web3_instance.js');
        importsList["Embark/contracts"] = fs.dappPath(".embark/contracts", '');

        self.plugins.getPluginsProperty('imports', 'imports').forEach(function (importObject) {
          let [importName, importLocation] = importObject;
          importsList[importName] = importLocation;
        });

        next();
      },
      function writeContracts(next) {
        self.events.request('contracts:list', (_err, contracts) => {
          // ensure the .embark/contracts directory exists (create if not exists)
          fs.mkdirp(fs.dappPath(".embark/contracts", ''), (err) => {
            if(err) return next(err);

            // Create a file .embark/contracts/index.js that requires all contract files
            // Used to enable alternate import syntax:
            // e.g. import {Token} from 'Embark/contracts'
            // e.g. import * as Contracts from 'Embark/contracts'
            let importsHelperFile = fs.createWriteStream(fs.dappPath(".embark/contracts", 'index.js'));
            importsHelperFile.write('module.exports = {\n');

            async.eachOf(contracts, (contract, idx, eachCb) => {
              self.events.request('code-generator:contract', contract.className, (contractCode) => {
                let filePath = fs.dappPath(".embark/contracts", contract.className + '.js');
                importsList["Embark/contracts/" + contract.className] = filePath;
                fs.writeFile(filePath, contractCode, eachCb);

                // add the contract to the exports list to support alternate import syntax
                importsHelperFile.write(`"${contract.className}": require('./${contract.className}').default`);
                if(idx < contracts.length - 1) importsHelperFile.write(',\n'); // add a comma if we have more contracts to add
              });
            }, function(){
              importsHelperFile.write('\n}'); // close the module.exports = {}
              importsHelperFile.close(next); // close the write stream
            });
          });
        });
      },
      function assetFileWrite(next) {
        async.eachOf(self.assetFiles, function (files, targetFile, cb) {
            async.map(files,
              function (file, fileCb) {
                self.logger.trace("reading " + file.filename);

                // Not a JS file
                if (file.filename.indexOf('.js') < 0) {
                  return file.content(function (fileContent) {
                    self.runPlugins(file, fileContent, fileCb);
                  });
                }

                // JS files
                async.waterfall([
                  function runWebpack(next) {
                    let built = false;
                    const webpackProcess = new ProcessLauncher({
                      env: self.env,
                      modulePath: utils.joinPath(__dirname, 'webpackProcess.js'),
                      logger: self.logger,
                      events: self.events,
                      exitCallback: function (code) {
                        if (!built) {
                          return next(`File building of ${file.filename} exited with code ${code} before the process finished`);
                        }
                        if (code) {
                          self.logger(__('File building process exited with code ', code));
                        }
                      }
                    });
                    webpackProcess.send({action: constants.pipeline.init, options: {env: self.env}});
                    webpackProcess.send({action: constants.pipeline.build, file, importsList});

                    webpackProcess.once('result', constants.pipeline.built, (msg) => {
                      built = true;
                      webpackProcess.kill();
                      return next(msg.error);
                    });
                  },

                  function readFile(next) {
                    fs.readFile('./.embark/' + file.filename, (err, data) => {
                      if (err) {
                        return next(err);
                      }
                      next(null, data.toString());
                    });
                  },

                  function runPluginsOnContent(fileContent, next) {
                    self.runPlugins(file, fileContent, next);
                  }

                ], function (err, contentFile) {
                  if (err) {
                    self.logger.error(err);
                    return fileCb(err);
                  }

                  fileCb(null, contentFile);
                });
              },
              function (err, contentFiles) {
                if (err) {
                  self.logger.error(__('errors found while generating') + ' ' + targetFile);
                }
                let dir = targetFile.split('/').slice(0, -1).join('/');
                self.logger.trace("creating dir " + self.buildDir + dir);
                fs.mkdirpSync(self.buildDir + dir);

                // if it's a directory
                if (targetFile.slice(-1) === '/' || targetFile.indexOf('.') === -1) {
                  let targetDir = targetFile;

                  if (targetDir.slice(-1) !== '/') {
                    targetDir = targetDir + '/';
                  }

                  async.each(contentFiles, function (file, mapCb) {
                    let filename = file.filename.replace(file.basedir + '/', '');
                    self.logger.info("writing file " + (self.buildDir + targetDir + filename).bold.dim);

                    fs.copy(file.path, self.buildDir + targetDir + filename, {overwrite: true}, mapCb);
                  }, cb);
                  return;
                }

                let content = contentFiles.map(function (file) {
                  if (file === undefined) {
                    return "";
                  }
                  return file.content;
                }).join("\n");

                self.logger.info(__("writing file") + " " + (self.buildDir + targetFile).bold.dim);
                if(new RegExp(/^index.html?/i).test(targetFile)){
                  targetFile = targetFile.replace('index', 'index-temp');
                  placeholderPage = targetFile;
                }
                fs.writeFile(self.buildDir + targetFile, content, cb);
              }
            );
          },
          next);
      },
      function removePlaceholderPage(next){
        let placeholderFile = self.buildDir + placeholderPage;
        fs.access(self.buildDir + placeholderPage, (err) => {
          if (err) return next(); // index-temp doesn't exist, do nothing

          // rename index-temp.htm/l to index.htm/l, effectively replacing our placeholder page
          // with the contents of the built index.html page
          fs.move(placeholderFile, placeholderFile.replace('index-temp', 'index'), {overwrite: true}, next);
        });
      }
    ], callback);
  }

  runPlugins(file, fileContent, fileCb) {
    const self = this;
    if (self.pipelinePlugins.length <= 0) {
      return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
    }
    async.eachSeries(self.pipelinePlugins,
      function(plugin, pluginCB) {
        if (file.options && file.options.skipPipeline) {
          return pluginCB();
        }

        fileContent = plugin.runPipeline({targetFile: file.filename, source: fileContent});
        file.modified = true;
        pluginCB();
      },
      function (err) {
        if (err) {
          self.logger.error(err.message);
        }
        return fileCb(null, {content: fileContent, filename: file.filename, path: file.path, basedir: file.basedir, modified: true});
      }
    );
  }

  buildContracts(cb) {
    const self = this;

    async.waterfall([
      function makeDirectory(next) {
        fs.mkdirp(fs.dappPath(self.buildDir, 'contracts'), (err, _result) => {
          next(err);
        });
      },
      function getContracts(next) {
        self.events.request('contracts:list', (err, contracts) => {
          next(err, contracts);
        });
      },
      function writeContractsJSON(contracts, next) {
        async.each(contracts, (contract, eachCb) => {
          fs.writeJson(fs.dappPath(self.buildDir, 'contracts', contract.className + ".json"), contract, {spaces: 2}, eachCb);
        }, () => { next(); });
      }
    ], cb);
  }

  buildWeb3JS(cb) {
    const self = this;
    async.waterfall([
      function makeDirectory(next) {
        fs.mkdirp(fs.dappPath(".embark"), (err, _result) => {
          next(err);
        });
      },
      function getWeb3Code(next) {
        self.events.request('code-generator:web3js', next);
      },
      function writeFile(code, next) {
        fs.writeFile(fs.dappPath(".embark", 'web3_instance.js'), code, next);
      }
    ], cb);
  }
}

module.exports = Pipeline;
<|endoftext|>


<commit_before>var CronJob = require('cron').CronJob;

const emailAdminHarnessTalentCv   = require('./utils/mailgun.js').emailAdminHarnessTalentCv;

const mailgun                   = require('./utils/mailgun.js');

exports.register = (server, options) => {

new CronJob('* * 4 * * * *', function() {

  emailAdminHarnessTalentCv.to = 'tormodsmith@gmail.com';
  mailgun.messages().send(emailAdminHarnessTalentCv);

console.log('yo sssssup');

}, null, true, 'America/Los_Angeles');

};

exports.register.attributes = {
  name: 'cron'
};

// add a warning date and expiry date to the data base on candidate submission. On warning date function runs to send and email to agency informing them to re upload the cv within a week
// must include name of candidate.

// on expiry date function is run to delete candidate from the database. IF candidate exists function is run to keep candidate and reset the expiration date for 7weeks.
// these functions will be in the harness-talent-submitcandidate route

// this function HERE will map through the entire list checking the warning date and expiration date
//triggers email function at warning date
// triggers delete function at expiration
<commit_msg>add cron timer with 3:30 email<commit_after>var CronJob = require('cron').CronJob;

const emailAdminHarnessTalentCv   = require('./utils/mailgun.js').emailAdminHarnessTalentCv;

const mailgun                   = require('./utils/mailgun.js');

exports.register = (server, options, next) => {

new CronJob('00 30 03 * * 1-5', function() {

emailAdminHarnessTalentCv.to = 'tormodsmith@gmail.com';
mailgun.messages().send(emailAdminHarnessTalentCv);

console.log('yo sssssup');

}, null, true, 'Europe/London');

return next();
};

exports.register.attributes = {
  name: 'cron'
};

// add a warning date and expiry date to the data base on candidate submission. On warning date function runs to send and email to agency informing them to re upload the cv within a week
// must include name of candidate.

// on expiry date function is run to delete candidate from the database. IF candidate exists function is run to keep candidate and reset the expiration date for 7weeks.
// these functions will be in the harness-talent-submitcandidate route

// this function HERE will map through the entire list checking the warning date and expiration date
//triggers email function at warning date
// triggers delete function at expiration
<|endoftext|>


<commit_before>/*
  Add a path that represents a file
*/

'use strict';

var Belt = require('jsbelt')
  , _ = require('underscore')
  , FS = require('fs')
  , Async = require('async')
  , FSTK = require('fstk');

module.exports = function(schema, options){
  var a = Belt.argulint(arguments, {
                         'validators': {
                            'options': [
                              {
                                'validator': function(){
                                   return this.path;
                                 }
                              , 'error': new Error('path is required')
                              }
                             ]
                          }
                       , 'options': options || {}
                       });

  a.o = _.defaults(a.o, {
    'path': false
  , 'schema': {
      'file_path': {type: String}
    , 'stat': Object
    }
  , 'array': false
  , 'auto_stat': true //stat path pre save
  , 'auto_remove': true //remove path when doc is removed
  , 'auto_touch': true //create path on save if it does not exist
  , 'auto_update': true //update file timestamps post save
  , 'auto_watch': false //watch path using FSTK pre init
  , 'exists_required': false //invalidate if path does not exist
  , 'virtual_prefix': '__'
  });

  var def = [a.o.schema];
  if (a.o.array) def = [def];

  schema.add(_.object([a.o.path], def));

  var vp = schema.virtual(a.o.path + '_prev_path');
  vp.get(function(){
    return this[a.o.virtual_prefix + a.o.path + '_prev_path'];
  });
  vp.set(function(val){
    return this[a.o.virtual_prefix + a.o.path + '_prev_path'] = val;
  });

  //stat the file at path
  schema.method('stat_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;
    return FSTK.stat(self.get(path + '.file_path'), function(err, stat){
      if (err) return b.cb(err);
      self.set(path + '.stat', stat);
      return b.cb(err, stat);
    });
  });

  //watch the file at path
  schema.method('watch_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    self.unwatch_file(path);

    return FSTK.watchFile(self.get(path + '.file_path'), _.pick(a.o, ['deserializer', 'serializer', 'auto_stat']), function(err, wf){
      if (err) return b.cb(err);
      self.get(path)[a.o.virtual_prefix + 'watcher'] = wf;

      if (a.o.auto_stat){
        self.set(path + '.stat', wf.stat);

        wf.emitter.on('read', function(){
          return self.set(path + '.stat', wf.stat);
        });

        wf.emitter.on('write', function(){
          return self.set(path + '.stat', wf.stat);
        });
      }

      return b.cb(err, wf);
    });
  });

  //unwatch the file at path
  schema.method('unwatch_file', function(path){
    var self = this;

    if (!Belt._get(self.get(path), a.o.virtual_prefix + 'watcher')) return false;

    Belt._call(self.get(path)[a.o.virtual_prefix + 'watcher.watcher'], 'close');
    self.get(path)[a.o.virtual_prefix + 'watcher'] = null;

    return true;
  });

  //remove the file at path
  schema.method('rm_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;
    return FSTK.rm(self.get(path + '.file_path'), function(err){
      return b.cb(err);
    });
  });

  //create the file at path
  schema.method('create_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    b.o = _.defaults(b.o, {
      'data': ''
    });

    return FSTK.writeFile(self.get(path + '.file_path'), b.o.data, function(err){
      return b.cb(err);
    });
  });

  //update file timestamps
  schema.method('update_ftimes', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    b.o = _.defaults(b.o, {
      'atime': new Date()
    , 'mtime': self.get('updated_at') || new Date()
    });

    return FS.utimes(self.get(path + '.file_path'), b.o.atime, b.o.mtime, function(err){
      return b.cb(err);
    });
  });

  //set file
  schema.method('set_file', function(path, file_path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this
      , globals = {};

    b.o = _.defaults(b.o, {
      'prev_path': false
    , 'data': false
    });

    return Async.waterfall([
      function(cb){
        self.unwatch_file(path);
        self.set(path + '.file_path', file_path);
        return cb();
      }
    , function(cb){
        if (!b.o.prev_path) return cb();
        return FSTK.mv(b.o.prev_path, file_path, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!b.o.data) return cb();
        return self.create_file(path, b.o, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!a.o.auto_touch) return cb();
        return FSTK.exists(file_path, Belt.cs(cb, globals, 'exists', 0));
      }
    , function(cb){
        if (!a.o.auto_touch || globals.exists) return cb();
        return self.create_file(path, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!a.o.auto_watch) return cb();
        return self.watch_file(path, Belt.cw(cb, 0));
      }
    ], function(err){
      return b.cb(err);
    });
  });

  schema.method('file_extension', function(){
    var p = this.get('file.file_path');
    if (!p) return;
    return p.split('.').pop();
  });

  //MIDDLEWARE

  schema.pre('save', function(next){
    if (!this.get(a.o.path + '_prev_path')) return next();

    var p = this.get(a.o.path + '_prev_path');
    this.set(a.o.path + '_prev_path', undefined);
    return FSTK.mv(p, this.get(a.o.path + '.file_path'), Belt.cw(next, 0));
  });

  //stat files pre-init
  if (a.o.auto_stat && !a.o.auto_watch) schema.post('init', function(){
    if (!this.get(a.o.path)) return;

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.stat_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.stat_file(a.o.path, Belt.noop);
  });

  //create files if it does not exist pre-save
  if (a.o.auto_touch) schema.pre('save', function(next){
    if (!this.get(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return FSTK.exists(self.get(a.o.path + '.' + (index - 1) + '.file_path')
        , function(exists){
          if (exists) return cb();

          return FSTK.writeFile(self.get(a.o.path + '.' + (index - 1) + '.file_path')
          , '', Belt.cw(cb, 0));
        });
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return FSTK.exists(self.get(a.o.path + '.file_path'), function(exists){
      if (exists) return next();

      return FSTK.writeFile(self.get(a.o.path + '.file_path'), '', Belt.cw(next, 0));
    });
  });

  //stat files pre-save
  if (a.o.auto_stat) schema.pre('save', function(next){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.stat_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return self.stat_file(a.o.path, Belt.cw(next, 0));
  });

  //setup file watching pre-init
  if (a.o.auto_watch) schema.post('init', function(){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.watch_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.watch_file(a.o.path, Belt.noop);
  });

  //stop watching file on removal
  schema.pre('remove', function(next){
    var self = this;

    if (!self.get(a.o.path)) return next();

    if (a.o.array)
      _.each(this.get(a.o.path), function(p, i){
        return self.unwatch_file(a.o.path + '.' + i);
      });

    this.unwatch_file(a.o.path);

    return next();
  });

  //remove file post-remove
  if (a.o.auto_remove) schema.post('remove', function(){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.rm_file(a.o.path + '.' + (index - 1), Belt.cw(cb));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.rm_file(a.o.path, Belt.noop);
  });

  //update file timestamps pre-save
  if (a.o.auto_update) schema.pre('save', function(next){
    if (!this.isModified(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();
        if (!self.isModified(a.o.path + '.' + (index -1))) return cb();

        return self.update_ftimes(a.o.path + '.' + (index - 1), Belt.cw(cb));
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();
    if (!self.isModified(a.o.path)) return next();

    return self.update_ftimes(a.o.path, Belt.cw(next, 0));
  });

  //require that file exists
  if (a.o.exists_required) schema.pre('validate', function(next){
    if (!this.get(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1))) return cb();

        return FSTK.exists(self.get(a.o.path + '.' + (index - 1) + '.file_path')
        , function(exists){
          return cb(exists ? null
                           : new Error(self.get(a.o.path + '.' + (index - 1) + '.file_path') + ' does not exist'));
        });
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return FSTK.exists(self.get(a.o.path + '.file_path'), function(exists){
      return next(exists ? null
             : new Error(self.get(a.o.path + '.file_path') + ' does not exist'));
    });
  });

  return schema;
};
<commit_msg>latest<commit_after>/*
  Add a path that represents a file
*/

'use strict';

var Belt = require('jsbelt')
  , _ = require('underscore')
  , FS = require('fs')
  , Async = require('async')
  , FSTK = require('fstk');

module.exports = function(schema, options){
  var a = Belt.argulint(arguments, {
                         'validators': {
                            'options': [
                              {
                                'validator': function(){
                                   return this.path;
                                 }
                              , 'error': new Error('path is required')
                              }
                             ]
                          }
                       , 'options': options || {}
                       });

  a.o = _.defaults(a.o, {
    'path': false
  , 'schema': {
      'file_path': {type: String}
    , 'stat': Object
    }
  , 'array': false
  , 'auto_stat': true //stat path pre save
  , 'auto_remove': true //remove path when doc is removed
  , 'auto_touch': true //create path on save if it does not exist
  , 'auto_update': true //update file timestamps post save
  , 'auto_watch': false //watch path using FSTK pre init
  , 'exists_required': false //invalidate if path does not exist
  , 'virtual_prefix': '__'
  });

  var def = [a.o.schema];
  if (a.o.array) def = [def];

  schema.add(_.object([a.o.path], def));

  var vp = schema.virtual(a.o.path + '_prev_path');
  vp.get(function(){
    return this[a.o.virtual_prefix + a.o.path + '_prev_path'];
  });
  vp.set(function(val){
    return this[a.o.virtual_prefix + a.o.path + '_prev_path'] = val;
  });

  var vp2 = schema.virtual(a.o.path + '_prev_buffer');
  vp2.get(function(){
    return this[a.o.virtual_prefix + a.o.path + '_prev_buffer'];
  });
  vp2.set(function(val){
    return this[a.o.virtual_prefix + a.o.path + '_prev_buffer'] = val;
  });

  //stat the file at path
  schema.method('stat_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;
    return FSTK.stat(self.get(path + '.file_path'), function(err, stat){
      if (err) return b.cb(err);
      self.set(path + '.stat', stat);
      return b.cb(err, stat);
    });
  });

  //watch the file at path
  schema.method('watch_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    self.unwatch_file(path);

    return FSTK.watchFile(self.get(path + '.file_path'), _.pick(a.o, ['deserializer', 'serializer', 'auto_stat']), function(err, wf){
      if (err) return b.cb(err);
      self.get(path)[a.o.virtual_prefix + 'watcher'] = wf;

      if (a.o.auto_stat){
        self.set(path + '.stat', wf.stat);

        wf.emitter.on('read', function(){
          return self.set(path + '.stat', wf.stat);
        });

        wf.emitter.on('write', function(){
          return self.set(path + '.stat', wf.stat);
        });
      }

      return b.cb(err, wf);
    });
  });

  //unwatch the file at path
  schema.method('unwatch_file', function(path){
    var self = this;

    if (!Belt._get(self.get(path), a.o.virtual_prefix + 'watcher')) return false;

    Belt._call(self.get(path)[a.o.virtual_prefix + 'watcher.watcher'], 'close');
    self.get(path)[a.o.virtual_prefix + 'watcher'] = null;

    return true;
  });

  //remove the file at path
  schema.method('rm_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;
    return FSTK.rm(self.get(path + '.file_path'), function(err){
      return b.cb(err);
    });
  });

  //create the file at path
  schema.method('create_file', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    b.o = _.defaults(b.o, {
      'data': ''
    });

    return FSTK.writeFile(self.get(path + '.file_path'), b.o.data, function(err){
      return b.cb(err);
    });
  });

  //update file timestamps
  schema.method('update_ftimes', function(path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this;

    b.o = _.defaults(b.o, {
      'atime': new Date()
    , 'mtime': self.get('updated_at') || new Date()
    });

    return FS.utimes(self.get(path + '.file_path'), b.o.atime, b.o.mtime, function(err){
      return b.cb(err);
    });
  });

  //set file
  schema.method('set_file', function(path, file_path, options, callback){
    var b = Belt.argulint(arguments)
      , self = this
      , globals = {};

    b.o = _.defaults(b.o, {
      'prev_path': false
    , 'data': false
    });

    return Async.waterfall([
      function(cb){
        self.unwatch_file(path);
        self.set(path + '.file_path', file_path);
        return cb();
      }
    , function(cb){
        if (!b.o.prev_path) return cb();
        return FSTK.mv(b.o.prev_path, file_path, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!b.o.data) return cb();
        return self.create_file(path, b.o, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!a.o.auto_touch) return cb();
        return FSTK.exists(file_path, Belt.cs(cb, globals, 'exists', 0));
      }
    , function(cb){
        if (!a.o.auto_touch || globals.exists) return cb();
        return self.create_file(path, Belt.cw(cb, 0));
      }
    , function(cb){
        if (!a.o.auto_watch) return cb();
        return self.watch_file(path, Belt.cw(cb, 0));
      }
    ], function(err){
      return b.cb(err);
    });
  });

  schema.method('file_extension', function(){
    var p = this.get('file.file_path');
    if (!p) return;
    return p.split('.').pop();
  });

  //MIDDLEWARE

  schema.pre('save', function(next){
    if (!this.get(a.o.path + '_prev_path')) return next();

    var p = this.get(a.o.path + '_prev_path');
    this.set(a.o.path + '_prev_path', undefined);
    return FSTK.mv(p, this.get(a.o.path + '.file_path'), Belt.cw(next, 0));
  });

  schema.pre('save', function(next){
    if (!this.get(a.o.path + '_prev_buffer')) return next();

    var p = this.get(a.o.path + '_prev_buffer');
    this.set(a.o.path + '_prev_buffer', undefined);

    return FSTK._fs.writeFile(this.get(a.o.path + '.file_path'), p, Belt.cw(next, 0));
  });

  //stat files pre-init
  if (a.o.auto_stat && !a.o.auto_watch) schema.post('init', function(){
    if (!this.get(a.o.path)) return;

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.stat_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.stat_file(a.o.path, Belt.noop);
  });

  //create files if it does not exist pre-save
  if (a.o.auto_touch) schema.pre('save', function(next){
    if (!this.get(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return FSTK.exists(self.get(a.o.path + '.' + (index - 1) + '.file_path')
        , function(exists){
          if (exists) return cb();

          return FSTK.writeFile(self.get(a.o.path + '.' + (index - 1) + '.file_path')
          , '', Belt.cw(cb, 0));
        });
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return FSTK.exists(self.get(a.o.path + '.file_path'), function(exists){
      if (exists) return next();

      return FSTK.writeFile(self.get(a.o.path + '.file_path'), '', Belt.cw(next, 0));
    });
  });

  //stat files pre-save
  if (a.o.auto_stat) schema.pre('save', function(next){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.stat_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return self.stat_file(a.o.path, Belt.cw(next, 0));
  });

  //setup file watching pre-init
  if (a.o.auto_watch) schema.post('init', function(){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.watch_file(a.o.path + '.' + (index - 1), Belt.cw(cb, 0));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.watch_file(a.o.path, Belt.noop);
  });

  //stop watching file on removal
  schema.pre('remove', function(next){
    var self = this;

    if (!self.get(a.o.path)) return next();

    if (a.o.array)
      _.each(this.get(a.o.path), function(p, i){
        return self.unwatch_file(a.o.path + '.' + i);
      });

    this.unwatch_file(a.o.path);

    return next();
  });

  //remove file post-remove
  if (a.o.auto_remove) schema.post('remove', function(){
    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();

        return self.rm_file(a.o.path + '.' + (index - 1), Belt.cw(cb));
      }, Belt.noop);
    }

    if (!self.get(a.o.path + '.file_path')) return;

    return self.rm_file(a.o.path, Belt.noop);
  });

  //update file timestamps pre-save
  if (a.o.auto_update) schema.pre('save', function(next){
    if (!this.isModified(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1) + '.file_path')) return cb();
        if (!self.isModified(a.o.path + '.' + (index -1))) return cb();

        return self.update_ftimes(a.o.path + '.' + (index - 1), Belt.cw(cb));
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();
    if (!self.isModified(a.o.path)) return next();

    return self.update_ftimes(a.o.path, Belt.cw(next, 0));
  });

  //require that file exists
  if (a.o.exists_required) schema.pre('validate', function(next){
    if (!this.get(a.o.path)) return next();

    var b = Belt.argulint(arguments)
      , self = this;

    if (a.o.array){
      var index = 0;
      return Async.eachSeries(self.get(a.o.path), function(p, cb){
        index++;
        if (!self.get(a.o.path + '.' + (index -1))) return cb();

        return FSTK.exists(self.get(a.o.path + '.' + (index - 1) + '.file_path')
        , function(exists){
          return cb(exists ? null
                           : new Error(self.get(a.o.path + '.' + (index - 1) + '.file_path') + ' does not exist'));
        });
      }, Belt.cw(next, 0));
    }

    if (!self.get(a.o.path + '.file_path')) return next();

    return FSTK.exists(self.get(a.o.path + '.file_path'), function(exists){
      return next(exists ? null
             : new Error(self.get(a.o.path + '.file_path') + ' does not exist'));
    });
  });

  return schema;
};
<|endoftext|>


<commit_before>/*
 * impresario
 * https://github.com/goliatone/impresario
 *
 * Copyright (c) 2015 goliatone
 * Licensed under the MIT license.
 */

'use strict';

var extend = require('gextend');
var _inherit = require('util').inherits;
var EventEmitter = require('events').EventEmitter;
var _format = require('util').format;

var DEFAULTS = {
    autoinitialize: true,
    optional: [],
    required: [],
    //TODO: This should be an empty array, and
    //have secrets be its own plugin
    loadFiles: ['./.secrets.json'],
    loadEnvironnment: false,
    defaults: {}
};

function Impresario(config){

    if(!(this instanceof Impresario)){
        return new Impresario(config);
    }

    EventEmitter.call(this);
    config = extend({}, this.constructor.DEFAULTS, config);

    if(config.autoinitialize ) this.init(config);
}

_inherit(Impresario, EventEmitter);

Impresario.DEFAULTS = DEFAULTS;

Impresario.REQUIRED_PROPERTY = 'Impresario required property "%s" not available';
Impresario._format = _format;

Impresario.prototype.init = function(config){
    if(this.initialized) return;
    this.initialized = true;

    this._loaders = [];

    extend(this, this.constructor.DEFAULTS, config);

    this.loadFiles.map(function(file){
        this.use(loadSecret.bind(null, file), 'loadFile');
    }, this);

    if(this.loadEnvironnment) this.use(loadEnv, 'loadEnv');

    this.use(loadDefaults.bind(this.defaults), 'defaults');

    return this;
};

Impresario.prototype.load = function(){

    var loaded = [];
    //TODO: Move this to module, async loader
    this._loaders.map(function(loader){
        var conf = loader.call(this);
        if(Object.keys(conf).length === 0) return;
        loaded.push(conf);
    }, this);

    var defaults = Array.prototype.slice.call(arguments, 0);
    var config = this._loadUserDefaults(defaults, loaded);

    config = this._loadRequired(config);

    config = this._loadOptional(config);

    var self = this;
    process.nextTick(function(){
        self.emit('loaded', config);
    });
    // this.emit('loaded', config);
};

Impresario.prototype.use = function(loader, id){
    // this._loaderIds =
    this._loaders.push(loader);
};

//TODO: This is actually TreeHugger, how to we use it locally?
Impresario.loadEnvironment = function(name, prefix){
    prefix = prefix || 'NODE';

    function environmentName(str, prefix){
        str = str || '';
        prefix = prefix || '';
        str = prefix + '_' + str;
        str = str.replace(/\W+/g, '_'
                .replace(/([a-z\d])([A-Z])/g, '$1_$2'));
        str = str.toUpperCase();
        return str;
    }

    var envName = environmentName(name, 'NODE_TREEHUGHER');
    if(process.env[envName]) return;
    process.env[envName] = Date.now();

    var secrets = loadSecret('./.secrets.json');
    var varName;
    Object.keys(secrets).map(function(key){
        varName = environmentName(key, prefix);
        process.env[varName] = secrets[key];
    });
};

Impresario.prototype.logger = console;

//////////////////////////////////////////
/// PRIVATE METHODS
//////////////////////////////////////////

/**
 * Load default objects passed in as
 * "load" arguments, this are the user defaults.
 *
 * We can also pass in process.argv processed by
 * a library like commander
 *
 * @param  {Array} defaults Array of default objects
 * @param  {Array} loaded   Array of loaded objects
 * @return {Object}          Merged object
 */
Impresario.prototype._loadUserDefaults = function(defaults, loaded){
    var configs = ([{}].concat(loaded)).concat(defaults);
    var config = extend.apply(null, configs);
    return config;
};

Impresario.prototype._loadRequired = function(config){
    if(!this.required || !this.required.length) return config;

    this.required.map(function(prop){
        //If we do not have a required option, throw
        //if we do, then store
        if(config.hasOwnProperty(prop)) return;
        //Shoult we emit error instead?
        this.emit('error', new Error(_format(Impresario.REQUIRED_PROPERTY, prop)));
    }, this);

    /*
     * Required props should not be filtered by
     * optional loader.
     */
    this.optional = this.optional.concat(this.required);

    return config;
};

Impresario.prototype._loadOptional = function(config){
    if(!this.optional || !this.optional.length) return config;

    var output = {};
    this.optional.map(function(key){
        output[key] = config[key];
    });
    return output;
};

function loadDefaults(defaults){
    return defaults || {};
}

function loadEnv(){
    // console.log('LOADING ENV');

    function capitalize(str){
        return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
    }

    function solveKeyPath(name){
        var names = name.toLowerCase().split('_');
        name = names.pop(0);
        names.map(function(bit){
            name += capitalize(bit);
        });

        return name;
    }

    var prop, mappedKey, out = {};
    Object.keys(process.env).map(function(key){
        prop = process.env[key];
        mappedKey = solveKeyPath(key);
        out[mappedKey] = prop;
    });

    return out;
}

function loadSecret(filename){
    var fs = require('fs');
    var resolve = require('path').resolve;
    var join = require('path').join;

    var file,
        config = {};

    try {
        file = fs.readFileSync(filename, 'utf-8');
    } catch(e) {
        console.log('FILE DOES NOT EXISTS', filename);
        return config;
    }

    try {
        config = JSON.parse(file);
    } catch(e){
        console.log(e);
        return config;
    }

    return config;
}
/**
 * Exports module
 */
module.exports = Impresario;
<commit_msg>LIB: refactoring to use external loader<commit_after>/*
 * impresario
 * https://github.com/goliatone/impresario
 *
 * Copyright (c) 2015 goliatone
 * Licensed under the MIT license.
 */

'use strict';

var extend = require('gextend');
var _inherit = require('util').inherits;
var EventEmitter = require('events').EventEmitter;
var _format = require('util').format;

var DEFAULTS = {
    autoinitialize: true,
    optional: [],
    required: [],
    //TODO: This should be an empty array, and
    //have secrets be its own plugin
    loadFiles: ['./.secrets.json'],
    loadEnvironnment: false,
    defaults: {}
};

function Impresario(config){

    if(!(this instanceof Impresario)){
        return new Impresario(config);
    }

    EventEmitter.call(this);
    config = extend({}, this.constructor.DEFAULTS, config);

    if(config.autoinitialize ) this.init(config);
}

_inherit(Impresario, EventEmitter);

Impresario.DEFAULTS = DEFAULTS;

Impresario.REQUIRED_PROPERTY = 'Impresario required property "%s" not available';
Impresario._format = _format;

Impresario.prototype.init = function(config){
    if(this.initialized) return;
    this.initialized = true;

    this._loaders = [];

    extend(this, this.constructor.DEFAULTS, config);

    var fileLoader = require('./file');
    this.loadFiles.map(function(file){
        this.use(fileLoader.loader.bind(null, file), fileLoader.id + file);
    }, this);

    if(this.loadEnvironnment){
        var environmentLoader = require('./environment');
        this.use(environmentLoader.loader, environmentLoader.id);
    }

    var defaultsLoader = require('./defaults');
    this.use(defaultsLoader.loader, defaultsLoader.id);

    return this;
};

Impresario.prototype.load = function(){

    var loaded = [];
    //TODO: Move this to module, async loader
    this._loaders.map(function(loader){
        var conf = loader.call(this);
        if(Object.keys(conf).length === 0) return;
        loaded.push(conf);
    }, this);

    var defaults = Array.prototype.slice.call(arguments, 0);
    var config = this._loadUserDefaults(defaults, loaded);

    config = this._loadRequired(config);

    config = this._loadOptional(config);

    var self = this;
    process.nextTick(function(){
        self.emit('loaded', config);
    });
    // this.emit('loaded', config);
};

Impresario.prototype.use = function(loader, id){
    // this._loaderIds =
    this._loaders.push(loader);
};

//TODO: This is actually TreeHugger, how to we use it locally?
Impresario.loadEnvironment = function(name, prefix){
    prefix = prefix || 'NODE';

    function environmentName(str, prefix){
        str = str || '';
        prefix = prefix || '';
        str = prefix + '_' + str;
        str = str.replace(/\W+/g, '_'
                .replace(/([a-z\d])([A-Z])/g, '$1_$2'));
        str = str.toUpperCase();
        return str;
    }

    var envName = environmentName(name, 'NODE_TREEHUGHER');
    if(process.env[envName]) return;
    process.env[envName] = Date.now();

    var secrets = loadSecret('./.secrets.json');
    var varName;
    Object.keys(secrets).map(function(key){
        varName = environmentName(key, prefix);
        process.env[varName] = secrets[key];
    });
};

Impresario.prototype.logger = console;

//////////////////////////////////////////
/// PRIVATE METHODS
//////////////////////////////////////////

/**
 * Load default objects passed in as
 * "load" arguments, this are the user defaults.
 *
 * We can also pass in process.argv processed by
 * a library like commander
 *
 * @param  {Array} defaults Array of default objects
 * @param  {Array} loaded   Array of loaded objects
 * @return {Object}          Merged object
 */
Impresario.prototype._loadUserDefaults = function(defaults, loaded){
    var configs = ([{}].concat(loaded)).concat(defaults);
    var config = extend.apply(null, configs);
    return config;
};

Impresario.prototype._loadRequired = function(config){
    if(!this.required || !this.required.length) return config;

    this.required.map(function(prop){
        //If we do not have a required option, throw
        //if we do, then store
        if(config.hasOwnProperty(prop)) return;
        //Shoult we emit error instead?
        this.emit('error', new Error(_format(Impresario.REQUIRED_PROPERTY, prop)));
    }, this);

    /*
     * Required props should not be filtered by
     * optional loader.
     */
    this.optional = this.optional.concat(this.required);

    return config;
};

Impresario.prototype._loadOptional = function(config){
    if(!this.optional || !this.optional.length) return config;

    var output = {};
    this.optional.map(function(key){
        output[key] = config[key];
    });
    return output;
};

function loadSecret(filename){
    var fs = require('fs');
    var resolve = require('path').resolve;
    var join = require('path').join;

    var file,
        config = {};

    try {
        file = fs.readFileSync(filename, 'utf-8');
    } catch(e) {
        console.log('FILE DOES NOT EXISTS', filename);
        return config;
    }

    try {
        config = JSON.parse(file);
    } catch(e){
        console.log(e);
        return config;
    }

    return config;
}
/**
 * Exports module
 */
module.exports = Impresario;
<|endoftext|>


<commit_before>var matrix = {
	conf: {},
	canvas: false,
	controls: false,
	data: {},
	elements: [],
	init: function() {
		matrix.conf.width = $('#canvas').width();
		matrix.conf.height = $('#canvas').height();
		matrix.conf.ratio = matrix.conf.height / matrix.conf.width;
		matrix.canvas = Raphael('canvas', matrix.conf.width, matrix.conf.height);
		matrix.controls = $('#controls');

		/* iniitialize data */

		matrix.parse();
		matrix.ui();

	},
	redraw: function() {

		var compare = [];
		var year = 0;

		var drawdata = {
			data: {},
			tables: [],
			min: {},
			max: {},
			axid: {},
			year: $('#year').val()
		};

		$("select.table", matrix.controls).each(function(idx,e){
			drawdata.tables.push($(e).val());
		});

		if (drawdata.tables[0] === drawdata.tables[1]) {

			alert("FAIL");
			return;

		}

		drawdata.axid[drawdata.tables[0]] = "y";
		drawdata.axid[drawdata.tables[1]] = "x";

		$(drawdata.tables).each(function(idx,e){

			if (matrix.data.tables[e].years[drawdata.year] === undefined) {

				alert("FAIL!");
				return;

			}

			drawdata.min[drawdata.axid[e]] = matrix.data.tables[e].minValue;
			drawdata.max[drawdata.axid[e]] = matrix.data.tables[e].maxValue;

			var x = e;

			$(data.data[matrix.data.tables[e].years[drawdata.year]].data).each(function(idx,d){

				if (drawdata.data[d.geoIndex] === undefined) {

					drawdata.data[d.geoIndex] = {};

				}

				drawdata.data[d.geoIndex][drawdata.axid[e]] = d.value;

			});

		});

		// console.log(drawdata);

		/* clear paper */

		matrix.elements = [];
		matrix.paper.clear();

		/* axes drawing */

		var axwidth = (matrix.conf.width - 80);
		var axheight = (matrix.conf.height - 80);

		var yrange = (drawdata.max.y-drawdata.min.y);
		var xrange = (drawdata.max.x-drawdata.min.x);

		matrix.elements.push(Raphael.g.axis(40, (matrix.conf.height-40), axheight, drawdata.min.y, drawdata.max.y, yrange, 1, [], "t", 2, matrix.canvas).attr('stroke','#999999'));
		matrix.elements.push(Raphael.g.axis(40, (matrix.conf.height-40), axwidth, drawdata.min.x, drawdata.max.x, xrange, 0, [], "t", 2, matrix.canvas).attr('stroke','#999999'));

		/* data drawing */

		var item;

		for (var key in drawdata.data) {

			item = drawdata.data[key];

			if (item.x !== 0 && item.y !== 0) {

				item.drawx = (40+(axwidth*((item.x-drawdata.min.x)/xrange)));
				item.drawy = (matrix.conf.height-(40+(axheight*((item.y-drawdata.min.y)/yrange))));

				item.element = matrix.canvas.circle(item.drawx,item.drawy,5);

				item.element.attr('fill','#cccccc');
				item.element.attr('stroke','#999999');
				item.element.attr('title','x: '+item.x+', y: '+item.y);

				matrix.elements.push(item.element);

			}

		}

	},
	ui: function() {

		/* build controls ui */

		var ui_select = $('<select name="table[]" class="table" size="1"></select>');
		$(matrix.data.table_names).each(function(idx,e){
			ui_select.append('<option value="'+idx+'">'+e+'</option>');
		});

		ui_select_2 = ui_select.clone()

		var change = function() {
			matrix.controls.submit();
		}

		$(ui_select).change(function(){
			change();
		});

		$(ui_select_2).change(function(){
			change();
		});

		matrix.controls.append(ui_select_2);
		matrix.controls.append(ui_select);

		/* fixme: year slider */

		var year_select = $('<select name="year" id="year" size="1"><option value="1992">1992</option><option value="1993">1993</option><option value="1994">1994</option><option value="1995">1995</option><option value="1996">1996</option><option value="1997">1997</option><option value="1998">1998</option><option value="1999">1999</option><option value="2000">2000</option><option value="2001">2001</option><option value="2002">2002</option><option value="2003">2003</option><option value="2004">2004</option><option value="2005">2005</option><option value="2006">2006</option><option value="2007">2007</option><option value="2008">2008</option><option value="2009">2009</option><option value="2010">2010</option><option value="2011">2011</option></select>')

		$(year_select).change(function(){
			change();
		});

		matrix.controls.append(year_select);

		matrix.controls.append($('<input type="submit" value="Vergleichen" />'));

		matrix.controls.submit(function(x){
			matrix.redraw();
		});

	},
	parse: function() {

		/* geodaten */

		matrix.data.regions = [];
		var geo = data.geo[0].data;
		for (var i = 0; i < geo.length; i++) {
			matrix.data.regions.push(geo[i].geometry.coordinates);
		}

		/* datensätze */

		matrix.data.tables = [];
		var obj = {};
		matrix.data.table_index = -1;
		matrix.data.table_names = [];
		for (var i = 0; i < data.data.length; i++) {
			var name = data.data[i].options.tableName;
			var year = data.data[i].options.year;
			if (obj[name] === undefined) {
				matrix.data.table_index++;
				matrix.data.tables[matrix.data.table_index] = {
					tableName: name,
					years: [],
					minYear:  1e10,
					maxYear: -1e10,
					minValue: 0,
					maxValue: -1e10
				}
				obj[name] = matrix.data.table_index;
				matrix.data.table_names[matrix.data.table_index] = name;
			}
			var tl = matrix.data.tables[obj[name]];
			tl.years[year] = i;
			if (tl.minYear > year) tl.minYear = year;
			if (tl.maxYear < year) tl.maxYear = year;

			var d = data.data[i].data;
			for (var j = 0; j < d.length; j++) {
				var v = d[j].value;
				if (tl.minValue > v) tl.minValue = v;
				if (tl.maxValue < v) tl.maxValue = v;
			}

			if (data.data[i].options.minValue !== undefined) tl.minValue = data.data[i].options.minValue;
			if (data.data[i].options.maxValue !== undefined) tl.maxValue = data.data[i].options.maxValue;
		}

		/*

		for (var i = 0; i < matrix.data.tables.length; i++) {
			var t = matrix.data.tables[i];

			if (minYear > t.minYear) minYear = t.minYear;
			if (maxYear < t.maxYear) maxYear = t.maxYear;

			t.node = $('
'+t.tableName+'
');
			$('#datasets').append(t.node);
			t.node.click((function () {
				var id = i;
				return function () {
					selectTable(id);
				}
			})());
		}

		*/
	}
}

$(document).ready(function(){
	matrix.init();
});<commit_msg>adding new projection system<commit_after>var matrix = {
	conf: {},
	canvas: false,
	controls: false,
	data: {},
	elements: [],
	init: function() {
		matrix.conf.width = $('#canvas').width();
		matrix.conf.height = $('#canvas').height();
		matrix.conf.ratio = matrix.conf.height / matrix.conf.width;
		matrix.paper = Raphael('canvas', matrix.conf.width, matrix.conf.height);
		matrix.controls = $('#controls');
		matrix.padding = { top: 20, bottom: 30, left: 60, right: 30 };

		/* initialize data */

		matrix.parse();
		matrix.ui();

	},
	redraw: function() {

		var compare = [];
		var year = 0;

		var drawdata = {
			data: {},
			tables: [],
			min: {},
			max: {},
			axid: {},
			year: $('#year').val()
		};

		$("select.table", matrix.controls).each(function(idx,e){
			drawdata.tables.push($(e).val());
		});

		if (drawdata.tables[0] === drawdata.tables[1]) {

			alert("FAIL");
			return;

		}

		drawdata.axid[drawdata.tables[0]] = "y";
		drawdata.axid[drawdata.tables[1]] = "x";

		$(drawdata.tables).each(function(idx,e){

			if (matrix.data.tables[e].years[drawdata.year] === undefined) {

				alert("FAIL!");
				return;

			}

			drawdata.min[drawdata.axid[e]] = matrix.data.tables[e].minValue;
			drawdata.max[drawdata.axid[e]] = matrix.data.tables[e].maxValue;

			var x = e;

			$(data.data[matrix.data.tables[e].years[drawdata.year]].data).each(function(idx,d){

				if (drawdata.data[d.geoIndex] === undefined) {

					drawdata.data[d.geoIndex] = {};

				}

				drawdata.data[d.geoIndex][drawdata.axid[e]] = d.value;

			});

		});

		// console.log(drawdata);

		/* clear paper */

		matrix.elements = [];
		matrix.paper.clear();

		var xAxis = new Axis(
			matrix.padding.left,
			matrix.conf.width - matrix.padding.right,
			drawdata.min.x,
			drawdata.max.x
		);

		var yAxis = new Axis(
			matrix.conf.height - matrix.padding.bottom,
			matrix.padding.top,
			drawdata.min.y,
			drawdata.max.y
		);

		/* axes drawing */

		var axwidth = (matrix.conf.width - 80);
		var axheight = (matrix.conf.height - 80);

		var yrange = (drawdata.max.y-drawdata.min.y);
		var xrange = (drawdata.max.x-drawdata.min.x);

		matrix.elements.push(Raphael.g.axis(40, (matrix.conf.height-40), axheight, drawdata.min.y, drawdata.max.y, yrange, 1, [], "t", 2, matrix.canvas).attr('stroke','#999999'));
		matrix.elements.push(Raphael.g.axis(40, (matrix.conf.height-40), axwidth, drawdata.min.x, drawdata.max.x, xrange, 0, [], "t", 2, matrix.canvas).attr('stroke','#999999'));

		/* data drawing */

		var item;

		for (var key in drawdata.data) {

			item = drawdata.data[key];

			if (item.x !== 0 && item.y !== 0) {

				item.drawx = (40+(axwidth*((item.x-drawdata.min.x)/xrange)));
				item.drawy = (matrix.conf.height-(40+(axheight*((item.y-drawdata.min.y)/yrange))));

				item.element = matrix.canvas.circle(item.drawx,item.drawy,5);

				item.element.attr('fill','#cccccc');
				item.element.attr('stroke','#999999');
				item.element.attr('title','x: '+item.x+', y: '+item.y);

				matrix.elements.push(item.element);

			}

		}

	},
	ui: function() {

		/* build controls ui */

		var ui_select = $('<select name="table[]" class="table" size="1"></select>');
		$(matrix.data.table_names).each(function(idx,e){
			ui_select.append('<option value="'+idx+'">'+e+'</option>');
		});

		ui_select_2 = ui_select.clone()

		var change = function() {
			matrix.controls.submit();
		}

		$(ui_select).change(function(){
			change();
		});

		$(ui_select_2).change(function(){
			change();
		});

		matrix.controls.append(ui_select_2);
		matrix.controls.append(ui_select);

		/* fixme: year slider */

		var year_select = $('<select name="year" id="year" size="1"><option value="1992">1992</option><option value="1993">1993</option><option value="1994">1994</option><option value="1995">1995</option><option value="1996">1996</option><option value="1997">1997</option><option value="1998">1998</option><option value="1999">1999</option><option value="2000">2000</option><option value="2001">2001</option><option value="2002">2002</option><option value="2003">2003</option><option value="2004">2004</option><option value="2005">2005</option><option value="2006">2006</option><option value="2007">2007</option><option value="2008">2008</option><option value="2009">2009</option><option value="2010">2010</option><option value="2011">2011</option></select>')

		$(year_select).change(function(){
			change();
		});

		matrix.controls.append(year_select);

		matrix.controls.append($('<input type="submit" value="Vergleichen" />'));

		matrix.controls.submit(function(x){
			matrix.redraw();
		});

	},
	parse: function() {

		/* geodaten */

		matrix.data.regions = [];
		var geo = data.geo[0].data;
		for (var i = 0; i < geo.length; i++) {
			matrix.data.regions.push(geo[i].geometry.coordinates);
		}

		/* datensätze */

		matrix.data.tables = [];
		var obj = {};
		matrix.data.table_index = -1;
		matrix.data.table_names = [];
		for (var i = 0; i < data.data.length; i++) {
			var name = data.data[i].options.tableName;
			var year = data.data[i].options.year;
			if (obj[name] === undefined) {
				matrix.data.table_index++;
				matrix.data.tables[matrix.data.table_index] = {
					tableName: name,
					years: [],
					minYear:  1e10,
					maxYear: -1e10,
					minValue: 0,
					maxValue: -1e10
				}
				obj[name] = matrix.data.table_index;
				matrix.data.table_names[matrix.data.table_index] = name;
			}
			var tl = matrix.data.tables[obj[name]];
			tl.years[year] = i;
			if (tl.minYear > year) tl.minYear = year;
			if (tl.maxYear < year) tl.maxYear = year;

			var d = data.data[i].data;
			for (var j = 0; j < d.length; j++) {
				var v = d[j].value;
				if (tl.minValue > v) tl.minValue = v;
				if (tl.maxValue < v) tl.maxValue = v;
			}

			if (data.data[i].options.minValue !== undefined) tl.minValue = data.data[i].options.minValue;
			if (data.data[i].options.maxValue !== undefined) tl.maxValue = data.data[i].options.maxValue;
		}

		/*

		for (var i = 0; i < matrix.data.tables.length; i++) {
			var t = matrix.data.tables[i];

			if (minYear > t.minYear) minYear = t.minYear;
			if (maxYear < t.maxYear) maxYear = t.maxYear;

			t.node = $('
'+t.tableName+'
');
			$('#datasets').append(t.node);
			t.node.click((function () {
				var id = i;
				return function () {
					selectTable(id);
				}
			})());
		}

		*/
	}
}

var Axis = function (pixelMin, pixelMax, valueMin, valueMax) {
	var pixelWidth = Math.abs(pixelMax - pixelMin);
	var valueWidth = Math.abs(valueMax - valueMin);
	var valueDensity = pixelWidth/valueWidth;

	var minTickSpace = 80;
	var step = valueDensity*minTickSpace;
	var e = Math.pow(10, Math.floor(Math.log(step)/Math.LN10));
	var v = step/e; // (1.0 ... 9.999)

	var majorTick, minorTick;

	if (v < 2) {
		majorTick =  2*e;
		minorTick =  1*e;
	} else if (v < 5) {
		majorTick =  5*e;
		minorTick =  1*e;
	} else {
		majorTick = 10*e;
		minorTick =  2*e;
	}

	var maxTickValue = Math.ceil( valueMax/majorTick - 1e-8)*majorTick;
	var minTickValue = Math.floor(valueMin/majorTick + 1e-8)*majorTick;

	var paramA = (pixelMax - pixelMin)/(valueMax - valueMin);
	var paramB = (-valueMin)*a + pixelMin;

	function project(value) {
		return value*a + b;
	}

	var me = this;
	me.majorTick = majorTick;
	me.minorTick = minorTick;
	me.maxValue = maxTickValue;
	me.minValue = minTickValue;
	me.project = project;

	return me;
}

$(document).ready(function(){
	matrix.init();
});<|endoftext|>


<commit_before>/** Representing an individual
 *
 * @module individual
 */

let _id = 0

export class Individual {
    constructor (species, id) {
        this.id = id ? id : Individual.id
        this.species = species
    }

    static get id() {
        return _id ++
    }
}

export let generate_basic_individual = (species, genome_generator) => {
    return new Individual(species)
}
<commit_msg>sex support<commit_after>/** Representing an individual
 *
 * @module individual
 */

let _id = 0

export class Individual {
    constructor (species, id) {
        this.id = id ? id : Individual.id
        this.species = species
    }

    static get id() {
        return _id ++
    }
}

export let generate_basic_individual = (species, genome_generator) => {
    return new Individual(species)
}

export let assign_random_sex = (individual) => {
    individual.is_female = Math.random() >= .5
    return individual
}
<|endoftext|>


<commit_before>var model = require('model')
  , path = require('path')
  , utils = require('utilities')
  , useCoffee = false;

module.exports = new (function () {

  var _getAdapterPath = function (base, name) {
        var p = path.join(base, utils.string.snakeize(name))
        , testPath;

        // Fucking CoffeeScript
        testPath = p + '.coffee';
        if (utils.file.existsSync(testPath)) {
          useCoffee = useCoffee || utils.file.requireLocal('coffee-script');
          return testPath;
        }
        // Normal JS
        testPath = p + '.js';
        if (utils.file.existsSync(testPath)) {
          return testPath;
        }
        // Nothing found
        return null;
      }

  var _getAdapterConfig = function (dbConfig, adapterName) {
    var info;
    for (var p in dbConfig) {
      // Return the first alias key recognized whose
      // canonical name is the same
      info = model.getAdapterInfo(p);
      if (info && info.name == adapterName) {
        return dbConfig[p];
      }
    }
  }

  this.init = function (app, callback) {
    var modelDir = path.join('app/models')
      , cwd = process.cwd()
      , builtinAdaptersPath = path.join(__dirname,
            '../../node_modules/model/lib/adapters')
      , appAdaptersPath = path.join(cwd, modelDir, 'adapters')
      , ctors;

    // May be running totally model-less
    if (!utils.file.existsSync(path.join(cwd, modelDir))) {
      return callback();
    }

    // Set any model properties from the app config
    utils.mixin(model, geddy.config.model);

    models = utils._getConstructorsFromDirectory(modelDir);
    models.forEach(function (m) {
      var name = m.ctorName
        , filePath = m.filePath
        , adapterInfo
        , adapterPath
        , adapterName
        , adapterCtor
        , adapter
        , config;

      require(filePath);

      // If the model doesn't exist, something is fucked up
      if (!model[name]) {
        throw new Error('Model ' + name + ' did not get registered properly.');
      }

      adapterName = model[name].adapter;
      // Is there a specific adapter defined for this model item?
      if (adapterName) {
        // See if it's a custom in-app adapter
        adapterPath = _getAdapterPath(appAdaptersPath, adapterName);
        // Try again, see if there's a built-in adapter
        if (!adapterPath) {
          adapterInfo = model.getAdapterInfo(adapterName);
          if (adapterInfo) {
            adapterName = adapterInfo.name;
            adapterPath = _getAdapterPath(builtinAdaptersPath, adapterInfo.filePath);
          }
        }
      }
      else {
        // Look for a default adapter
        adapterName = model.defaultAdapter;
        if (adapterName) {
          adapterInfo = model.getAdapterInfo(adapterName);
          if (adapterInfo) {
            adapterName = adapterInfo.name;
            adapterPath =
                _getAdapterPath(builtinAdaptersPath, adapterInfo.filePath);
          }
        }
      }

      // No adapter, log an error
      if (!adapterPath) {
        geddy.log.info('Model adapter not found for ' + name +
            '. Set .adapter for this model, or set model.defaultAdapter.');
      }
      else {
        adapter = model.loadedAdapters[adapterName];
        if (!adapter) {
          config = _getAdapterConfig(geddy.config.db, adapterName);
          adapterCtor = require(adapterPath).Adapter;
          adapter = new adapterCtor(config);
          if (typeof adapter.connect == 'function') {
            adapter.connect();
          }
          model.loadedAdapters[adapterName] = adapter;
          if (typeof adapter.createTable == 'function') {
            // FIXME -- fire-and-forget bad, need to make this
            // recursive
            adapter.createTable(name, function () {});
          }
        }
        model.adapters[name] = adapter;
      }

    });
    callback();
  };

})();

<commit_msg>Loaded adapters should be registered per-model<commit_after>var model = require('model')
  , path = require('path')
  , utils = require('utilities')
  , useCoffee = false;

module.exports = new (function () {

  var _getAdapterPath = function (base, name) {
        var p = path.join(base, utils.string.snakeize(name))
        , testPath;

        // Fucking CoffeeScript
        testPath = p + '.coffee';
        if (utils.file.existsSync(testPath)) {
          useCoffee = useCoffee || utils.file.requireLocal('coffee-script');
          return testPath;
        }
        // Normal JS
        testPath = p + '.js';
        if (utils.file.existsSync(testPath)) {
          return testPath;
        }
        // Nothing found
        return null;
      }

  var _getAdapterConfig = function (dbConfig, adapterName) {
    var info;
    for (var p in dbConfig) {
      // Return the first alias key recognized whose
      // canonical name is the same
      info = model.getAdapterInfo(p);
      if (info && info.name == adapterName) {
        return dbConfig[p];
      }
    }
  }

  this.init = function (app, callback) {
    var modelDir = path.join('app/models')
      , cwd = process.cwd()
      , builtinAdaptersPath = path.join(__dirname,
            '../../node_modules/model/lib/adapters')
      , appAdaptersPath = path.join(cwd, modelDir, 'adapters')
      , ctors;

    // May be running totally model-less
    if (!utils.file.existsSync(path.join(cwd, modelDir))) {
      return callback();
    }

    // Set any model properties from the app config
    utils.mixin(model, geddy.config.model);

    models = utils._getConstructorsFromDirectory(modelDir);
    models.forEach(function (m) {
      var name = m.ctorName
        , filePath = m.filePath
        , adapterInfo
        , adapterPath
        , adapterName
        , adapterCtor
        , adapter
        , config;

      require(filePath);

      // If the model doesn't exist, something is fucked up
      if (!model[name]) {
        throw new Error('Model ' + name + ' did not get registered properly.');
      }

      adapterName = model[name].adapter;
      // Is there a specific adapter defined for this model item?
      if (adapterName) {
        // See if it's a custom in-app adapter
        adapterPath = _getAdapterPath(appAdaptersPath, adapterName);
        // Try again, see if there's a built-in adapter
        if (!adapterPath) {
          adapterInfo = model.getAdapterInfo(adapterName);
          if (adapterInfo) {
            adapterName = adapterInfo.name;
            adapterPath = _getAdapterPath(builtinAdaptersPath, adapterInfo.filePath);
          }
        }
      }
      else {
        // Look for a default adapter
        adapterName = model.defaultAdapter;
        if (adapterName) {
          adapterInfo = model.getAdapterInfo(adapterName);
          if (adapterInfo) {
            adapterName = adapterInfo.name;
            adapterPath =
                _getAdapterPath(builtinAdaptersPath, adapterInfo.filePath);
          }
        }
      }

      // No adapter, log an error
      if (!adapterPath) {
        geddy.log.info('Model adapter not found for ' + name +
            '. Set .adapter for this model, or set model.defaultAdapter.');
      }
      else {
        adapter = model.loadedAdapters[adapterName];
        if (!adapter) {
          config = _getAdapterConfig(geddy.config.db, adapterName);
          adapterCtor = require(adapterPath).Adapter;
          adapter = new adapterCtor(config);
          if (typeof adapter.connect == 'function') {
            adapter.connect();
          }
          model.loadedAdapters[name] = adapter;
          if (typeof adapter.createTable == 'function') {
            // FIXME -- fire-and-forget bad, need to make this
            // recursive
            adapter.createTable(name, function () {});
          }
        }
        model.adapters[name] = adapter;
      }

    });
    callback();
  };

})();

<|endoftext|>


<commit_before>'use strict';

/**
 * Init system for Node.js, main file.
 * (C) 2015 Alex Fernández.
 */

// requires
require('prototypes');
var Log = require('log');
var util = require('util');
var events = require('events');
var domain = require('domain');
var queueLib = require('./queueLib.js');

// globals
var globalDomain = domain.create();

// constants
var EVENTS = ['init', 'start', 'stop', 'finish'];
var DEFAULT_OPTIONS = {
	catchSignals: true,
	catchErrors: true,
	exitProcess: true,
	showErrors: true,
	showTraces: false,
	logTimes: true,
	stopOnError: true,
	maxTaskTimeSec: 10,
	stopInParallel: false,
};

function InitSystem()
{
	this.taskQueues = {};
	this.flags = {};
	this.standaloneTask = null;
	this.startingUp = false;
	this.shuttingDown = false;
	this.finished = false;
	this.phase = 'pre';
	this.log = new Log('info');
	this.options = {};
	this.options.overwriteWith(DEFAULT_OPTIONS);
}

util.inherits(InitSystem, events.EventEmitter);

InitSystem.prototype.startup = function()
{
	var self = this;
	EVENTS.forEach(function(event)
	{
		self.taskQueues[event] = queueLib.create(event);
		self[event] = self.getAdder(event);
	});
	events.EventEmitter.call(self);
	setImmediate(function()
	{
		setTimeout(function()
		{
			self.reallyStartup();
		}, 0);
	});
};

InitSystem.prototype.getAdder = function(event)
{
	var self = this;
	return function(order, task)
	{
		if (self.flags[event])
		{
			return self.manageInternalError('Could not add ' + event + ' to queue after it has run: ' + new Error().stack);
		}
		if (typeof order == 'function')
		{
			task = order;
			order = null;
		}
		if (!task)
		{
			return self.manageInternalError('Could not add empty task to queue ' + event);
		}
		self.taskQueues[event].add(order, task);
	};
};

InitSystem.prototype.reallyStartup = function()
{
	var self = this;
	if (self.startingUp)
	{
		return self.manageInternalError('Could not start up again');
	}
	self.startingUp = true;
	var start = Date.now();
	self.emit('startup');
	self.setupErrors();
	self.runAll('init', function(error)
	{
		if (error)
		{
			return self.manageInternalError('Could not run init tasks: ' + error);
		}
		self.runAll('start', function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run start tasks: ' + error);
			}
			if (self.options.logTimes)
			{
				var elapsedSeconds = (Date.now() - start) / 1000;
				self.log.info('Initialization took %s seconds', elapsedSeconds.toFixed(1));
			}
			self.startingUp = false;
			self.emit('ready');
		});
	});
};

InitSystem.prototype.manageInternalError = function(error)
{
	var self = this;
	if (self.listeners('error').length > 0)
	{
		self.emit('error', error);
	}
	if (self.options.showTraces)
	{
		error = new Error(error).stack;
	}
	self.startShutdownByError(util.format('Error in phase %s: %s', self.phase, error));
};

InitSystem.prototype.runAll = function(event, callback)
{
	var self = this;
	if (self.flags[event])
	{
		return callback('Tasks for ' + event + ' already run');
	}
	if (self.taskQueues[event].remaining())
	{
		self.log.debug('Running queue for %s: %s tasks', event, self.taskQueues[event].remaining());
	}
	self.phase = event;
	self.emitInProgress(event);
	var runner = 'runQueue';
	if (self.options[event + 'InParallel'])
	{
		runner = 'runInParallel';
	}
	self[runner](self.taskQueues[event], function(error)
	{
		if (error)
		{
			return callback(error);
		}
		self.flags[event] = true;
		self.emit(event + 'ed');
		return callback(null);
	});
};

InitSystem.prototype.emitInProgress = function(event)
{
	var self = this;
	self.emit(event + 'ing');
	if (event.endsWith('p'))
	{
		self.emit(event + 'ping');
	}
};

InitSystem.prototype.runQueue = function(queue, callback)
{
	var self = this;
	if (!queue.remaining())
	{
		return callback(null);
	}
	var current = queue.next();
	self.run(current, function(error)
	{
		if (error)
		{
			if (self.options.showErrors)
			{
				self.log.error('Error in phase %s: %s', self.phase, error);
			}
			if (self.options.stopOnError)
			{
				return callback(error);
			}
		}
		return self.runQueue(queue, callback);
	});
};

InitSystem.prototype.runInParallel = function(queue, callback)
{
	var self = this;
	var total = queue.remaining();
	if (!total)
	{
		return callback(null);
	}
	var received = 0;
	while (queue.remaining())
	{
		var task = queue.next();
		self.run(task, function(error)
		{
			if (error)
			{
				if (self.options.showErrors)
				{
					self.log.error('Error in phase %s: %s', self.phase, error);
				}
				if (self.options.stopOnError && received < total)
				{
					received += total;
					return callback(error);
				}
			}
			received += 1;
			if (received == total)
			{
				return callback(null);
			}
		});
	}
};

InitSystem.prototype.run = function(current, callback)
{
	var self = this;
	self.log.debug('Running task: %s', current.name);
	var timeout = setTimeout(function()
	{
		self.log.warning('Task %s is taking more than %s seconds', current.name, self.options.maxTaskTimeSec);
	}, self.options.maxTaskTimeSec * 1000);
	timeout.unref();
	globalDomain.run(function()
	{
		current(function(error)
		{
			clearTimeout(timeout);
			callback(error);
		});
	});
};

InitSystem.prototype.setupErrors = function()
{
	var self = this;
	if (self.options.catchErrors)
	{
		globalDomain.on('error', function(error)
		{
			self.manageCrash('error', error);
		});
		process.on('uncaughtException', function(error)
		{
			self.manageCrash('uncaught exception', error);
		});
		process.on('beforeExit', function()
		{
			if (!self.shuttingDown)
			{
				self.shutdown();
			}
		});
		process.on('exit', function()
		{
			if (!self.finished && self.options.showErrors)
			{
				self.log.warning('Unexpected exit, please see documentation: https://github.com/alexfernandez/inits#unexpected-exit');
			}
		});
	}
	if (self.options.catchSignals)
	{
		process.on('SIGINT', function()
		{
			self.log.notice('User pressed control-C');
			self.signalled();
		});
		process.on('SIGTERM', function()
		{
			self.log.notice('Process killed');
			self.signalled();
		});
	}
};

InitSystem.prototype.manageCrash = function(type, error)
{
	var self = this;
	if (!self.options.catchErrors)
	{
		return;
	}
	if (self.listeners('error').length > 0)
	{
		self.emit('error', 'Unexpected ' + type + ': ' + error);
	}
	if (error.stack)
	{
		error = error.stack;
	}
	self.startShutdownByError(util.format('Process crashed with %s: %s', type, error));
};

InitSystem.prototype.startShutdownByError = function(error)
{
	var self = this;
	if (self.options.showErrors)
	{
		self.log.error(error);
	}
	if (!self.startingUp && !self.shuttingDown)
	{
		return self.shutdown(1);
	}
	if (self.options.showErrors)
	{
		var when = 'starting up';
		if (self.shuttingDown)
		{
			when = 'shutting down';
		}
		self.log.warning('Error while %s: exiting', when);
	}
	if (self.options.exitProcess)
	{
		self.finished = true;
		process.exit(1);
	}
};

InitSystem.prototype.signalled = function()
{
	var self = this;
	if (!self.options.catchSignals)
	{
		return;
	}
	self.shutdown();
};

/**
 * Shut down. Pass an error code if you want process.exit(errorCode), otherwise 0.
 */
InitSystem.prototype.shutdown = function(errorCode)
{
	var self = this;
	if (self.shuttingDown)
	{
		if (self.options.showErrors)
		{
			self.log.warning('Could not shutdown again');
		}
		return;
	}
	self.shuttingDown = true;
	var start = Date.now();
	self.emit('shutdown');
	self.runAll('stop', function(error)
	{
		if (error)
		{
			return self.manageInternalError('Could not run stop tasks: ' + error);
		}
		self.runAll('finish', function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run finish tasks: ' + error);
			}
			if (self.options.logTimes)
			{
				var elapsedSeconds = (Date.now() - start) / 1000;
				self.log.info('Shutdown took %s seconds', elapsedSeconds.toFixed(1));
			}
			self.emit('end');
			self.finished = true;
			if (self.options.exitProcess)
			{
				process.exit(errorCode || 0);
			}
		});
	});
};

InitSystem.prototype.standalone = function(task)
{
	var self = this;
	if (self.standaloneTask)
	{
		return self.manageInternalError('Already have standalone task');
	}
	self.standaloneTask = task;
	self.on('ready', self.runStandalone);
};

InitSystem.prototype.runStandalone = function()
{
	var self = this;
	self.phase = 'standalone';
	setImmediate(function()
	{
		self.standaloneTask(function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run standalone task: ' + error);
			}
			setImmediate(function()
			{
				self.shutdown();
			});
		});
	});
};

function create()
{
	var initSystem = new InitSystem();
	initSystem.startup();
	return initSystem;
}

module.exports = create();
module.exports.create = create;

<commit_msg>Issue https://github.com/alexfernandez/inits/issues/1.<commit_after>'use strict';

/**
 * Init system for Node.js, main file.
 * (C) 2015 Alex Fernández.
 */

// requires
require('prototypes');
var Log = require('log');
var util = require('util');
var events = require('events');
var domain = require('domain');
var queueLib = require('./queueLib.js');

// globals
var globalDomain = domain.create();

// constants
var EVENTS = ['init', 'start', 'stop', 'finish'];
var DEFAULT_OPTIONS = {
	catchSignals: true,
	catchErrors: true,
	exitProcess: true,
	showErrors: true,
	showTraces: false,
	logTimes: true,
	stopOnError: true,
	maxTaskTimeSec: 10,
	stopInParallel: false,
};

function InitSystem()
{
	this.taskQueues = {};
	this.flags = {};
	this.standaloneTask = null;
	this.startingUp = false;
	this.shuttingDown = false;
	this.finished = false;
	this.phase = 'pre';
	this.log = new Log('info');
	this.options = {};
	this.options.overwriteWith(DEFAULT_OPTIONS);
}

util.inherits(InitSystem, events.EventEmitter);

InitSystem.prototype.startup = function()
{
	var self = this;
	EVENTS.forEach(function(event)
	{
		self.taskQueues[event] = queueLib.create(event);
		self[event] = self.getAdder(event);
	});
	events.EventEmitter.call(self);
	setImmediate(function()
	{
		setTimeout(function()
		{
			self.reallyStartup();
		}, 0);
	});
};

InitSystem.prototype.getAdder = function(event)
{
	var self = this;
	return function(order, task)
	{
		if (self.flags[event])
		{
			return self.manageInternalError('Could not add ' + event + ' to queue after it has run: ' + new Error().stack);
		}
		if (typeof order == 'function')
		{
			task = order;
			order = null;
		}
		if (!task)
		{
			return self.manageInternalError('Could not add empty task to queue ' + event);
		}
		self.taskQueues[event].add(order, task);
	};
};

InitSystem.prototype.reallyStartup = function()
{
	var self = this;
	if (self.startingUp)
	{
		return self.manageInternalError('Could not start up again');
	}
	self.startingUp = true;
	var start = Date.now();
	self.emit('startup');
	self.setupErrors();
	self.runAll('init', function(error)
	{
		if (error)
		{
			return self.manageInternalError('Could not run init tasks: ' + error);
		}
		self.runAll('start', function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run start tasks: ' + error);
			}
			if (self.options.logTimes)
			{
				var elapsedSeconds = (Date.now() - start) / 1000;
				self.log.info('Initialization took %s seconds', elapsedSeconds.toFixed(1));
			}
			self.startingUp = false;
			self.emit('ready');
		});
	});
};

InitSystem.prototype.manageInternalError = function(error)
{
	var self = this;
	if (self.listeners('error').length > 0)
	{
		self.emit('error', error);
	}
	if (self.options.showTraces)
	{
		error = new Error(error).stack;
	}
	self.startShutdownByError(util.format('Error in phase %s: %s', self.phase, error));
};

InitSystem.prototype.runAll = function(event, callback)
{
	var self = this;
	if (self.flags[event])
	{
		return callback('Tasks for ' + event + ' already run');
	}
	if (self.taskQueues[event].remaining())
	{
		self.log.debug('Running queue for %s: %s tasks', event, self.taskQueues[event].remaining());
	}
	self.phase = event;
	self.emitInProgress(event);
	var runner = 'runQueue';
	if (self.options[event + 'InParallel'])
	{
		runner = 'runInParallel';
	}
	self[runner](self.taskQueues[event], function(error)
	{
		if (error)
		{
			return callback(error);
		}
		self.flags[event] = true;
		self.emit(event + 'ed');
		if (event == 'stop') self.emit(event + 'ped');
		return callback(null);
	});
};

InitSystem.prototype.emitInProgress = function(event)
{
	var self = this;
	self.emit(event + 'ing');
	if (event.endsWith('p'))
	{
		self.emit(event + 'ping');
	}
};

InitSystem.prototype.runQueue = function(queue, callback)
{
	var self = this;
	if (!queue.remaining())
	{
		return callback(null);
	}
	var current = queue.next();
	self.run(current, function(error)
	{
		if (error)
		{
			if (self.options.showErrors)
			{
				self.log.error('Error in phase %s: %s', self.phase, error);
			}
			if (self.options.stopOnError)
			{
				return callback(error);
			}
		}
		return self.runQueue(queue, callback);
	});
};

InitSystem.prototype.runInParallel = function(queue, callback)
{
	var self = this;
	var total = queue.remaining();
	if (!total)
	{
		return callback(null);
	}
	var received = 0;
	while (queue.remaining())
	{
		var task = queue.next();
		self.run(task, function(error)
		{
			if (error)
			{
				if (self.options.showErrors)
				{
					self.log.error('Error in phase %s: %s', self.phase, error);
				}
				if (self.options.stopOnError && received < total)
				{
					received += total;
					return callback(error);
				}
			}
			received += 1;
			if (received == total)
			{
				return callback(null);
			}
		});
	}
};

InitSystem.prototype.run = function(current, callback)
{
	var self = this;
	self.log.debug('Running task: %s', current.name);
	var timeout = setTimeout(function()
	{
		self.log.warning('Task %s is taking more than %s seconds', current.name, self.options.maxTaskTimeSec);
	}, self.options.maxTaskTimeSec * 1000);
	timeout.unref();
	globalDomain.run(function()
	{
		current(function(error)
		{
			clearTimeout(timeout);
			callback(error);
		});
	});
};

InitSystem.prototype.setupErrors = function()
{
	var self = this;
	if (self.options.catchErrors)
	{
		globalDomain.on('error', function(error)
		{
			self.manageCrash('error', error);
		});
		process.on('uncaughtException', function(error)
		{
			self.manageCrash('uncaught exception', error);
		});
		process.on('beforeExit', function()
		{
			if (!self.shuttingDown)
			{
				self.shutdown();
			}
		});
		process.on('exit', function()
		{
			if (!self.finished && self.options.showErrors)
			{
				self.log.warning('Unexpected exit, please see documentation: https://github.com/alexfernandez/inits#unexpected-exit');
			}
		});
	}
	if (self.options.catchSignals)
	{
		process.on('SIGINT', function()
		{
			self.log.notice('User pressed control-C');
			self.signalled();
		});
		process.on('SIGTERM', function()
		{
			self.log.notice('Process killed');
			self.signalled();
		});
	}
};

InitSystem.prototype.manageCrash = function(type, error)
{
	var self = this;
	if (!self.options.catchErrors)
	{
		return;
	}
	if (self.listeners('error').length > 0)
	{
		self.emit('error', 'Unexpected ' + type + ': ' + error);
	}
	if (error.stack)
	{
		error = error.stack;
	}
	self.startShutdownByError(util.format('Process crashed with %s: %s', type, error));
};

InitSystem.prototype.startShutdownByError = function(error)
{
	var self = this;
	if (self.options.showErrors)
	{
		self.log.error(error);
	}
	if (!self.startingUp && !self.shuttingDown)
	{
		return self.shutdown(1);
	}
	if (self.options.showErrors)
	{
		var when = 'starting up';
		if (self.shuttingDown)
		{
			when = 'shutting down';
		}
		self.log.warning('Error while %s: exiting', when);
	}
	if (self.options.exitProcess)
	{
		self.finished = true;
		process.exit(1);
	}
};

InitSystem.prototype.signalled = function()
{
	var self = this;
	if (!self.options.catchSignals)
	{
		return;
	}
	self.shutdown();
};

/**
 * Shut down. Pass an error code if you want process.exit(errorCode), otherwise 0.
 */
InitSystem.prototype.shutdown = function(errorCode)
{
	var self = this;
	if (self.shuttingDown)
	{
		if (self.options.showErrors)
		{
			self.log.warning('Could not shutdown again');
		}
		return;
	}
	self.shuttingDown = true;
	var start = Date.now();
	self.emit('shutdown');
	self.runAll('stop', function(error)
	{
		if (error)
		{
			return self.manageInternalError('Could not run stop tasks: ' + error);
		}
		self.runAll('finish', function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run finish tasks: ' + error);
			}
			if (self.options.logTimes)
			{
				var elapsedSeconds = (Date.now() - start) / 1000;
				self.log.info('Shutdown took %s seconds', elapsedSeconds.toFixed(1));
			}
			self.emit('end');
			self.finished = true;
			if (self.options.exitProcess)
			{
				process.exit(errorCode || 0);
			}
		});
	});
};

InitSystem.prototype.standalone = function(task)
{
	var self = this;
	if (self.standaloneTask)
	{
		return self.manageInternalError('Already have standalone task');
	}
	self.standaloneTask = task;
	self.on('ready', self.runStandalone);
};

InitSystem.prototype.runStandalone = function()
{
	var self = this;
	self.phase = 'standalone';
	setImmediate(function()
	{
		self.standaloneTask(function(error)
		{
			if (error)
			{
				return self.manageInternalError('Could not run standalone task: ' + error);
			}
			setImmediate(function()
			{
				self.shutdown();
			});
		});
	});
};

function create()
{
	var initSystem = new InitSystem();
	initSystem.startup();
	return initSystem;
}

module.exports = create();
module.exports.create = create;

<|endoftext|>