<commit_before>var fs = require('fs');
var util = require('util');

var Meta = require('./meta')();

var MJS_RC = '.mjsrc';
var MJS_NPM = 'mjsConfig';
var DEFAULT_CONFIG = {
  map: true,
  sourceInMap: true,
  mapEmbed: true,
  fullMacroErrors: false,
  emitIdentifierStatements: false,
  skipCore: false,
  es5Generators: false,
  runtime: true
};

var stdout = function (line) { process.stdout.write(line + '\n'); };
var stderr = function (line) { process.stderr.write(line + '\n'); };

function parseArgs(argv) {
  var minimist = require('minimist');
  var minimistOpts = {
    string: ['map-file', 'map-root', 'out'],
    boolean: ['debug', 'help', 'map', 'map-embed', 'map-source', 'color', 'es5-generators',
              'runtime', 'skip-core', 'skip-config', 'verbose', 'version'],
    default: {
      'color': process.stdout.isTTY && process.stderr.isTTY,
      'debug': false,
      'help': false,
      'skip-config': false,
      'version': false,
    },
    alias: {
      'c': 'color',
      'd': 'debug',
      'h': 'help',
      'm': 'map',
      'o': 'out',
      'r': 'runtime',
      'v': 'verbose',
    }
  };
  var opts;

  // Parse a first time for non-config related stuff
  opts = minimist(argv, minimistOpts);

  if (opts.help) {
    showHelpAndExit();
  } else if (opts.version) {
    console.log('Metascript compiler version ' + Meta.version);
    process.exit(0);
  }

  ['out', 'map-file', 'map-root'].forEach(function (arg) {
    if (opts[arg] === '') {
      showHelpAndExit('missing argument for option --' + arg, 1);
    }
  });

  if (opts._.length === 0) {
    showHelpAndExit('source file not specified.', 1);
  } else if (typeof opts._.length > 1) {
    showHelpAndExit('at most only one source file can be specified', 1);
  }

  // Check the source file
  var source = opts._[0];
  if (source === '-') {
    source = '<stdin>';
  } else if (!fs.existsSync(source)) {
    showHelpAndExit('Source file "' + source + '" does not exists.');
  }

  var config = opts['skip-config'] ? DEFAULT_CONFIG : getConfig(source, DEFAULT_CONFIG);
  config.source = source;

  if (opts['out']) {
    config.output = opts['out'] === '-' ? '<stdout>' : opts['out'];
  } else if (source === '<stdin>') {
    config.output = '<stdout>';
  } else {
    var path = require('path');
    config.output = path.dirname(source) + path.sep + path.basename(source, '.mjs') + '.js';
  }
  if (config.output === '<stdout>') {
    delete config.output;
    config.mapEmbed = true;
  }

  // Apply configuration to options parser default values
  var defs = minimistOpts.default;
  // Debug mode forces a specific config
  if (opts['debug']) {
    defs['verbose'] = true;
    config.map = true;
    config.sourceInMap = true;
    config.mapEmbed = true;
    config.fullMacroErrors = true;
    config.emitIdentifierStatements = true;
  }
  // Enable source maps if any sub-options is given
  if (opts['map-file'] || opts['map-source'] || opts['map-embed'] || opts['map-root']) {
    config.map = true;
  }

  // Apply defaults
  defs['es5-generators'] = config.es5Generators;
  defs['runtime'] = config.runtime;
  defs['map'] = !!config.map;
  defs['map-source'] = config.sourceInMap;
  defs['map-embed'] = config.mapEmbed;
  defs['map-file'] = '';
  defs['skip-core'] = config.skipCore;

  // Parse again with the adjusted default values
  opts = minimist(argv, minimistOpts);

  // Override config values with arguments

  config.es5Generators = opts['es5-generators'];
  config.runtime = opts['runtime'];
  config.skipCore = opts['skip-core'];
  config.mapEmbed = opts['map-embed'];
  config.sourceInMap = opts['map-source'];
  config.mapRoot = opts['map-root'] || '';
  config.sourceInMap = opts['map-source'];
  if (opts['map']) {
    if (opts['map-file']) {
      config.map = opts['map-file'];
    } else if (config.output) {
      config.map = config.output + '.map';
    } else {
      config.map = '';
    }
  } else {
    delete config.map;
  }

  return {config: config, options: opts};
}

function showHelpAndExit(error, exitcode) {
  if (error) {
    stderr('Error: ' + error);
  }
  stdout([
    '',
    'Usage: mjs [options...] <file.mjs|->',
    '',
    '             -c, --color  Color output [default: on]',
    '             -d, --debug  Debug mode code generation [default: off]',
    '              -h, --help  Show this help and exit',
    '             --skip-core  Skip loading of core macros [default: off]',
    '               -m, --map  Source map generation [default: on]',
    '             --map-embed  Embed source map in the javascript [default: on]',
    '       --map-file <file>  Destination source map file',
    '       --map-root <root>  Define a root for source map references',
    '            --map-source  Include original source code in map [default: on]',
    '        --es5-generators  Emulate generators for ES5 [default: off]',
    '               --runtime  Embed runtime [default: on]',
    ' -o <file>, --out <file>  Destination file (use - for stdout)',
    '           --skip-config  Skip loading of config values [default: off]',
    '           -v, --verbose  Verbose reporting [default: off]',
    '               --version  Show version and exit',
    '',
    ' * Note: options can be disabled by prefixing them with "--no-"',
    ''
  ].join('\n'));

  process.exit(typeof exitcode === 'undefined' ? 0 : exitcode);
}

// Get configuration from NPM package or from resource files
function getConfig(fpath, defaults) {
  var path = require('path');
  var dpath = path.dirname(path.resolve(fpath));

  function parentpath(fromdir, pattern) {
    var pp = require('parentpath'),
        cwd = process.cwd();
    try {
      process.chdir(fromdir);
      return pp.sync(pattern);
    } catch (e) {
      return null;
    } finally {
      process.chdir(cwd);
    }
  }

  function fromNpm() {
    var config;
    var dir = parentpath(dpath, 'package.json');
    if (dir) {
      try {
        config = require(dir + '/package.json')[MJS_NPM];
        config.__origin__ = dir + '/package.json';
      } catch (e) {
      }
    }
    return config;
  }

  function fromResourceFile() {
    var candidates = [
      parentpath(path, MJS_RC),
      process.env.HOME, process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOMEDRIVE + process.env.HOMEPATH
    ];

    var config;
    for (var i = 0; i < candidates.length; i++) {
      var candidate = candidates[i] + '/' + MJS_RC;
      if (fs.existsSync(candidate)) {
        try {
          config = JSON.parse(fs.readFileSync(candidate));
          config.__origin__ = candidate;
          break;
        } catch (e) {
          showHelpAndExit('Unable to read config from "' + candidate + '": ' + e.message, 1);
        }
      }
    }
    return config;
  }

  var config = fromNpm() || fromResourceFile() || {};
  // Make sure we apply defaults to missing values
  Object.keys(defaults).filter(function (k) {
    return config[k] == null
  }).forEach(function (k) {
    config[k] = defaults[k];
  });
  return config;
}

function shorterPath(fpath) {
  var path = require('path'),
      abs = path.resolve(fpath),
      rel = path.relative(process.cwd(), abs);
  return abs.length > rel.length ? rel : abs;
};

function main(argv) {
  var cfg = parseArgs(argv.slice(2))

  require('colors').mode = cfg.options['color'] ? 'console' : 'none';
  var debug = function (s) { return ('[debug] '.bold + s).yellow },
      strmul = function (s, n) { return (new Array(n)).join(s); };

  if (cfg.options['verbose'] && cfg.config.__origin__) {
    stderr(debug('Config loaded from ' + cfg.config.__origin__));
    delete cfg.config.__origin__;
  }

  if (cfg.options['debug'] && cfg.options['verbose']) {
    var pairs = [];
    Object.keys(cfg.config).forEach(function (k) {
      pairs.push(k + '=' + JSON.stringify(cfg.config[k]));
    })
    stderr(debug('Config: ' + pairs.join(' ')));
  }

  Meta.setOptions(cfg.config);

  var compiler, sourceCode,
      source = cfg.config.source;

  if (source === '<stdin>') {
    sourceCode = fs.readFileSync('/dev/stdin').toString();
    compiler = Meta.compilerFromString(sourceCode, source);
  } else {
    compiler = Meta.compilerFromFile(source);
  }

  var prettyHrtime = require('pretty-hrtime'),
      prettyTime,
      hrstart = process.hrtime();

  var code = compiler.compile();

  prettyTime = prettyHrtime(process.hrtime(hrstart));

  if (compiler.errors.length > 0) {
    if (cfg.options['verbose']) {
      var lines = sourceCode
                ? sourceCode.split('\n')
                : fs.existsSync(source)
                ? fs.readFileSync(compiler.parser.source, 'utf-8').toString().split('\n')
                : [];

      compiler.errors.forEach(function (err) {
        stderr(
          (shorterPath(source) + ':' + err.line + ':' + err.column).bold + ': ' +
          'error: '.red.bold + err.message.bold.white
        );
        if (lines.length >= err.line) {
          stderr(lines[err.line - 1]);
          stderr(strmul(' ', err.column+1) + '^'.blue.bold);
        }
      });

      stderr(compiler.errors.length + ' error(s) found on.');
    } else {
      compiler.errors.forEach(function (err) {
        stderr(err.toString());
      });
    }
  } else if (!cfg.config.output) {
    process.stdout.write(code);
  } else if (cfg.options['verbose']) {
    stdout('Successfully generated ' + shorterPath(cfg.config.output) + ' in ' + prettyTime + '.');
  }

  process.exit(compiler.errors.length);
}

module.exports = main;
<commit_msg>fixed verbose reporting for macro generated errors and nested errors<commit_after>var fs = require('fs');
var util = require('util');

var Meta = require('./meta')();

var MJS_RC = '.mjsrc';
var MJS_NPM = 'mjsConfig';
var DEFAULT_CONFIG = {
  map: true,
  sourceInMap: true,
  mapEmbed: true,
  fullMacroErrors: false,
  emitIdentifierStatements: false,
  skipCore: false,
  es5Generators: false,
  runtime: true
};

var stdout = function (line) { process.stdout.write(line + '\n'); };
var stderr = function (line) { process.stderr.write(line + '\n'); };

function parseArgs(argv) {
  var minimist = require('minimist');
  var minimistOpts = {
    string: ['map-file', 'map-root', 'out'],
    boolean: ['debug', 'help', 'map', 'map-embed', 'map-source', 'color', 'es5-generators',
              'runtime', 'skip-core', 'skip-config', 'verbose', 'version'],
    default: {
      'color': process.stdout.isTTY && process.stderr.isTTY,
      'debug': false,
      'help': false,
      'skip-config': false,
      'version': false,
    },
    alias: {
      'c': 'color',
      'd': 'debug',
      'h': 'help',
      'm': 'map',
      'o': 'out',
      'r': 'runtime',
      'v': 'verbose',
    }
  };
  var opts;

  // Parse a first time for non-config related stuff
  opts = minimist(argv, minimistOpts);

  if (opts.help) {
    showHelpAndExit();
  } else if (opts.version) {
    console.log('Metascript compiler version ' + Meta.version);
    process.exit(0);
  }

  ['out', 'map-file', 'map-root'].forEach(function (arg) {
    if (opts[arg] === '') {
      showHelpAndExit('missing argument for option --' + arg, 1);
    }
  });

  if (opts._.length === 0) {
    showHelpAndExit('source file not specified.', 1);
  } else if (typeof opts._.length > 1) {
    showHelpAndExit('at most only one source file can be specified', 1);
  }

  // Check the source file
  var source = opts._[0];
  if (source === '-') {
    source = '<stdin>';
  } else if (!fs.existsSync(source)) {
    showHelpAndExit('Source file "' + source + '" does not exists.');
  }

  var config = opts['skip-config'] ? DEFAULT_CONFIG : getConfig(source, DEFAULT_CONFIG);
  config.source = source;

  if (opts['out']) {
    config.output = opts['out'] === '-' ? '<stdout>' : opts['out'];
  } else if (source === '<stdin>') {
    config.output = '<stdout>';
  } else {
    var path = require('path');
    config.output = path.dirname(source) + path.sep + path.basename(source, '.mjs') + '.js';
  }
  if (config.output === '<stdout>') {
    delete config.output;
    config.mapEmbed = true;
  }

  // Apply configuration to options parser default values
  var defs = minimistOpts.default;
  // Debug mode forces a specific config
  if (opts['debug']) {
    defs['verbose'] = true;
    config.map = true;
    config.sourceInMap = true;
    config.mapEmbed = true;
    config.fullMacroErrors = true;
    config.emitIdentifierStatements = true;
  }
  // Enable source maps if any sub-options is given
  if (opts['map-file'] || opts['map-source'] || opts['map-embed'] || opts['map-root']) {
    config.map = true;
  }

  // Apply defaults
  defs['es5-generators'] = config.es5Generators;
  defs['runtime'] = config.runtime;
  defs['map'] = !!config.map;
  defs['map-source'] = config.sourceInMap;
  defs['map-embed'] = config.mapEmbed;
  defs['map-file'] = '';
  defs['skip-core'] = config.skipCore;

  // Parse again with the adjusted default values
  opts = minimist(argv, minimistOpts);

  // Override config values with arguments

  config.es5Generators = opts['es5-generators'];
  config.runtime = opts['runtime'];
  config.skipCore = opts['skip-core'];
  config.mapEmbed = opts['map-embed'];
  config.sourceInMap = opts['map-source'];
  config.mapRoot = opts['map-root'] || '';
  config.sourceInMap = opts['map-source'];
  if (opts['map']) {
    if (opts['map-file']) {
      config.map = opts['map-file'];
    } else if (config.output) {
      config.map = config.output + '.map';
    } else {
      config.map = '';
    }
  } else {
    delete config.map;
  }

  return {config: config, options: opts};
}

function showHelpAndExit(error, exitcode) {
  if (error) {
    stderr('Error: ' + error);
  }
  stdout([
    '',
    'Usage: mjs [options...] <file.mjs|->',
    '',
    '             -c, --color  Color output [default: on]',
    '             -d, --debug  Debug mode code generation [default: off]',
    '              -h, --help  Show this help and exit',
    '             --skip-core  Skip loading of core macros [default: off]',
    '               -m, --map  Source map generation [default: on]',
    '             --map-embed  Embed source map in the javascript [default: on]',
    '       --map-file <file>  Destination source map file',
    '       --map-root <root>  Define a root for source map references',
    '            --map-source  Include original source code in map [default: on]',
    '        --es5-generators  Emulate generators for ES5 [default: off]',
    '               --runtime  Embed runtime [default: on]',
    ' -o <file>, --out <file>  Destination file (use - for stdout)',
    '           --skip-config  Skip loading of config values [default: off]',
    '           -v, --verbose  Verbose reporting [default: off]',
    '               --version  Show version and exit',
    '',
    ' * Note: options can be disabled by prefixing them with "--no-"',
    ''
  ].join('\n'));

  process.exit(typeof exitcode === 'undefined' ? 0 : exitcode);
}

// Get configuration from NPM package or from resource files
function getConfig(fpath, defaults) {
  var path = require('path');
  var dpath = path.dirname(path.resolve(fpath));

  function parentpath(fromdir, pattern) {
    var pp = require('parentpath'),
        cwd = process.cwd();
    try {
      process.chdir(fromdir);
      return pp.sync(pattern);
    } catch (e) {
      return null;
    } finally {
      process.chdir(cwd);
    }
  }

  function fromNpm() {
    var config;
    var dir = parentpath(dpath, 'package.json');
    if (dir) {
      try {
        config = require(dir + '/package.json')[MJS_NPM];
        config.__origin__ = dir + '/package.json';
      } catch (e) {
      }
    }
    return config;
  }

  function fromResourceFile() {
    var candidates = [
      parentpath(path, MJS_RC),
      process.env.HOME, process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOMEDRIVE + process.env.HOMEPATH
    ];

    var config;
    for (var i = 0; i < candidates.length; i++) {
      var candidate = candidates[i] + '/' + MJS_RC;
      if (fs.existsSync(candidate)) {
        try {
          config = JSON.parse(fs.readFileSync(candidate));
          config.__origin__ = candidate;
          break;
        } catch (e) {
          showHelpAndExit('Unable to read config from "' + candidate + '": ' + e.message, 1);
        }
      }
    }
    return config;
  }

  var config = fromNpm() || fromResourceFile() || {};
  // Make sure we apply defaults to missing values
  Object.keys(defaults).filter(function (k) {
    return config[k] == null
  }).forEach(function (k) {
    config[k] = defaults[k];
  });
  return config;
}

function shorterPath(fpath) {
  var path = require('path'),
      abs = path.resolve(fpath),
      rel = path.relative(process.cwd(), abs);
  return abs.length > rel.length ? rel : abs;
};

var sourceLines = {};
function getSourceLine(fpath, line) {
  if (!(fpath in sourceLines)) {
    try {
      sourceLines[fpath] = fs.readFileSync(fpath, 'utf-8').toString().split('\n');
    } catch (e) {
      sourceLines[fpath] = [];
      return null;
    }
  }

  var lines = sourceLines[fpath];
  if (line > lines.length) return null;

  return lines[line - 1];
};

function main(argv) {
  var cfg = parseArgs(argv.slice(2))

  require('colors').mode = cfg.options['color'] ? 'console' : 'none';
  var debug = function (s) { return ('[debug] '.bold + s).yellow },
      strmul = function (s, n) { return (new Array(n)).join(s); };

  if (cfg.options['verbose'] && cfg.config.__origin__) {
    stderr(debug('Config loaded from ' + cfg.config.__origin__));
    delete cfg.config.__origin__;
  }

  if (cfg.options['debug'] && cfg.options['verbose']) {
    var pairs = [];
    Object.keys(cfg.config).forEach(function (k) {
      pairs.push(k + '=' + JSON.stringify(cfg.config[k]));
    })
    stderr(debug('Config: ' + pairs.join(' ')));
  }

  Meta.setOptions(cfg.config);

  var compiler, sourceCode,
      source = cfg.config.source;

  if (source === '<stdin>') {
    sourceCode = fs.readFileSync('/dev/stdin').toString();
    sourceLines[source] = sourceCode.split('\n');
    compiler = Meta.compilerFromString(sourceCode, source);
  } else {
    compiler = Meta.compilerFromFile(source);
  }

  var prettyHrtime = require('pretty-hrtime'),
      prettyTime,
      hrstart = process.hrtime();

  var code = compiler.compile();

  prettyTime = prettyHrtime(process.hrtime(hrstart));

  if (compiler.errors.length > 0) {
    if (cfg.options['verbose']) {
      compiler.errors.forEach(function (err) {
        stderr(
          (shorterPath(source) + ':' + err.line + ':' + err.column).bold + ': ' +
          'error: '.red.bold + err.message.bold.white
        );
        var line = getSourceLine(source, err.line);
        if (line) {
          stderr(line);
          stderr(strmul(' ', err.column+1) + '^'.blue.bold);
        }

        err.nestedErrors.forEach(function (nested) {
          stderr(
            (shorterPath(source) + ':' + nested.line + ':' + nested.column).bold + ': ' +
            'note: '.grey.bold + nested.message.bold.white
          );
          line = getSourceLine(source, nested.line);
          if (line) {
            stderr(line);
            stderr(strmul(' ', nested.column+1) + '^'.blue.bold);
          }
        });

        if (err.originalLine !== null) {
          stderr(
            (shorterPath(err.originalSource) + ':' + err.originalLine + ':' + err.originalColumn).bold + ': ' +
            'note: '.grey.bold + 'expanded from:'.bold.white
          );
          line = getSourceLine(err.originalSource, err.originalLine);
          if (line) {
            stderr(line);
            stderr(strmul(' ', err.originalColumn+1) + '^'.blue.bold);
          }
        }
      });

      stderr(compiler.errors.length + ' error(s) found on.');
    } else {
      compiler.errors.forEach(function (err) {
        stderr(err.toString());
      });
    }
  } else if (!cfg.config.output) {
    process.stdout.write(code);
  } else if (cfg.options['verbose']) {
    stdout('Successfully generated ' + shorterPath(cfg.config.output) + ' in ' + prettyTime + '.');
  }

  process.exit(compiler.errors.length);
}

module.exports = main;
<|endoftext|>


<commit_before>var fs = require('fs');
var util = require('util');

var Meta = require('./meta')();

var MJS_RC = '.mjsrc';
var MJS_NPM = 'mjsConfig';
var DEFAULT_CONFIG = {
  map: true,
  sourceInMap: true,
  mapEmbed: true,
  fullMacroErrors: false,
  emitIdentifierStatements: false,
  skipCore: false,
  es5Generators: false,
  runtime: true
};

var stdout = function (line) { process.stdout.write(line + '\n'); };
var stderr = function (line) { process.stderr.write(line + '\n'); };

function parseArgs(argv) {
  var minimist = require('minimist');
  var minimistOpts = {
    string: ['map-file', 'map-root', 'out'],
    boolean: ['debug', 'help', 'map', 'map-embed', 'map-source', 'color', 'es5-generators',
              'runtime', 'skip-core', 'skip-config', 'verbose', 'version'],
    default: {
      'color': process.stdout.isTTY && process.stderr.isTTY,
      'debug': false,
      'help': false,
      'skip-config': false,
      'version': false,
    },
    alias: {
      'c': 'color',
      'd': 'debug',
      'h': 'help',
      'm': 'map',
      'o': 'out',
      'r': 'runtime',
      'v': 'verbose',
    }
  };
  var opts;

  // Parse a first time for non-config related stuff
  opts = minimist(argv, minimistOpts);

  if (opts.help) {
    showHelpAndExit();
  } else if (opts.version) {
    console.log('Metascript compiler version ' + Meta.version);
    process.exit(0);
  }

  ['out', 'map-file', 'map-root'].forEach(function (arg) {
    if (opts[arg] === '') {
      showHelpAndExit('missing argument for option --' + arg, 1);
    }
  });

  if (opts._.length === 0) {
    showHelpAndExit('source file not specified.', 1);
  } else if (typeof opts._.length > 1) {
    showHelpAndExit('at most only one source file can be specified', 1);
  }

  // Check the source file
  var source = opts._[0];
  if (source === '-') {
    source = '<stdin>';
  } else if (!fs.existsSync(source)) {
    showHelpAndExit('Source file "' + source + '" does not exists.');
  }

  var config = opts['skip-config'] ? DEFAULT_CONFIG : getConfig(source, DEFAULT_CONFIG);
  config.source = source;

  if (opts['out']) {
    config.output = opts['out'] === '-' ? '<stdout>' : opts['out'];
  } else if (source === '<stdin>') {
    config.output = '<stdout>';
  } else {
    var path = require('path');
    config.output = path.dirname(source) + path.sep + path.basename(source, '.mjs') + '.js';
  }
  if (config.output === '<stdout>') {
    delete config.output;
    config.mapEmbed = true;
  }

  // Apply configuration to options parser default values
  var defs = minimistOpts.default;
  // Debug mode forces a specific config
  if (opts['debug']) {
    defs['verbose'] = true;
    config.map = true;
    config.sourceInMap = true;
    config.mapEmbed = true;
    config.fullMacroErrors = true;
    config.emitIdentifierStatements = true;
  }
  // Enable source maps if any sub-options is given
  if (opts['map-file'] || opts['map-source'] || opts['map-embed'] || opts['map-root']) {
    config.map = true;
  }

  // Apply defaults
  defs['es5-generators'] = config.es5Generators;
  defs['runtime'] = config.runtime;
  defs['map'] = !!config.map;
  defs['map-source'] = config.sourceInMap;
  defs['map-embed'] = config.mapEmbed;
  defs['map-file'] = '';
  defs['skip-core'] = config.skipCore;

  // Parse again with the adjusted default values
  opts = minimist(argv, minimistOpts);

  // Override config values with arguments

  config.es5Generators = opts['es5-generators'];
  config.runtime = opts['runtime'];
  config.skipCore = opts['skip-core'];
  config.mapEmbed = opts['map-embed'];
  config.sourceInMap = opts['map-source'];
  config.mapRoot = opts['map-root'] || '';
  config.sourceInMap = opts['map-source'];
  if (opts['map']) {
    if (opts['map-file']) {
      config.map = opts['map-file'];
    } else if (config.output) {
      config.map = config.output + '.map';
    } else {
      config.map = '';
    }
  } else {
    delete config.map;
  }

  return {config: config, options: opts};
}

function showHelpAndExit(error, exitcode) {
  if (error) {
    stderr('Error: ' + error);
  }
  stdout([
    '',
    'Usage: mjs [options...] <file.mjs|->',
    '',
    '             -c, --color  Color output [default: on]',
    '             -d, --debug  Debug mode code generation [default: off]',
    '              -h, --help  Show this help and exit',
    '             --skip-core  Skip loading of core macros [default: off]',
    '               -m, --map  Source map generation [default: on]',
    '             --map-embed  Embed source map in the javascript [default: on]',
    '       --map-file <file>  Destination source map file',
    '       --map-root <root>  Define a root for source map references',
    '            --map-source  Include original source code in map [default: on]',
    '        --es5-generators  Emulate generators for ES5 [default: off]',
    '               --runtime  Embed runtime [default: off]',
    ' -o <file>, --out <file>  Destination file (use - for stdout)',
    '           --skip-config  Skip loading of config values [default: off]',
    '           -v, --verbose  Verbose reporting [default: off]',
    '               --version  Show version and exit',
    '',
    ' * Note: options can be disabled by prefixing them with "--no-"',
    ''
  ].join('\n'));

  process.exit(typeof exitcode === 'undefined' ? 0 : exitcode);
}

// Get configuration from NPM package or from resource files
function getConfig(fpath, defaults) {
  var path = require('path');
  var dpath = path.dirname(path.resolve(fpath));

  function parentpath(fromdir, pattern) {
    var pp = require('parentpath'),
        cwd = process.cwd();
    try {
      process.chdir(fromdir);
      return pp.sync(pattern);
    } catch (e) {
      return null;
    } finally {
      process.chdir(cwd);
    }
  }

  function fromNpm() {
    var config;
    var dir = parentpath(dpath, 'package.json');
    if (dir) {
      try {
        config = require(dir + '/package.json')[MJS_NPM];
        config.__origin__ = dir + '/package.json';
      } catch (e) {
      }
    }
    return config;
  }

  function fromResourceFile() {
    var candidates = [
      parentpath(path, MJS_RC),
      process.env.HOME, process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOMEDRIVE + process.env.HOMEPATH
    ];

    var config;
    for (var i = 0; i < candidates.length; i++) {
      var candidate = candidates[i] + '/' + MJS_RC;
      if (fs.existsSync(candidate)) {
        try {
          config = JSON.parse(fs.readFileSync(candidate));
          config.__origin__ = candidate;
          break;
        } catch (e) {
          showHelpAndExit('Unable to read config from "' + candidate + '": ' + e.message, 1);
        }
      }
    }
    return config;
  }

  var config = fromNpm() || fromResourceFile() || {};
  // Make sure we apply defaults to missing values
  Object.keys(defaults).filter(function (k) {
    return config[k] == null
  }).forEach(function (k) {
    config[k] = defaults[k];
  });
  return config;
}

function shorterPath(fpath) {
  var path = require('path'),
      abs = path.resolve(fpath),
      rel = path.relative(process.cwd(), abs);
  return abs.length > rel.length ? rel : abs;
};

function main(argv) {
  var cfg = parseArgs(argv.slice(2))

  require('colors').mode = cfg.options['color'] ? 'console' : 'none';
  var debug = function (s) { return ('[debug] '.bold + s).yellow },
      strmul = function (s, n) { return (new Array(n)).join(s); };

  if (cfg.options['verbose'] && cfg.config.__origin__) {
    stderr(debug('Config loaded from ' + cfg.config.__origin__));
    delete cfg.config.__origin__;
  }

  if (cfg.options['debug'] && cfg.options['verbose']) {
    var pairs = [];
    Object.keys(cfg.config).forEach(function (k) {
      pairs.push(k + '=' + JSON.stringify(cfg.config[k]));
    })
    stderr(debug('Config: ' + pairs.join(' ')));
  }

  Meta.setOptions(cfg.config);

  var compiler, sourceCode,
      source = cfg.config.source;

  if (source === '<stdin>') {
    sourceCode = fs.readFileSync('/dev/stdin').toString();
    compiler = Meta.compilerFromString(sourceCode, source);
  } else {
    compiler = Meta.compilerFromFile(source);
  }

  var prettyHrtime = require('pretty-hrtime'),
      prettyTime,
      hrstart = process.hrtime();

  var code = compiler.compile();

  prettyTime = prettyHrtime(process.hrtime(hrstart));

  if (compiler.errors.length > 0) {
    if (cfg.options['verbose']) {
      var lines = sourceCode
                ? sourceCode.split('\n')
                : fs.existsSync(source)
                ? fs.readFileSync(compiler.parser.source, 'utf-8').toString().split('\n')
                : [];

      compiler.errors.forEach(function (err) {
        stderr(
          (shorterPath(source) + ':' + err.line + ':' + err.column).bold + ': ' +
          'error: '.red.bold + err.message.bold.white
        );
        if (lines.length >= err.line) {
          stderr(lines[err.line - 1]);
          stderr(strmul(' ', err.column+1) + '^'.blue.bold);
        }
      });

      stderr(compiler.errors.length + ' error(s) found on.');
    } else {
      compiler.errors.forEach(function (err) {
        stderr(err.toString());
      });
    }
  } else if (!cfg.config.output) {
    process.stdout.write(code);
  } else if (cfg.options['verbose']) {
    stdout('Successfully generated ' + shorterPath(cfg.config.output) + ' in ' + prettyTime + '.');
  }

  process.exit(compiler.errors.length);
}

module.exports = main;
<commit_msg>fixed typo on help message<commit_after>var fs = require('fs');
var util = require('util');

var Meta = require('./meta')();

var MJS_RC = '.mjsrc';
var MJS_NPM = 'mjsConfig';
var DEFAULT_CONFIG = {
  map: true,
  sourceInMap: true,
  mapEmbed: true,
  fullMacroErrors: false,
  emitIdentifierStatements: false,
  skipCore: false,
  es5Generators: false,
  runtime: true
};

var stdout = function (line) { process.stdout.write(line + '\n'); };
var stderr = function (line) { process.stderr.write(line + '\n'); };

function parseArgs(argv) {
  var minimist = require('minimist');
  var minimistOpts = {
    string: ['map-file', 'map-root', 'out'],
    boolean: ['debug', 'help', 'map', 'map-embed', 'map-source', 'color', 'es5-generators',
              'runtime', 'skip-core', 'skip-config', 'verbose', 'version'],
    default: {
      'color': process.stdout.isTTY && process.stderr.isTTY,
      'debug': false,
      'help': false,
      'skip-config': false,
      'version': false,
    },
    alias: {
      'c': 'color',
      'd': 'debug',
      'h': 'help',
      'm': 'map',
      'o': 'out',
      'r': 'runtime',
      'v': 'verbose',
    }
  };
  var opts;

  // Parse a first time for non-config related stuff
  opts = minimist(argv, minimistOpts);

  if (opts.help) {
    showHelpAndExit();
  } else if (opts.version) {
    console.log('Metascript compiler version ' + Meta.version);
    process.exit(0);
  }

  ['out', 'map-file', 'map-root'].forEach(function (arg) {
    if (opts[arg] === '') {
      showHelpAndExit('missing argument for option --' + arg, 1);
    }
  });

  if (opts._.length === 0) {
    showHelpAndExit('source file not specified.', 1);
  } else if (typeof opts._.length > 1) {
    showHelpAndExit('at most only one source file can be specified', 1);
  }

  // Check the source file
  var source = opts._[0];
  if (source === '-') {
    source = '<stdin>';
  } else if (!fs.existsSync(source)) {
    showHelpAndExit('Source file "' + source + '" does not exists.');
  }

  var config = opts['skip-config'] ? DEFAULT_CONFIG : getConfig(source, DEFAULT_CONFIG);
  config.source = source;

  if (opts['out']) {
    config.output = opts['out'] === '-' ? '<stdout>' : opts['out'];
  } else if (source === '<stdin>') {
    config.output = '<stdout>';
  } else {
    var path = require('path');
    config.output = path.dirname(source) + path.sep + path.basename(source, '.mjs') + '.js';
  }
  if (config.output === '<stdout>') {
    delete config.output;
    config.mapEmbed = true;
  }

  // Apply configuration to options parser default values
  var defs = minimistOpts.default;
  // Debug mode forces a specific config
  if (opts['debug']) {
    defs['verbose'] = true;
    config.map = true;
    config.sourceInMap = true;
    config.mapEmbed = true;
    config.fullMacroErrors = true;
    config.emitIdentifierStatements = true;
  }
  // Enable source maps if any sub-options is given
  if (opts['map-file'] || opts['map-source'] || opts['map-embed'] || opts['map-root']) {
    config.map = true;
  }

  // Apply defaults
  defs['es5-generators'] = config.es5Generators;
  defs['runtime'] = config.runtime;
  defs['map'] = !!config.map;
  defs['map-source'] = config.sourceInMap;
  defs['map-embed'] = config.mapEmbed;
  defs['map-file'] = '';
  defs['skip-core'] = config.skipCore;

  // Parse again with the adjusted default values
  opts = minimist(argv, minimistOpts);

  // Override config values with arguments

  config.es5Generators = opts['es5-generators'];
  config.runtime = opts['runtime'];
  config.skipCore = opts['skip-core'];
  config.mapEmbed = opts['map-embed'];
  config.sourceInMap = opts['map-source'];
  config.mapRoot = opts['map-root'] || '';
  config.sourceInMap = opts['map-source'];
  if (opts['map']) {
    if (opts['map-file']) {
      config.map = opts['map-file'];
    } else if (config.output) {
      config.map = config.output + '.map';
    } else {
      config.map = '';
    }
  } else {
    delete config.map;
  }

  return {config: config, options: opts};
}

function showHelpAndExit(error, exitcode) {
  if (error) {
    stderr('Error: ' + error);
  }
  stdout([
    '',
    'Usage: mjs [options...] <file.mjs|->',
    '',
    '             -c, --color  Color output [default: on]',
    '             -d, --debug  Debug mode code generation [default: off]',
    '              -h, --help  Show this help and exit',
    '             --skip-core  Skip loading of core macros [default: off]',
    '               -m, --map  Source map generation [default: on]',
    '             --map-embed  Embed source map in the javascript [default: on]',
    '       --map-file <file>  Destination source map file',
    '       --map-root <root>  Define a root for source map references',
    '            --map-source  Include original source code in map [default: on]',
    '        --es5-generators  Emulate generators for ES5 [default: off]',
    '               --runtime  Embed runtime [default: on]',
    ' -o <file>, --out <file>  Destination file (use - for stdout)',
    '           --skip-config  Skip loading of config values [default: off]',
    '           -v, --verbose  Verbose reporting [default: off]',
    '               --version  Show version and exit',
    '',
    ' * Note: options can be disabled by prefixing them with "--no-"',
    ''
  ].join('\n'));

  process.exit(typeof exitcode === 'undefined' ? 0 : exitcode);
}

// Get configuration from NPM package or from resource files
function getConfig(fpath, defaults) {
  var path = require('path');
  var dpath = path.dirname(path.resolve(fpath));

  function parentpath(fromdir, pattern) {
    var pp = require('parentpath'),
        cwd = process.cwd();
    try {
      process.chdir(fromdir);
      return pp.sync(pattern);
    } catch (e) {
      return null;
    } finally {
      process.chdir(cwd);
    }
  }

  function fromNpm() {
    var config;
    var dir = parentpath(dpath, 'package.json');
    if (dir) {
      try {
        config = require(dir + '/package.json')[MJS_NPM];
        config.__origin__ = dir + '/package.json';
      } catch (e) {
      }
    }
    return config;
  }

  function fromResourceFile() {
    var candidates = [
      parentpath(path, MJS_RC),
      process.env.HOME, process.env.USERPROFILE, process.env.HOMEPATH, process.env.HOMEDRIVE + process.env.HOMEPATH
    ];

    var config;
    for (var i = 0; i < candidates.length; i++) {
      var candidate = candidates[i] + '/' + MJS_RC;
      if (fs.existsSync(candidate)) {
        try {
          config = JSON.parse(fs.readFileSync(candidate));
          config.__origin__ = candidate;
          break;
        } catch (e) {
          showHelpAndExit('Unable to read config from "' + candidate + '": ' + e.message, 1);
        }
      }
    }
    return config;
  }

  var config = fromNpm() || fromResourceFile() || {};
  // Make sure we apply defaults to missing values
  Object.keys(defaults).filter(function (k) {
    return config[k] == null
  }).forEach(function (k) {
    config[k] = defaults[k];
  });
  return config;
}

function shorterPath(fpath) {
  var path = require('path'),
      abs = path.resolve(fpath),
      rel = path.relative(process.cwd(), abs);
  return abs.length > rel.length ? rel : abs;
};

function main(argv) {
  var cfg = parseArgs(argv.slice(2))

  require('colors').mode = cfg.options['color'] ? 'console' : 'none';
  var debug = function (s) { return ('[debug] '.bold + s).yellow },
      strmul = function (s, n) { return (new Array(n)).join(s); };

  if (cfg.options['verbose'] && cfg.config.__origin__) {
    stderr(debug('Config loaded from ' + cfg.config.__origin__));
    delete cfg.config.__origin__;
  }

  if (cfg.options['debug'] && cfg.options['verbose']) {
    var pairs = [];
    Object.keys(cfg.config).forEach(function (k) {
      pairs.push(k + '=' + JSON.stringify(cfg.config[k]));
    })
    stderr(debug('Config: ' + pairs.join(' ')));
  }

  Meta.setOptions(cfg.config);

  var compiler, sourceCode,
      source = cfg.config.source;

  if (source === '<stdin>') {
    sourceCode = fs.readFileSync('/dev/stdin').toString();
    compiler = Meta.compilerFromString(sourceCode, source);
  } else {
    compiler = Meta.compilerFromFile(source);
  }

  var prettyHrtime = require('pretty-hrtime'),
      prettyTime,
      hrstart = process.hrtime();

  var code = compiler.compile();

  prettyTime = prettyHrtime(process.hrtime(hrstart));

  if (compiler.errors.length > 0) {
    if (cfg.options['verbose']) {
      var lines = sourceCode
                ? sourceCode.split('\n')
                : fs.existsSync(source)
                ? fs.readFileSync(compiler.parser.source, 'utf-8').toString().split('\n')
                : [];

      compiler.errors.forEach(function (err) {
        stderr(
          (shorterPath(source) + ':' + err.line + ':' + err.column).bold + ': ' +
          'error: '.red.bold + err.message.bold.white
        );
        if (lines.length >= err.line) {
          stderr(lines[err.line - 1]);
          stderr(strmul(' ', err.column+1) + '^'.blue.bold);
        }
      });

      stderr(compiler.errors.length + ' error(s) found on.');
    } else {
      compiler.errors.forEach(function (err) {
        stderr(err.toString());
      });
    }
  } else if (!cfg.config.output) {
    process.stdout.write(code);
  } else if (cfg.options['verbose']) {
    stdout('Successfully generated ' + shorterPath(cfg.config.output) + ' in ' + prettyTime + '.');
  }

  process.exit(compiler.errors.length);
}

module.exports = main;
<|endoftext|>


<commit_before>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    carapace = require('./carapace');

module.exports = function overrideNet() {
  //
  // Helper function from Node code to parse port arguments
  // passed to net.prototype.Server.listen
  //
  function toPort(x) {
    return (x = Number(x)) >= 0 ? x : false;
  }

  //
  // ### function nextPort (port)
  // #### @port {Number} Port to increment from.
  // Gets the next port in sequence from the
  // specified `port`.
  //
  function nextPort(port) {
    if (!port) {
      return 8000;
    }

    //
    // Find the next port that we are not supposed to ignore or cause errors on
    //
    var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
    do {
      port = port + 1;
    } while (unavailable.indexOf(port) !== -1);

    return port;
  }

  //
  // Internal mapping of server instances to
  // ports that have been mapped via `.listen()`.
  //
  carapace.servers = {};

  var _listen2 = net.Server.prototype._listen2;
  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (carapace.ports.throw.indexOf(port) !== -1) {
      self.close();
      //
      // Build fake error
      //
      err = new Error('EADDRINUSE, Address already in use');
      err.code = 'EADDRINUSE';
      err.syscall = 'bind';
      err.errno = 100;
      return self.emit('error', err);
    }
    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        self.close();
        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, address, port, addressType);
    });
  };
};

<commit_msg>[fix] server may be auto-closed by node ignore if it is closed already<commit_after>/*
 * net.js: Wrapper around node.js core `net` module for observing relevant events
 *
 * (C) 2011 Nodejitsu Inc.
 *
 */

var net = require('net'),
    carapace = require('./carapace');

module.exports = function overrideNet() {
  //
  // Helper function from Node code to parse port arguments
  // passed to net.prototype.Server.listen
  //
  function toPort(x) {
    return (x = Number(x)) >= 0 ? x : false;
  }

  //
  // ### function nextPort (port)
  // #### @port {Number} Port to increment from.
  // Gets the next port in sequence from the
  // specified `port`.
  //
  function nextPort(port) {
    if (!port) {
      return 8000;
    }

    //
    // Find the next port that we are not supposed to ignore or cause errors on
    //
    var unavailable = carapace.ports.ignore.concat(carapace.ports.throw);
    do {
      port = port + 1;
    } while (unavailable.indexOf(port) !== -1);

    return port;
  }

  //
  // Internal mapping of server instances to
  // ports that have been mapped via `.listen()`.
  //
  carapace.servers = {};

  var _listen2 = net.Server.prototype._listen2;
  net.Server.prototype._listen2 = function ourListen(address, port, addressType, desired) {
    var self = this;

    port = toPort(port);
    desired || (desired = port);

    //
    // Always throw if our desired port was one that should always throw
    //
    if (carapace.ports.throw.indexOf(port) !== -1) {
      self.close();
      //
      // Build fake error
      //
      err = new Error('EADDRINUSE, Address already in use');
      err.code = 'EADDRINUSE';
      err.syscall = 'bind';
      err.errno = 100;
      return self.emit('error', err);
    }
    //
    // Since desired is not on a throwing port
    // we want to skip ports in both throw and ignore
    //
    port || (port = nextPort(port));

    //
    // We rely on `error` event to check if address it taken/available, however
    // user may want to hook up to `error` in his application as well (and
    // usually exit when it's emitted). This messes things up. Here we store
    // `error` event listeners and remove them. They will be restored after we
    // start listening or get an error which is not `EADDRINUSE`.
    //
    var errorListeners = self.listeners('error');
    self.removeAllListeners('error');

    function restoreErrorListeners() {
      errorListeners.forEach(function (listener) {
        self.on('error', listener);
      });
    }

    //
    // Problem with `listening` events is a bit different. We want to ensure
    // that we first emit `carapace::port` and *then* the proper `listening`
    // event (which can be consumed by user's app).
    //
    // (Also, not doing so breaks `net/net-multiple-servers-test` test.)
    //
    var listeningListeners = self.listeners('listening');
    self.removeAllListeners('listening');

    function restoreListeningListeners() {
      listeningListeners.forEach(function (listener) {
        self.on('listening', listener);
      });
    }

    function onListen() {
      //
      // Yay, we made it! Lets restore `error` listeners and tell the world
      // that we totally owned this port.
      //

      self.removeListener('error', onError);

      restoreErrorListeners();
      restoreListeningListeners();

      //
      // Store the server that has listened on the `desired` port
      // on the carapace itself, indexed by port.
      //
      carapace.servers[desired] = self;

      carapace.emit('port', {
        id: carapace.id,
        addr: address,
        port: port,
        desired: desired
      });

      process.nextTick(function () {
        self.emit('listening');
      });
    }

    function onError(err) {
      //
      // We failed to listen. Unless it's not EADDRINUSE lets try doing the
      // same thing, just with next port.
      //

      self.removeListener('listening', onListen);

      //
      // We can safely restore these listeners here. We're going to call
      // `ourFunction`, so they will be removed again anyway.
      //
      restoreErrorListeners();
      restoreListeningListeners();

      if (err.code !== 'EADDRINUSE') {
        try { self.close(); } catch (e) { }
        return self.emit('error', err);
      }

      ourListen.call(self, address, nextPort(port), addressType, desired);
    }

    self.once('listening', onListen);
    self.once('error', onError);

    //
    // Call original _listen2 function.
    //
    process.nextTick(function () {
      _listen2.call(self, address, port, addressType);
    });
  };
};

<|endoftext|>


<commit_before>var read = require('read');
var fs = require('fs');
var path = require('path');
var PZ = require('promzard').PromZard;
var input = require.resolve('./input.js');
var body = require.resolve('./body.js');
var template = require('./template').template;
var dir = process.cwd();

module.exports = function () {
    return create(dir, input, body, function (er) {
        if (er) console.log('\nbye');
    })
};

function create(dir, input, body, cb) {
    var api = {};
    var pz = new PZ(input, {});

    pz.on('error', cb);
    pz.on('data', function (data) {
        Object.keys(data).forEach(function (k) {
            if (data[k] !== undefined && data[k] !== null) api[k] = data[k]
        });

        var apiType = api.type.toLowerCase();
        if (apiType === 'post') {
            var n = api.keys_length;
            delete api.keys_length;
            if (n === '0') {
                readOne(stringify(api));
            } else {
                getParameters(body, n, function (err, data) {
                    if (err) return cb(err);
                    api.body = data;
                    readOne(stringify(api));
                });
            }

            function stringify(api) {
                return JSON.stringify(api, null, 2) + '\n';
            }

            var bodies = [];
            function getParameters(body, n, cb) {
                var _body = {};
                var pzbody = new PZ(body, {});
                pzbody.on('error', cb);
                pzbody.on('data', function (data) {
                    Object.keys(data).forEach(function (k) {
                        if (data[k] !== undefined && data[k] !== null) _body[k] = data[k]
                    });
                    bodies.push(_body);

                    if (n > 1) {
                        n--;
                        return getParameters(body, n, cb);
                    } else {
                        return cb(null, bodies)
                    }
                })
            }
        }

        var filename = api.name + '.json';
        var path2 = path.resolve(dir, filename);

        function readOne(obj) {
            console.log('About to write to %s:\n\n%s\n', path2, obj);
            read({prompt: 'Is this ok? ', default: 'yes'}, function (er, ok) {
                if (!ok || ok.toLowerCase().charAt(0) !== 'y') {
                    console.log('Aborted.')
                } else {
                    template(obj, function (res) {
                        write2md(res.filename, res.md)
                    });
                }
            })
        }

        function write2md(filename, md) {
            var mdstr = md.name + md.type + md.url;
            if (md.args) {
                mdstr += md.args;
            }
            fs.writeFile(filename, mdstr, 'utf8', function (er) {
                if (er) return cb(er);
            })
        }
    })
}

<commit_msg>rename bodies to parameters<commit_after>var read = require('read');
var fs = require('fs');
var path = require('path');
var PZ = require('promzard').PromZard;
var input = require.resolve('./input.js');
var body = require.resolve('./body.js');
var template = require('./template').template;
var dir = process.cwd();

module.exports = function () {
    return create(dir, input, body, function (er) {
        if (er) console.log('\nbye');
    })
};

function create(dir, input, body, cb) {
    var api = {};
    var pz = new PZ(input, {});

    pz.on('error', cb);
    pz.on('data', function (data) {
        Object.keys(data).forEach(function (k) {
            if (data[k] !== undefined && data[k] !== null) api[k] = data[k]
        });

        var apiType = api.type.toLowerCase();
        if (apiType === 'post') {
            var n = api.keys_length;
            delete api.keys_length;
            if (n === '0') {
                readOne(stringify(api));
            } else {
                getParameters(body, n, function (err, data) {
                    if (err) return cb(err);
                    api.body = data;
                    readOne(stringify(api));
                });
            }

            function stringify(api) {
                return JSON.stringify(api, null, 2) + '\n';
            }

            var parameters = [];
            function getParameters(body, n, cb) {
                var _parameters = {};
                var pzbody = new PZ(body, {});
                pzbody.on('error', cb);
                pzbody.on('data', function (data) {
                    Object.keys(data).forEach(function (k) {
                        if (data[k] !== undefined && data[k] !== null) _parameters[k] = data[k]
                    });
                    parameters.push(_parameters);

                    if (n > 1) {
                        n--;
                        return getParameters(body, n, cb);
                    } else {
                        return cb(null, parameters)
                    }
                })
            }
        }

        var filename = api.name + '.json';
        var path2 = path.resolve(dir, filename);

        function readOne(obj) {
            console.log('About to write to %s:\n\n%s\n', path2, obj);
            read({prompt: 'Is this ok? ', default: 'yes'}, function (er, ok) {
                if (!ok || ok.toLowerCase().charAt(0) !== 'y') {
                    console.log('Aborted.')
                } else {
                    template(obj, function (res) {
                        write2md(res.filename, res.md)
                    });
                }
            })
        }

        function write2md(filename, md) {
            var mdstr = md.name + md.type + md.url;
            if (md.args) {
                mdstr += md.args;
            }
            fs.writeFile(filename, mdstr, 'utf8', function (er) {
                if (er) return cb(er);
            })
        }
    })
}

<|endoftext|>


<commit_before>var git = require( '../' );

var _Oid = function( obj ) {
  var self = {};

  if( obj instanceof git.raw.Oid ) {
    self.oid = obj;
  }
  else {
    self.oid = new git.raw.Oid();

    if( typeof obj === 'string' ) {
      self.oid.mkstr( obj );
    }
  }

  return self;
};

exports.oid = _Oid;
<commit_msg>Tidied oid<commit_after>var git = require( '../' );

var _Oid = function(obj) {
  var self = {};

  if(obj instanceof git.raw.Oid) {
    self.oid = obj;
  } else {
    self.oid = new git.raw.Oid();

    if (typeof obj === 'string') {
      self.oid.mkstr(obj);
    }
  }
  return self;
};

exports.oid = _Oid;
<|endoftext|>


<commit_before>/*jslint indent: 2, nomen:true, node: true*/
"use strict";

var phantomWrapper = require("./phantom-wrapper.js"),
  pdftkWrapper = require("./pdftk-wrapper.js"),
  os = require("os"),
  async = require("async"),
  fs = require("fs"),
  cache = require("./cache.js"),
  progress = require("./progress.js"),
  stock,
  bleed,
  hasBleed,
  pathToCache;

exports.generatePdfPage = function (markup, path, callback) {
  var dimensions = {
    width: stock.width,
    height: stock.height
  };

  if (hasBleed) {
    dimensions.width += bleed * 2;
    dimensions.height += bleed * 2;
  }

  phantomWrapper.generatePdfPage(markup, path, dimensions, callback);
};

function concatenatePagesFromCache(pathToPdf, callback) {
  async.waterfall([
    function (callback) {
      cache.getCachedPdfs(callback);
    },
    function (pathsToPdfs, callback) {
      pdftkWrapper.concatenatePages(pathsToPdfs, pathToPdf, callback);
    }
  ], callback);
}

exports.generatePdfFromPages = function (pages, pathToPdf, callback) {
  var pathsToPdfs = [];

  progress.start("Rendering PDF pages");

  async.eachSeries(pages,
    function (page, callback) {
      var path = pathToCache + "/pdf/" + page.order + ".pdf";
      exports.generatePdfPage(page.htmlContent, path, function (err, pathForPage) {
        if (err) {
          callback(err);
          return;
        }

        pathsToPdfs.push(pathForPage);
        progress.update(pathsToPdfs.length + " of " + pages.length);
        callback();
      });
    },
    function (err) {
      if (err) {
        callback(err);
        return;
      }

      progress.end();
      concatenatePagesFromCache(pathToPdf, callback);
    });
};

exports.init = function (options, callback) {
  stock = options.stock;
  bleed = options.bleed;
  hasBleed = options.hasBleed;
  pathToCache = options.pathToCache;
  callback();
};
<commit_msg>got pdf.js to use tmp folder rather than cache<commit_after>/*jslint indent: 2, nomen:true, node: true*/
"use strict";

var phantomWrapper = require("./phantom-wrapper.js"),
  pdftkWrapper = require("./pdftk-wrapper.js"),
  os = require("os"),
  async = require("async"),
  fs = require("fs"),
  progress = require("./progress.js"),
  stock,
  bleed,
  hasBleed,
  pathToTmp;

exports.generatePdfPage = function (markup, path, callback) {
  var dimensions = {
    width: stock.width,
    height: stock.height
  };

  if (hasBleed) {
    dimensions.width += bleed * 2;
    dimensions.height += bleed * 2;
  }

  phantomWrapper.generatePdfPage(markup, path, dimensions, callback);
};

function concatenatePagesFromTmp(pathToPdf, callback) {
  async.waterfall([
    function (callback) {
      fs.readdir(pathToTmp, callback);
    },
    function (filenames, callback) {
      var filenamesWithPath;

      // order by the number in the name
      // to prevent, say, 11.pdf from coming before 2.pdf
      filenames.sort(function (a, b) {
        var aNum = parseInt(a.slice(0, -4), 10),
          bNum = parseInt(b.slice(0, -4), 10);
        return aNum - bNum;
      });

      filenamesWithPath = filenames.map(function (filename) {
        return pathToTmp + filename;
      });

      callback(null, filenamesWithPath);
    },
    function (pathsToPdfs, callback) {
      pdftkWrapper.concatenatePages(pathsToPdfs, pathToPdf, callback);
    }
  ], callback);
}

exports.generatePdfFromPages = function (pages, pathToPdf, callback) {
  var pathsToPdfs = [];

  progress.start("Rendering PDF pages");

  async.eachSeries(pages,
    function (page, callback) {
      var path = pathToTmp + page.order + ".pdf";
      exports.generatePdfPage(page.htmlContent, path, function (err, pathForPage) {
        if (err) {
          callback(err);
          return;
        }

        pathsToPdfs.push(pathForPage);
        progress.update(pathsToPdfs.length + " of " + pages.length);
        callback();
      });
    },
    function (err) {
      if (err) {
        callback(err);
        return;
      }

      progress.end();
      concatenatePagesFromTmp(pathToPdf, callback);
    });
};

exports.init = function (options, callback) {
  stock = options.stock;
  bleed = options.bleed;
  hasBleed = options.hasBleed;
  pathToTmp = options.pathToTmp;
  callback();
};
<|endoftext|>


<commit_before>'use strict'

const EE = require('events').EventEmitter
const URL = require('url')
const hdr = require('hdr-histogram-js')
const clone = require('shallow-clone')
const timestring = require('timestring')
const Client = require('./httpClient')
const DefaultOptions = require('./defaultOptions')
const xtend = require('xtend')
const histUtil = require('hdr-histogram-percentiles-obj')
const reInterval = require('reinterval')
const histAsObj = histUtil.histAsObj
const addPercentiles = histUtil.addPercentiles

function run (opts, cb) {
  const cbPassedIn = (typeof cb === 'function')

  cb = cb || noop

  const tracker = new EE()

  const latencies = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 10000,
    numberOfSignificantValueDigits: 5
  })

  const requests = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 1000000,
    numberOfSignificantValueDigits: 3
  })

  const throughput = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 100000000000,
    numberOfSignificantValueDigits: 1
  })

  const statusCodes = [
    0, // 1xx
    0, // 2xx
    0, // 3xx
    0, // 4xx
    0 // 5xx
  ]

  opts = xtend(clone(DefaultOptions), opts)

  // do error checking, if error, return
  if (checkOptsForErrors()) return

  // set tracker.opts here, so throwing over invalid opts and setting defaults etc.
  // is done
  tracker.opts = opts

  if (opts.url.indexOf('http') !== 0) opts.url = 'http://' + opts.url
  const url = URL.parse(opts.url)

  let counter = 0
  let bytes = 0
  let errors = 0
  let timeouts = 0
  let totalBytes = 0
  let totalRequests = 0
  let totalCompletedRequests = 0
  let amount = opts.amount
  let stop = false
  let restart = true
  let numRunning = opts.connections
  let startTime = Date.now()
  let includeErrorStats = !opts.excludeErrorStats

  // copy over fields so that the client
  // performs the right HTTP requests
  url.pipelining = opts.pipelining
  url.method = opts.method
  url.body = opts.body
  url.headers = opts.headers
  url.setupClient = opts.setupClient
  url.timeout = opts.timeout
  url.requests = opts.requests
  url.reconnectRate = opts.reconnectRate
  url.responseMax = amount || opts.maxConnectionRequests || opts.maxOverallRequests
  url.rate = opts.connectionRate || opts.overallRate
  url.idReplacement = opts.idReplacement
  url.socketPath = opts.socketPath
  url.servername = opts.servername

  let clients = []
  initialiseClients(clients)

  if (!amount) {
    var stopTimer = setTimeout(() => {
      stop = true
    }, opts.duration * 1000)
  }

  tracker.stop = () => {
    stop = true
    restart = false
  }

  const interval = reInterval(tickInterval, 1000)

  // put the start emit in a setImmediate so trackers can be added, etc.
  setImmediate(() => { tracker.emit('start') })

  function tickInterval () {
    totalBytes += bytes
    totalCompletedRequests += counter
    requests.recordValue(counter)
    throughput.recordValue(bytes)
    counter = 0
    bytes = 0
    tracker.emit('tick')

    if (stop) {
      if (stopTimer) clearTimeout(stopTimer)
      interval.clear()
      clients.forEach((client) => client.destroy())
      let result = {
        title: opts.title,
        url: opts.url,
        socketPath: opts.socketPath,
        requests: histAsObj(requests, totalCompletedRequests),
        latency: addPercentiles(latencies, histAsObj(latencies)),
        throughput: histAsObj(throughput, totalBytes),
        errors: errors,
        timeouts: timeouts,
        duration: Math.round((Date.now() - startTime) / 1000),
        start: new Date(startTime),
        finish: new Date(),
        connections: opts.connections,
        pipelining: opts.pipelining,
        'non2xx': statusCodes[0] + statusCodes[2] + statusCodes[3] + statusCodes[4]
      }
      result.requests.sent = totalRequests
      statusCodes.forEach((code, index) => { result[(index + 1) + 'xx'] = code })
      if (result.throughput.min === Number.MAX_SAFE_INTEGER) result.throughput.min = 0
      if (result.latency.min === Number.MAX_SAFE_INTEGER) result.latency.min = 0

      tracker.emit('done', result)
      if (!opts.forever) cb(null, result)

      // the restart function
      setImmediate(() => {
        if (opts.forever && restart) {
          stop = false
          stopTimer = setTimeout(() => {
            stop = true
          }, opts.duration * 1000)
          errors = 0
          timeouts = 0
          totalBytes = 0
          totalRequests = 0
          totalCompletedRequests = 0
          statusCodes.fill(0)
          requests.reset()
          latencies.reset()
          throughput.reset()
          startTime = Date.now()

          // reinitialise clients
          clients = []
          initialiseClients(clients)

          interval.reschedule(1000)
          tracker.emit('start')
        }
      })
    }
  }

  function initialiseClients (clients) {
    for (let i = 0; i < opts.connections; i++) {
      if (!amount && !opts.maxConnectionRequests && opts.maxOverallRequests) {
        url.responseMax = distributeNums(opts.maxOverallRequests, i)
      }
      if (amount) {
        url.responseMax = distributeNums(amount, i)
      }
      if (!opts.connectionRate && opts.overallRate) {
        url.rate = distributeNums(opts.overallRate, i)
      }

      let client = new Client(url)
      client.on('response', onResponse)
      client.on('connError', onError)
      client.on('timeout', onTimeout)
      client.on('request', () => { totalRequests++ })
      client.on('done', onDone)
      clients.push(client)

      // we will miss the initial request emits because the client emits request on construction
      totalRequests += url.pipelining < url.rate ? url.rate : url.pipelining
    }

    function distributeNums (x, i) {
      return (Math.floor(x / opts.connections) + (((i + 1) <= (x % opts.connections)) ? 1 : 0))
    }

    function onResponse (statusCode, resBytes, responseTime) {
      tracker.emit('response', this, statusCode, resBytes, responseTime)
      const codeIndex = Math.floor(parseInt(statusCode) / 100) - 1
      statusCodes[codeIndex] += 1
      // only recordValue 2xx latencies
      if (codeIndex === 1 || includeErrorStats) latencies.recordValue(responseTime)
      if (codeIndex === 1 || includeErrorStats) bytes += resBytes
      counter++
    }

    function onError (error) {
      for (let i = 0; i < opts.pipelining; i++) tracker.emit('reqError', error)
      errors++
      if (opts.bailout && errors >= opts.bailout) stop = true
    }

    // treat a timeout as a special type of error
    function onTimeout () {
      let error = new Error('request timed out')
      for (let i = 0; i < opts.pipelining; i++) tracker.emit('reqError', error)
      errors++
      timeouts++
      if (opts.bailout && errors >= opts.bailout) stop = true
    }

    function onDone () {
      if (!--numRunning) stop = true
    }
  }

  // will return true if error with opts entered
  function checkOptsForErrors () {
    if (!opts.url && !opts.socketPath) {
      errorCb(new Error('url or socketPath option required'))
      return true
    }

    if (typeof opts.duration === 'string') {
      if (/[a-zA-Z]/.exec(opts.duration)) opts.duration = timestring(opts.duration)
      else opts.duration = Number(opts.duration.trim())
    }

    if (typeof opts.duration === 'number') {
      if (lessThanZeroError(opts.duration, 'duration')) return true
    } else {
      errorCb(new Error('duration entered was in an invalid format'))
      return true
    }

    if (lessThanOneError(opts.connections, 'connections')) return true
    if (lessThanOneError(opts.pipelining, 'pipelining factor')) return true
    if (greaterThanZeroError(opts.timeout, 'timeout')) return true
    if (opts.bailout && lessThanOneError(opts.bailout, 'bailout threshold')) return true
    if (opts.connectionRate && lessThanOneError(opts.connectionRate, 'connectionRate')) return true
    if (opts.overallRate && lessThanOneError(opts.overallRate, 'bailout overallRate')) return true
    if (opts.amount && lessThanOneError(opts.amount, 'amount')) return true
    if (opts.maxConnectionRequests && lessThanOneError(opts.maxConnectionRequests, 'maxConnectionRequests')) return true
    if (opts.maxOverallRequests && lessThanOneError(opts.maxOverallRequests, 'maxOverallRequests')) return true

    if (opts.forever && cbPassedIn) {
      errorCb(new Error('should not use the callback parameter when the `forever` option is set to true. Use the `done` event on this event emitter'))
      return true
    }

    function lessThanZeroError (x, label) {
      if (x < 0) {
        errorCb(new Error(`${label} can not be less than 0`))
        return true
      }
      return false
    }

    function lessThanOneError (x, label) {
      if (x < 1) {
        errorCb(new Error(`${label} can not be less than 1`))
        return true
      }
      return false
    }

    function greaterThanZeroError (x, label) {
      if (x <= 0) {
        errorCb(new Error(`${label} must be greater than 0`))
        return true
      }
      return false
    }

    function errorCb (error) {
      if (cbPassedIn) {
        cb(error)
      } else {
        // wrapped in setImmediate so any error event handlers that are added to
        // the tracker can be added before being emitted
        setImmediate(() => { tracker.emit('error', error) })
      }
    }

    return false
  } // checkOptsForErrors

  return tracker
} // run

function noop () {}

module.exports = run
<commit_msg>Fix throughput stats<commit_after>'use strict'

const EE = require('events').EventEmitter
const URL = require('url')
const hdr = require('hdr-histogram-js')
const clone = require('shallow-clone')
const timestring = require('timestring')
const Client = require('./httpClient')
const DefaultOptions = require('./defaultOptions')
const xtend = require('xtend')
const histUtil = require('hdr-histogram-percentiles-obj')
const reInterval = require('reinterval')
const histAsObj = histUtil.histAsObj
const addPercentiles = histUtil.addPercentiles

function run (opts, cb) {
  const cbPassedIn = (typeof cb === 'function')

  cb = cb || noop

  const tracker = new EE()

  const latencies = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 10000,
    numberOfSignificantValueDigits: 5
  })

  const requests = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 1000000,
    numberOfSignificantValueDigits: 3
  })

  const throughput = hdr.build({
    bitBucketSize: 64,
    autoResize: true,
    lowestDiscernibleValue: 1,
    highestTrackableValue: 100000000000,
    numberOfSignificantValueDigits: 3
  })

  const statusCodes = [
    0, // 1xx
    0, // 2xx
    0, // 3xx
    0, // 4xx
    0 // 5xx
  ]

  opts = xtend(clone(DefaultOptions), opts)

  // do error checking, if error, return
  if (checkOptsForErrors()) return

  // set tracker.opts here, so throwing over invalid opts and setting defaults etc.
  // is done
  tracker.opts = opts

  if (opts.url.indexOf('http') !== 0) opts.url = 'http://' + opts.url
  const url = URL.parse(opts.url)

  let counter = 0
  let bytes = 0
  let errors = 0
  let timeouts = 0
  let totalBytes = 0
  let totalRequests = 0
  let totalCompletedRequests = 0
  let amount = opts.amount
  let stop = false
  let restart = true
  let numRunning = opts.connections
  let startTime = Date.now()
  let includeErrorStats = !opts.excludeErrorStats

  // copy over fields so that the client
  // performs the right HTTP requests
  url.pipelining = opts.pipelining
  url.method = opts.method
  url.body = opts.body
  url.headers = opts.headers
  url.setupClient = opts.setupClient
  url.timeout = opts.timeout
  url.requests = opts.requests
  url.reconnectRate = opts.reconnectRate
  url.responseMax = amount || opts.maxConnectionRequests || opts.maxOverallRequests
  url.rate = opts.connectionRate || opts.overallRate
  url.idReplacement = opts.idReplacement
  url.socketPath = opts.socketPath
  url.servername = opts.servername

  let clients = []
  initialiseClients(clients)

  if (!amount) {
    var stopTimer = setTimeout(() => {
      stop = true
    }, opts.duration * 1000)
  }

  tracker.stop = () => {
    stop = true
    restart = false
  }

  const interval = reInterval(tickInterval, 1000)

  // put the start emit in a setImmediate so trackers can be added, etc.
  setImmediate(() => { tracker.emit('start') })

  function tickInterval () {
    totalBytes += bytes
    totalCompletedRequests += counter
    requests.recordValue(counter)
    throughput.recordValue(bytes)
    counter = 0
    bytes = 0
    tracker.emit('tick')

    if (stop) {
      if (stopTimer) clearTimeout(stopTimer)
      interval.clear()
      clients.forEach((client) => client.destroy())
      let result = {
        title: opts.title,
        url: opts.url,
        socketPath: opts.socketPath,
        requests: histAsObj(requests, totalCompletedRequests),
        latency: addPercentiles(latencies, histAsObj(latencies)),
        throughput: histAsObj(throughput, totalBytes),
        errors: errors,
        timeouts: timeouts,
        duration: Math.round((Date.now() - startTime) / 1000),
        start: new Date(startTime),
        finish: new Date(),
        connections: opts.connections,
        pipelining: opts.pipelining,
        'non2xx': statusCodes[0] + statusCodes[2] + statusCodes[3] + statusCodes[4]
      }
      result.requests.sent = totalRequests
      statusCodes.forEach((code, index) => { result[(index + 1) + 'xx'] = code })
      if (result.throughput.min === Number.MAX_SAFE_INTEGER) result.throughput.min = 0
      if (result.latency.min === Number.MAX_SAFE_INTEGER) result.latency.min = 0

      tracker.emit('done', result)
      if (!opts.forever) cb(null, result)

      // the restart function
      setImmediate(() => {
        if (opts.forever && restart) {
          stop = false
          stopTimer = setTimeout(() => {
            stop = true
          }, opts.duration * 1000)
          errors = 0
          timeouts = 0
          totalBytes = 0
          totalRequests = 0
          totalCompletedRequests = 0
          statusCodes.fill(0)
          requests.reset()
          latencies.reset()
          throughput.reset()
          startTime = Date.now()

          // reinitialise clients
          clients = []
          initialiseClients(clients)

          interval.reschedule(1000)
          tracker.emit('start')
        }
      })
    }
  }

  function initialiseClients (clients) {
    for (let i = 0; i < opts.connections; i++) {
      if (!amount && !opts.maxConnectionRequests && opts.maxOverallRequests) {
        url.responseMax = distributeNums(opts.maxOverallRequests, i)
      }
      if (amount) {
        url.responseMax = distributeNums(amount, i)
      }
      if (!opts.connectionRate && opts.overallRate) {
        url.rate = distributeNums(opts.overallRate, i)
      }

      let client = new Client(url)
      client.on('response', onResponse)
      client.on('connError', onError)
      client.on('timeout', onTimeout)
      client.on('request', () => { totalRequests++ })
      client.on('done', onDone)
      clients.push(client)

      // we will miss the initial request emits because the client emits request on construction
      totalRequests += url.pipelining < url.rate ? url.rate : url.pipelining
    }

    function distributeNums (x, i) {
      return (Math.floor(x / opts.connections) + (((i + 1) <= (x % opts.connections)) ? 1 : 0))
    }

    function onResponse (statusCode, resBytes, responseTime) {
      tracker.emit('response', this, statusCode, resBytes, responseTime)
      const codeIndex = Math.floor(parseInt(statusCode) / 100) - 1
      statusCodes[codeIndex] += 1
      // only recordValue 2xx latencies
      if (codeIndex === 1 || includeErrorStats) latencies.recordValue(responseTime)
      if (codeIndex === 1 || includeErrorStats) bytes += resBytes
      counter++
    }

    function onError (error) {
      for (let i = 0; i < opts.pipelining; i++) tracker.emit('reqError', error)
      errors++
      if (opts.bailout && errors >= opts.bailout) stop = true
    }

    // treat a timeout as a special type of error
    function onTimeout () {
      let error = new Error('request timed out')
      for (let i = 0; i < opts.pipelining; i++) tracker.emit('reqError', error)
      errors++
      timeouts++
      if (opts.bailout && errors >= opts.bailout) stop = true
    }

    function onDone () {
      if (!--numRunning) stop = true
    }
  }

  // will return true if error with opts entered
  function checkOptsForErrors () {
    if (!opts.url && !opts.socketPath) {
      errorCb(new Error('url or socketPath option required'))
      return true
    }

    if (typeof opts.duration === 'string') {
      if (/[a-zA-Z]/.exec(opts.duration)) opts.duration = timestring(opts.duration)
      else opts.duration = Number(opts.duration.trim())
    }

    if (typeof opts.duration === 'number') {
      if (lessThanZeroError(opts.duration, 'duration')) return true
    } else {
      errorCb(new Error('duration entered was in an invalid format'))
      return true
    }

    if (lessThanOneError(opts.connections, 'connections')) return true
    if (lessThanOneError(opts.pipelining, 'pipelining factor')) return true
    if (greaterThanZeroError(opts.timeout, 'timeout')) return true
    if (opts.bailout && lessThanOneError(opts.bailout, 'bailout threshold')) return true
    if (opts.connectionRate && lessThanOneError(opts.connectionRate, 'connectionRate')) return true
    if (opts.overallRate && lessThanOneError(opts.overallRate, 'bailout overallRate')) return true
    if (opts.amount && lessThanOneError(opts.amount, 'amount')) return true
    if (opts.maxConnectionRequests && lessThanOneError(opts.maxConnectionRequests, 'maxConnectionRequests')) return true
    if (opts.maxOverallRequests && lessThanOneError(opts.maxOverallRequests, 'maxOverallRequests')) return true

    if (opts.forever && cbPassedIn) {
      errorCb(new Error('should not use the callback parameter when the `forever` option is set to true. Use the `done` event on this event emitter'))
      return true
    }

    function lessThanZeroError (x, label) {
      if (x < 0) {
        errorCb(new Error(`${label} can not be less than 0`))
        return true
      }
      return false
    }

    function lessThanOneError (x, label) {
      if (x < 1) {
        errorCb(new Error(`${label} can not be less than 1`))
        return true
      }
      return false
    }

    function greaterThanZeroError (x, label) {
      if (x <= 0) {
        errorCb(new Error(`${label} must be greater than 0`))
        return true
      }
      return false
    }

    function errorCb (error) {
      if (cbPassedIn) {
        cb(error)
      } else {
        // wrapped in setImmediate so any error event handlers that are added to
        // the tracker can be added before being emitted
        setImmediate(() => { tracker.emit('error', error) })
      }
    }

    return false
  } // checkOptsForErrors

  return tracker
} // run

function noop () {}

module.exports = run
<|endoftext|>


<commit_before>'use strict';

var hasArgument = require('./hasArgument');
var isCommand = require('./isCommand');
var replaceArgument = require('./replaceArgument');
var replaceCommand = require('./replaceCommand');
var spawnMeteor = require('./spawnMeteor');
var spawnTestPackagesMeteor = require('./spawnTestPackagesMeteor');

module.exports = function run(options) {
  var meteorArguments = options.args;
  var meteorEnvironment = options.env;

  meteorArguments = replaceCommand(meteorArguments, 'test-package', 'test-packages');

  if (isCommand(meteorArguments, 'test-app')) {
    meteorArguments = replaceCommand(meteorArguments, 'test-app', 'run');
    meteorArguments = replaceArgument(meteorArguments, '--ci', '--test');

    spawnMeteor({
      args: meteorArguments,
      env: meteorEnvironment
    });
  } else if (isCommand(meteorArguments, 'test-packages')) {
    if (!hasArgument(meteorArguments, '--release')) {
      meteorArguments.push('--release', 'velocity:METEOR@1.1.0.2_3');
    }

    if (!hasArgument(meteorArguments, '--driver-package')) {
      meteorArguments.push('--driver-package', 'velocity:html-reporter');
    }

    meteorArguments = replaceArgument(meteorArguments, '--ci', '--velocity');

    spawnTestPackagesMeteor({
      args: meteorArguments,
      env: meteorEnvironment
    });
  } else {
    console.error('Velocity does not support this command.');
    console.log('Supported commands:');
    console.log('  * velocity test-package my-package');
  }
}
<commit_msg>Add test-app command to help output<commit_after>'use strict';

var hasArgument = require('./hasArgument');
var isCommand = require('./isCommand');
var replaceArgument = require('./replaceArgument');
var replaceCommand = require('./replaceCommand');
var spawnMeteor = require('./spawnMeteor');
var spawnTestPackagesMeteor = require('./spawnTestPackagesMeteor');

module.exports = function run(options) {
  var meteorArguments = options.args;
  var meteorEnvironment = options.env;

  meteorArguments = replaceCommand(meteorArguments, 'test-package', 'test-packages');

  if (isCommand(meteorArguments, 'test-app')) {
    meteorArguments = replaceCommand(meteorArguments, 'test-app', 'run');
    meteorArguments = replaceArgument(meteorArguments, '--ci', '--test');

    spawnMeteor({
      args: meteorArguments,
      env: meteorEnvironment
    });
  } else if (isCommand(meteorArguments, 'test-packages')) {
    if (!hasArgument(meteorArguments, '--release')) {
      meteorArguments.push('--release', 'velocity:METEOR@1.1.0.2_3');
    }

    if (!hasArgument(meteorArguments, '--driver-package')) {
      meteorArguments.push('--driver-package', 'velocity:html-reporter');
    }

    meteorArguments = replaceArgument(meteorArguments, '--ci', '--velocity');

    spawnTestPackagesMeteor({
      args: meteorArguments,
      env: meteorEnvironment
    });
  } else {
    console.error('Velocity does not support this command.');
    console.log('Supported commands:');
    console.log('  * velocity test-app');
    console.log('  * velocity test-package my-package');
  }
}
<|endoftext|>


<commit_before>const querystring = require('querystring');
const Cache = require('./cache');
const utils = require('./utils');
const vm = require('vm');

// A shared cache to keep track of html5player js functions.
exports.cache = new Cache();

/**
 * Extract signature deciphering and n parameter transform functions from html5player file.
 *
 * @param {string} html5playerfile
 * @param {Object} options
 * @returns {Promise<Array.<string>>}
 */
exports.getFunctions = (html5playerfile, options) => exports.cache.getOrSet(html5playerfile, async() => {
  const body = await utils.exposedMiniget(html5playerfile, options).text();
  const functions = exports.extractFunctions(body);
  if (!functions || !functions.length) {
    throw Error('Could not extract functions');
  }
  exports.cache.set(html5playerfile, functions);
  return functions;
});

/**
 * Extracts the actions that should be taken to decipher a signature
 * and tranform the n parameter
 *
 * @param {string} body
 * @returns {Array.<string>}
 */
exports.extractFunctions = body => {
  const functions = [];
  const extractManipulations = caller => {
    const functionName = utils.between(caller, `a=a.split("");`, `.`);
    if (!functionName) return '';
    const functionStart = `var ${functionName}={`;
    const ndx = body.indexOf(functionStart);
    if (ndx < 0) return '';
    const subBody = body.slice(ndx + functionStart.length - 1);
    return `var ${functionName}=${utils.cutAfterJSON(subBody)}`;
  };
  const extractDecipher = () => {
    const functionName = utils.between(body, `a.set("alr","yes");c&&(c=`, `(decodeURIC`);
    if (functionName && functionName.length) {
      const functionStart = `${functionName}=function(a)`;
      const ndx = body.indexOf(functionStart);
      if (ndx >= 0) {
        const subBody = body.slice(ndx + functionStart.length);
        let functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)}`;
        functionBody = `${extractManipulations(functionBody)};${functionBody};${functionName}(sig);`;
        functions.push(functionBody);
      }
    }
  };
  const extractNCode = () => {
    const functionName = utils.between(body, `&&(b=a.get("n"))&&(b=`, `(b)`);
    if (functionName && functionName.length) {
      const functionStart = `${functionName}=function(a)`;
      const ndx = body.indexOf(functionStart);
      if (ndx >= 0) {
        const subBody = body.slice(ndx + functionStart.length);
        const functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)};${functionName}(ncode);`;
        functions.push(functionBody);
      }
    }
  };
  extractDecipher();
  extractNCode();
  return functions;
};

/**
 * Apply decipher and n-transform to individual format
 *
 * @param {Object} format
 * @param {vm.Script} decipherScript
 * @param {vm.Script} nTransformScript
 */
exports.setDownloadURL = (format, decipherScript, nTransformScript) => {
  const decipher = url => {
    const args = querystring.parse(url);
    if (!args.s || !decipherScript) return args.url;
    const components = new URL(decodeURIComponent(args.url));
    components.searchParams.set(args.sp ? args.sp : 'signature',
      decipherScript.runInNewContext({ sig: decodeURIComponent(args.s) }));
    return components.toString();
  };
  const ncode = url => {
    const components = new URL(decodeURIComponent(url));
    const n = components.searchParams.get('n');
    if (!n || !nTransformScript) return url;
    components.searchParams.set('n', nTransformScript.runInNewContext({ ncode: n }));
    return components.toString();
  };
  const cipher = !format.url;
  const url = format.url || format.signatureCipher || format.cipher;
  format.url = cipher ? ncode(decipher(url)) : ncode(url);
  delete format.signatureCipher;
  delete format.cipher;
};

/**
 * Applies decipher and n parameter transforms to all format URL's.
 *
 * @param {Array.<Object>} formats
 * @param {string} html5player
 * @param {Object} options
 */
exports.decipherFormats = async(formats, html5player, options) => {
  let decipheredFormats = {};
  let functions = await exports.getFunctions(html5player, options);
  const decipherScript = functions.length ? new vm.Script(functions[0]) : null;
  const nTransformScript = functions.length > 1 ? new vm.Script(functions[1]) : null;
  formats.forEach(format => {
    exports.setDownloadURL(format, decipherScript, nTransformScript);
    decipheredFormats[format.url] = format;
  });
  return decipheredFormats;
};
<commit_msg>fix: parsing for N transform function name. (#1055)<commit_after>const querystring = require('querystring');
const Cache = require('./cache');
const utils = require('./utils');
const vm = require('vm');

// A shared cache to keep track of html5player js functions.
exports.cache = new Cache();

/**
 * Extract signature deciphering and n parameter transform functions from html5player file.
 *
 * @param {string} html5playerfile
 * @param {Object} options
 * @returns {Promise<Array.<string>>}
 */
exports.getFunctions = (html5playerfile, options) => exports.cache.getOrSet(html5playerfile, async() => {
  const body = await utils.exposedMiniget(html5playerfile, options).text();
  const functions = exports.extractFunctions(body);
  if (!functions || !functions.length) {
    throw Error('Could not extract functions');
  }
  exports.cache.set(html5playerfile, functions);
  return functions;
});

/**
 * Extracts the actions that should be taken to decipher a signature
 * and tranform the n parameter
 *
 * @param {string} body
 * @returns {Array.<string>}
 */
exports.extractFunctions = body => {
  const functions = [];
  const extractManipulations = caller => {
    const functionName = utils.between(caller, `a=a.split("");`, `.`);
    if (!functionName) return '';
    const functionStart = `var ${functionName}={`;
    const ndx = body.indexOf(functionStart);
    if (ndx < 0) return '';
    const subBody = body.slice(ndx + functionStart.length - 1);
    return `var ${functionName}=${utils.cutAfterJSON(subBody)}`;
  };
  const extractDecipher = () => {
    const functionName = utils.between(body, `a.set("alr","yes");c&&(c=`, `(decodeURIC`);
    if (functionName && functionName.length) {
      const functionStart = `${functionName}=function(a)`;
      const ndx = body.indexOf(functionStart);
      if (ndx >= 0) {
        const subBody = body.slice(ndx + functionStart.length);
        let functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)}`;
        functionBody = `${extractManipulations(functionBody)};${functionBody};${functionName}(sig);`;
        functions.push(functionBody);
      }
    }
  };
  const extractNCode = () => {
    let functionName = utils.between(body, `&&(b=a.get("n"))&&(b=`, `(b)`);
    if (functionName.includes('[')) functionName = utils.between(body, `${functionName.split('[')[0]}=[`, `]`);
    if (functionName && functionName.length) {
      const functionStart = `${functionName}=function(a)`;
      const ndx = body.indexOf(functionStart);
      if (ndx >= 0) {
        const subBody = body.slice(ndx + functionStart.length);
        const functionBody = `var ${functionStart}${utils.cutAfterJSON(subBody)};${functionName}(ncode);`;
        functions.push(functionBody);
      }
    }
  };
  extractDecipher();
  extractNCode();
  return functions;
};

/**
 * Apply decipher and n-transform to individual format
 *
 * @param {Object} format
 * @param {vm.Script} decipherScript
 * @param {vm.Script} nTransformScript
 */
exports.setDownloadURL = (format, decipherScript, nTransformScript) => {
  const decipher = url => {
    const args = querystring.parse(url);
    if (!args.s || !decipherScript) return args.url;
    const components = new URL(decodeURIComponent(args.url));
    components.searchParams.set(args.sp ? args.sp : 'signature',
      decipherScript.runInNewContext({ sig: decodeURIComponent(args.s) }));
    return components.toString();
  };
  const ncode = url => {
    const components = new URL(decodeURIComponent(url));
    const n = components.searchParams.get('n');
    if (!n || !nTransformScript) return url;
    components.searchParams.set('n', nTransformScript.runInNewContext({ ncode: n }));
    return components.toString();
  };
  const cipher = !format.url;
  const url = format.url || format.signatureCipher || format.cipher;
  format.url = cipher ? ncode(decipher(url)) : ncode(url);
  delete format.signatureCipher;
  delete format.cipher;
};

/**
 * Applies decipher and n parameter transforms to all format URL's.
 *
 * @param {Array.<Object>} formats
 * @param {string} html5player
 * @param {Object} options
 */
exports.decipherFormats = async(formats, html5player, options) => {
  let decipheredFormats = {};
  let functions = await exports.getFunctions(html5player, options);
  const decipherScript = functions.length ? new vm.Script(functions[0]) : null;
  const nTransformScript = functions.length > 1 ? new vm.Script(functions[1]) : null;
  formats.forEach(format => {
    exports.setDownloadURL(format, decipherScript, nTransformScript);
    decipheredFormats[format.url] = format;
  });
  return decipheredFormats;
};
<|endoftext|>


<commit_before>var Template = require('./template');

var template = new Template(require('./runtime_node'));

exports.template = template;
exports.compile = template.compile;
<commit_msg>Fix slm.js<commit_after>var Template = require('./template');

var template = new Template(require('./runtime_node'));

exports.template = template;
exports.compile = function(source, options) {
  return template.compile(source, options);
};
exports.eval = function(src, context) {
  return template.eval(src, context);
}
<|endoftext|>