<commit_before>#!/usr/bin/env node
const SMTPServer = require('smtp-server').SMTPServer;
const simpleParser = require('mailparser').simpleParser;
const express = require("express");
const basicAuth = require('express-basic-auth');
const path = require("path");
const _ = require("lodash");
const moment = require("moment");
const cli = require('cli').enable('catchall').enable('status');

const config = cli.parse({
  'smtp-port': ['s', 'SMTP port to listen on', 'number', 1025],
  'smtp-ip': [false, 'IP Address to bind SMTP service to', 'ip', '0.0.0.0'],
  'http-port': ['h', 'HTTP port to listen on', 'number', 1080],
  'http-ip': [false, 'IP Address to bind HTTP service to', 'ip', '0.0.0.0'],
  whitelist: ['w', 'Only accept e-mails from these adresses. Accepts multiple e-mails comma-separated', 'string'],
  max: ['m', 'Max number of e-mails to keep', 'number', 100],
  auth: ['a', 'Enable Authentication', 'string'],
  headers: [false, 'Enable headers in responses']
});

const whitelist = config.whitelist ? config.whitelist.split(',') : [];

let users = null;
if (config.auth && !/.+:.+/.test(config.auth)) {
    cli.error("Please provide authentication details in USERNAME:PASSWORD format");
    console.log(process.exit(1))
}
if (config.auth) {
  let authConfig = config.auth.split(":");
  users = {};
  users[authConfig[0]] = authConfig[1];
}

const mails = [];

const server = new SMTPServer({
  authOptional: true,
  onMailFrom(address, session, cb) {
    if (whitelist.length == 0 || whitelist.indexOf(address.address) !== -1) {
      cb();
    } else {
      cb(new Error('Invalid email from: ' + address.address));
    }
  },
  onData(stream, session, callback) {
    parseEmail(stream).then(
      mail => {
        cli.debug(JSON.stringify(mail, null, 2));

        mails.unshift(mail);

        //trim list of emails if necessary
        while (mails.length > config.max) {
          mails.pop();
        }

        callback();
      },
      callback
    );
  }
});

function formatHeaders(headers) {
  const result = {};
  for (const [key, value] of headers) {
    result[key] = value;
  }
  return result;
}

function parseEmail(stream) {
  return simpleParser(stream).then(email => {
    if (config.headers) {
      email.headers = formatHeaders(email.headers);
    } else {
      delete email.headers;
    }
    return email;
  });
}

server.on('error', err => {
  cli.error(err);
});

server.listen(config['smtp-port'], config['smtp-ip']);

const app = express();

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

if (users) {
    app.use(basicAuth({
        users: users,
        challenge: true
    }));
}

const buildDir = path.join(__dirname, 'build');

app.use(express.static(buildDir));

function emailFilter(filter) {
  return email => {
    if (filter.since || filter.until) {
      const date = moment(email.date);
      if (filter.since && date.isBefore(filter.since)) {
        return false;
      }
      if (filter.until && date.isAfter(filter.until)) {
        return false;
      }
    }

    if (filter.to && _.every(email.to.value, to => to.address !== filter.to)) {
      return false;
    }

    if (filter.from && _.every(email.from.value, from => from.address !== filter.from)) {
      return false;
    }

    return true;
  }
}

app.get('/api/emails', (req, res) => {
  res.json(mails.filter(emailFilter(req.query)));
});

app.delete('/api/emails', (req, res) => {
    mails.length = 0;
    res.send();
});

app.listen(config['http-port'], config['http-ip'], () => {
  cli.info("HTTP server listening on http://" + config['http-ip'] +  ":" + config['http-port']);
});

cli.info("SMTP server listening on " + config['smtp-ip'] + ":" + config['smtp-port']);
<commit_msg>Fix `421: Mail command failed` issue by adding `MaxUnauthAllowed` attempts 1000<commit_after>#!/usr/bin/env node
const SMTPServer = require('smtp-server').SMTPServer;
const simpleParser = require('mailparser').simpleParser;
const express = require("express");
const basicAuth = require('express-basic-auth');
const path = require("path");
const _ = require("lodash");
const moment = require("moment");
const cli = require('cli').enable('catchall').enable('status');

const config = cli.parse({
  'smtp-port': ['s', 'SMTP port to listen on', 'number', 1025],
  'smtp-ip': [false, 'IP Address to bind SMTP service to', 'ip', '0.0.0.0'],
  'http-port': ['h', 'HTTP port to listen on', 'number', 1080],
  'http-ip': [false, 'IP Address to bind HTTP service to', 'ip', '0.0.0.0'],
  whitelist: ['w', 'Only accept e-mails from these adresses. Accepts multiple e-mails comma-separated', 'string'],
  max: ['m', 'Max number of e-mails to keep', 'number', 100],
  auth: ['a', 'Enable Authentication', 'string'],
  headers: [false, 'Enable headers in responses']
});

const whitelist = config.whitelist ? config.whitelist.split(',') : [];

let users = null;
if (config.auth && !/.+:.+/.test(config.auth)) {
    cli.error("Please provide authentication details in USERNAME:PASSWORD format");
    console.log(process.exit(1))
}
if (config.auth) {
  let authConfig = config.auth.split(":");
  users = {};
  users[authConfig[0]] = authConfig[1];
}

const mails = [];

const server = new SMTPServer({
  authOptional: true,
  maxAllowedUnauthenticatedCommands: 1000,
  onMailFrom(address, session, cb) {
    if (whitelist.length == 0 || whitelist.indexOf(address.address) !== -1) {
      cb();
    } else {
      cb(new Error('Invalid email from: ' + address.address));
    }
  },
  onData(stream, session, callback) {
    parseEmail(stream).then(
      mail => {
        cli.debug(JSON.stringify(mail, null, 2));

        mails.unshift(mail);

        //trim list of emails if necessary
        while (mails.length > config.max) {
          mails.pop();
        }

        callback();
      },
      callback
    );
  }
});

function formatHeaders(headers) {
  const result = {};
  for (const [key, value] of headers) {
    result[key] = value;
  }
  return result;
}

function parseEmail(stream) {
  return simpleParser(stream).then(email => {
    if (config.headers) {
      email.headers = formatHeaders(email.headers);
    } else {
      delete email.headers;
    }
    return email;
  });
}

server.on('error', err => {
  cli.error(err);
});

server.listen(config['smtp-port'], config['smtp-ip']);

const app = express();

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

if (users) {
    app.use(basicAuth({
        users: users,
        challenge: true
    }));
}

const buildDir = path.join(__dirname, 'build');

app.use(express.static(buildDir));

function emailFilter(filter) {
  return email => {
    if (filter.since || filter.until) {
      const date = moment(email.date);
      if (filter.since && date.isBefore(filter.since)) {
        return false;
      }
      if (filter.until && date.isAfter(filter.until)) {
        return false;
      }
    }

    if (filter.to && _.every(email.to.value, to => to.address !== filter.to)) {
      return false;
    }

    if (filter.from && _.every(email.from.value, from => from.address !== filter.from)) {
      return false;
    }

    return true;
  }
}

app.get('/api/emails', (req, res) => {
  res.json(mails.filter(emailFilter(req.query)));
});

app.delete('/api/emails', (req, res) => {
    mails.length = 0;
    res.send();
});

app.listen(config['http-port'], config['http-ip'], () => {
  cli.info("HTTP server listening on http://" + config['http-ip'] +  ":" + config['http-port']);
});

cli.info("SMTP server listening on " + config['smtp-ip'] + ":" + config['smtp-port']);
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var fs = require('graceful-fs');
var _ = require('lodash');
var through = require('through2');
var convert = require('convert-source-map');

class Wallabify {

  constructor(opts, initializer) {
    this._patchModuleDependenciesModule();

    this._opts = opts || {};
    this._initializer = initializer;

    this._b = null;
    this._browserifyCache = {};
    this._affectedFilesCache = {};
    this._initRequired = false;
    this._allTrackedFiles = {};
  }

  createPostprocessor() {
    var self = this;
    try {
      this._browserify = require('browserify');
    }
    catch (e) {
      console.error('Browserify node module is not found, missing `npm install browserify --save-dev`?');
      return;
    }

    // wallaby.js postprocessor for browserify
    // The postprocessor creates and reuses browserify instance.
    // It splices browserify pipeline so that file concatenation doesn't happen.
    // Instead, the postprocessor creates new files and lets wallaby.js to serve them to browser as requested.
    // This allows to leverage file-based browser caching as opposed to always reload a full bundle.
    // When separate files load, they only add a function with the file body to the cache object.
    // Actual loading happens when window.__moduleBundler.loadTests is called (from bootstrap function).

    return wallaby => {
      var logger = wallaby.logger;
      var affectedFiles = wallaby.affectedFiles;
      if (!self._b || wallaby.anyFilesAdded || wallaby.anyFilesDeleted) {

        if (!self._b) {
          logger.debug('New browserify instance created');
        }
        else {
          logger.debug('Browserify instance re-created because some tracked files were added or deleted');
        }

        self._initRequired = true;
        self._affectedFilesCache = {};
        self._allTrackedFiles = _.reduce(wallaby.allFiles, function (memo, file) {
          memo[file.fullPath] = file;
          return memo;
        }, {});
        affectedFiles = wallaby.allFiles;

        self._b = self._createBrowserify({
          entries: _.map(wallaby.allTestFiles, testFile => testFile.fullPath),
          paths: wallaby.nodeModulesDir ? [wallaby.nodeModulesDir] : [],
          cache: {}, packageCache: {}, fullPaths: true
        });

        self._browserifyCache = self._b._options.cache;

        self._b.on('dep', function (dep) {
          if (typeof dep.id === 'string') {
            var key = dep.id;
            if (!self._browserifyCache[key]) {
              self._browserifyCache[key] = dep;
              // external files are cached by file name as well to avoid re-processing them every time
              if (dep.expose) {
                self._browserifyCache[dep.file] = dep;
              }
              // new file that has not been cached before (node module or a source file)
              self._affectedFilesCache[key] = dep;
            }
          }
        });

        // no need to pack the bundle, wallaby.js serves files one by one to leverage browser caching
        self._b.pipeline.splice('pack');
      }

      // todo: handle node modules external update
      // todo: bundle node_modules into a single file

      // removing changed files tracked by wallaby.js from browserify cache
      if (!self._initRequired) {
        _.each(affectedFiles, file => {
          delete self._browserifyCache[file.fullPath];
        });
      }

      return new Promise(
        function (resolve, reject) {
          try {
            // incremental bundling
            self._b.bundle()
              .on('data', () => {
              })
              .on('error', err => reject(err))
              .on('end', () => resolve());
          } catch (err) {
            reject(err);
          }
        })
        .then(function () {
          var createFilePromises = [];

          // test loader for wallaby.js
          // works exactly as browserify bundle loading, but with separate files as opposed to a single bundle file
          if (self._initRequired) {
            self._initRequired = false;

            createFilePromises.push(wallaby.createFile({
              order: -1,  // need to be the first file to load
              path: 'wallabify.js',
              content: Wallabify._getLoaderContent()
            }));
          }

          // handling changed files tracked by wallaby.js
          _.each(affectedFiles, function (file) {
            var cached = self._browserifyCache[file.fullPath];
            if (cached) {
              var code = cached.source;
              var sourceMap;
              var sourceMapConverter = convert.fromSource(code);
              if (sourceMapConverter) {
                sourceMap = sourceMapConverter.toJSON();
                code = convert.removeComments(code);
              }

              // cloning an original file and browserify-ing it
              createFilePromises.push(wallaby.createFile({
                // adding the suffix to store browserified file along with the original copies
                path: file.path + '.bro' + path.extname(file.path),
                original: file,
                content: Wallabify._wallabifyFile(file.fullPath, code, cached.deps),
                sourceMap: sourceMap
              }));
              delete self._affectedFilesCache[file.fullPath];
            }
          });

          // handling externally added and not tracked files (such as node modules and external files)
          try {
            _.each(self._affectedFilesCache, function (file) {
              if (!file.expose && !~file.id.indexOf(wallaby.nodeModulesDir)) {
                throw new Error('File ' + file.id + ' is neither a node module nor an external dependency.');
              }
              createFilePromises.push(wallaby.createFile({
                path: file.expose
                  ? path.join('browserify_external', file.id, 'external' +  + path.extname(file.id))
                  : path.join('browserify_node_modules', path.relative(wallaby.nodeModulesDir, file.id)),
                content: Wallabify._wallabifyFile(file.id, file.source, file.deps),
                ts: 1   // constant timestamp to cache forever (until wallaby restarts)
              }));
            });
          }
          catch (e) {
            return Promise.reject(e);
          }

          // resetting till next incremental bundle run
          self._affectedFilesCache = {};

          logger.debug('Emitting %s files', createFilePromises.length);

          return Promise.all(createFilePromises);
        });
    }
  }

  _createBrowserify(mandatoryOpts) {
    var paths = mandatoryOpts.paths.concat(this._opts.paths || []);
    var mergedOpts = _.extend(this._opts, mandatoryOpts);
    mergedOpts.paths = paths;

    var instance = this._browserify(mergedOpts);
    if (this._initializer && _.isFunction(this._initializer)) {
      return this._initializer(instance) || instance;
    }

    return instance;
  }

  static _wallabifyFile(id, content, deps) {
    return 'window.__moduleBundler.cache["' + id + '"] = [function(require, module, exports) {'
      + content + '\n}, ' + JSON.stringify(deps) + '];';
  }

  static _getLoaderContent() {
    return 'window.__moduleBundler = {};'
      + 'window.__moduleBundler.cache = {};'
      + 'window.__moduleBundler.loadTests = function () {'
        // browser pack prelude
      + '(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module \'"+o+"\'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})'
        // passing accumulated files and entry points (browserified tests for the current sandbox)
      + '(window.__moduleBundler.cache, {}, (function(){ var testIds = []; for(var i = 0, len = wallaby.loadedTests.length; i < len; i++) { var test = wallaby.loadedTests[i]; if (test.substr(-7) === ".bro.js") testIds.push(wallaby.baseDir + test.substr(0, test.length - 7)); } return testIds; })()); };'
  }

  _patchModuleDependenciesModule() {
    var wallabify = this;
    // patching module dependencies to use wallaby cache
    try {
      require('browserify/node_modules/module-deps').prototype.readFile = function (file, id) {
        var self = this;
        var tr = through();
        if (this.cache && this.cache[file]) {
          tr.push(this.cache[file].source);
          tr.push(null);
          return tr;
        }

        // wallaby.js may already have the file cached (if not, it will just read it from disk)
        if (wallabify._allTrackedFiles && wallabify._allTrackedFiles[file]) {
          wallabify._allTrackedFiles[file].getContent().then(function (source) {
            tr.push(source);
            tr.push(null);
          });
          return tr;
        }

        var rs = fs.createReadStream(file);
        rs.on('error', function (err) {
          self.emit('error', err)
        });
        this.emit('file', file, id);
        return rs;
      };
    }
    catch (e) {
      // not critical
      console.warn('Failed to patch `module-deps` module, wallaby.js file cache will not be used.'
      + '\nIt\'s not a critical issue, however tests will run faster when wallaby.js file cache is used.');
    }
  }
}

module.exports = function (opts, initializer) {
  return new Wallabify(opts, initializer).createPostprocessor();
};<commit_msg>Code comments<commit_after>'use strict';

var path = require('path');
var fs = require('graceful-fs');
var _ = require('lodash');
var through = require('through2');
var convert = require('convert-source-map');

class Wallabify {

  constructor(opts, initializer) {
    this._patchModuleDependenciesModule();

    this._opts = opts || {};
    this._initializer = initializer;

    this._b = null;
    this._browserifyCache = {};
    this._affectedFilesCache = {};
    this._initRequired = false;
    this._allTrackedFiles = {};
  }

  createPostprocessor() {
    var self = this;
    try {
      this._browserify = require('browserify');
    }
    catch (e) {
      console.error('Browserify node module is not found, missing `npm install browserify --save-dev`?');
      return;
    }

    // wallaby.js postprocessor for browserify
    // The postprocessor creates and reuses browserify instance.
    // It splices browserify pipeline so that file concatenation doesn't happen.
    // Instead, the postprocessor creates new files and lets wallaby.js to serve them to browser as requested.
    // This allows to leverage file-based browser caching as opposed to always reload a full bundle.
    // When separate files load, they only add a function with the file body to the cache object.
    // Actual loading happens when window.__moduleBundler.loadTests is called (from bootstrap function).

    return wallaby => {
      var logger = wallaby.logger;
      var affectedFiles = wallaby.affectedFiles;
      if (!self._b || wallaby.anyFilesAdded || wallaby.anyFilesDeleted) {

        if (!self._b) {
          logger.debug('New browserify instance created');
        }
        else {
          logger.debug('Browserify instance re-created because some tracked files were added or deleted');
        }

        self._initRequired = true;
        self._affectedFilesCache = {};
        self._allTrackedFiles = _.reduce(wallaby.allFiles, function (memo, file) {
          memo[file.fullPath] = file;
          return memo;
        }, {});
        affectedFiles = wallaby.allFiles;

        self._b = self._createBrowserify({
          entries: _.map(wallaby.allTestFiles, testFile => testFile.fullPath),
          paths: wallaby.nodeModulesDir ? [wallaby.nodeModulesDir] : [],
          cache: {}, packageCache: {}, fullPaths: true
        });

        self._browserifyCache = self._b._options.cache;

        self._b.on('dep', function (dep) {
          if (typeof dep.id === 'string') {
            var key = dep.id;
            if (!self._browserifyCache[key]) {
              self._browserifyCache[key] = dep;
              // external files are cached by file name as well to avoid re-processing them every time
              if (dep.expose) {
                self._browserifyCache[dep.file] = dep;
              }
              // new file that has not been cached before (node module or a source file)
              self._affectedFilesCache[key] = dep;
            }
          }
        });

        // no need to pack the bundle, wallaby.js serves files one by one to leverage browser caching
        self._b.pipeline.splice('pack');
      }

      // todo: handle node modules external update
      // todo: bundle node_modules into a single file

      // removing changed files tracked by wallaby.js from browserify cache
      if (!self._initRequired) {
        _.each(affectedFiles, file => {
          delete self._browserifyCache[file.fullPath];
        });
      }

      return new Promise(
        function (resolve, reject) {
          try {
            // incremental bundling
            self._b.bundle()
              .on('data', () => {
              })
              .on('error', err => reject(err))
              .on('end', () => resolve());
          } catch (err) {
            reject(err);
          }
        })
        .then(function () {
          var createFilePromises = [];

          // test loader for wallaby.js
          // works exactly as browserify bundle loading, but with separate files as opposed to a single bundle file
          if (self._initRequired) {
            self._initRequired = false;

            createFilePromises.push(wallaby.createFile({
              order: -1,  // need to be the first file to load
              path: 'wallabify.js',
              content: Wallabify._getLoaderContent()
            }));
          }

          // handling changed files tracked by wallaby.js
          _.each(affectedFiles, function (file) {
            var cached = self._browserifyCache[file.fullPath];
            if (cached) {
              var code = cached.source;
              var sourceMap;
              var sourceMapConverter = convert.fromSource(code);
              if (sourceMapConverter) {
                sourceMap = sourceMapConverter.toJSON();
                code = convert.removeComments(code);
              }

              // cloning an original file and browserify-ing it
              createFilePromises.push(wallaby.createFile({
                // adding the suffix to store browserified file along with the original copies
                path: file.path + '.bro' + path.extname(file.path),
                original: file,
                content: Wallabify._wallabifyFile(file.fullPath, code, cached.deps),
                sourceMap: sourceMap
              }));
              delete self._affectedFilesCache[file.fullPath];
            }
          });

          // handling externally added and not tracked files (such as node modules and external files)
          try {
            _.each(self._affectedFilesCache, function (file) {
              if (!file.expose && !~file.id.indexOf(wallaby.nodeModulesDir)) {
                throw new Error('File ' + file.id + ' is neither a node module nor an external dependency.');
              }
              createFilePromises.push(wallaby.createFile({
                path: file.expose
                  ? path.join('browserify_external', file.id, 'external' +  + path.extname(file.id))
                  : path.join('browserify_node_modules', path.relative(wallaby.nodeModulesDir, file.id)),
                content: Wallabify._wallabifyFile(file.id, file.source, file.deps),
                ts: 1   // constant timestamp to cache the file in browser/phantomjs forever (until wallaby restarts)
              }));
            });
          }
          catch (e) {
            return Promise.reject(e);
          }

          // resetting till next incremental bundle run
          self._affectedFilesCache = {};

          logger.debug('Emitting %s files', createFilePromises.length);

          return Promise.all(createFilePromises);
        });
    }
  }

  _createBrowserify(mandatoryOpts) {
    var paths = mandatoryOpts.paths.concat(this._opts.paths || []);
    var mergedOpts = _.extend(this._opts, mandatoryOpts);
    mergedOpts.paths = paths;

    var instance = this._browserify(mergedOpts);
    if (this._initializer && _.isFunction(this._initializer)) {
      return this._initializer(instance) || instance;
    }

    return instance;
  }

  static _wallabifyFile(id, content, deps) {
    return 'window.__moduleBundler.cache["' + id + '"] = [function(require, module, exports) {'
      + content + '\n}, ' + JSON.stringify(deps) + '];';
  }

  static _getLoaderContent() {
    return 'window.__moduleBundler = {};'
      + 'window.__moduleBundler.cache = {};'
      + 'window.__moduleBundler.loadTests = function () {'
        // browser pack prelude
      + '(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module \'"+o+"\'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})'
        // passing accumulated files and entry points (browserified tests for the current sandbox)
      + '(window.__moduleBundler.cache, {}, (function(){ var testIds = []; for(var i = 0, len = wallaby.loadedTests.length; i < len; i++) { var test = wallaby.loadedTests[i]; if (test.substr(-7) === ".bro.js") testIds.push(wallaby.baseDir + test.substr(0, test.length - 7)); } return testIds; })()); };'
  }

  _patchModuleDependenciesModule() {
    var wallabify = this;
    // patching module dependencies to use wallaby cache
    try {
      require('browserify/node_modules/module-deps').prototype.readFile = function (file, id) {
        var self = this;
        var tr = through();
        if (this.cache && this.cache[file]) {
          tr.push(this.cache[file].source);
          tr.push(null);
          return tr;
        }

        // wallaby.js may already have the file cached (if not, it will just read it from disk)
        if (wallabify._allTrackedFiles && wallabify._allTrackedFiles[file]) {
          wallabify._allTrackedFiles[file].getContent().then(function (source) {
            tr.push(source);
            tr.push(null);
          });
          return tr;
        }

        var rs = fs.createReadStream(file);
        rs.on('error', function (err) {
          self.emit('error', err)
        });
        this.emit('file', file, id);
        return rs;
      };
    }
    catch (e) {
      // not critical
      console.warn('Failed to patch `module-deps` module, wallaby.js file cache will not be used.'
      + '\nIt\'s not a critical issue, however tests will run faster when wallaby.js file cache is used.');
    }
  }
}

module.exports = function (opts, initializer) {
  return new Wallabify(opts, initializer).createPostprocessor();
};<|endoftext|>


<commit_before>var SplitByNamePlugin = module.exports = function (options) {
  this.options = options;
};

SplitByNamePlugin.prototype.apply = function(compiler) {
  var options = this.options;

  function findMatchingBucket(chunk) {
    var match = null;
    options.buckets.some(function (bucket) {
      if (bucket.regex.test(chunk.rawRequest)) {
        match = bucket;
        return true;
      }
    });
    return match;
  }

  compiler.plugin("compilation", function(compilation) {
    var extraChunks = {};

    // Find the chunk which was already created by this bucket.
    // This is also the grossest function name I've written today.
    function bucketToChunk(bucket) {
      return extraChunks[bucket.name];
    }

    compilation.plugin("optimize-chunks", function(chunks) {
      var addChunk = this.addChunk.bind(this);
      chunks
        // only parse the entry chunk
        .filter(function (chunk) {
          return chunk.entry;
        })
        .forEach(function(chunk) {
          chunk.modules.slice().forEach(function (mod) {
            var bucket = findMatchingBucket(mod),
                newChunk;
            if (!bucket) {
              // it stays in the original bucket
              return;
            }
            if (!(newChunk = bucketToChunk(bucket))) {
              newChunk = extraChunks[bucket.name] = addChunk(bucket.name);
            }
            // add the module to the new chunk
            newChunk.addModule(mod);
            mod.addChunk(newChunk);
            // remove it from the existing chunk
            mod.removeChunk(chunk);
          });

          options.buckets
            .map(bucketToChunk)
            .filter(Boolean)
            .concat(chunk)
            .forEach(function (chunk, index, allChunks) { // allChunks = [bucket0, bucket1, .. bucketN, orig]
              if (index) { // not the first one, they get the first chunk as a parent
                chunk.parents = [allChunks[0]];
              } else { // the first chunk, it gets the others as 'sub' chunks
                chunk.chunks = allChunks.slice(1);
              }
              chunk.initial = chunk.entry = !index;
            });
        });
    });
  });
};
<commit_msg>Support string bucket regexes<commit_after>var SplitByNamePlugin = module.exports = function (options) {
  this.options = options;

  // process buckets
  this.options.buckets = this.options.buckets.slice(0).map(function (bucket) {
    if (!(bucket.regex instanceof RegExp)) {
      bucket.regex = new RegExp(bucket.regex);
    }
    return bucket;
  });
};

SplitByNamePlugin.prototype.apply = function(compiler) {
  var options = this.options;

  function findMatchingBucket(chunk) {
    var match = null;
    options.buckets.some(function (bucket) {
      if (bucket.regex.test(chunk.rawRequest)) {
        match = bucket;
        return true;
      }
    });
    return match;
  }

  compiler.plugin("compilation", function(compilation) {
    var extraChunks = {};

    // Find the chunk which was already created by this bucket.
    // This is also the grossest function name I've written today.
    function bucketToChunk(bucket) {
      return extraChunks[bucket.name];
    }

    compilation.plugin("optimize-chunks", function(chunks) {
      var addChunk = this.addChunk.bind(this);
      chunks
        // only parse the entry chunk
        .filter(function (chunk) {
          return chunk.entry;
        })
        .forEach(function(chunk) {
          chunk.modules.slice().forEach(function (mod) {
            var bucket = findMatchingBucket(mod),
                newChunk;
            if (!bucket) {
              // it stays in the original bucket
              return;
            }
            if (!(newChunk = bucketToChunk(bucket))) {
              newChunk = extraChunks[bucket.name] = addChunk(bucket.name);
            }
            // add the module to the new chunk
            newChunk.addModule(mod);
            mod.addChunk(newChunk);
            // remove it from the existing chunk
            mod.removeChunk(chunk);
          });

          options.buckets
            .map(bucketToChunk)
            .filter(Boolean)
            .concat(chunk)
            .forEach(function (chunk, index, allChunks) { // allChunks = [bucket0, bucket1, .. bucketN, orig]
              if (index) { // not the first one, they get the first chunk as a parent
                chunk.parents = [allChunks[0]];
              } else { // the first chunk, it gets the others as 'sub' chunks
                chunk.chunks = allChunks.slice(1);
              }
              chunk.initial = chunk.entry = !index;
            });
        });
    });
  });
};
<|endoftext|>


<commit_before>
var EE = require('events').EventEmitter,
    util = require('util'),
    redis = require('redis'),
    cradle = require('cradle'),
    Pagelet = require('packages-pagelet'),
    Registry = require('npm-registry'),
    Dynamis = require('dynamis'),
    Githulk = require('githulk');

module.exports = PreHeat;

util.inherits(PreHeat, EE);

function PreHeat (options) {
  options = options || {};
  if (!options.couchdb || !options.redis || !options.tokens) {
    throw new Error('This requires redis, couchdb, and tokens option');
  }

  options.registry = options.registry || 'https://registry.nodejitsu.com';

  this.options = options;

  this.couchdb = new (cradle).Connection(options.couchdb);
  this.redis = redis.createClient(options.redis.port, options.redis.host,
                                  { auth_pass: options.redis.auth });

  this.githulk = new Githulk({
    cache: new Dynamis('cradle', this.couchdb, options.couchdb),
    tokens: options.tokens
  });

  this.redis.on('error', this.emit.bind(this, 'error'));

  this.registry = new Registry({
    githulk: this.githulk,
    registry: options.registry
  });
  this.prefix = '';

  this.pagelet = new (Pagelet.extend({
    cache: new Dynamis('redis', this.redis, options.redis),
    registry: this.registry,
    githulk: this.githulk,
    key: this.key.bind(this)
  }).optimize());

}

PreHeat.prototype.key = function (name, version) {
  return this.prefix + Pagelet.prototype.key.call(this, name, version);
};

//
// Take the package name, resolve it and its dependencies and cache it.
// Allow a registry host to also be passed in
//
PreHeat.prototype.cache = function (package, host, callback) {
  if (!callback && typeof host === 'function') {
    callback = host;
    host = undefined;
  }
  if (host) {
    this.registry = new Registry({
      githulk: this.githulk,
      registry: host
    });
    this.prefix += host + ':private:';
    this.pagelet.registry = this.registry;
  }
  this._callback = callback && typeof callback === 'function'
    ? callback
    : undefined;

  this.pagelet.latest(package, this._onLatest.bind(this, package, host));
};

PreHeat.prototype._onLatest = function (package, host, err, version) {
  if (err) { return this.onError(err); }
  var key = this.pagelet.key(package, version);

  this.pagelet.fireforget('get', key, this._onFetch.bind(this, key, package, host));
};

PreHeat.prototype._onFetch = function (key, package, host, err, data) {
  if (err) { return this.onError(err) }
  if (!err && data) { return this.done() }

  // Allow host to override the registry instance so a new one is created
  // with the proper URL
  this.pagelet.resolve(package, {
    registry: this.registry,
    githulk: this.githulk
  }, this._onResolved.bind(this, key));
};

PreHeat.prototype._onResolved = function (key, err, data) {
  if (err) { return this.onError(err) }
  this.pagelet.fireforget('set', key, data,
                          this.pagelet.expire.data,
                          this.answer.bind(this));
};

PreHeat.prototype.answer = function (err) {
  return err
    ? this.onError(err)
    : this.done();
};

PreHeat.prototype.done = function () {
  return this._callback
    ? this._callback()
    : this.emit('done');
};

PreHeat.prototype.onError = function (err) {
  return this._callback
    ? this._callback(err)
    : this.emit('error', err);
};
<commit_msg>[fix] resimplify<commit_after>
var EE = require('events').EventEmitter,
    util = require('util'),
    redis = require('redis'),
    cradle = require('cradle'),
    Pagelet = require('packages-pagelet'),
    Registry = require('npm-registry'),
    Dynamis = require('dynamis'),
    Githulk = require('githulk');

module.exports = PreHeat;

util.inherits(PreHeat, EE);

function PreHeat (options) {
  options = options || {};
  if (!options.couchdb || !options.redis || !options.tokens) {
    throw new Error('This requires redis, couchdb, and tokens option');
  }

  options.registry = options.registry || 'https://registry.nodejitsu.com';

  this.options = options;

  this.couchdb = new (cradle).Connection(options.couchdb);
  this.redis = redis.createClient(options.redis.port, options.redis.host,
                                  { auth_pass: options.redis.auth });

  this.githulk = new Githulk({
    cache: new Dynamis('cradle', this.couchdb, options.couchdb),
    tokens: options.tokens
  });

  this.redis.on('error', this.emit.bind(this, 'error'));

  this.registry = new Registry({
    githulk: this.githulk,
    registry: options.registry
  });

  this.prefix = options.private
    ? options.registry + ':private:'
    : '';

  this.pagelet = new (Pagelet.extend({
    cache: new Dynamis('redis', this.redis, options.redis),
    registry: this.registry,
    githulk: this.githulk,
    key: this.key.bind(this)
  }).optimize());

}

PreHeat.prototype.key = function (name, version) {
  return this.prefix + Pagelet.prototype.key.call(this, name, version);
};

//
// Take the package name, resolve it and its dependencies and cache it.
// Allow a registry host to also be passed in
//
PreHeat.prototype.cache = function (package, callback) {
  this._callback = callback && typeof callback === 'function'
    ? callback
    : undefined;

  this.pagelet.latest(package, this._onLatest.bind(this, package));
};

PreHeat.prototype._onLatest = function (package, err, version) {
  if (err) { return this.onError(err); }
  var key = this.pagelet.key(package, version);
  console.log(key);
  this.pagelet.fireforget('get', key, this._onFetch.bind(this, key, package));
};

PreHeat.prototype._onFetch = function (key, package, err, data) {
  if (err) { return this.onError(err) }
  if (!err && data) { return this.done() }

  // Allow host to override the registry instance so a new one is created
  // with the proper URL
  this.pagelet.resolve(package, {
    registry: this.registry,
    githulk: this.githulk
  }, this._onResolved.bind(this, key));
};

PreHeat.prototype._onResolved = function (key, err, data) {
  if (err) { return this.onError(err) }
  this.pagelet.fireforget('set', key, data,
                          this.pagelet.expire.data,
                          this.answer.bind(this));
};

PreHeat.prototype.answer = function (err) {
  return err
    ? this.onError(err)
    : this.done();
};

PreHeat.prototype.done = function () {
  return this._callback
    ? this._callback()
    : this.emit('done');
};

PreHeat.prototype.onError = function (err) {
  return this._callback
    ? this._callback(err)
    : this.emit('error', err);
};
<|endoftext|>


<commit_before>window.Plot = function Plot(selector, func) {
	var canvas = this.canvas = document.querySelector(selector);
	var context = canvas.getContext('2d');
	var clientRect = canvas.getBoundingClientRect();

	var func = this.func = func;

	var scale = 100;
	var dx = canvas.width * 0.5;
	var dy = canvas.height * 0.5;

	var currentX, currentY;
	var lastX, lastY;
	var mouseDown = false;

	var lastDistance;

	context.lineCap = 'round';
	function zoom(multiplier, x, y) {
		scale *= multiplier;
		dx = (dx - x) * multiplier + x;
		dy = (dy - y) * multiplier + y;
	}
	function clear() {
		context.clearRect(0, 0, canvas.width, canvas.height);
	}
	function renderAxis() {
		context.font = "10px sans";
		context.textBaseline = 'middle';
		context.textAlign="center";

		var step = Math.pow(2, ~~(Math.log(100 / scale)/Math.log(2))) * scale;

		for(var x = dx % step; x <= canvas.width; x += step) {
			if(x == dx) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(x, 0, 1, canvas.height);
			context.fillStyle = 'black';
			context.fillRect(x, dy - 2, 1, 4);

 			context.fillText(((x - dx)/scale).toPrecision(3), x, dy + 10);
		}

		context.textAlign = "right";
		for(var y = dy % step; y <= canvas.height; y += step) {
			if(y == dy) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(0, y, canvas.width, 1);
			context.fillStyle = 'black';
			context.fillRect(dx - 2, y, 4, 1);

 			context.fillText(((dy - y)/scale).toPrecision(3), dx - 6, y);
		}

		context.fillRect(0, dy, canvas.width, 1);
		context.fillRect(dx, 0, 1, canvas.height);
	}
	function renderTip() {
		context.beginPath();
		context.arc(currentX, -scale * func((currentX - dx) / scale) + dy, 3, 0, 2 * Math.PI);
		context.fill();
	}
	function render() {
		clear();

		renderAxis();

		context.lineWidth = 2;
		context.strokeStyle = 'black';
		context.beginPath();
		for(var x = 0; x < canvas.width; x++) {
			context.lineTo(x, -scale * func((x - dx) / scale) + dy);
		}
		context.stroke();

		renderTip();
	}
	canvas.addEventListener('mousedown', function(e) {
		mouseDown = true;
		lastX = e.clientX;
		lastY = e.clientY;
	});
	canvas.addEventListener('mouseup', function(e) {
		mouseDown = false;
	})
	canvas.addEventListener('mousemove', function(e) {
		currentX = e.clientX;
		correntY = e.clientY;

		if(mouseDown) {
			dx += e.clientX - lastX;
			dy += e.clientY - lastY;

			lastX = e.clientX;
			lastY = e.clientY;
		}

		render();
	});

	canvas.addEventListener('touchstart', function(e) {
		lastX = e.touches[0].clientX;
		lastY = e.touches[0].clientY;

		if(e.touches.length == 2) {
			lastDistance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;

			lastX = averageX;
			lastY = averageY;
		}
	});

	canvas.addEventListener('touchmove', function(e) {
		if(e.touches.length == 2) {
			var distance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));
			var multiplier = distance / lastDistance;

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;
			zoom(multiplier, averageX, averageY);

			lastDistance = distance;

			dx += averageX - lastX;
			dy += averageY - lastY;

			lastX = averageX;
			lastY = averageY;
		} else {
			dx += e.touches[0].clientX - lastX;
			dy += e.touches[0].clientY - lastY;

			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}

		render();
	});

	canvas.addEventListener('touchend', function(e) {
		if(e.touches.length == 1) {
			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}
	});

	canvas.addEventListener('wheel', function(e) {
		var multiplier = 0.9;
		if(e.deltaY < 0) {
			multiplier = 1.1;
		}
		zoom(multiplier, e.clientX - clientRect.left, e.clientY - clientRect.top);
		render();
	});

	render();
};<commit_msg>Fixing tip on mobile<commit_after>window.Plot = function Plot(selector, func) {
	var canvas = this.canvas = document.querySelector(selector);
	var context = canvas.getContext('2d');
	var clientRect = canvas.getBoundingClientRect();

	var func = this.func = func;

	var scale = 100;
	var dx = canvas.width * 0.5;
	var dy = canvas.height * 0.5;

	var currentX;
	var lastX, lastY;
	var mouseDown = false;

	var lastDistance;

	context.lineCap = 'round';
	function zoom(multiplier, x, y) {
		scale *= multiplier;
		dx = (dx - x) * multiplier + x;
		dy = (dy - y) * multiplier + y;
	}
	function clear() {
		context.clearRect(0, 0, canvas.width, canvas.height);
	}
	function renderAxis() {
		context.font = "10px sans";
		context.textBaseline = 'middle';
		context.textAlign="center";

		var step = Math.pow(2, ~~(Math.log(100 / scale)/Math.log(2))) * scale;

		for(var x = dx % step; x <= canvas.width; x += step) {
			if(x == dx) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(x, 0, 1, canvas.height);
			context.fillStyle = 'black';
			context.fillRect(x, dy - 2, 1, 4);

 			context.fillText(((x - dx)/scale).toPrecision(3), x, dy + 10);
		}

		context.textAlign = "right";
		for(var y = dy % step; y <= canvas.height; y += step) {
			if(y == dy) continue;

			context.fillStyle = 'lightgray';
			context.fillRect(0, y, canvas.width, 1);
			context.fillStyle = 'black';
			context.fillRect(dx - 2, y, 4, 1);

 			context.fillText(((dy - y)/scale).toPrecision(3), dx - 6, y);
		}

		context.fillRect(0, dy, canvas.width, 1);
		context.fillRect(dx, 0, 1, canvas.height);
	}
	function renderTip() {
		context.beginPath();
		context.arc(currentX, -scale * func((currentX - dx) / scale) + dy, 3, 0, 2 * Math.PI);
		context.fill();
	}
	function render() {
		clear();

		renderAxis();

		context.lineWidth = 2;
		context.strokeStyle = 'black';
		context.beginPath();
		for(var x = 0; x < canvas.width; x++) {
			context.lineTo(x, -scale * func((x - dx) / scale) + dy);
		}
		context.stroke();

		renderTip();
	}
	canvas.addEventListener('mousedown', function(e) {
		mouseDown = true;
		lastX = e.clientX;
		lastY = e.clientY;
	});
	canvas.addEventListener('mouseup', function(e) {
		mouseDown = false;
	})
	canvas.addEventListener('mousemove', function(e) {
		currentX = e.clientX;

		if(mouseDown) {
			dx += e.clientX - lastX;
			dy += e.clientY - lastY;

			lastX = e.clientX;
			lastY = e.clientY;
		}

		render();
	});

	canvas.addEventListener('touchstart', function(e) {
		lastX = e.touches[0].clientX;
		lastY = e.touches[0].clientY;

		if(e.touches.length == 2) {
			lastDistance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;

			lastX = averageX;
			lastY = averageY;
		}
	});

	canvas.addEventListener('touchmove', function(e) {
		currentX = e.touches[0].clientX;

		if(e.touches.length == 2) {
			var distance = Math.sqrt(Math.pow(e.touches[0].clientX - e.touches[1].clientX, 2) + Math.pow(e.touches[0].clientY - e.touches[1].clientY, 2));
			var multiplier = distance / lastDistance;

			var averageX = (e.touches[0].clientX + e.touches[1].clientX) * 0.5;
			var averageY = (e.touches[0].clientY + e.touches[1].clientY) * 0.5;
			zoom(multiplier, averageX, averageY);

			lastDistance = distance;

			dx += averageX - lastX;
			dy += averageY - lastY;

			lastX = averageX;
			lastY = averageY;
		} else {
			dx += e.touches[0].clientX - lastX;
			dy += e.touches[0].clientY - lastY;

			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}

		render();
	});

	canvas.addEventListener('touchend', function(e) {
		if(e.touches.length == 1) {
			lastX = e.touches[0].clientX;
			lastY = e.touches[0].clientY;
		}
	});

	canvas.addEventListener('wheel', function(e) {
		var multiplier = 0.9;
		if(e.deltaY < 0) {
			multiplier = 1.1;
		}
		zoom(multiplier, e.clientX - clientRect.left, e.clientY - clientRect.top);
		render();
	});

	render();
};<|endoftext|>


<commit_before>// Entry
const http = require('http');
const https = require('https');
const fs = require('fs');

if(process.getuid() === 0){
  console.error('Error: The server must be started by a non-root user.');
  process.exit();
}

//const {fork} = require('child_process');
const NODE_ENV = process.env.NODE_ENV;

const { onListening,
  onError,
  normalizePort } = require('./common/util');

module.exports = function(userConf){

  require('./lib/init-session-path');

  const conf = {
    port: 3000,
    sessionSecret: 'devSessionSecret',
    sshPort: 22
  };

  Object.assign(conf, userConf);

  global.IS_PRO = NODE_ENV === 'production';
  global.CONF = conf;

  // const createWebSocketServer = require('./web-socket-server');
  const app = require('./app');

  const port = normalizePort(process.env.PORT || conf.port);
  app.set('port', port);

  var server;
  if(conf.ssl){
    server = https.createServer({
      key: fs.readFileSync(conf.ssl.key, 'utf-8'),
      cert: fs.readFileSync(conf.ssl.cert, 'utf-8')
    }, app);
  }else{
    server = http.createServer(app);
  }

  server.listen(port);
  server.on('error', onError(port));
  server.on('listening', onListening(server, () => {
    console.log('linux remote server start!\n');
  }));

  const handleServerUpgrade = require('./ws-server');
  handleServerUpgrade(server);
}<commit_msg>Revert "The server must be started by a non-root user."<commit_after>// Entry
const http = require('http');
const https = require('https');
const fs = require('fs');

if(process.getuid() !== 0){
  console.error('linux-remote server must start-up by root user');
  process.exit();
}

//const {fork} = require('child_process');
const NODE_ENV = process.env.NODE_ENV;

const { onListening,
  onError,
  normalizePort } = require('./common/util');

module.exports = function(userConf){

  require('./lib/init-session-path');

  const conf = {
    port: 3000,
    sessionSecret: 'devSessionSecret',
    sshPort: 22
  };

  Object.assign(conf, userConf);

  global.IS_PRO = NODE_ENV === 'production';
  global.CONF = conf;

  // const createWebSocketServer = require('./web-socket-server');
  const app = require('./app');

  const port = normalizePort(process.env.PORT || conf.port);
  app.set('port', port);

  var server;
  if(conf.ssl){
    server = https.createServer({
      key: fs.readFileSync(conf.ssl.key, 'utf-8'),
      cert: fs.readFileSync(conf.ssl.cert, 'utf-8')
    }, app);
  }else{
    server = http.createServer(app);
  }

  server.listen(port);
  server.on('error', onError(port));
  server.on('listening', onListening(server, () => {
    console.log('linux remote server start!\n');
  }));

  const handleServerUpgrade = require('./ws-server');
  handleServerUpgrade(server);
}<|endoftext|>


<commit_before>var path = require('path');
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var concat = require('gulp-concat');
var argv = require('yargs').argv;
var uglify = require('gulp-uglify');
var gulpif = require('gulp-if');
var babel = require('gulp-babel');
var cached = require('gulp-cached');
var remember = require('gulp-remember');
var streamqueue = require('streamqueue');

module.exports = function(options) {
  options = options || {};

  options.files = options.files || [];
  options.moduleFiles = options.moduleFiles || ['src/**/*.js'];
  options.bootstrapFiles = options.bootstrapFiles || ['bootstrap.js'];
  options.outputFile = options.outputFile || 'dist/extension.js';

  gulp.task('default', function() {
    var stream = streamqueue({objectMode: true});

    stream.queue(gulp.src(options.files));

    stream.queue(gulp.src(options.moduleFiles)
      .pipe(cached('scripts'))
      .pipe(babel({ modules: 'amd', moduleIds: true, moduleRoot: options.modulePrefix }))
      .pipe(remember('scripts')));

    stream.queue(gulp.src(options.bootstrapFiles)
      .pipe(babel()));

    stream.done()
      .pipe(concat(path.basename(options.outputFile)))
      .pipe(gulpif(argv.production, uglify()))
      .pipe(gulp.dest(path.dirname(options.outputFile)))
      .pipe(livereload());
  });

  gulp.task('watch', ['default'], function () {
    livereload.listen();
    var watcher = gulp.watch(options.moduleFiles.concat(options.files), ['default']);
    watcher.on('change', function (event) {
      if (event.type === 'deleted') {
        delete cached.caches.scripts[event.path];
        remember.forget('scripts', event.path);
      }
    });
  });
};
<commit_msg>Add option to externalize babel helpers.<commit_after>var path = require('path');
var gulp = require('gulp');
var livereload = require('gulp-livereload');
var concat = require('gulp-concat');
var argv = require('yargs').argv;
var uglify = require('gulp-uglify');
var gulpif = require('gulp-if');
var babel = require('gulp-babel');
var cached = require('gulp-cached');
var remember = require('gulp-remember');
var streamqueue = require('streamqueue');

module.exports = function(options) {
  options = options || {};

  options.files = options.files || [];
  options.moduleFiles = options.moduleFiles || ['src/**/*.js'];
  options.bootstrapFiles = options.bootstrapFiles || ['bootstrap.js'];
  options.outputFile = options.outputFile || 'dist/extension.js';

  gulp.task('default', function() {
    var stream = streamqueue({objectMode: true});

    stream.queue(gulp.src(options.files));

    stream.queue(gulp.src(options.moduleFiles)
      .pipe(cached('scripts'))
      .pipe(babel({
        modules: 'amd',
        moduleIds: true,
        moduleRoot: options.modulePrefix,
        externalHelpers: options.externalHelpers
      }))
      .pipe(remember('scripts')));

    stream.queue(gulp.src(options.bootstrapFiles)
      .pipe(babel({
        externalHelpers: options.externalHelpers
      })));

    stream.done()
      .pipe(concat(path.basename(options.outputFile)))
      .pipe(gulpif(argv.production, uglify()))
      .pipe(gulp.dest(path.dirname(options.outputFile)))
      .pipe(livereload());
  });

  gulp.task('watch', ['default'], function () {
    livereload.listen();
    var watcher = gulp.watch(options.moduleFiles.concat(options.files), ['default']);
    watcher.on('change', function (event) {
      if (event.type === 'deleted') {
        delete cached.caches.scripts[event.path];
        remember.forget('scripts', event.path);
      }
    });
  });
};
<|endoftext|>


<commit_before>/*
Name:           doTest - Unit tests runner
Description:    Yet another unit test runner for Node.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-dotest
Feedback:       https://github.com/fvdm/nodejs-dotest/issues
License:        Unlicense (public domain, see LICENSE file)
*/

var path = require ('path');
var dir = path.parse (process.mainModule.filename) .dir;
var pkg = require (path.join (dir, 'package.json'));

var queue = [];
var next = -1;
var unitTests = {};
var counters = {
  fail: 0,
  warn: 0
};

/**
 * ANSI colorize a string
 *
 * @param color {String} - The color to add
 * @param str {String} - The string to alter
 * @returns {String}
 */

function colorStr (color, str) {
  var colors = {
    red: '\u001b[31m',
    green: '\u001b[32m',
    yellow: '\u001b[33m',
    blue: '\u001b[34m',
    magenta: '\u001b[35m',
    cyan: '\u001b[36m',
    gray: '\u001b[37m',
    bold: '\u001b[1m',
    plain: '\u001b[0m'
  };

  return colors [color] + str + colors.plain;
}

/**
 * console.log with style
 *
 * @param [type] {String=plain} - Formatting style
 * @param str {String} - The string to alter
 * @returns {void}
 */

function log (type, str) {
  var types = {
    fail: ['red', 'FAIL'],
    good: ['green', 'good'],
    warn: ['yellow', 'warn'],
    info: ['cyan', 'info']
  };

  if (!str) {
    str = type;
    type = 'plain';
  }

  switch (type) {
    case 'note':
      console.log (colorStr ('bold', str));
      break;
    case 'error':
      console.log (colorStr ('red', colorStr ('bold', 'ERROR   ')) + str.message + '\n');
      console.dir (str, {
        depth: null,
        colors: true
      });
      console.log ();
      console.log (str.stack);
      console.log ();
      break;
    case 'plain': console.log (str); break;
    default:
      console.log (colorStr (types[type][0], types[type][1]) + '    ' + str);
      break;
  }
}

/**
 * Run next test in queue
 *
 * @callback callback
 * @param [callback] {function} - Run callback before next test
 * @returns {void}
 */

function doNext (callback) {
  if (callback instanceof Function) {
    callback (next);
  }

  next++;

  if (queue [next]) {
    console.log (
      '\n'
      + colorStr ('cyan', (next + 1) + '/' + queue.length)
      + '  '
      + colorStr ('bold', queue [next] .label)
    );
    queue [next] .runner ();
  }
}

unitTests = {
  done: doNext
};

/**
 * Write test result to console
 *
 * @param data {object}
 * @param data.result {boolean} - Test outcome
 * @param data.level {string} - fail, warn
 * @param data.describe {string} - Human text to describe outcome
 * @returns {void}
 */

function output (data) {
  var state = (data.result === true) ? 'good' : data.level;
  var str = '';

  switch (state) {
    case 'good': str = colorStr ('green', 'good'); break;
    case 'fail': str = colorStr ('red', 'fail'); break;
    case 'warn': str = colorStr ('yellow', 'warn'); break;
    default: str = str; break;
  }

  str += '    ' + data.describe;
  console.log (str);
}

/**
 * Get any var type
 *
 * @param input {mixed} - The value to check
 * @returns {string}
 */

function getType (input) {
  if (input instanceof Error) {
    return 'error';
  }

  if (input instanceof Function) {
    return 'function';
  }

  if (input instanceof Array) {
    return 'array';
  }

  if (input instanceof Object) {
    return 'object';
  }

  return (typeof input);
}

/**
 * Get formatted var type for console
 *
 * @param str {string} - The var to convert
 * @returns {string}
 */

function typeStr (str) {
  var type = getType (str);

  if (type === 'string' && str.length < 20) {
    str = '"' + str + '"';
  } else if (type === 'string') {
    str = 'string';
  } else if (str === null) {
    str = 'null';
  } else if (type === 'object') {
    str = 'object';
  } else if (type === 'array') {
    str = 'array';
  } else if (type === 'error') {
    str = 'error';
  }

  return colorStr ('magenta', str);
}

/**
 * Test for Error
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isError = function isError (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'error',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Error';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Error';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Object
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isObject = function isObject (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'object',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Object';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Object';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Array
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isArray = function isArray (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'array',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Array';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Array';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for String
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test againstuncaughtException
 * @returns {object} - unitTests
 */

unitTests.isString = function isString (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'string',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a String';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a String';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Number
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isNumber = function isNumber (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'number',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Number';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Number';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Undefined
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isUndefined = function isUndefined (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'undefined',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is Undefined';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not Undefined';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Boolean
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isBoolean = function isBoolean (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'boolean',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Boolean';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Boolean';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Function
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isFunction = function isFunction (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'function',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Function';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Function';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Check if two values are exactly the same
 *
 * @param level {string} - fail, warn
 * @param one {mixed} - variable to test against
 * @param two {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isExactly = function isExactly (level, what, one, two) {
  var typestrOne = typeStr (one);
  var typestrTwo = typeStr (two);
  var data = {
    level: level,
    result: one === two,
    get describe () {
      var str = '';

      if (this.result) {
        str = colorStr ('blue', what) + ' is exactly ' + typestrTwo + ' (' + getType (two) + ')';
        return str;
      }

      str += colorStr ('blue', what) + ' ' + typestrOne + ' and ' + typestrTwo + '';
      str += ' are not exact matches';

      counters[level]++;
      return str;
    }
  };

  output (data);
  return unitTests;
};

/**
 * Check if the two values meet the condition
 *
 * @param level {string} - fail, warn
 * @param what {string} - describe the test
 * @param one {mixed} - variable to test against
 * @param operator {string} - < > <= >=
 * @param two {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isCondition = function isCondition (level, what, one, operator, two) {
  var typestrOne = typeStr (one) + ' (' + getType (one) + ')';
  var typestrTwo = typeStr (two) + ' (' + getType (two) + ')';
  var data = {
    level: level,
    result: false,
    get describe () {
      var opstr = typestrOne + ' ' + operator + ' ' + typestrTwo;
      var str = colorStr ('blue', what) + ' ' + opstr;

      if (!this.result) {
        counters[level]++;
      }

      return str;
    }
  };

  switch (operator) {
    case '<': data.result = one < two; break;
    case '>': data.result = one > two; break;
    case '<=': data.result = one <= two; break;
    case '>=': data.result = one >= two; break;
    default: data.result = false; break;
  }

  output (data);
  return unitTests;
};

/**
 * Check if input is not an empty var, string, object, array, error
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isNotEmpty = function isNotEmpty (level, what, input) {
  var type = getType (input);
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: true,
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' ' + typestr + ' is not empty';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' ' + typestr + ' should not be empty';
    }
  };

  if (type === 'undefined') {
    data.result = false;
  } else if (input === null) {
    data.result = false;
  } else if (type === 'string' && !input) {
    data.result = false;
  } else if (type === 'object' && !Object.keys (input).length) {
    data.result = false;
  } else if (type === 'array' && !input.length) {
    data.result = false;
  } else if (type === 'error' && !Object.keys (input).length && !input.message) {
    data.result = false;
  }

  output (data);
  return unitTests;
};

function test (err) {
  if (err) {
    counters.fail++;
    log ('error', err);
  }

  return unitTests;
}

/**
 * Start tests
 */

function run () {
  if (next === -1) {
    log ('note', 'Running tests...\n');
    log ('note', 'Module name:      ' + pkg.name);
    log ('note', 'Module version:   ' + pkg.version);
    log ('note', 'Node.js version:  ' + process.versions.node);
  }

  doNext ();
}

/**
 * Add a test to the queue
 */

function add (label, runner) {
  queue.push ({
    label: label,
    runner: runner
  });
}

/**
 * Handle process exit
 */

function processExit () {
  console.log ();
  log ('info', counters.fail + ' errors');
  log ('info', counters.warn + ' warnings');
  console.log ();

  if (counters.fail) {
    process.exit (1);
  } else {
    process.exit (0);
  }
}

process.on ('exit', processExit);

/**
 * Prevent errors from killing the process
 */

function uncaughtException (err) {
  console.log (err);
  console.log ();
  console.log (err.stack);
  console.log ();
  counters.fail++;
}

process.on ('uncaughtException', uncaughtException);

/**
 * Module interface
 */

module.exports = {
  add: add,
  run: run,
  log: log,
  test: test,
  exit: processExit
};
<commit_msg>Added isEmpty check<commit_after>/*
Name:           doTest - Unit tests runner
Description:    Yet another unit test runner for Node.js
Author:         Franklin van de Meent (https://frankl.in)
Source & docs:  https://github.com/fvdm/nodejs-dotest
Feedback:       https://github.com/fvdm/nodejs-dotest/issues
License:        Unlicense (public domain, see LICENSE file)
*/

var path = require ('path');
var dir = path.parse (process.mainModule.filename) .dir;
var pkg = require (path.join (dir, 'package.json'));

var queue = [];
var next = -1;
var unitTests = {};
var counters = {
  fail: 0,
  warn: 0
};

/**
 * ANSI colorize a string
 *
 * @param color {String} - The color to add
 * @param str {String} - The string to alter
 * @returns {String}
 */

function colorStr (color, str) {
  var colors = {
    red: '\u001b[31m',
    green: '\u001b[32m',
    yellow: '\u001b[33m',
    blue: '\u001b[34m',
    magenta: '\u001b[35m',
    cyan: '\u001b[36m',
    gray: '\u001b[37m',
    bold: '\u001b[1m',
    plain: '\u001b[0m'
  };

  return colors [color] + str + colors.plain;
}

/**
 * console.log with style
 *
 * @param [type] {String=plain} - Formatting style
 * @param str {String} - The string to alter
 * @returns {void}
 */

function log (type, str) {
  var types = {
    fail: ['red', 'FAIL'],
    good: ['green', 'good'],
    warn: ['yellow', 'warn'],
    info: ['cyan', 'info']
  };

  if (!str) {
    str = type;
    type = 'plain';
  }

  switch (type) {
    case 'note':
      console.log (colorStr ('bold', str));
      break;
    case 'error':
      console.log (colorStr ('red', colorStr ('bold', 'ERROR   ')) + str.message + '\n');
      console.dir (str, {
        depth: null,
        colors: true
      });
      console.log ();
      console.log (str.stack);
      console.log ();
      break;
    case 'plain': console.log (str); break;
    default:
      console.log (colorStr (types[type][0], types[type][1]) + '    ' + str);
      break;
  }
}

/**
 * Run next test in queue
 *
 * @callback callback
 * @param [callback] {function} - Run callback before next test
 * @returns {void}
 */

function doNext (callback) {
  if (callback instanceof Function) {
    callback (next);
  }

  next++;

  if (queue [next]) {
    console.log (
      '\n'
      + colorStr ('cyan', (next + 1) + '/' + queue.length)
      + '  '
      + colorStr ('bold', queue [next] .label)
    );
    queue [next] .runner ();
  }
}

unitTests = {
  done: doNext
};

/**
 * Write test result to console
 *
 * @param data {object}
 * @param data.result {boolean} - Test outcome
 * @param data.level {string} - fail, warn
 * @param data.describe {string} - Human text to describe outcome
 * @returns {void}
 */

function output (data) {
  var state = (data.result === true) ? 'good' : data.level;
  var str = '';

  switch (state) {
    case 'good': str = colorStr ('green', 'good'); break;
    case 'fail': str = colorStr ('red', 'fail'); break;
    case 'warn': str = colorStr ('yellow', 'warn'); break;
    default: str = str; break;
  }

  str += '    ' + data.describe;
  console.log (str);
}

/**
 * Get any var type
 *
 * @param input {mixed} - The value to check
 * @returns {string}
 */

function getType (input) {
  if (input instanceof Error) {
    return 'error';
  }

  if (input instanceof Function) {
    return 'function';
  }

  if (input instanceof Array) {
    return 'array';
  }

  if (input instanceof Object) {
    return 'object';
  }

  return (typeof input);
}

/**
 * Get formatted var type for console
 *
 * @param str {string} - The var to convert
 * @returns {string}
 */

function typeStr (str) {
  var type = getType (str);

  if (type === 'string' && str.length < 20) {
    str = '"' + str + '"';
  } else if (type === 'string') {
    str = 'string';
  } else if (str === null) {
    str = 'null';
  } else if (type === 'object') {
    str = 'object';
  } else if (type === 'array') {
    str = 'array';
  } else if (type === 'error') {
    str = 'error';
  }

  return colorStr ('magenta', str);
}

/**
 * Test for Error
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isError = function isError (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'error',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Error';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Error';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Object
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isObject = function isObject (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'object',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Object';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Object';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Array
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isArray = function isArray (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'array',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is an Array';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not an Array';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for String
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test againstuncaughtException
 * @returns {object} - unitTests
 */

unitTests.isString = function isString (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'string',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a String';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a String';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Number
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isNumber = function isNumber (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'number',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Number';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Number';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Undefined
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isUndefined = function isUndefined (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'undefined',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is Undefined';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not Undefined';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Boolean
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isBoolean = function isBoolean (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'boolean',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Boolean';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Boolean';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Test for Function
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isFunction = function isFunction (level, what, input) {
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: getType (input) === 'function',
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' is a Function';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' (' + typestr + ') is not a Function';
    }
  };

  output (data);
  return unitTests;
};

/**
 * Check if two values are exactly the same
 *
 * @param level {string} - fail, warn
 * @param one {mixed} - variable to test against
 * @param two {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isExactly = function isExactly (level, what, one, two) {
  var typestrOne = typeStr (one);
  var typestrTwo = typeStr (two);
  var data = {
    level: level,
    result: one === two,
    get describe () {
      var str = '';

      if (this.result) {
        str = colorStr ('blue', what) + ' is exactly ' + typestrTwo + ' (' + getType (two) + ')';
        return str;
      }

      str += colorStr ('blue', what) + ' ' + typestrOne + ' and ' + typestrTwo + '';
      str += ' are not exact matches';

      counters[level]++;
      return str;
    }
  };

  output (data);
  return unitTests;
};

/**
 * Check if the two values meet the condition
 *
 * @param level {string} - fail, warn
 * @param what {string} - describe the test
 * @param one {mixed} - variable to test against
 * @param operator {string} - < > <= >=
 * @param two {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isCondition = function isCondition (level, what, one, operator, two) {
  var typestrOne = typeStr (one) + ' (' + getType (one) + ')';
  var typestrTwo = typeStr (two) + ' (' + getType (two) + ')';
  var data = {
    level: level,
    result: false,
    get describe () {
      var opstr = typestrOne + ' ' + operator + ' ' + typestrTwo;
      var str = colorStr ('blue', what) + ' ' + opstr;

      if (!this.result) {
        counters[level]++;
      }

      return str;
    }
  };

  switch (operator) {
    case '<': data.result = one < two; break;
    case '>': data.result = one > two; break;
    case '<=': data.result = one <= two; break;
    case '>=': data.result = one >= two; break;
    default: data.result = false; break;
  }

  output (data);
  return unitTests;
};

/**
 * Check if input is an empty var, string, object, array, error
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isEmpty = function isEmpty (level, what, input) {
  var type = getType (input);
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: false,
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' ' + typestr + ' is empty';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' ' + typestr + ' should be empty';
    }
  };

  if (type === 'undefined') {
    data.result = true;
  } else if (input === null) {
    data.result = true;
  } else if (type === 'string' && !input) {
    data.result = true;
  } else if (type === 'object' && !Object.keys (input).length) {
    data.result = true;
  } else if (type === 'array' && !input.length) {
    data.result = true;
  } else if (type === 'error' && !Object.keys (input).length && !input.message) {
    data.result = true;
  }

  output (data);
  return unitTests;
};

/**
 * Check if input is not an empty var, string, object, array, error
 *
 * @param level {string} - fail, warn
 * @param input {mixed} - variable to test against
 * @returns {object} - unitTests
 */

unitTests.isNotEmpty = function isNotEmpty (level, what, input) {
  var type = getType (input);
  var typestr = typeStr (input);
  var data = {
    level: level,
    result: true,
    get describe () {
      if (this.result) {
        return colorStr ('blue', what) + ' ' + typestr + ' is not empty';
      }

      counters[level]++;
      return colorStr ('blue', what) + ' ' + typestr + ' should not be empty';
    }
  };

  if (type === 'undefined') {
    data.result = false;
  } else if (input === null) {
    data.result = false;
  } else if (type === 'string' && !input) {
    data.result = false;
  } else if (type === 'object' && !Object.keys (input).length) {
    data.result = false;
  } else if (type === 'array' && !input.length) {
    data.result = false;
  } else if (type === 'error' && !Object.keys (input).length && !input.message) {
    data.result = false;
  }

  output (data);
  return unitTests;
};

function test (err) {
  if (err) {
    counters.fail++;
    log ('error', err);
  }

  return unitTests;
}

/**
 * Start tests
 */

function run () {
  if (next === -1) {
    log ('note', 'Running tests...\n');
    log ('note', 'Module name:      ' + pkg.name);
    log ('note', 'Module version:   ' + pkg.version);
    log ('note', 'Node.js version:  ' + process.versions.node);
  }

  doNext ();
}

/**
 * Add a test to the queue
 */

function add (label, runner) {
  queue.push ({
    label: label,
    runner: runner
  });
}

/**
 * Handle process exit
 */

function processExit () {
  console.log ();
  log ('info', counters.fail + ' errors');
  log ('info', counters.warn + ' warnings');
  console.log ();

  if (counters.fail) {
    process.exit (1);
  } else {
    process.exit (0);
  }
}

process.on ('exit', processExit);

/**
 * Prevent errors from killing the process
 */

function uncaughtException (err) {
  console.log (err);
  console.log ();
  console.log (err.stack);
  console.log ();
  counters.fail++;
}

process.on ('uncaughtException', uncaughtException);

/**
 * Module interface
 */

module.exports = {
  add: add,
  run: run,
  log: log,
  test: test,
  exit: processExit
};
<|endoftext|>


<commit_before>var postcss  = require('postcss');
var fileSave = require('file-save');
var path     = require('path');

module.exports = postcss.plugin('postcss-extract-media', function (opts) {

    return function(css, result) {
        // get fileinfo
        var fileinfo = path.parse(result.opts.to);

        // let's start our new file with @charset "UTF-8" and save file in the same dir appending a prefix
        var newFile = fileSave(fileinfo.dir + '/' + fileinfo.name + opts.prefix + fileinfo.ext, '@charset "UTF-8"');

        // let's loop through all rules and extract all @media print
        css.walksAtRules(function(rule) {
            if (rule.name.match(/^media/) && rule.params.match(opts.match)) {
                // add nodes to print file
                newFile.write(rule.nodes.toString(), 'utf8');

                // TODO: maybe add a option (default true) to remove occurences
                // let's remove all occurences of @media print from the current css
                rule.remove();
            }
        });
        newFile.end();
    };
});
<commit_msg>typo on postcss command (see, this is why we need tests)<commit_after>var postcss  = require('postcss');
var fileSave = require('file-save');
var path     = require('path');

module.exports = postcss.plugin('postcss-extract-media', function(opts) {
    return function(css, result) {
        // get fileinfo
        var fileinfo = path.parse(result.opts.to);

        // let's start our new file with @charset "UTF-8" and save file in the same dir appending a prefix
        var newFile = fileSave(fileinfo.dir + '/' + fileinfo.name + opts.prefix + fileinfo.ext, '@charset "UTF-8"');

        // let's loop through all rules and extract all @media print
        css.walkAtRules(function(rule) {
            if (rule.name.match(/^media/) && rule.params.match(opts.match)) {
                // add nodes to print file
                newFile.write(rule.nodes.toString(), 'utf8');

                // TODO: maybe add a option (default true) to remove occurences
                // let's remove all occurences of @media print from the current css
                rule.remove();
            }
        });
        newFile.end();
    };
});
<|endoftext|>


<commit_before>'use strict'

module.exports = function (filename, encoding) {
  filename = filename || '.env'
  encoding = encoding || 'utf8'
}
<commit_msg>Add the method read to the index.js file.<commit_after>'use strict'

var fs = require('fs')

module.exports = function (filename, encoding) {
  filename = filename || '.env'
  encoding = encoding || 'utf8'

  var read = function (filename, encoding) {
    try {
      return fs.fileReadSync(filename, encoding)
    } catch (error) {
      return ''
    }
  }

  return {
    read: read
  }
}
<|endoftext|>


<commit_before>'use strict';

const levelToColourCode = Object.freeze({

    debug: 34,
    info: 92,
    warn: 93,
    error: 91,
    critical: 31
});

const allLogLevels = Object.freeze( Object.keys( levelToColourCode ) );

// getting the optional LOG_LEVELS environment variable if it's defined:
let envLogLevels;

if( process.env.LOG_LEVELS ) {

    envLogLevels = Object.freeze( process.env.LOG_LEVELS.split( ' ' ) );
}
else {

    envLogLevels = null;
}

const logLevels = envLogLevels || allLogLevels;

// getting the optional ROOT_LOGGER_PATH environment variable if it's defined:
let envRootLoggerPath;

if( process.env.ROOT_LOGGER_PATH ) {

    envRootLoggerPath = `${ process.env.ROOT_LOGGER_PATH }/`;
}
else {

    envRootLoggerPath = null;
}

const relativePathIndentifier = envRootLoggerPath;

function log( level, path, message ) {

    const colourCode = levelToColourCode[ level ];

    const levelColour = `\x1b[${ colourCode }m`;
    const pathColour = '\x1b[90m';
    const defaultColour = '\x1b[0m';

    const loggerMessage = `${ level }: ${ pathColour }${ path }:${ levelColour } ${ message }`;

    console.log( `${ levelColour }${ loggerMessage }${ defaultColour }` );
}

function logIfLevelEnabled( level, path, message ) {

    const levelIsEnabled = (logLevels.indexOf( level ) >= 0);

    if( levelIsEnabled ) {

        log( level, path, message );
    }
}

function getLogger( path ) {

    const logger = {};

    allLogLevels.forEach( function( logLevel ) {

        logger[ logLevel ] = function( message ) {

            logIfLevelEnabled( logLevel, path, message );
        }
    });

    return Object.freeze( logger );
}

function getRealitivePath( path ) {

    if( relativePathIndentifier ) {

        const relativePath = path.substring(

            path.lastIndexOf( relativePathIndentifier ) +
            relativePathIndentifier.length
        );

        return relativePath;
    }

    return path;
}

module.exports = Object.freeze({

    setPathAndGetLogger( path ) {

        const relativePath = getRealitivePath( path );

        return getLogger( relativePath );
    }
});
<commit_msg>updated<commit_after>'use strict';

const pathColour = '\x1b[90m';

const defaultColour = '\x1b[0m';

const levelToColourCode = Object.freeze({

    debug: 34,
    info: 92,
    warn: 93,
    error: 91,
    critical: 31
});

const allLogLevels = Object.freeze( Object.keys( levelToColourCode ) );

// getting the optional LOG_LEVELS environment variable if it's defined:
let envLogLevels;

if( process.env.LOG_LEVELS ) {

    envLogLevels = Object.freeze( process.env.LOG_LEVELS.split( ' ' ) );
}
else {

    envLogLevels = null;
}

const logLevels = envLogLevels || allLogLevels;

// getting the optional ROOT_LOGGER_PATH environment variable if it's defined:
let envRootLoggerPath;

if( process.env.ROOT_LOGGER_PATH ) {

    envRootLoggerPath = `${ process.env.ROOT_LOGGER_PATH }/`;
}
else {

    envRootLoggerPath = null;
}

const relativePathIndentifier = envRootLoggerPath;

function log( level, path, message ) {

    const colourCode = levelToColourCode[ level ];

    const levelColour = `\x1b[${ colourCode }m`;

    const loggerMessage = `${ level }: ${ pathColour }${ path }:${ levelColour } ${ message }`;

    console.log( `${ levelColour }${ loggerMessage }${ defaultColour }` );
}

function logIfLevelEnabled( level, path, message ) {

    const levelIsEnabled = (logLevels.indexOf( level ) >= 0);

    if( levelIsEnabled ) {

        log( level, path, message );
    }
}

function getLogger( path ) {

    const logger = {};

    allLogLevels.forEach( function( logLevel ) {

        logger[ logLevel ] = function( message ) {

            logIfLevelEnabled( logLevel, path, message );
        }
    });

    return Object.freeze( logger );
}

function getRealitivePath( path ) {

    if( relativePathIndentifier ) {

        const relativePath = path.substring(

            path.lastIndexOf( relativePathIndentifier ) +
            relativePathIndentifier.length
        );

        return relativePath;
    }

    return path;
}

module.exports = Object.freeze({

    setPathAndGetLogger( path ) {

        const relativePath = getRealitivePath( path );

        return getLogger( relativePath );
    }
});
<|endoftext|>