<commit_before>var fs = require('fs');
var parse = require('parse-diff');
var argv = require('minimist')(process.argv.slice(2));

var warningsTotal = 0;
var unifiedDiff = argv._[0];

if (unifiedDiff && unifiedDiff.endsWith('.diff')) {
    readFile(argv._[0], function(warnings) {
        if (warnings && warnings.length > 0) {
            warnings.forEach(function(item) {
                console.log(item.content.message);
            });

            var summary = warnings.length + ' warning(s) found';

            if (warningsTotal > 0) {
                var warningsFiltered = warningsTotal - warnings.length;
                summary += ', ' +
                    warningsFiltered + ' / ' + warningsTotal +
                    ' (' + warningsFiltered / warningsTotal * 100 + '%) ' +
                    'warnings(s) filtered';
            }

            console.log(summary + '.');
        }
    });
} else {
    help();
}

function readFile(file, callback) {
    fs.readFile(file, "utf-8", function(err, data) {
        if (err) {
            console.error(err);
            callback(undefined);
        }
        findBug(data, function(warnings) {
            callback(warnings);
        });
    });
}

function findBug(diff, callback) {

    // Store New Warnings \ Old Warnings
    var warnings = [];

    var files = parse(diff);

    files.forEach(function(file) {
        file.chunks.forEach(function(chunk) {

            // Store all deletions and additions in the original orders
            var changes = [];

            for (var i = 0; i < chunk.changes.length; i++) {

                var change = chunk.changes[i];
                if (change.type === 'del' || change.type === 'add') {
                    if (containsWarning(change) && !shouldFilterWarning(change)) {
                        changes.push(parseWarning(change));
                    }

                    if (change.content.startsWith('+|  Warnings          :')) {
                        warningsTotal = getWarningsTotal(change.content);
                    }
                }
            }

            warnings = warnings.concat(filterChanges(changes));
        });
    });

    callback(warnings);
}

function parseWarning(change) {
    var decodedChange = JSON.parse(JSON.stringify(change));

    var components = change.content.split(':');
    var content = {
        message: change.content.substring(1),
        filename: components[0].substring(1),
        startLine: Number(components[1]),
        startCol: Number(components[2].split('~')[0]),
        endLine: Number(components[2].split('~')[1]),
        endCol: Number(components[3]),
        warning: components[4].substring(1)
    }
    decodedChange.content = content;

    return decodedChange;
}

function isSameChange(delChange, addChange) {
    return delChange.content.filename === addChange.content.filename && delChange.content.startLine === addChange.content.startLine && delChange.content.warning === addChange.content.warning;
}

function filterChanges(changes) {
    var filteredIndex = [];
    var filteredChanges = [];

    for (var i = 0; i < changes.length; i++) {
        if (changes[i].type === 'del' && filteredIndex.indexOf(i) === -1) {
            var del = changes[i];

            for (var j = i + 1; j < changes.length; j++) {
                if (changes[j].type === 'add' && filteredIndex.indexOf(j) === -1) {
                    var add = changes[j];

                    if (isSameChange(del, add)) {
                        filteredIndex.push(i, j);
                    }
                }
            }
        }
    }

    for (var i = 0; i < changes.length; i++) {
        if (filteredIndex.indexOf(i) === -1 && changes[i].type === 'add')
            filteredChanges.push(changes[i]);
    }

    return (filteredChanges);
}

function containsWarning(change) {
    return change.content.indexOf('[Warning]') > -1
}

function shouldFilterWarning(change) {
    var content = change.content;

    // Conditional expression [expr] is always true / false
    if (content.indexOf('Conditional expression') > -1 && content.indexOf('is always') > -1) {
        return true;
    }

    // Too many / few arguments to function
    if (content.indexOf('Too many arguments to function') > -1 || content.indexOf('Too few arguments to function') > -1) {
        return true;
    }

    // Reading absent property [prop] of object [obj], where property [prop] can be [val].
    if (content.indexOf('Reading absent property') > -1 && content.indexOf('where property') > -1 && content.indexOf('can be') > -1) {
        return true;
    }

    if (argv.filter) {
        var filter = argv.filter;

        if (isDirectoryExists(filter)) {
        	// Filter warnings based on the JavaScript files in a directory
            var files = fs.readdirSync(filter);
            for (var i in files) {
            	if (files[i].endsWith('.js') && content.substring(1).startsWith(files[i])) {
            		return true;
            	}
            }
        } else {
            // Filter warnings based on filename
            if (content.substring(1).startsWith(filter)) {
                return true;
            }
        }
    }

    return false;
}

function getWarningsTotal(content) {
    var tokens = content.split(' ');

    for (var i in tokens) {
        var result = parseInt(tokens[i]);

        if (!isNaN(result)) {
            return result;
        }
    }

    return 0;
}

function isDirectoryExists(dir) {
    try {
        fs.statSync(dir);
        return true;
    } catch (e) {
        return false;
    }
}

function help() {
    console.log('Usage');
    console.log('\tnode index.js path/to/diff [options]\n');
    console.log('\t--filter=[directory | filename]');
}

module.exports = {
    readFile: readFile,
    findBug: findBug,
    parseWarning: parseWarning,
    isSameChange: isSameChange,
    filterChanges: filterChanges,
    shouldFilterWarning: shouldFilterWarning,
    getWarningsTotal: getWarningsTotal
}
<commit_msg>Round percentage warnings filtered to 2 decimal places<commit_after>var fs = require('fs');
var parse = require('parse-diff');
var argv = require('minimist')(process.argv.slice(2));

var warningsTotal = 0;
var unifiedDiff = argv._[0];

if (unifiedDiff && unifiedDiff.endsWith('.diff')) {
    readFile(argv._[0], function(warnings) {
        if (warnings && warnings.length > 0) {
            warnings.forEach(function(item) {
                console.log(item.content.message);
            });

            var summary = warnings.length + ' warning(s) found';

            if (warningsTotal > 0) {
                var warningsFiltered = warningsTotal - warnings.length;
                summary += ', ' +
                    warningsFiltered + '/' + warningsTotal +
                    ' (' + (warningsFiltered / warningsTotal * 100).toFixed(2) + '%) ' +
                    'warnings(s) filtered';
            }

            console.log(summary + '.');
        }
    });
} else {
    help();
}

function readFile(file, callback) {
    fs.readFile(file, "utf-8", function(err, data) {
        if (err) {
            console.error(err);
            callback(undefined);
        }
        findBug(data, function(warnings) {
            callback(warnings);
        });
    });
}

function findBug(diff, callback) {

    // Store New Warnings \ Old Warnings
    var warnings = [];

    var files = parse(diff);

    files.forEach(function(file) {
        file.chunks.forEach(function(chunk) {

            // Store all deletions and additions in the original orders
            var changes = [];

            for (var i = 0; i < chunk.changes.length; i++) {

                var change = chunk.changes[i];
                if (change.type === 'del' || change.type === 'add') {
                    if (containsWarning(change) && !shouldFilterWarning(change)) {
                        changes.push(parseWarning(change));
                    }

                    if (change.content.startsWith('+|  Warnings          :')) {
                        warningsTotal = getWarningsTotal(change.content);
                    }
                }
            }

            warnings = warnings.concat(filterChanges(changes));
        });
    });

    callback(warnings);
}

function parseWarning(change) {
    var decodedChange = JSON.parse(JSON.stringify(change));

    var components = change.content.split(':');
    var content = {
        message: change.content.substring(1),
        filename: components[0].substring(1),
        startLine: Number(components[1]),
        startCol: Number(components[2].split('~')[0]),
        endLine: Number(components[2].split('~')[1]),
        endCol: Number(components[3]),
        warning: components[4].substring(1)
    }
    decodedChange.content = content;

    return decodedChange;
}

function isSameChange(delChange, addChange) {
    return delChange.content.filename === addChange.content.filename && delChange.content.startLine === addChange.content.startLine && delChange.content.warning === addChange.content.warning;
}

function filterChanges(changes) {
    var filteredIndex = [];
    var filteredChanges = [];

    for (var i = 0; i < changes.length; i++) {
        if (changes[i].type === 'del' && filteredIndex.indexOf(i) === -1) {
            var del = changes[i];

            for (var j = i + 1; j < changes.length; j++) {
                if (changes[j].type === 'add' && filteredIndex.indexOf(j) === -1) {
                    var add = changes[j];

                    if (isSameChange(del, add)) {
                        filteredIndex.push(i, j);
                    }
                }
            }
        }
    }

    for (var i = 0; i < changes.length; i++) {
        if (filteredIndex.indexOf(i) === -1 && changes[i].type === 'add')
            filteredChanges.push(changes[i]);
    }

    return (filteredChanges);
}

function containsWarning(change) {
    return change.content.indexOf('[Warning]') > -1
}

function shouldFilterWarning(change) {
    var content = change.content;

    // Conditional expression [expr] is always true / false
    if (content.indexOf('Conditional expression') > -1 && content.indexOf('is always') > -1) {
        return true;
    }

    // Too many / few arguments to function
    if (content.indexOf('Too many arguments to function') > -1 || content.indexOf('Too few arguments to function') > -1) {
        return true;
    }

    // Reading absent property [prop] of object [obj], where property [prop] can be [val].
    if (content.indexOf('Reading absent property') > -1 && content.indexOf('where property') > -1 && content.indexOf('can be') > -1) {
        return true;
    }

    if (argv.filter) {
        var filter = argv.filter;

        if (isDirectoryExists(filter)) {
        	// Filter warnings based on the JavaScript files in a directory
            var files = fs.readdirSync(filter);
            for (var i in files) {
            	if (files[i].endsWith('.js') && content.substring(1).startsWith(files[i])) {
            		return true;
            	}
            }
        } else {
            // Filter warnings based on filename
            if (content.substring(1).startsWith(filter)) {
                return true;
            }
        }
    }

    return false;
}

function getWarningsTotal(content) {
    var tokens = content.split(' ');

    for (var i in tokens) {
        var result = parseInt(tokens[i]);

        if (!isNaN(result)) {
            return result;
        }
    }

    return 0;
}

function isDirectoryExists(dir) {
    try {
        fs.statSync(dir);
        return true;
    } catch (e) {
        return false;
    }
}

function help() {
    console.log('Usage');
    console.log('\tnode index.js path/to/diff [options]\n');
    console.log('\t--filter=[directory | filename]');
}

module.exports = {
    readFile: readFile,
    findBug: findBug,
    parseWarning: parseWarning,
    isSameChange: isSameChange,
    filterChanges: filterChanges,
    shouldFilterWarning: shouldFilterWarning,
    getWarningsTotal: getWarningsTotal
}
<|endoftext|>


<commit_before>'use strict';

var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var Promise = require('rsvp').Promise;
var Plugin = require('broccoli-plugin');
var walkSync = require('walk-sync');
var mapSeries = require('promise-map-series');
var symlinkOrCopySync = require('symlink-or-copy').sync;
var debugGenerator = require('debug');
var md5Hex = require('md5-hex');
var Processor = require('./lib/processor');
var defaultProccessor = require('./lib/strategies/default');
var hashForDep = require('hash-for-dep');
var BlankObject = require('blank-object');
var FSTree = require('fs-tree-diff');

module.exports = Filter;

Filter.prototype = Object.create(Plugin.prototype);
Filter.prototype.constructor = Filter;

function Filter(inputTree, options) {
  if (!this || !(this instanceof Filter) ||
      Object.getPrototypeOf(this) === Filter.prototype) {
    throw new TypeError('Filter is an abstract class and must be sub-classed');
  }

  var name = 'broccoli-persistent-filter:' + (this.constructor.name);

  if (this.description) {
    name += ' > [' + this.description + ']';
  }

  this._debug = debugGenerator(name);

  Plugin.call(this, [inputTree]);

  this.processor = new Processor(options);
  this.processor.setStrategy(defaultProccessor);
  this.currentTree = new FSTree();
  this._persistentOutput = true;

  /* Destructuring assignment in node 0.12.2 would be really handy for this! */
  if (options) {
    if (options.extensions != null)      this.extensions = options.extensions;
    if (options.targetExtension != null) this.targetExtension = options.targetExtension;
    if (options.inputEncoding != null)   this.inputEncoding = options.inputEncoding;
    if (options.outputEncoding != null)  this.outputEncoding = options.outputEncoding;
    if (options.persist) {
      this.processor.setStrategy(require('./lib/strategies/persistent'));
    }
  }

  this.processor.init(this);

  this._canProcessCache = new BlankObject();
  this._destFilePathCache = new BlankObject();
}

Filter.prototype.build = function() {
  var srcDir = this.inputPaths[0];
  var destDir = this.outputPath;
  var entries = walkSync.entries(srcDir);
  var nextTree = new FSTree.fromEntries(entries);
  var currentTree = this.currentTree;

  this.currentTree = nextTree;
  var patches = currentTree.calculatePatch(nextTree);

  return mapSeries(patches, function(patch) {
    var operation = patch[0];
    var relativePath = patch[1];
    var entry = patch[2];
    var outputPath = destDir + '/' + relativePath;
    var outputFilePath = this.getDestFilePath(outputPath) || outputPath;

    this._debug('[operation:%s] %s', operation, relativePath);

    switch (operation) {
      case 'mkdir':  return fs.mkdirSync(outputPath);
      case 'rmdir':  return fs.rmdirSync(outputPath);
      case 'unlink': return fs.unlinkSync(outputPath);
      case 'change':
        fs.unlinkSync(outputFilePath);
        return this._handleFile(relativePath, srcDir, destDir, entry, outputFilePath);
      case 'create':
        return this._handleFile(relativePath, srcDir, destDir, entry, outputFilePath);
    }
  }, this);
};

Filter.prototype._handleFile = function(relativePath, srcDir, destDir, entry, outputPath) {
  if (this.canProcessFile(relativePath)) {
    return this.processAndCacheFile(srcDir, destDir, entry);
  } else {
    var srcPath = srcDir + '/' + relativePath;
    return symlinkOrCopySync(srcPath, outputPath);
  }
};

/*
 The cache key to be used for this plugins set of dependencies. By default
 a hash is created based on `package.json` and nested dependencies.

 Implement this to customize the cache key (for example if you need to
 account for non-NPM dependencies).

 @public
 @method cacheKey
 @returns {String}
 */
Filter.prototype.cacheKey = function() {
  return hashForDep(this.baseDir());
};

/* @public
 *
 * @method baseDir
 * @returns {String} absolute path to the root of the filter...
 */
Filter.prototype.baseDir = function() {
  throw Error('Filter must implement prototype.baseDir');
};

/**
 * @public
 *
 * optionally override this to build a more rhobust cache key
 * @param  {String} string The contents of a file that is being processed
 * @return {String}        A cache key
 */
Filter.prototype.cacheKeyProcessString = function(string, relativePath) {
  return md5Hex(string + 0x00 + relativePath);
};

Filter.prototype.canProcessFile =
    function canProcessFile(relativePath) {
  return !!this.getDestFilePath(relativePath);
};

Filter.prototype.getDestFilePath = function(relativePath) {
  if (this.extensions == null) {
    return relativePath;
  }

  for (var i = 0, ii = this.extensions.length; i < ii; ++i) {
    var ext = this.extensions[i];
    if (relativePath.slice(-ext.length - 1) === '.' + ext) {
      if (this.targetExtension != null) {
        relativePath = relativePath.slice(0, -ext.length) + this.targetExtension;
      }
      return relativePath;
    }
  }

  return null;
};

Filter.prototype.processAndCacheFile = function(srcDir, destDir, entry) {
  var filter = this;
  var relativePath = entry.relativePath;

  return Promise.resolve().
      then(function asyncProcessFile() {
        return filter.processFile(srcDir, destDir, relativePath);
      }).
      then(undefined,
      // TODO(@caitp): error wrapper is for API compat, but is not particularly
      // useful.
      // istanbul ignore next
      function asyncProcessFileErrorWrapper(e) {
        if (typeof e !== 'object') e = new Error('' + e);
        e.file = relativePath;
        e.treeDir = srcDir;
        throw e;
      });
};

function invoke(context, fn, args) {
  return new Promise(function(resolve) {
    resolve(fn.apply(context, args));
  });
}

Filter.prototype.processFile = function(srcDir, destDir, relativePath) {
  var filter = this;
  var inputEncoding = this.inputEncoding;
  var outputEncoding = this.outputEncoding;

  if (inputEncoding === undefined)  inputEncoding  = 'utf8';
  if (outputEncoding === undefined) outputEncoding = 'utf8';

  var contents = fs.readFileSync(srcDir + '/' + relativePath, {
    encoding: inputEncoding
  });

  var string = invoke(this.processor, this.processor.processString, [this, contents, relativePath]);

  return string.then(function asyncOutputFilteredFile(outputString) {

    var outputPath = filter.getDestFilePath(relativePath);

    if (outputPath == null) {
      throw new Error('canProcessFile("' + relativePath +
                      '") is true, but getDestFilePath("' +
                      relativePath + '") is null');
    }

    outputPath = destDir + '/' + outputPath;

    try {
      fs.writeFileSync(outputPath, outputString, {
        encoding: outputEncoding
      });

    } catch(e) {
      // optimistically assume the DIR was patched correctly
      mkdirp.sync(path.dirname(outputPath));
      fs.writeFileSync(outputPath, outputString, {
        encoding: outputEncoding
      });
    }

    return outputString;
  });
};

Filter.prototype.processString = function(/* contents, relativePath */) {
  throw new Error(
      'When subclassing cauliflower-filter you must implement the ' +
      '`processString()` method.');
};
<commit_msg>update abstract method assertion wording to match current project name<commit_after>'use strict';

var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var Promise = require('rsvp').Promise;
var Plugin = require('broccoli-plugin');
var walkSync = require('walk-sync');
var mapSeries = require('promise-map-series');
var symlinkOrCopySync = require('symlink-or-copy').sync;
var debugGenerator = require('debug');
var md5Hex = require('md5-hex');
var Processor = require('./lib/processor');
var defaultProccessor = require('./lib/strategies/default');
var hashForDep = require('hash-for-dep');
var BlankObject = require('blank-object');
var FSTree = require('fs-tree-diff');

module.exports = Filter;

Filter.prototype = Object.create(Plugin.prototype);
Filter.prototype.constructor = Filter;

function Filter(inputTree, options) {
  if (!this || !(this instanceof Filter) ||
      Object.getPrototypeOf(this) === Filter.prototype) {
    throw new TypeError('Filter is an abstract class and must be sub-classed');
  }

  var name = 'broccoli-persistent-filter:' + (this.constructor.name);

  if (this.description) {
    name += ' > [' + this.description + ']';
  }

  this._debug = debugGenerator(name);

  Plugin.call(this, [inputTree]);

  this.processor = new Processor(options);
  this.processor.setStrategy(defaultProccessor);
  this.currentTree = new FSTree();
  this._persistentOutput = true;

  /* Destructuring assignment in node 0.12.2 would be really handy for this! */
  if (options) {
    if (options.extensions != null)      this.extensions = options.extensions;
    if (options.targetExtension != null) this.targetExtension = options.targetExtension;
    if (options.inputEncoding != null)   this.inputEncoding = options.inputEncoding;
    if (options.outputEncoding != null)  this.outputEncoding = options.outputEncoding;
    if (options.persist) {
      this.processor.setStrategy(require('./lib/strategies/persistent'));
    }
  }

  this.processor.init(this);

  this._canProcessCache = new BlankObject();
  this._destFilePathCache = new BlankObject();
}

Filter.prototype.build = function() {
  var srcDir = this.inputPaths[0];
  var destDir = this.outputPath;
  var entries = walkSync.entries(srcDir);
  var nextTree = new FSTree.fromEntries(entries);
  var currentTree = this.currentTree;

  this.currentTree = nextTree;
  var patches = currentTree.calculatePatch(nextTree);

  return mapSeries(patches, function(patch) {
    var operation = patch[0];
    var relativePath = patch[1];
    var entry = patch[2];
    var outputPath = destDir + '/' + relativePath;
    var outputFilePath = this.getDestFilePath(outputPath) || outputPath;

    this._debug('[operation:%s] %s', operation, relativePath);

    switch (operation) {
      case 'mkdir':  return fs.mkdirSync(outputPath);
      case 'rmdir':  return fs.rmdirSync(outputPath);
      case 'unlink': return fs.unlinkSync(outputPath);
      case 'change':
        fs.unlinkSync(outputFilePath);
        return this._handleFile(relativePath, srcDir, destDir, entry, outputFilePath);
      case 'create':
        return this._handleFile(relativePath, srcDir, destDir, entry, outputFilePath);
    }
  }, this);
};

Filter.prototype._handleFile = function(relativePath, srcDir, destDir, entry, outputPath) {
  if (this.canProcessFile(relativePath)) {
    return this.processAndCacheFile(srcDir, destDir, entry);
  } else {
    var srcPath = srcDir + '/' + relativePath;
    return symlinkOrCopySync(srcPath, outputPath);
  }
};

/*
 The cache key to be used for this plugins set of dependencies. By default
 a hash is created based on `package.json` and nested dependencies.

 Implement this to customize the cache key (for example if you need to
 account for non-NPM dependencies).

 @public
 @method cacheKey
 @returns {String}
 */
Filter.prototype.cacheKey = function() {
  return hashForDep(this.baseDir());
};

/* @public
 *
 * @method baseDir
 * @returns {String} absolute path to the root of the filter...
 */
Filter.prototype.baseDir = function() {
  throw Error('Filter must implement prototype.baseDir');
};

/**
 * @public
 *
 * optionally override this to build a more rhobust cache key
 * @param  {String} string The contents of a file that is being processed
 * @return {String}        A cache key
 */
Filter.prototype.cacheKeyProcessString = function(string, relativePath) {
  return md5Hex(string + 0x00 + relativePath);
};

Filter.prototype.canProcessFile =
    function canProcessFile(relativePath) {
  return !!this.getDestFilePath(relativePath);
};

Filter.prototype.getDestFilePath = function(relativePath) {
  if (this.extensions == null) {
    return relativePath;
  }

  for (var i = 0, ii = this.extensions.length; i < ii; ++i) {
    var ext = this.extensions[i];
    if (relativePath.slice(-ext.length - 1) === '.' + ext) {
      if (this.targetExtension != null) {
        relativePath = relativePath.slice(0, -ext.length) + this.targetExtension;
      }
      return relativePath;
    }
  }

  return null;
};

Filter.prototype.processAndCacheFile = function(srcDir, destDir, entry) {
  var filter = this;
  var relativePath = entry.relativePath;

  return Promise.resolve().
      then(function asyncProcessFile() {
        return filter.processFile(srcDir, destDir, relativePath);
      }).
      then(undefined,
      // TODO(@caitp): error wrapper is for API compat, but is not particularly
      // useful.
      // istanbul ignore next
      function asyncProcessFileErrorWrapper(e) {
        if (typeof e !== 'object') e = new Error('' + e);
        e.file = relativePath;
        e.treeDir = srcDir;
        throw e;
      });
};

function invoke(context, fn, args) {
  return new Promise(function(resolve) {
    resolve(fn.apply(context, args));
  });
}

Filter.prototype.processFile = function(srcDir, destDir, relativePath) {
  var filter = this;
  var inputEncoding = this.inputEncoding;
  var outputEncoding = this.outputEncoding;

  if (inputEncoding === undefined)  inputEncoding  = 'utf8';
  if (outputEncoding === undefined) outputEncoding = 'utf8';

  var contents = fs.readFileSync(srcDir + '/' + relativePath, {
    encoding: inputEncoding
  });

  var string = invoke(this.processor, this.processor.processString, [this, contents, relativePath]);

  return string.then(function asyncOutputFilteredFile(outputString) {

    var outputPath = filter.getDestFilePath(relativePath);

    if (outputPath == null) {
      throw new Error('canProcessFile("' + relativePath +
                      '") is true, but getDestFilePath("' +
                      relativePath + '") is null');
    }

    outputPath = destDir + '/' + outputPath;

    try {
      fs.writeFileSync(outputPath, outputString, {
        encoding: outputEncoding
      });

    } catch(e) {
      // optimistically assume the DIR was patched correctly
      mkdirp.sync(path.dirname(outputPath));
      fs.writeFileSync(outputPath, outputString, {
        encoding: outputEncoding
      });
    }

    return outputString;
  });
};

Filter.prototype.processString = function(/* contents, relativePath */) {
  throw new Error(
      'When subclassing broccoli-persistent-filter you must implement the ' +
      '`processString()` method.');
};
<|endoftext|>


<commit_before>
var Slack = require('node-slack');
var express = require('express');
var bufferEq = require('buffer-equal-constant-time');
var crypto = require('crypto');

function initSlack() {
    if (process.env.HOOK_URL) {
        hookURL = process.env.HOOK_URL;
    } else {
        console.log("Must configure HOOK_URL!");
        process.exit(1);
    }
    return new Slack(hookURL);
}

function main()  {
    var slack = initSlack();
    var app = newServer(slack);

    app.set('port', (process.env.PORT || 5000));
    app.listen(app.get('port'), '127.0.0.1', function() {
        console.log('Node app is running on port', app.get('port'));
    });
}

function hasValidSignature(sig, body) {
    var secret = process.env.GITHUB_SECRET;
    if (!secret) {
        console.error("GITHUB_SECRET is not configured");
        return true;
    }
    if (!sig) {
        console.error("Request is unsigned");
        return false;
    }

    var computedSig = 'sha1=' + crypto.createHmac('sha1', secret).update(body).digest('hex');
    return bufferEq(new Buffer(sig), new Buffer(computedSig));
}

function newServer(slack) {
    var app = express();

    // concatenate raw body
    app.use(function(req, res, next) {
        var data = '';
        req.setEncoding('utf8');
        req.on('data', function(chunk) {
            data += chunk;
        });
        req.on('end', function() {
            req.rawBody = data;
            next();
        });
    });

    var handlers = {};

    var newHandler = function(handler) {
        return handler(slack);
    };

    handlers['ping'] = newHandler(pingHandler);
    handlers['commit_comment'] = newHandler(commitCommentHandler);
    handlers['pull_request'] = newHandler(pullRequestHandler);
    handlers['pull_request_review_comment'] = newHandler(pullRequestCommentHandler);
    handlers['status'] = newHandler(statusHandler);

    app.post('/', function (req, res) {
        var rawBody = req.rawBody;
        var sig = req.headers['x-hub-signature'];
        if (!hasValidSignature(sig, rawBody)) {
            console.error("Invalid signature");
            res.sendStatus(403);
            res.end();
            return;
        }

        var event = req.headers['x-github-event'];
        if (!handlers[event]) {
            res.send('Unhandled event: ' + handlers[event]);
            res.end();
            return;
        }

        var json = JSON.parse(rawBody)

        res.sendStatus(handlers[event](json));
        res.end();
    });
    return app;
}

function pingHandler(slack) {
    return function(data) {
        slack.send({
            text: 'Howdy ping!',
            channel: '@matt.hauck',
        });
        return 200;
    }
}

function commitCommentHandler(slack) {
    return function(data) {
        return 200;
    }
}

function pullRequestHandler(slack) {
    return function(data) {
        return 200;
    }
}

function pullRequestCommentHandler(slack) {
    return function(data) {
        return 200;
    }
}

function statusHandler(slack) {
    return function(data) {
        return 200;
    }
}

if (require.main === module) {
    main();
}
<commit_msg>Revert "Force listen on localhost, ipv4"<commit_after>
var Slack = require('node-slack');
var express = require('express');
var bufferEq = require('buffer-equal-constant-time');
var crypto = require('crypto');

function initSlack() {
    if (process.env.HOOK_URL) {
        hookURL = process.env.HOOK_URL;
    } else {
        console.log("Must configure HOOK_URL!");
        process.exit(1);
    }
    return new Slack(hookURL);
}

function main()  {
    var slack = initSlack();
    var app = newServer(slack);

    app.set('port', (process.env.PORT || 5000));
    app.listen(app.get('port'), function() {
        console.log('Node app is running on port', app.get('port'));
    });
}

function hasValidSignature(sig, body) {
    var secret = process.env.GITHUB_SECRET;
    if (!secret) {
        console.error("GITHUB_SECRET is not configured");
        return true;
    }
    if (!sig) {
        console.error("Request is unsigned");
        return false;
    }

    var computedSig = 'sha1=' + crypto.createHmac('sha1', secret).update(body).digest('hex');
    return bufferEq(new Buffer(sig), new Buffer(computedSig));
}

function newServer(slack) {
    var app = express();

    // concatenate raw body
    app.use(function(req, res, next) {
        var data = '';
        req.setEncoding('utf8');
        req.on('data', function(chunk) {
            data += chunk;
        });
        req.on('end', function() {
            req.rawBody = data;
            next();
        });
    });

    var handlers = {};

    var newHandler = function(handler) {
        return handler(slack);
    };

    handlers['ping'] = newHandler(pingHandler);
    handlers['commit_comment'] = newHandler(commitCommentHandler);
    handlers['pull_request'] = newHandler(pullRequestHandler);
    handlers['pull_request_review_comment'] = newHandler(pullRequestCommentHandler);
    handlers['status'] = newHandler(statusHandler);

    app.post('/', function (req, res) {
        var rawBody = req.rawBody;
        var sig = req.headers['x-hub-signature'];
        if (!hasValidSignature(sig, rawBody)) {
            console.error("Invalid signature");
            res.sendStatus(403);
            res.end();
            return;
        }

        var event = req.headers['x-github-event'];
        if (!handlers[event]) {
            res.send('Unhandled event: ' + handlers[event]);
            res.end();
            return;
        }

        var json = JSON.parse(rawBody)

        res.sendStatus(handlers[event](json));
        res.end();
    });
    return app;
}

function pingHandler(slack) {
    return function(data) {
        slack.send({
            text: 'Howdy ping!',
            channel: '@matt.hauck',
        });
        return 200;
    }
}

function commitCommentHandler(slack) {
    return function(data) {
        return 200;
    }
}

function pullRequestHandler(slack) {
    return function(data) {
        return 200;
    }
}

function pullRequestCommentHandler(slack) {
    return function(data) {
        return 200;
    }
}

function statusHandler(slack) {
    return function(data) {
        return 200;
    }
}

if (require.main === module) {
    main();
}
<|endoftext|>


<commit_before>var pathfinder = require('./pathfinder');
var rafLoop = require('raf-loop');
var noop = require('no-op');

module.exports = kimi;

function kimi(settings) {

  if(!( this instanceof kimi)) {

    return new kimi(settings);
  }

  settings = settings || {};
  this.onUpdate = settings.onUpdate || noop;
  this.onState = settings.onState || noop;
  this.allowReverse = settings.allowReverse || true;

  this.directions = pathfinder();
  this.animator = {};
  this.states = {};

  this.currentTime = 0;
  this.currentState = null;
  this.targetState = null;
  this.currentPath = [];
  this.onComplete = null;

  if(!settings.manualStep) {
    this.engine = rafLoop(this.step.bind(this));
  }
}

kimi.prototype = {

  state: function(name, value) {

    this.states[ name ] = value;
  },

  fromTo: function(from, to, duration, animator) {

    if(arguments.length < 4) {
      throw new Error('incorrect amount of arguments sent when defining fromTo');
    }

    this.directions.fromTo(from, to, duration);

    setAnimator.call(this, from, to, animator);
  },

  init: function(state) {

    this.currentState = state;

    sendUpdate.call(this);
  },

  set: function(state) {

    var setToTarget;

    if(this.currentPath.length > 0) {
      setToTarget = this.currentPath[ this.currentPath.length - 1 ] === state;
    } else {
      setToTarget = this.targetState === state;
    }

    this.currentState = state;
    this.currentTime = 0;
    this.targetState = null;
    this.currentPath = [];

    if(this.engine) {
      this.engine.stop();
    }

    sendUpdate.call(this);

    if(setToTarget && this.onComplete) {
      this.onComplete(
        this.states[ state ],
        state
      );
    }

    this.onComplete = null;
  },

  go: function(to, onComplete) {

    if(this.currentState) {

      this.onComplete = onComplete || noop;

      // if we're trying to go to our current state
      if(to === this.currentState) {

        if(!this.allowReverse) {

          this.currentPath = this.directions.getPath(this.currentState, this.targetState, to).path;
          this.currentPath.shift();
        } else {

          this.currentPath = [ to ];
        }
      // if we're not going to our current state then just get the path
      } else {

        if(this.targetState && this.currentState !== this.targetState) {

          this.currentPath = this.directions.getPath( {
            from: this.currentState,
            to: this.targetState,
            location: this.currentTime / 1000
          }, to);
        } else {

          this.currentPath = this.directions.getPath( this.currentState, to);
        }
      }

      if(this.currentPath === null) {
        throw new Error('It is not possible to go from ' + this.currentState + ' to ' + to);
      } else if(!this.targetState) {
        // check if we're at the current state then we can
        // simply remove ourselves
        if(this.currentTime === 0) {
          this.currentPath.shift();
        }

        this.targetState = this.currentPath[ 0 ];
      }

      if(this.engine) {
        this.engine.start();
      }
    } else {

      throw new Error('call init with your initial state before calling go');
    }
  },

  destroy: function() {
    if(this.engine) {
      this.engine.stop();
    }

    // kill the engine
    this.engine = null;

    // this is a bit heavy handed but it ensures
    // that no one can do anything with the ui instance
    // anymore
    this.step = function() {};
  },

  step: function(delta) {

    if(this.currentPath.length || this.targetState) {

      var to = this.currentPath[ 0 ];
      var isReversing = this.allowReverse && (this.currentState === to || ( this.targetState && to && to !== this.targetState ));
      var duration = this.directions.fromTo(this.currentState, this.targetState) * 1000;
      var animator = this.animator[ this.currentState ][ this.targetState ];

      // we should reverse when we're trying to go from to the same place
      // or when the state we're going to isn't the same as the path to
      if(isReversing) {

        this.currentTime = Math.max(this.currentTime - delta, 0);

        if(this.currentTime === 0) {

          // this will send an update with the current state object
          // by reference
          sendUpdate.call(this, duration);

          // we were reversing to the same state
          if(this.currentState === to) {

            // we've reached our target state which is the current state
            this.targetState = this.currentPath.shift();
          // we were reversing cause we need to go to a new state
          } else if(to != this.targetState) {

            // now allow it to go to the target state
            this.targetState = to;
          }
        } else {

          // send an update that is calculated
          sendUpdate.call(this, duration, animator);
        }
      } else {

        this.currentTime = Math.min(this.currentTime + delta, duration);

        if(this.currentTime === duration) {

          this.currentTime = 0;
          this.currentState = this.currentPath.shift();
          this.targetState = this.currentPath[ 0 ];

          sendUpdate.call(this, duration);
        } else {

          sendUpdate.call(this, duration, animator);
        }
      }

      // we don't have anywhere to go anymore
      if(this.currentPath.length === 0) {

        if(this.engine) {
          this.engine.stop();
        }

        this.onComplete(
          this.states[ this.currentState ],
          this.currentState
        );
      }
    }
  }
};

function sendUpdate(duration, animator) {

  if(animator) {

    this.onUpdate(
      animator(this.currentTime / duration, this.states[ this.currentState ], this.states[ this.targetState ]),
      this.currentState,
      this.currentTime
    );
  } else {

    this.onUpdate(
      this.states[ this.currentState ],
      this.currentState,
      this.currentTime
    );

    this.onState(
      this.states[ this.currentState ],
      this.currentState,
      this.currentTime
    );
  }
}

function setAnimator(from, to, animator) {

  var animators = this.animator[ from ] || (this.animator[ from ] = {});

  animators[ to ] = animator;
}<commit_msg>Added a check that when go is called a new path wont be calculated if you're alrady going to the state you asked<commit_after>var pathfinder = require('./pathfinder');
var rafLoop = require('raf-loop');
var noop = require('no-op');

module.exports = kimi;

function kimi(settings) {

  if(!( this instanceof kimi)) {

    return new kimi(settings);
  }

  settings = settings || {};
  this.onUpdate = settings.onUpdate || noop;
  this.onState = settings.onState || noop;
  this.allowReverse = settings.allowReverse || true;

  this.directions = pathfinder();
  this.animator = {};
  this.states = {};

  this.currentTime = 0;
  this.currentState = null;
  this.targetState = null;
  this.currentPath = [];
  this.onComplete = null;

  if(!settings.manualStep) {
    this.engine = rafLoop(this.step.bind(this));
  }
}

kimi.prototype = {

  state: function(name, value) {

    this.states[ name ] = value;
  },

  fromTo: function(from, to, duration, animator) {

    if(arguments.length < 4) {
      throw new Error('incorrect amount of arguments sent when defining fromTo');
    }

    this.directions.fromTo(from, to, duration);

    setAnimator.call(this, from, to, animator);
  },

  init: function(state) {

    this.currentState = state;

    sendUpdate.call(this);
  },

  set: function(state) {

    var setToTarget;

    if(this.currentPath.length > 0) {
      setToTarget = this.currentPath[ this.currentPath.length - 1 ] === state;
    } else {
      setToTarget = this.targetState === state;
    }

    this.currentState = state;
    this.currentTime = 0;
    this.targetState = null;
    this.currentPath = [];

    if(this.engine) {
      this.engine.stop();
    }

    sendUpdate.call(this);

    if(setToTarget && this.onComplete) {
      this.onComplete(
        this.states[ state ],
        state
      );
    }

    this.onComplete = null;
  },

  go: function(to, onComplete) {

    // this is to check if init has been called
    if(this.currentState) {

      this.onComplete = onComplete || noop;

      // we want to check that this to will not be going to the to state already
      // this check will ensure that the path is not recalculated
      if(true || this.currentPath.length === 0 || this.currentPath[ this.currentPath.length - 1 ] !== to) {

        // if we're trying to go to our current state
        if(to === this.currentState) {

          if(!this.allowReverse) {

            this.currentPath = this.directions.getPath(this.currentState, this.targetState, to).path;
            this.currentPath.shift();
          } else {

            this.currentPath = [ to ];
          }
        // if we're not going to our current state then just get the path
        } else {

          if(this.targetState && this.currentState !== this.targetState) {

            this.currentPath = this.directions.getPath( {
              from: this.currentState,
              to: this.targetState,
              location: this.currentTime / 1000
            }, to);
          } else {

            this.currentPath = this.directions.getPath( this.currentState, to);
          }
        }

        if(this.currentPath === null) {
          throw new Error('It is not possible to go from ' + this.currentState + ' to ' + to);
        } else if(!this.targetState) {
          // check if we're at the current state then we can
          // simply remove ourselves
          if(this.currentTime === 0) {
            this.currentPath.shift();
          }

          this.targetState = this.currentPath[ 0 ];
        }

        if(this.engine) {
          this.engine.start();
        }
      }
    } else {

      throw new Error('call init with your initial state before calling go');
    }
  },

  destroy: function() {
    if(this.engine) {
      this.engine.stop();
    }

    // kill the engine
    this.engine = null;

    // this is a bit heavy handed but it ensures
    // that no one can do anything with the ui instance
    // anymore
    this.step = function() {};
  },

  step: function(delta) {

    if(this.currentPath.length || this.targetState) {

      var to = this.currentPath[ 0 ];
      var isReversing = this.allowReverse && (this.currentState === to || ( this.targetState && to && to !== this.targetState ));
      var duration = this.directions.fromTo(this.currentState, this.targetState) * 1000;
      var animator = this.animator[ this.currentState ][ this.targetState ];

      // we should reverse when we're trying to go from to the same place
      // or when the state we're going to isn't the same as the path to
      if(isReversing) {

        this.currentTime = Math.max(this.currentTime - delta, 0);

        if(this.currentTime === 0) {

          // this will send an update with the current state object
          // by reference
          sendUpdate.call(this, duration);

          // we were reversing to the same state
          if(this.currentState === to) {

            // we've reached our target state which is the current state
            this.targetState = this.currentPath.shift();
          // we were reversing cause we need to go to a new state
          } else if(to != this.targetState) {

            // now allow it to go to the target state
            this.targetState = to;
          }
        } else {

          // send an update that is calculated
          sendUpdate.call(this, duration, animator);
        }
      } else {

        this.currentTime = Math.min(this.currentTime + delta, duration);

        if(this.currentTime === duration) {

          this.currentTime = 0;
          this.currentState = this.currentPath.shift();
          this.targetState = this.currentPath[ 0 ];

          sendUpdate.call(this, duration);
        } else {

          sendUpdate.call(this, duration, animator);
        }
      }

      // we don't have anywhere to go anymore
      if(this.currentPath.length === 0) {

        if(this.engine) {
          this.engine.stop();
        }

        this.onComplete(
          this.states[ this.currentState ],
          this.currentState
        );
      }
    }
  }
};

function sendUpdate(duration, animator) {

  if(animator) {

    this.onUpdate(
      animator(this.currentTime / duration, this.states[ this.currentState ], this.states[ this.targetState ]),
      this.currentState,
      this.currentTime
    );
  } else {

    this.onUpdate(
      this.states[ this.currentState ],
      this.currentState,
      this.currentTime
    );

    this.onState(
      this.states[ this.currentState ],
      this.currentState,
      this.currentTime
    );
  }
}

function setAnimator(from, to, animator) {

  var animators = this.animator[ from ] || (this.animator[ from ] = {});

  animators[ to ] = animator;
}<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 **/
var _ = require('lodash'),
	async = require('async'),
	mongoose = require('mongoose'),
	chalk = require('chalk'),
	path = require('path');

function Seeder() {
	this.connected = false;
}

Seeder.prototype.connect = function(db, cb) {
	var _this = this;
	/*
		switch (mongoose.connection.readyState) {
			case 0 : Disconnected;
			case 1 : Connected;
			case 2 : Connecting;
			case 3 : Disconnecting;
		}
		source http://mongoosejs.com/docs/api.html#connection_Connection-readyState
	*/
	if (mongoose.connection.readyState == 1) {
		_this.connected = true;
		console.log('Successfully initialized mongoose-seed');
		cb();
	}
	mongoose.connect(db, function(err) {
		// Log Error
		if (err) {
			console.error(chalk.red('Could not connect to MongoDB!'));
			console.log(err);
		} else {
			_this.connected = true;
			console.log('Successfully initialized mongoose-seed');
			cb();
		}
	});
};

Seeder.prototype.loadModels = function(modelPaths) {
	console.log(modelPaths);
	modelPaths.forEach(function(modelPath) {
		require(path.resolve(modelPath));
	});
};

Seeder.prototype.invalidModelCheck = function(models, cb) {
	var invalidModels = [];

	models.forEach(function(model) {
		if(_.indexOf(mongoose.modelNames(), model) === -1) {
			invalidModels.push(model);
		}
	});

	if (invalidModels.length) {
		cb(new Error('Models not registered in Mongoose: ' + invalidModels));
	} else {
		cb();
	}
};

Seeder.prototype.clearModels = function(models, cb) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = [];

	// Convert to array if not already
	if (Array.isArray(models)) {
		modelNames = models;
	} else if (typeof(models) === 'string') {
		modelNames.push(models);
	} else {
		console.error(chalk.red('Error: Invalid model type'));
		return;
	}

	// Confirm that all Models have been registered in Mongoose
	this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Clear each model
		async.each(modelNames, function(modelName, done) {
			var Model = mongoose.model(modelName);
			Model.remove({}, function(err) {
				if (err) {
					console.error(chalk.red('Error: ' + err.message));
					return;
				}
				console.log(modelName + 's collection cleared');
				done();
			});
		}, function(err) {
		// Final async callback
			if(err) { return; }
			cb();
		});
	});
};

Seeder.prototype.populateModels = function(seedData, cb) {
	if(!this.connected) {
		return new Error('Not connected to db, exiting function');
	}

	var modelNames = _.unique(_.pluck(seedData,'model'));

	// Confirm that all Models have been registered in Mongoose
	var invalidModels = this.invalidModelCheck(modelNames, function(err) {
		if (err) {
			console.error(chalk.red('Error: ' + err.message));
			return;
		}

		// Populate each model
		seedData.forEach(function(entry) {
			var Model = mongoose.model(entry.model);
			entry.documents.forEach(function(document, j) {
				Model.create(document, function(err) {
					if (err) {
						console.error(chalk.red('Error creating document [' + j + '] of ' + entry.model + ' model'));
						console.error(chalk.red('Error: ' + err.message));
						return;
					}
					console.log('Successfully created document [' + j + '] of ' + entry.model + ' model');
				});
			});
		});
	});
	cb();
};

module.exports = new Seeder();
<commit_msg>creat check instanceof model<commit_after>'use strict';

/**
 * Module dependencies.
 **/
var _ = require('lodash'),
    async = require('async'),
    mongoose = require('mongoose'),
    chalk = require('chalk'),
    path = require('path');

function Seeder() {
    this.connected = false;
}

Seeder.prototype.connect = function(db, cb) {
    var _this = this;
    /*
		switch (mongoose.connection.readyState) {
			case 0 : Disconnected;
			case 1 : Connected;
			case 2 : Connecting;
			case 3 : Disconnecting;
		}
		source http://mongoosejs.com/docs/api.html#connection_Connection-readyState
	*/
    if (mongoose.connection.readyState == 1) {
        _this.connected = true;
        console.log('Successfully initialized mongoose-seed');
        cb();
    }
    mongoose.connect(db, function(err) {
        // Log Error
        if (err) {
            console.error(chalk.red('Could not connect to MongoDB!'));
            console.log(err);
        } else {
            _this.connected = true;
            console.log('Successfully initialized mongoose-seed');
            cb();
        }
    });
};

Seeder.prototype.loadModels = function(modelPaths) {
    console.log(modelPaths);
    modelPaths.forEach(function(modelPath) {
        var model = require(path.resolve(modelPath));
        if (model instanceof Function) {
            model();
        }
    });
};

Seeder.prototype.invalidModelCheck = function(models, cb) {
    var invalidModels = [];

    models.forEach(function(model) {
        if (_.indexOf(mongoose.modelNames(), model) === -1) {
            invalidModels.push(model);
        }
    });

    if (invalidModels.length) {
        cb(new Error('Models not registered in Mongoose: ' + invalidModels));
    } else {
        cb();
    }
};

Seeder.prototype.clearModels = function(models, cb) {
    if (!this.connected) {
        return new Error('Not connected to db, exiting function');
    }

    var modelNames = [];

    // Convert to array if not already
    if (Array.isArray(models)) {
        modelNames = models;
    } else if (typeof(models) === 'string') {
        modelNames.push(models);
    } else {
        console.error(chalk.red('Error: Invalid model type'));
        return;
    }

    // Confirm that all Models have been registered in Mongoose
    this.invalidModelCheck(modelNames, function(err) {
        if (err) {
            console.error(chalk.red('Error: ' + err.message));
            return;
        }

        // Clear each model
        async.each(modelNames, function(modelName, done) {
            var Model = mongoose.model(modelName);
            Model.remove({}, function(err) {
                if (err) {
                    console.error(chalk.red('Error: ' + err.message));
                    return;
                }
                console.log(modelName + 's collection cleared');
                done();
            });
        }, function(err) {
            // Final async callback
            if (err) {
                return;
            }
            cb();
        });
    });
};

Seeder.prototype.populateModels = function(seedData, cb) {
    if (!this.connected) {
        return new Error('Not connected to db, exiting function');
    }

    var modelNames = _.unique(_.pluck(seedData, 'model'));

    // Confirm that all Models have been registered in Mongoose
    var invalidModels = this.invalidModelCheck(modelNames, function(err) {
        if (err) {
            console.error(chalk.red('Error: ' + err.message));
            return;
        }

        // Populate each model
        seedData.forEach(function(entry) {
            var Model = mongoose.model(entry.model);
            entry.documents.forEach(function(document, j) {
                Model.create(document, function(err) {
                    if (err) {
                        console.error(chalk.red('Error creating document [' + j + '] of ' + entry.model + ' model'));
                        console.error(chalk.red('Error: ' + err.message));
                        return;
                    }
                    console.log('Successfully created document [' + j + '] of ' + entry.model + ' model');
                });
            });
        });
    });
    cb();
};

module.exports = new Seeder();
<|endoftext|>


<commit_before>'use strict';

const Rela = require('./lib'),
      info = require('./package');

/* index.js
 * Server initialization and package information.
 * * */

// Library initializer
let rela = function(opts){
  return new Rela(opts);
};

// Raw server accessor.
rela.Rela = Rela;

// Meta
rela.version = info.version;
rela.author = info.author;
rela.license = info.license;

module.exports = rela;
<commit_msg>Adapt to new lib/index.js<commit_after>'use strict';

const lib = require('./lib'),
      info = require('./package'),
      Server = lib.Server;

/* index.js
 * Server initialization and package information.
 * * */

// Library initializer
let rela = function(opts){
  return new Server(opts);
};

// Library access
Object.assign(rela, lib);

// Meta
rela.version = info.version;
rela.author = info.author;
rela.license = info.license;

// Export
module.exports = rela;
<|endoftext|>


<commit_before>function depends(a, b, list, path = []) {
  if(!list[a]) return;
  path = path.concat([a]);
  var dep = list[a];
  if(dep.dependencies.indexOf(b) !== -1) return path.concat([b]);
  return dep.dependencies
    .reduce((found, dep) => found ? found : depends(dep, b, list, path), null);
}

class Container {
  constructor() {
    this.factories = {};
  }
  register(name, dependencies, factory) {
    if(typeof dependencies == 'function') {
      factory = dependencies;
      dependencies = [];
    }
    this.factories[name] = {
      dependencies: dependencies,
      factory: factory
    };
  }
  init() {
    var factories = Object.keys(this.factories);
    factories.forEach(dep => {
      var path;
      if(path = depends(dep, dep, this.factories)) {
        throw new Error(dep + ' depends on itself! (' + path.join('->') +')');
      }
    });
  }
  resolve(name) {
    if(!this.factories[name]) {
      throw new Error('Dependency ' + name + ' not found!');
    }
    return this.factories[name].instance
      ? this.factories[name].instance
      : this.factories[name].instance = this.create(name);
  }
  create(name) {
    return this.factories[name].factory.apply(
      null,
      this.factories[name].dependencies.map(dep => this.resolve(dep))
    );
  }
}

export default Container;
<commit_msg>Allow parent lookup<commit_after>function depends(a, b, list, path = []) {
  if(!list[a]) return;
  path = path.concat([a]);
  var dep = list[a];
  if(dep.dependencies.indexOf(b) !== -1) return path.concat([b]);
  return dep.dependencies
    .reduce((found, dep) => found ? found : depends(dep, b, list, path), null);
}

class Container {
  constructor(parent) {
    this.parent = parent;
    this.factories = {};
  }
  register(name, dependencies, factory) {
    if(typeof dependencies == 'function') {
      factory = dependencies;
      dependencies = [];
    }
    this.factories[name] = {
      dependencies: dependencies,
      factory: factory
    };
  }
  init() {
    var factories = Object.keys(this.factories);
    factories.forEach(dep => {
      var path;
      if(path = depends(dep, dep, this.factories)) {
        throw new Error(dep + ' depends on itself! (' + path.join('->') +')');
      }
    });
  }
  resolve(name) {
    if(!this.factories[name] && !this.parent) {
      throw new Error('Dependency ' + name + ' not found!');
    } else if(this.parent) {
      return this.parent.resolve(name);
    }
    return this.factories[name].instance
      ? this.factories[name].instance
      : this.factories[name].instance = this.create(name);
  }
  create(name) {
    return this.factories[name].factory.apply(
      null,
      this.factories[name].dependencies.map(dep => this.resolve(dep))
    );
  }
}

export default Container;
<|endoftext|>


<commit_before>'use strict';

const AWS = require('aws-sdk');

// Wrapper class for AWS Lambda
class Wrapped {
  constructor(mod, opts) {
    const options = opts || {};

    this.lambdaModule = mod;
    const handler = options.handler || 'handler';

    if (mod[handler]) {
      this.handler = mod[handler];
    }
  }

  runHandler(event, customContext, cb) {
    return new Promise((resolve, reject) => {

      const promiseCallback = (error, response) => {
        if(error) {
          return reject(error);
        }
        return resolve(response);
      };

      const callback = cb || promiseCallback;

      const defaultContext = {
        succeed: success => callback(null, success),
        fail: error => callback(error, null),
        done: (error, success) => callback(error, success)
      };

      const lambdaContext = Object.assign({}, defaultContext, customContext);

      try {
        if (this.handler) {
          this.handler(event, lambdaContext, callback);
        } else {
          if (this.lambdaModule.region) {
            AWS.config.update({
              region: this.lambdaModule.region
            });
          }

          const lambda = new AWS.Lambda();
          const params = {
            FunctionName: this.lambdaModule.lambdaFunction,
            InvocationType: 'RequestResponse',
            LogType: 'None',
            Payload: JSON.stringify(event)
          };

          lambda.invoke(params, (err, data) => {
            if (err) {
              return callback(err);
            }

            return callback(null, JSON.parse(data.Payload));
          });
        }
      } catch (ex) {
        throw (ex);
      }
    });
  }

  run(event, context, callback) {
    let callbackFunction = callback;
    let contextObject = context;
    if (typeof context === 'function') {
      // backwards compability
      callbackFunction = context;
      contextObject = {};
    }
    return this.runHandler(event, contextObject, callbackFunction);
  }
}

// Wrapper factory

const wrap = (mod, options) => new Wrapped(mod, options);

// Static variables (for backwards compatibility)

let latest;

// Public interface for the module

module.exports = exports = {

  // reusable wrap method
  wrap,

  // static init/run interface for backwards compatibility
  init: (mod, options) => {
    latest = wrap(mod, options);
  },
  run: (event, context, callback) => new Promise((resolve, reject) => {
    let callbackFunction = callback;
    let contextObject = context;
    if (typeof context === 'function') {
      // backwards compability
      callbackFunction = context;
      contextObject = {};
    }
    if (typeof latest === typeof undefined) {
      const error = 'Module not initialized';
      reject(error);
      return callbackFunction(error, null);
    }
    return latest.run(event, contextObject, (err, data) => {
      if (callbackFunction) {
        return callbackFunction(err, data);
      }
      if (err) {
        return reject(err);
      }
      return resolve(data);
    });
  })
};
<commit_msg>Ensure consistent error handling<commit_after>'use strict';

const AWS = require('aws-sdk');

// Wrapper class for AWS Lambda
class Wrapped {
  constructor(mod, opts) {
    const options = opts || {};

    this.lambdaModule = mod;
    const handler = options.handler || 'handler';

    if (mod[handler]) {
      this.handler = mod[handler];
    }
  }

  runHandler(event, customContext, cb) {
    return new Promise((resolve, reject) => {

      const promiseCallback = (error, response) => {
        if(error) {
          return reject(error);
        }
        return resolve(response);
      };

      const callback = cb || promiseCallback;

      const defaultContext = {
        succeed: success => callback(null, success),
        fail: error => callback(error, null),
        done: (error, success) => callback(error, success)
      };

      const lambdaContext = Object.assign({}, defaultContext, customContext);

      try {
        if (this.handler) {
          this.handler(event, lambdaContext, callback);
        } else {
          if (this.lambdaModule.region) {
            AWS.config.update({
              region: this.lambdaModule.region
            });
          }

          const lambda = new AWS.Lambda();
          const params = {
            FunctionName: this.lambdaModule.lambdaFunction,
            InvocationType: 'RequestResponse',
            LogType: 'None',
            Payload: JSON.stringify(event)
          };

          lambda.invoke(params, (err, data) => {
            if (err) {
              return callback(err);
            }
            if (data.FunctionError) {
              return callback(Object.assign(new Error(JSON.parse(data.Payload).errorMessage), data));
            }
            return callback(null, JSON.parse(data.Payload));
          });
        }
      } catch (ex) {
        throw (ex);
      }
    });
  }

  run(event, context, callback) {
    let callbackFunction = callback;
    let contextObject = context;
    if (typeof context === 'function') {
      // backwards compability
      callbackFunction = context;
      contextObject = {};
    }
    return this.runHandler(event, contextObject, callbackFunction);
  }
}

// Wrapper factory

const wrap = (mod, options) => new Wrapped(mod, options);

// Static variables (for backwards compatibility)

let latest;

// Public interface for the module

module.exports = exports = {

  // reusable wrap method
  wrap,

  // static init/run interface for backwards compatibility
  init: (mod, options) => {
    latest = wrap(mod, options);
  },
  run: (event, context, callback) => new Promise((resolve, reject) => {
    let callbackFunction = callback;
    let contextObject = context;
    if (typeof context === 'function') {
      // backwards compability
      callbackFunction = context;
      contextObject = {};
    }
    if (typeof latest === typeof undefined) {
      const error = 'Module not initialized';
      reject(error);
      return callbackFunction(error, null);
    }
    return latest.run(event, contextObject, (err, data) => {
      if (callbackFunction) {
        return callbackFunction(err, data);
      }
      if (err) {
        return reject(err);
      }
      return resolve(data);
    });
  })
};
<|endoftext|>