<commit_before>#!/usr/bin/env node
/* eslint no-console:0, no-var:0 */
var Liftoff = require('liftoff');
var Promise = require('bluebird');
var interpret = require('interpret');
var path = require('path');
var chalk = require('chalk');
var tildify = require('tildify');
var commander = require('commander');
var argv = require('minimist')(process.argv.slice(2));
var fs = Promise.promisifyAll(require('fs'));
var cliPkg = require('../package');

function exit(text) {
  if (text instanceof Error) {
    chalk.red(console.error(text.stack));
  } else {
    chalk.red(console.error(text));
  }
  process.exit(1);
}

function success(text) {
  console.log(text);
  process.exit(0);
}

function checkLocalModule(env) {
  if (!env.modulePath) {
    console.log(chalk.red('No local knex install found in:'), chalk.magenta(tildify(env.cwd)));
    exit('Try running: npm install knex.');
  }
}

function initKnex(env) {

  checkLocalModule(env);

  if (!env.configPath) {
    exit('No knexfile found in this directory. Specify a path with --knexfile');
  }

  if (process.cwd() !== env.cwd) {
    process.chdir(env.cwd);
    console.log('Working directory changed to', chalk.magenta(tildify(env.cwd)));
  }

  var environment = commander.env || process.env.NODE_ENV;
  var defaultEnv = 'development';
  var config = require(env.configPath);

  if (!environment && typeof config[defaultEnv] === 'object') {
    environment = defaultEnv;
  }

  if (environment) {
    console.log('Using environment:', chalk.magenta(environment));
    config = config[environment] || config;
  }

  if (!config) {
    console.log(chalk.red('Warning: unable to read knexfile config'));
    process.exit(1);
  }

  if (argv.debug !== undefined)
    config.debug = argv.debug;
  var knex = require(env.modulePath);
  return knex(config);
}

function invoke(env) {

  var filetypes = ['js', 'coffee', 'ts', 'eg', 'ls'];
  var pending = null;

  commander
    .version(
      chalk.blue('Knex CLI version: ', chalk.green(cliPkg.version)) + '\n' +
      chalk.blue('Local Knex version: ', chalk.green(env.modulePackage.version)) + '\n'
    )
    .option('--debug', 'Run with debugging.')
    .option('--knexfile [path]', 'Specify the knexfile path.')
    .option('--cwd [path]', 'Specify the working directory.')
    .option('--env [name]', 'environment, default: process.env.NODE_ENV || development');

  commander
    .command('init')
    .description('        Create a fresh knexfile.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the knexfile extension (default js)')
    .action(function() {
      var type = (argv.x || 'js').toLowerCase();
      if (filetypes.indexOf(type) === -1) {
        exit(`Invalid filetype specified: ${type}`);
      }
      if (env.configPath) {
        exit(`Error: ${env.configPath} already exists`);
      }
      checkLocalModule(env);
      var stubPath = `./knexfile.${type}`;
      pending = fs.readFileAsync(
        path.dirname(env.modulePath) +
        '/lib/migrate/stub/knexfile-' +
        type + '.stub'
      ).then(function(code) { return fs.writeFileAsync(stubPath, code) }).then(function() {
        success(chalk.green(`Created ${stubPath}`));
      }).catch(exit);
    });

  commander
    .command('migrate:make <name>')
    .description('        Create a named migration file.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
    .action(function(name) {
      var instance = initKnex(env);
      var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
      pending = instance.migrate.make(name, {extension: ext}).then(function(name) {
        success(chalk.green(`Created Migration: ${name}`));
      }).catch(exit);
    });

  commander
    .command('migrate:latest')
    .description('        Run all migrations that have not yet been run.')
    .action(function() {
      pending = initKnex(env).migrate.latest().spread(function(batchNo, log) {
        if (log.length === 0) {
          success(chalk.cyan('Already up to date'));
        }
        success(
          chalk.green(`Batch ${batchNo} run: ${log.length} migrations \n`) +
          chalk.cyan(log.join('\n'))
        );
      }).catch(exit);
    });

  commander
    .command('migrate:rollback')
    .description('        Rollback the last set of migrations performed.')
    .action(function() {
      pending = initKnex(env).migrate.rollback().spread(function(batchNo, log) {
        if (log.length === 0) {
          success(chalk.cyan('Already at the base migration'));
        }
        success(
          chalk.green(`Batch ${batchNo} rolled back: ${log.length} migrations \n`) +
          chalk.cyan(log.join('\n'))
        );
      }).catch(exit);
    });

  commander
    .command('migrate:currentVersion')
    .description('        View the current version for the migration.')
    .action(function () {
      pending = initKnex(env).migrate.currentVersion().then(function(version) {
        success(chalk.green('Current Version: ') + chalk.blue(version));
      }).catch(exit);
    });

  commander
    .command('seed:make <name>')
    .description('        Create a named seed file.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
    .action(function(name) {
      var instance = initKnex(env);
      var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
      pending = instance.seed.make(name, {extension: ext}).then(function(name) {
        success(chalk.green(`Created seed file: ${name}`));
      }).catch(exit);
    });

  commander
    .command('seed:run')
    .description('        Run seed files.')
    .action(function() {
      pending = initKnex(env).seed.run().spread(function(log) {
        if (log.length === 0) {
          success(chalk.cyan('No seed files exist'));
        }
        success(chalk.green(`Ran ${log.length} seed files \n${chalk.cyan(log.join('\n'))}`));
      }).catch(exit);
    });

  commander.parse(process.argv);

  Promise.resolve(pending).then(function() {
    commander.help();
  });
}

var cli = new Liftoff({
  name: 'knex',
  extensions: interpret.jsVariants,
  v8flags: require('v8flags')
});

cli.on('require', function(name) {
  console.log('Requiring external module', chalk.magenta(name));
});

cli.on('requireFail', function(name) {
  console.log(chalk.red('Failed to load external module'), chalk.magenta(name));
});

cli.launch({
  cwd: argv.cwd,
  configPath: argv.knexfile,
  require: argv.require,
  completion: argv.completion
}, invoke);
<commit_msg>2351 CLI sets exit-code 1 if the command supplied was not parseable (#2358)<commit_after>#!/usr/bin/env node
/* eslint no-console:0, no-var:0 */
var Liftoff = require('liftoff');
var Promise = require('bluebird');
var interpret = require('interpret');
var path = require('path');
var chalk = require('chalk');
var tildify = require('tildify');
var commander = require('commander');
var argv = require('minimist')(process.argv.slice(2));
var fs = Promise.promisifyAll(require('fs'));
var cliPkg = require('../package');

function exit(text) {
  if (text instanceof Error) {
    console.error(chalk.red(text.stack));
  } else {
    console.error(chalk.red(text));
  }
  process.exit(1);
}

function success(text) {
  console.log(text);
  process.exit(0);
}

function checkLocalModule(env) {
  if (!env.modulePath) {
    console.log(chalk.red('No local knex install found in:'), chalk.magenta(tildify(env.cwd)));
    exit('Try running: npm install knex.');
  }
}

function initKnex(env) {

  checkLocalModule(env);

  if (!env.configPath) {
    exit('No knexfile found in this directory. Specify a path with --knexfile');
  }

  if (process.cwd() !== env.cwd) {
    process.chdir(env.cwd);
    console.log('Working directory changed to', chalk.magenta(tildify(env.cwd)));
  }

  var environment = commander.env || process.env.NODE_ENV;
  var defaultEnv = 'development';
  var config = require(env.configPath);

  if (!environment && typeof config[defaultEnv] === 'object') {
    environment = defaultEnv;
  }

  if (environment) {
    console.log('Using environment:', chalk.magenta(environment));
    config = config[environment] || config;
  }

  if (!config) {
    console.log(chalk.red('Warning: unable to read knexfile config'));
    process.exit(1);
  }

  if (argv.debug !== undefined)
    config.debug = argv.debug;
  var knex = require(env.modulePath);
  return knex(config);
}

function invoke(env) {

  var filetypes = ['js', 'coffee', 'ts', 'eg', 'ls'];
  var pending = null;

  commander
    .version(
      chalk.blue('Knex CLI version: ', chalk.green(cliPkg.version)) + '\n' +
      chalk.blue('Local Knex version: ', chalk.green(env.modulePackage.version)) + '\n'
    )
    .option('--debug', 'Run with debugging.')
    .option('--knexfile [path]', 'Specify the knexfile path.')
    .option('--cwd [path]', 'Specify the working directory.')
    .option('--env [name]', 'environment, default: process.env.NODE_ENV || development');

  commander
    .command('init')
    .description('        Create a fresh knexfile.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the knexfile extension (default js)')
    .action(function() {
      var type = (argv.x || 'js').toLowerCase();
      if (filetypes.indexOf(type) === -1) {
        exit(`Invalid filetype specified: ${type}`);
      }
      if (env.configPath) {
        exit(`Error: ${env.configPath} already exists`);
      }
      checkLocalModule(env);
      var stubPath = `./knexfile.${type}`;
      pending = fs.readFileAsync(
        path.dirname(env.modulePath) +
        '/lib/migrate/stub/knexfile-' +
        type + '.stub'
      ).then(function(code) { return fs.writeFileAsync(stubPath, code) }).then(function() {
        success(chalk.green(`Created ${stubPath}`));
      }).catch(exit);
    });

  commander
    .command('migrate:make <name>')
    .description('        Create a named migration file.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
    .action(function(name) {
      var instance = initKnex(env);
      var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
      pending = instance.migrate.make(name, {extension: ext}).then(function(name) {
        success(chalk.green(`Created Migration: ${name}`));
      }).catch(exit);
    });

  commander
    .command('migrate:latest')
    .description('        Run all migrations that have not yet been run.')
    .action(function() {
      pending = initKnex(env).migrate.latest().spread(function(batchNo, log) {
        if (log.length === 0) {
          success(chalk.cyan('Already up to date'));
        }
        success(
          chalk.green(`Batch ${batchNo} run: ${log.length} migrations \n`) +
          chalk.cyan(log.join('\n'))
        );
      }).catch(exit);
    });

  commander
    .command('migrate:rollback')
    .description('        Rollback the last set of migrations performed.')
    .action(function() {
      pending = initKnex(env).migrate.rollback().spread(function(batchNo, log) {
        if (log.length === 0) {
          success(chalk.cyan('Already at the base migration'));
        }
        success(
          chalk.green(`Batch ${batchNo} rolled back: ${log.length} migrations \n`) +
          chalk.cyan(log.join('\n'))
        );
      }).catch(exit);
    });

  commander
    .command('migrate:currentVersion')
    .description('        View the current version for the migration.')
    .action(function () {
      pending = initKnex(env).migrate.currentVersion().then(function(version) {
        success(chalk.green('Current Version: ') + chalk.blue(version));
      }).catch(exit);
    });

  commander
    .command('seed:make <name>')
    .description('        Create a named seed file.')
    .option(`-x [${filetypes.join('|')}]`, 'Specify the stub extension (default js)')
    .action(function(name) {
      var instance = initKnex(env);
      var ext = (argv.x || env.configPath.split('.').pop()).toLowerCase();
      pending = instance.seed.make(name, {extension: ext}).then(function(name) {
        success(chalk.green(`Created seed file: ${name}`));
      }).catch(exit);
    });

  commander
    .command('seed:run')
    .description('        Run seed files.')
    .action(function() {
      pending = initKnex(env).seed.run().spread(function(log) {
        if (log.length === 0) {
          success(chalk.cyan('No seed files exist'));
        }
        success(chalk.green(`Ran ${log.length} seed files \n${chalk.cyan(log.join('\n'))}`));
      }).catch(exit);
    });

  commander.parse(process.argv);

  Promise.resolve(pending).then(function() {
    commander.outputHelp();
    exit('Unknown command-line options, exiting');
  });
}

var cli = new Liftoff({
  name: 'knex',
  extensions: interpret.jsVariants,
  v8flags: require('v8flags')
});

cli.on('require', function(name) {
  console.log('Requiring external module', chalk.magenta(name));
});

cli.on('requireFail', function(name) {
  console.log(chalk.red('Failed to load external module'), chalk.magenta(name));
});

cli.launch({
  cwd: argv.cwd,
  configPath: argv.knexfile,
  require: argv.require,
  completion: argv.completion
}, invoke);
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

var pkg = require('../package.json');
var Promise = require('rsvp').Promise;
var CMDS = ['on', 'off', 'state', 'temp', 'version', 'voltage'];

var _ = require('lodash');

var yargs = require('yargs');
var argv = yargs
	.demand(1)
	.usage('Usage: $0 cmd [relay] [opts]')
	.help('h')
	.alias('h', ['?', 'help'])
	.version(pkg.version + '\n', 'version')
	.showHelpOnFail(true, 'Valid commands are: ' + CMDS.join(', '))
	.describe('p', 'The usb port uri to use. Leave empty to use port scan')
	.alias('p', 'port')
	.describe('n', 'The number of relays on the board')
	.alias('n', 'relayCount')
	.defaults('n', 2)
	.boolean('v')
	.describe('v', 'Enables verbose mode (for debug only)')
	.alias('v', 'verbose')
	.check(function (argv, opts) {
		return _.contains(CMDS, argv._[0]);
	})
	.argv;

var Tosr0x = require('tosr0x').Tosr0x;
var cmd = argv._[0];
var ctl;

process.title = 'Tosr0x';

if (cmd === 'temp') {
	cmd = 'temperature';
} else if (cmd === 'state') {
	cmd = 'refreshStates';
}

var run = function (c) {
	ctl = c;
	return ctl.open().then(function () {
		return ctl[cmd](argv._[1]);
	});
};

var display = function (res) {
	if (_.isObject(res)) {
		_.forOwn(res, function (val, key) {
			if (key !== 'ctl') {
				console.log(val);
			}
		});
	} else {
		console.log(res);
	}
	console.log('Done.');
};

var error = function (err) {
	console.error(err);
};

var close = function () {
	if (!!ctl) {
		ctl.closeImmediate();
	}
};

Tosr0x.create(argv.p, {
	debug: argv.v,
	relayCount: argv.n
})
.then(run)
.then(display)
.catch(error)
.finally(close);
<commit_msg>added exit code<commit_after>#!/usr/bin/env node

'use strict';

var pkg = require('../package.json');
var Promise = require('rsvp').Promise;
var CMDS = ['on', 'off', 'state', 'temp', 'version', 'voltage'];
var exitCode = 0;
var _ = require('lodash');
var yargs = require('yargs');
var argv = yargs
	.demand(1)
	.usage('Usage: $0 cmd [relay] [opts]')
	.help('h')
	.alias('h', ['?', 'help'])
	.version(pkg.version + '\n', 'version')
	.showHelpOnFail(true, 'Valid commands are: ' + CMDS.join(', '))
	.describe('p', 'The usb port uri to use. Leave empty to use port scan')
	.alias('p', 'port')
	.describe('n', 'The number of relays on the board')
	.alias('n', 'relayCount')
	.defaults('n', 2)
	.boolean('v')
	.describe('v', 'Enables verbose mode (for debug only)')
	.alias('v', 'verbose')
	.check(function (argv, opts) {
		return _.contains(CMDS, argv._[0]);
	})
	.argv;

var Tosr0x = require('tosr0x').Tosr0x;
var cmd = argv._[0];
var ctl;

process.title = 'Tosr0x';

if (cmd === 'temp') {
	cmd = 'temperature';
} else if (cmd === 'state') {
	cmd = 'refreshStates';
}

var run = function (c) {
	ctl = c;
	return ctl.open().then(function () {
		return ctl[cmd](argv._[1]);
	});
};

var display = function (res) {
	if (_.isObject(res)) {
		_.forOwn(res, function (val, key) {
			if (key !== 'ctl') {
				console.log(val);
			}
		});
	} else {
		console.log(res);
	}
	console.log('Done.');
};

var error = function (err) {
	console.error(err);
	exitCode = 1;
};

var close = function () {
	if (!!ctl) {
		ctl.closeImmediate();
	}
	process.exit(exitCode);
};

Tosr0x.create(argv.p, {
	debug: argv.v,
	relayCount: argv.n
})
.then(run)
.then(display)
.catch(error)
.finally(close);
<|endoftext|>


<commit_before>#!/usr/bin/env node
const prettyCLI = require('@tryghost/pretty-cli');
const ui = require('@tryghost/pretty-cli').ui;
const _ = require('lodash');
const chalk = require('chalk');
const gscan = require('../lib');

const options = {
    format: 'cli'
};

let levels;

prettyCLI
    .configure({
        name: 'gscan'
    })
    .groupOrder([
        'Sources:',
        'Utilities:',
        'Commands:',
        'Arguments:',
        'Required Options:',
        'Options:',
        'Global Options:'
    ])
    .positional('<themePath>', {
        paramsDesc: 'Theme folder or .zip file path',
        mustExist: true
    })
    .boolean('-p, --pre', {
        desc: 'Run a pre-check only'
    })
    .boolean('-z, --zip', {
        desc: 'Theme path points to a zip file'
    })
    .boolean('-1, --v1', {
        desc: 'Check theme for Ghost 1.0 compatibility, instead of 2.0'
    })
    .parseAndExit()
    .then((argv) => {
        if (argv.v1) {
            options.checkVersion = 'v1';
        } else {
            // CASE: set default value
            options.checkVersion = 'latest';
        }

        ui.log(chalk.bold('Checking theme compatibility..'));

        if (argv.zip) {
            gscan.checkZip(argv.themePath, options)
                .then(theme => outputResults(theme, options))
                .catch((error) => {
                    ui.log(error);
                });
        } else {
            gscan.check(argv.themePath, options)
                .then(theme => outputResults(theme, options))
                .catch(function ENOTDIRPredicate(err) {
                    return err.code === 'ENOTDIR';
                }, function (err) {
                    ui.log(err.message);
                    ui.log('Did you mean to add the -z flag to read a zip file?');
                });
        }
    });

levels = {
    error: chalk.red,
    warning: chalk.yellow,
    recommendation: chalk.yellow,
    feature: chalk.green
};

function outputResult(result) {
    ui.log('-', levels[result.level](result.level), result.rule);

    if (result.failures && result.failures.length) {
        ui.log(`${chalk.bold('Files')}: ${_.map(result.failures, 'ref')}`);
    }
}

function getSummary(theme) {
    let summaryText = '';
    const errorCount = theme.results.error.length;
    const warnCount = theme.results.warning.length;
    const pluralize = require('pluralize');
    const checkSymbol = '\u2713';

    if (errorCount === 0 && warnCount === 0) {
        summaryText = `${chalk.green(checkSymbol)} Your theme is compatible with Ghost ${theme.checkedVersion}`;
    } else {
        summaryText = `Your theme has`;

        if (!_.isEmpty(theme.results.error)) {
            summaryText += chalk.red.bold(` ${pluralize('error', theme.results.error.length, true)}`);
        }

        if (!_.isEmpty(theme.results.error) && !_.isEmpty(theme.results.warning)) {
            summaryText += ' and';
        }

        if (!_.isEmpty(theme.results.warning)) {
            summaryText += chalk.yellow.bold(` ${pluralize('warning', theme.results.warning.length, true)}`);
        }

        summaryText += '!';

        // NOTE: had to subtract the number of 'invisible' formating symbols
        //       needs update if formatting above changes
        const hiddenSymbols = 38;
        summaryText += '\n' + _.repeat('-', (summaryText.length - hiddenSymbols));
    }

    return summaryText;
}

function outputResults(theme, options) {
    theme = gscan.format(theme, options);

    let errorCount = theme.results.error.length;
    let warnCount = theme.results.warning.length;

    ui.log('\n' + getSummary(theme));

    if (!_.isEmpty(theme.results.error)) {
        ui.log(chalk.red.bold('\nErrors'));
        ui.log(chalk.red.bold('------'));
        ui.log(chalk.red('Very recommended to fix, functionality can be restricted.\n'));

        _.each(theme.results.error, outputResult);
    }

    if (!_.isEmpty(theme.results.warning)) {
        ui.log(chalk.yellow.bold('\nWarnings'));
        ui.log(chalk.yellow.bold('--------'));

        _.each(theme.results.warning, outputResult);
    }

    if (!_.isEmpty(theme.results.recommendation)) {
        ui.log(chalk.yellow.bold('\nRecommendations'));
        ui.log(chalk.yellow.bold('---------------'));

        _.each(theme.results.recommendation, outputResult);
    }

    ui.log(`\nGet more help at ${chalk.cyan.underline('https://docs.ghost.org/api/handlebars-themes/')}`);
    ui.log(`You can also check theme compatibility at ${chalk.cyan.underline('https://gscan.ghost.org/')}`);

    if (errorCount > 0 || warnCount > 0) {
        process.exit(1);
    } else {
        process.exit(0);
    }
}
<commit_msg>Updated check result ouput style<commit_after>#!/usr/bin/env node
const prettyCLI = require('@tryghost/pretty-cli');
const ui = require('@tryghost/pretty-cli').ui;
const _ = require('lodash');
const chalk = require('chalk');
const gscan = require('../lib');

const options = {
    format: 'cli'
};

let levels;

prettyCLI
    .configure({
        name: 'gscan'
    })
    .groupOrder([
        'Sources:',
        'Utilities:',
        'Commands:',
        'Arguments:',
        'Required Options:',
        'Options:',
        'Global Options:'
    ])
    .positional('<themePath>', {
        paramsDesc: 'Theme folder or .zip file path',
        mustExist: true
    })
    .boolean('-p, --pre', {
        desc: 'Run a pre-check only'
    })
    .boolean('-z, --zip', {
        desc: 'Theme path points to a zip file'
    })
    .boolean('-1, --v1', {
        desc: 'Check theme for Ghost 1.0 compatibility, instead of 2.0'
    })
    .parseAndExit()
    .then((argv) => {
        if (argv.v1) {
            options.checkVersion = 'v1';
        } else {
            // CASE: set default value
            options.checkVersion = 'latest';
        }

        ui.log(chalk.bold('Checking theme compatibility..'));

        if (argv.zip) {
            gscan.checkZip(argv.themePath, options)
                .then(theme => outputResults(theme, options))
                .catch((error) => {
                    ui.log(error);
                });
        } else {
            gscan.check(argv.themePath, options)
                .then(theme => outputResults(theme, options))
                .catch(function ENOTDIRPredicate(err) {
                    return err.code === 'ENOTDIR';
                }, function (err) {
                    ui.log(err.message);
                    ui.log('Did you mean to add the -z flag to read a zip file?');
                });
        }
    });

levels = {
    error: chalk.red,
    warning: chalk.yellow,
    recommendation: chalk.yellow,
    feature: chalk.green
};

function outputResult(result) {
    ui.log(levels[result.level](`- ${_.capitalize(result.level)}:`), result.rule);

    if (result.failures && result.failures.length) {
        ui.log(`${chalk.bold('Files:')} ${_.map(result.failures, 'ref')}`);
    }

    ui.log('');
}

function getSummary(theme) {
    let summaryText = '';
    const errorCount = theme.results.error.length;
    const warnCount = theme.results.warning.length;
    const pluralize = require('pluralize');
    const checkSymbol = '\u2713';

    if (errorCount === 0 && warnCount === 0) {
        summaryText = `${chalk.green(checkSymbol)} Your theme is compatible with Ghost ${theme.checkedVersion}`;
    } else {
        summaryText = `Your theme has`;

        if (!_.isEmpty(theme.results.error)) {
            summaryText += chalk.red.bold(` ${pluralize('error', theme.results.error.length, true)}`);
        }

        if (!_.isEmpty(theme.results.error) && !_.isEmpty(theme.results.warning)) {
            summaryText += ' and';
        }

        if (!_.isEmpty(theme.results.warning)) {
            summaryText += chalk.yellow.bold(` ${pluralize('warning', theme.results.warning.length, true)}`);
        }

        summaryText += '!';

        // NOTE: had to subtract the number of 'invisible' formating symbols
        //       needs update if formatting above changes
        const hiddenSymbols = 38;
        summaryText += '\n' + _.repeat('-', (summaryText.length - hiddenSymbols));
    }

    return summaryText;
}

function outputResults(theme, options) {
    theme = gscan.format(theme, options);

    let errorCount = theme.results.error.length;
    let warnCount = theme.results.warning.length;

    ui.log('\n' + getSummary(theme));

    if (!_.isEmpty(theme.results.error)) {
        ui.log(chalk.red.bold('\nErrors'));
        ui.log(chalk.red.bold('------'));
        ui.log(chalk.red('Very recommended to fix, functionality can be restricted.\n'));

        _.each(theme.results.error, outputResult);
    }

    if (!_.isEmpty(theme.results.warning)) {
        ui.log(chalk.yellow.bold('\nWarnings'));
        ui.log(chalk.yellow.bold('--------'));

        _.each(theme.results.warning, outputResult);
    }

    if (!_.isEmpty(theme.results.recommendation)) {
        ui.log(chalk.yellow.bold('\nRecommendations'));
        ui.log(chalk.yellow.bold('---------------'));

        _.each(theme.results.recommendation, outputResult);
    }

    ui.log(`\nGet more help at ${chalk.cyan.underline('https://docs.ghost.org/api/handlebars-themes/')}`);
    ui.log(`You can also check theme compatibility at ${chalk.cyan.underline('https://gscan.ghost.org/')}`);

    if (errorCount > 0 || warnCount > 0) {
        process.exit(1);
    } else {
        process.exit(0);
    }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs');
var validateEmails = require('../lib').validateEmails;

var emailBody = null;

var readEmailBodyFile = function(filename) {
  try {
    emailBody = fs.readFileSync(filename, {encoding: 'utf-8'});
    if (!emailBody) {
      return "The file containing the email body was empty.";
    }
  }
  catch (err) {
    return err.message;
  }
  return false;
};

var options = require('nomnom')
  .script('nodemailer')
  .option('service', {
    abbr: 't',
    help: 'The nodemailer service identifier, if any.'
  })
  .option('username', {
    abbr: 'u',
    default: process.env.USER,
    help: 'The SMTP username to use when authenticating.'
  })
  .option('password', {
    abbr: 'p',
    help: 'The plain-text password to use when authenticating.'
  })
  .option('server', {
    abbr: 's',
    help: 'The SMTP server that mail will be delivered to.'
  })
  .option('port', {
    abbr: 'r',
    default: process.env.SMTP_PORT || 465,
    help: 'The port to use when contacting the SMTP server.'
  })
  .option('nossl', {
    abbr: 'n',
    flag: true,
    help: 'If set, SSL will not be used when sending mail.'
  })
  .option('subject', {
    abbr: 'j',
    help: 'The string to be used as the email\'s subject.'
  })
  .option('cc', {
    help: 'An email address to Carbon Copy. List multiple recipients by appending multiple --cc parameters.',
    callback: validateEmails.bind(this, 'cc', true)
  })
  .option('bcc', {
    help: 'An email address to Blind Carbon Copy. List multiple recipients by appending multiple -bcc parameters.',
    callback: validateEmails.bind(this, 'bcc', true)
  })
  .option('replyTo', {
    help: 'An email address that should receive replies if a recipient replies to your message.',
    callback: validateEmails.bind(this, 'replyTo', false)
  })
  .option('body', {
    help: "A file to use as the message body.",
    callback: readEmailBodyFile
  })
  .option('attachment', {
    help: 'A path to a file that should be attached. List multiple attachments by appending multiple --attachment parameters.',
    list: true
  })
  .option('to', {
    position: 0,
    required: true,
    help: 'Email address, or comma separated list of email addresses to send mail to.',
    callback: validateEmails.bind(this, 'to', true)
  })
  .option('from', {
    position: 1,
    required: true,
    help: 'Email address that the message should be from.',
    callback: validateEmails.bind(this, 'from', false)
  })
  .option('bodyText', {
    position: 2,
    help: 'The plaintext message body.'
  })
  .option('version', {
    flag: true,
    help: 'print version and exit',
    callback: function() {
      var pkg = require('../package.json');
      var nodemailerPkg = require('nodemailer/package.json');
      return "version " + pkg.version + ", nodemailer: " + nodemailerPkg.version;
    }
  })
  .parse();

// we have a "no ssl" flag, so we need to invert it
options.useSSL = options.nossl ? false : true;

var Mailer = require('../lib').Mailer;
var mailer = new Mailer(options);

// build the mail data object
var data = {
  from: options.from,
  to: options.to,
  cc: options.cc,
  bcc: options.bcc,
  replyTo: options.replyTo,
  subject: options.subject,
  text: emailBody || options.bodyText,
  attachments: options.attachment ? options.attachment.map(function (attachment) { return { path: attachment }; }) : null
};

// nomnom won't allow this sort of logic, so we need to do it after the fact
if (!options.subject && !data.text) {
  console.error("ERROR: You must have at least a subject or a message body.");
  process.exit(1);
}

mailer.sendMail(data, function(err, result) {
  if (err) {
    console.error(err);
  }
  else {
    console.log("Sent successfully: " + result.response);
  }
});
<commit_msg>fixes listing cc and bcc parameters; adds abbreviation for version<commit_after>#!/usr/bin/env node

var fs = require('fs');
var validateEmails = require('../lib').validateEmails;

var emailBody = null;

var readEmailBodyFile = function(filename) {
  try {
    emailBody = fs.readFileSync(filename, {encoding: 'utf-8'});
    if (!emailBody) {
      return "The file containing the email body was empty.";
    }
  }
  catch (err) {
    return err.message;
  }
  return false;
};

var options = require('nomnom')
  .script('nodemailer')
  .option('service', {
    abbr: 't',
    help: 'The nodemailer service identifier, if any.'
  })
  .option('username', {
    abbr: 'u',
    default: process.env.USER,
    help: 'The SMTP username to use when authenticating.'
  })
  .option('password', {
    abbr: 'p',
    help: 'The plain-text password to use when authenticating.'
  })
  .option('server', {
    abbr: 's',
    help: 'The SMTP server that mail will be delivered to.'
  })
  .option('port', {
    abbr: 'r',
    default: process.env.SMTP_PORT || 465,
    help: 'The port to use when contacting the SMTP server.'
  })
  .option('nossl', {
    abbr: 'n',
    flag: true,
    help: 'If set, SSL will not be used when sending mail.'
  })
  .option('subject', {
    abbr: 'j',
    help: 'The string to be used as the email\'s subject.'
  })
  .option('cc', {
    help: 'An email address to Carbon Copy. List multiple recipients by appending multiple --cc parameters.',
    callback: validateEmails.bind(this, 'cc', true),
    list: true
  })
  .option('bcc', {
    help: 'An email address to Blind Carbon Copy. List multiple recipients by appending multiple -bcc parameters.',
    callback: validateEmails.bind(this, 'bcc', true),
    list: true
  })
  .option('replyTo', {
    help: 'An email address that should receive replies if a recipient replies to your message.',
    callback: validateEmails.bind(this, 'replyTo', false)
  })
  .option('body', {
    help: "A file to use as the message body.",
    callback: readEmailBodyFile
  })
  .option('attachment', {
    help: 'A path to a file that should be attached. List multiple attachments by appending multiple --attachment parameters.',
    list: true
  })
  .option('to', {
    position: 0,
    required: true,
    help: 'Email address, or comma separated list of email addresses to send mail to.',
    callback: validateEmails.bind(this, 'to', true)
  })
  .option('from', {
    position: 1,
    required: true,
    help: 'Email address that the message should be from.',
    callback: validateEmails.bind(this, 'from', false)
  })
  .option('bodyText', {
    position: 2,
    help: 'The plaintext message body.'
  })
  .option('version', {
    flag: true,
    help: 'print version and exit',
    abbr: 'v',
    callback: function() {
      var pkg = require('../package.json');
      var nodemailerPkg = require('nodemailer/package.json');
      return "version " + pkg.version + ", nodemailer: " + nodemailerPkg.version;
    }
  })
  .parse();

// we have a "no ssl" flag, so we need to invert it
options.useSSL = options.nossl ? false : true;

var Mailer = require('../lib').Mailer;
var mailer = new Mailer(options);

// build the mail data object
var data = {
  from: options.from,
  to: options.to,
  cc: options.cc,
  bcc: options.bcc,
  replyTo: options.replyTo,
  subject: options.subject,
  text: emailBody || options.bodyText,
  attachments: options.attachment ? options.attachment.map(function (attachment) { return { path: attachment }; }) : null
};

// nomnom won't allow this sort of logic, so we need to do it after the fact
if (!options.subject && !data.text) {
  console.error("ERROR: You must have at least a subject or a message body.");
  process.exit(1);
}

mailer.sendMail(data, function(err, result) {
  if (err) {
    console.error(err);
  }
  else {
    console.log("Sent successfully: " + result.response);
  }
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
var createTorrent = require('../')
var fs = require('fs')
var minimist = require('minimist')

var argv = minimist(process.argv.slice(2), {
  alias: {
    o: 'outfile',
    n: 'name',
    h: 'help'
  },
  boolean: [
    'help'
  ],
  string: [
    'outfile',
    'name',
    'creationDate',
    'comment',
    'createdBy',
    'announce',
    'urlList'
  ]
})

var infile = argv._[0]
var outfile = argv.outfile

if (!infile || argv.help) {
  console.log('usage: create-torrent <directory OR file> [OPTIONS]')
  console.log('')
  console.log('Create a torrent file from a directory or file.')
  console.log('')
  console.log('If an output file isn\'t specified with `-o`, the torrent file will be ')
  console.log('written to stdout.')
  console.log('')
  console.log('-o, --outfile    Output file. If not specified, stdout is used [string]')
  console.log('-n, --name       Torrent name [string]')
  console.log('--creationDate   Creation date [Date]')
  console.log('--comment        Torrent comment [string]')
  console.log('--createdBy      Created by client [string]')
  console.log('--private        Private torrent? [boolean] [default: false]')
  console.log('--pieceLength    Piece length [number] [default: reasonable length]')
  console.log('--announce       Tracker url [string] [default: reasonable trackers]')
  console.log('--urlList        Web seed url [string]')
  console.log('')
  process.exit(0)
}

createTorrent(infile, argv, function (err, torrent) {
  if (err) {
    console.error(err.stack)
    process.exit(1)
  } else if (outfile) {
    fs.writeFile(outfile, torrent, function (err) {
      if (err) {
        console.error(err.stack)
        process.exit(1)
      }
    })
  } else {
    process.stdout.write(torrent)
  }
})
<commit_msg>cmd: add -v/--version flags<commit_after>#!/usr/bin/env node
var createTorrent = require('../')
var fs = require('fs')
var minimist = require('minimist')

var argv = minimist(process.argv.slice(2), {
  alias: {
    o: 'outfile',
    n: 'name',
    h: 'help',
    v: 'version'
  },
  boolean: [
    'help',
    'version'
  ],
  string: [
    'outfile',
    'name',
    'creationDate',
    'comment',
    'createdBy',
    'announce',
    'urlList'
  ]
})

var infile = argv._[0]
var outfile = argv.outfile

if (argv.version) {
  console.log(require('../package.json').version)
  process.exit(0)
}

if (!infile || argv.help) {
  console.log('usage: create-torrent <directory OR file> [OPTIONS]')
  console.log('')
  console.log('Create a torrent file from a directory or file.')
  console.log('')
  console.log('If an output file isn\'t specified with `-o`, the torrent file will be ')
  console.log('written to stdout.')
  console.log('')
  console.log('-o, --outfile    Output file. If not specified, stdout is used [string]')
  console.log('-n, --name       Torrent name [string]')
  console.log('--creationDate   Creation date [Date]')
  console.log('--comment        Torrent comment [string]')
  console.log('--createdBy      Created by client [string]')
  console.log('--private        Private torrent? [boolean] [default: false]')
  console.log('--pieceLength    Piece length [number] [default: reasonable length]')
  console.log('--announce       Tracker url [string] [default: reasonable trackers]')
  console.log('--urlList        Web seed url [string]')
  console.log('')
  process.exit(0)
}

createTorrent(infile, argv, function (err, torrent) {
  if (err) {
    console.error(err.stack)
    process.exit(1)
  } else if (outfile) {
    fs.writeFile(outfile, torrent, function (err) {
      if (err) {
        console.error(err.stack)
        process.exit(1)
      }
    })
  } else {
    process.stdout.write(torrent)
  }
})
<|endoftext|>


<commit_before>#!/usr/bin/env node

var clivas = require('clivas')
var cp = require('child_process')
var fs = require('fs')
var minimist = require('minimist')
var moment = require('moment')
var networkAddress = require('network-address')
var path = require('path')
var prettysize = require('prettysize')
var WebTorrent = require('../')

process.title = 'WebTorrent'

process.on('exit', function (code) {
  if (code !== 0) {
    clivas.line('{red:ERROR:} If you think this is a bug in webtorrent, report it!')
    console.log('=====>                                               <=====')
    console.log('=====>  https://github.com/feross/webtorrent/issues  <=====')
    console.log('=====>                                               <=====')
  }
})

var argv = minimist(process.argv.slice(2), {
  alias: {
    p: 'port',
    b: 'blocklist',
    t: 'subtitles',
    l: 'list',
    i: 'index',
    o: 'out',
    q: 'quiet',
    h: 'help',
    v: 'version'
  },
  boolean: [ // options that are always boolean
    'airplay',
    'chromecast',
    'mplayer',
    'mpv',
    'vlc',
    'xbmc',
    'stdout',
    'list',
    'quiet',
    'help',
    'version'
  ],
  default: {
    port: 8000
  }
})

if (argv.version) {
  console.log(require('../package.json').version)
  return done()
}

var torrentId = argv._[0]

if (argv.help || !torrentId) {
  fs.readFileSync(path.join(__dirname, 'ascii-logo.txt'), 'utf8')
    .split('\n')
    .forEach(function (line) {
      clivas.line('{bold:' + line.substring(0, 20) + '}{red:' + line.substring(20) + '}')
    })

  console.log(function () {/*
  Usage:
      webtorrent <options> <torrent-uri>

      Download the torrent from:
          * magnet uri
          * http url to .torrent file
          * filesystem path to .torrent file
          * info hash (hex string)

  Streaming options:
      --airplay               Apple TV
      --chromecast            Chromecast
      --mplayer               MPlayer
      --mpv                   MPV
      --omx [jack]            omx [default: hdmi]
      --vlc                   VLC
      --xbmc                  XBMC
      --stdout                standard out (implies --quiet)

  Options:
      -o, --out [path]        set download destination [default: /tmp/webtorrent]
      -l, --list              list files in torrent (with indexes)
      -i, --index [index]     stream a particular file from torrent (by index)
      -p, --port [number]     change the http port [default: 8000]
      -b, --blocklist [path]  load blocklist file/http url
      -t, --subtitles [file]  load subtitles file
      -q, --quiet             don't show UI on stdout
      -v, --version           print the current version

  Please report bugs!  https://github.com/feross/webtorrent/issues

    */}.toString().split(/\n/).slice(1, -1).join('\n'))
  return done()
}

if (process.env.DEBUG || argv.stdout) {
  argv.quiet = argv.q = true
}

var VLC_ARGS = process.env.DEBUG
  ? '-q --play-and-exit'
  : '--play-and-exit --extraintf=http:logger --verbose=2 --file-logging --logfile=vlc-log.txt'
var MPLAYER_EXEC = 'mplayer -ontop -really-quiet -noidx -loop 0'
var MPV_EXEC = 'mpv --ontop --really-quiet --loop=no'
var OMX_EXEC = 'omxplayer -r -o ' + (typeof argv.omx === 'string')
  ? argv.omx
  : 'hdmi'

if (argv.subtitles) {
  VLC_ARGS += ' --sub-file=' + argv.subtitles
  MPLAYER_EXEC += ' -sub ' + argv.subtitles
  MPV_EXEC += ' --sub-file=' + argv.subtitles
  OMX_EXEC += ' --subtitles ' + argv.subtitles
}

function error (err) {
  clivas.line('{red:ERROR:} ' + (err.message || err))
}

function errorAndExit (err) {
  error(err)
  process.exit(1)
}

var started = Date.now()
function getRuntime () {
  return Math.floor((Date.now() - started) / 1000)
}

var client = new WebTorrent({
  blocklist: argv.blocklist
})
.on('error', errorAndExit)

if (!argv.out) { // If no output file has been specified
  process.on('SIGINT', remove)
  process.on('SIGTERM', remove)
}

function remove () {
  process.removeListener('SIGINT', remove)
  process.removeListener('SIGTERM', remove)

  // destroying can take a while, so print a message to the user
  clivas.line('')
  clivas.line('{green:webtorrent is exiting...}')

  client.destroy(process.exit)
}

var torrent = client.add(torrentId, (argv.out ? { tmp: argv.out } : {}))

torrent.on('infoHash', function () {
  function updateMetadata () {
    var numPeers = torrent.swarm.numPeers
    clivas.clear()
    clivas.line('{green:fetching torrent metadata from} {bold:'+numPeers+'} {green:peers}')
  }

  if (!argv.quiet && !argv.list) {
    torrent.swarm.on('wire', updateMetadata)
    torrent.on('metadata', function () {
      torrent.swarm.removeListener('wire', updateMetadata)
    })
    updateMetadata()
  }
})

var filename, swarm, wires, server, serving

if (argv.list) torrent.once('ready', onReady)
else {
  server = torrent.createServer()
  server.listen(argv.port, function () {
    if (torrent.ready) onReady()
    else torrent.once('ready', onReady)
  }).once('connection', function () {
    serving = true
  })
}

function done () {
  if (!serving) {
    process.exit(0)
  }
}

function onReady () {
  filename = torrent.name
  swarm = torrent.swarm
  wires = torrent.swarm.wires

  if (argv.list) {
    torrent.files.forEach(function (file, i) {
      clivas.line('{3+bold:'+i+'} : {magenta:'+file.name+'} {blue:('+bytes(file.length)+')}')
    })
    return done()
  }

  torrent.on('verifying', function (data) {
    if (argv.quiet) return
    clivas.clear()
    clivas.line(
      '{green:verifying existing torrent} {bold:'+Math.floor(data.percentDone)+'%} ' +
      '({bold:'+Math.floor(data.percentVerified)+'%} {green:passed verification})'
    )
  })

  torrent.on('done', function () {
    if (!argv.quiet) {
      // TODO: expose this data from bittorrent-swarm
      var numActiveWires = torrent.swarm.wires.reduce(function (num, wire) {
        return num + (wire.downloaded > 0)
      }, 0)
      clivas.line(
        'torrent downloaded {green:successfully} from ' +
        '{bold:'+numActiveWires+'/'+torrent.swarm.wires.length+'} {green:peers} ' +
        'in {bold:'+getRuntime()+'s}!'
      )
    }
    done()
  })

  var cmd, player
  var playerName = argv.airplay ? 'Airplay'
    : argv.chromecast ? 'Chromecast'
    : argv.xbmc ? 'XBMC'
    : argv.vlc ? 'VLC'
    : argv.mplayer ? 'MPlayer'
    : argv.mpv ? 'mpv'
    : argv.omx ? 'OMXPlayer'
    : null

  // if no index specified, use largest file
  var index = (typeof argv.index === 'number')
    ? argv.index
    : torrent.files.indexOf(torrent.files.reduce(function (a, b) {
      return a.length > b.length ? a : b
    }))
  var href = 'http://' + networkAddress() + ':' + argv.port + '/' + index

  if (playerName) torrent.files[index].select()
  if (argv.stdout) torrent.files[index].createReadStream().pipe(process.stdout)

  if (argv.vlc && process.platform === 'win32') {
    var registry = require('windows-no-runnable').registry
    var key
    if (process.arch === 'x64') {
      try {
        key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC')
      } catch (e) {}
    } else {
      try {
        key = registry('HKLM/Software/VideoLAN/VLC')
      } catch (err) {}
    }

    if (key) {
      var vlcPath = key.InstallDir.value + path.sep + 'vlc'
      VLC_ARGS = VLC_ARGS.split(' ')
      VLC_ARGS.unshift(href)
      cp.execFile(vlcPath, VLC_ARGS, function (err) {
        if (err) return errorAndExit(err)
        done()
      })
    }
  } else if (argv.vlc) {
    var root = '/Applications/VLC.app/Contents/MacOS/VLC'
    var home = (process.env.HOME || '') + root
    cmd = 'vlc ' + href + ' ' + VLC_ARGS + ' || ' +
      root + ' ' + href + ' ' + VLC_ARGS + ' || ' +
      home + ' ' + href + ' ' + VLC_ARGS
  } else if (argv.mplayer) {
    cmd = MPLAYER_EXEC + ' ' + href
  } else if (argv.mpv) {
    cmd = MPV_EXEC + ' ' + href
  } else if (argv.omx) {
    cmd = OMX_EXEC + ' ' + href
  }

  if (cmd) {
    player = cp.exec(cmd, function (err) {
      if (err) return errorAndExit(err)
      done()
    })
  }

  if (argv.airplay) {
    var airplay = require('airplay-js')
    airplay.createBrowser()
      .on('deviceOn', function (device) {
        device.play(href, 0, function () {})
      })
      .start()
    // TODO: handle case where user closes airplay. do same thing as when VLC is closed
  }

  if (argv.chromecast) {
    var chromecast = require('chromecast-js')
    new chromecast.Browser()
      .on('deviceOn', function (device) {
        device.connect()
        device.on('connected', function () {
          device.play(href)
        })
      })
  }

  if (argv.xbmc) {
    var xbmc = require('nodebmc')
    new xbmc.Browser()
      .on('deviceOn', function (device) {
          device.play(href, function () {})
      })
  }

  var hotswaps = 0
  torrent.on('hotswap', function () {
    hotswaps += 1
  })

  if (!argv.quiet) {
    process.stdout.write(new Buffer('G1tIG1sySg==', 'base64')) // clear for drawing

    setInterval(draw, 500)
  }

  function active (wire) {
    return !wire.peerChoking
  }

  function draw () {
    var unchoked = wires.filter(active)
    var linesremaining = clivas.height
    var peerslisted = 0
    var speed = swarm.downloadSpeed()
    var estimatedSecondsRemaining = Math.max(0, torrent.length - swarm.downloaded) / (speed > 0 ? speed : -1)
    var estimate = moment.duration(estimatedSecondsRemaining, 'seconds').humanize()

    clivas.clear()

    if (playerName)
      clivas.line('{green:Streaming to} {bold:' + playerName + '}')
    if (server)
      clivas.line('{green:server running at} {bold:' + href + '}')

    clivas.line('')
    clivas.line('{green:downloading:} {bold:' + filename + '}')
    clivas.line(
      '{green:speed: }{bold:' + bytes(speed) + '/s}  ' +
      '{green:downloaded:} {bold:' + bytes(swarm.downloaded) + '}' +
      '/{bold:' + bytes(torrent.length) + '}  ' +
      '{green:uploaded:} {bold:' + bytes(swarm.uploaded) + '}  ' +
      '{green:peers:} {bold:' + unchoked.length + '/' + wires.length + '}  ' +
      '{green:hotswaps:} {bold:' + hotswaps + '}'
    )
    clivas.line(
      '{green:time remaining:} {bold:' + estimate + ' remaining}  ' +
      '{green:total time:} {bold:' + getRuntime() + 's}  ' +
      '{green:queued peers:} {bold:' + swarm.numQueued + '}  ' +
      '{green:blocked:} {bold:' + torrent.numBlockedPeers + '}'
    )
    clivas.line('{80:}')
    linesremaining -= 8

    var pieces = torrent.storage.pieces
    var piecesBar = []
    for(var i = 0; i < pieces.length; i++) {
      var piece = pieces[i]
      if (piece.verified || piece.blocksWritten === 0) {
        continue;
      }
      var bar = ''
      for(var j = 0; j < piece.blocks.length; j++) {
        bar += piece.blocks[j] ? '{green:█}' : '{red:█}';
      }
      clivas.line('{4+cyan:' + i + '} ' + bar);
      linesremaining -= 1
    }
    clivas.line('{80:}')
    linesremaining -= 1

    wires.every(function (wire) {
      var progress = '?'
      if (torrent.parsedTorrent) {
        var bits = 0
        var piececount = Math.ceil(torrent.parsedTorrent.length / torrent.parsedTorrent.pieceLength)
        for(var i = 0; i < piececount; i++) {
          if (wire.peerPieces.get(i)) {
            bits++
          }
        }
        progress = bits === piececount ? 'S' : Math.floor(100 * bits / piececount) + '%'
      }
      var tags = []
      if (wire.peerChoking) tags.push('choked')
      var reqStats = wire.requests.map(function(req) {
          return req.piece;
      })
      clivas.line(
        '{3:' + progress + '} ' +
        '{25+magenta:' + wire.remoteAddress + '} {10:'+bytes(wire.downloaded)+'} ' +
        '{10+cyan:' + bytes(wire.downloadSpeed()) + '/s} ' +
        '{10+red:' + bytes(wire.uploadSpeed()) + '/s} ' +
        '{15+grey:' + tags.join(', ') + '}' +
        '{15+cyan:' + reqStats.join(' ') + '}'
      )
      peerslisted++
      return linesremaining - peerslisted > 4
    })
    linesremaining -= peerslisted

    if (wires.length > peerslisted) {
      clivas.line('{80:}')
      clivas.line('... and '+(wires.length - peerslisted)+' more')
    }

    clivas.line('{80:}')
    clivas.flush(true)
  }
}

function bytes (num) {
  return prettysize(num)
}
<commit_msg>use localhost when possible<commit_after>#!/usr/bin/env node

var clivas = require('clivas')
var cp = require('child_process')
var fs = require('fs')
var minimist = require('minimist')
var moment = require('moment')
var networkAddress = require('network-address')
var path = require('path')
var prettysize = require('prettysize')
var WebTorrent = require('../')

process.title = 'WebTorrent'

process.on('exit', function (code) {
  if (code !== 0) {
    clivas.line('{red:ERROR:} If you think this is a bug in webtorrent, report it!')
    console.log('=====>                                               <=====')
    console.log('=====>  https://github.com/feross/webtorrent/issues  <=====')
    console.log('=====>                                               <=====')
  }
})

var argv = minimist(process.argv.slice(2), {
  alias: {
    p: 'port',
    b: 'blocklist',
    t: 'subtitles',
    l: 'list',
    i: 'index',
    o: 'out',
    q: 'quiet',
    h: 'help',
    v: 'version'
  },
  boolean: [ // options that are always boolean
    'airplay',
    'chromecast',
    'mplayer',
    'mpv',
    'vlc',
    'xbmc',
    'stdout',
    'list',
    'quiet',
    'help',
    'version'
  ],
  default: {
    port: 8000
  }
})

if (argv.version) {
  console.log(require('../package.json').version)
  return done()
}

var torrentId = argv._[0]

if (argv.help || !torrentId) {
  fs.readFileSync(path.join(__dirname, 'ascii-logo.txt'), 'utf8')
    .split('\n')
    .forEach(function (line) {
      clivas.line('{bold:' + line.substring(0, 20) + '}{red:' + line.substring(20) + '}')
    })

  console.log(function () {/*
  Usage:
      webtorrent <options> <torrent-uri>

      Download the torrent from:
          * magnet uri
          * http url to .torrent file
          * filesystem path to .torrent file
          * info hash (hex string)

  Streaming options:
      --airplay               Apple TV
      --chromecast            Chromecast
      --mplayer               MPlayer
      --mpv                   MPV
      --omx [jack]            omx [default: hdmi]
      --vlc                   VLC
      --xbmc                  XBMC
      --stdout                standard out (implies --quiet)

  Options:
      -o, --out [path]        set download destination [default: /tmp/webtorrent]
      -l, --list              list files in torrent (with indexes)
      -i, --index [index]     stream a particular file from torrent (by index)
      -p, --port [number]     change the http port [default: 8000]
      -b, --blocklist [path]  load blocklist file/http url
      -t, --subtitles [file]  load subtitles file
      -q, --quiet             don't show UI on stdout
      -v, --version           print the current version

  Please report bugs!  https://github.com/feross/webtorrent/issues

    */}.toString().split(/\n/).slice(1, -1).join('\n'))
  return done()
}

if (process.env.DEBUG || argv.stdout) {
  argv.quiet = argv.q = true
}

var VLC_ARGS = process.env.DEBUG
  ? '-q --play-and-exit'
  : '--play-and-exit --extraintf=http:logger --verbose=2 --file-logging --logfile=vlc-log.txt'
var MPLAYER_EXEC = 'mplayer -ontop -really-quiet -noidx -loop 0'
var MPV_EXEC = 'mpv --ontop --really-quiet --loop=no'
var OMX_EXEC = 'omxplayer -r -o ' + (typeof argv.omx === 'string')
  ? argv.omx
  : 'hdmi'

if (argv.subtitles) {
  VLC_ARGS += ' --sub-file=' + argv.subtitles
  MPLAYER_EXEC += ' -sub ' + argv.subtitles
  MPV_EXEC += ' --sub-file=' + argv.subtitles
  OMX_EXEC += ' --subtitles ' + argv.subtitles
}

function error (err) {
  clivas.line('{red:ERROR:} ' + (err.message || err))
}

function errorAndExit (err) {
  error(err)
  process.exit(1)
}

var started = Date.now()
function getRuntime () {
  return Math.floor((Date.now() - started) / 1000)
}

var client = new WebTorrent({
  blocklist: argv.blocklist
})
.on('error', errorAndExit)

if (!argv.out) { // If no output file has been specified
  process.on('SIGINT', remove)
  process.on('SIGTERM', remove)
}

function remove () {
  process.removeListener('SIGINT', remove)
  process.removeListener('SIGTERM', remove)

  // destroying can take a while, so print a message to the user
  clivas.line('')
  clivas.line('{green:webtorrent is exiting...}')

  client.destroy(process.exit)
}

var torrent = client.add(torrentId, (argv.out ? { tmp: argv.out } : {}))

torrent.on('infoHash', function () {
  function updateMetadata () {
    var numPeers = torrent.swarm.numPeers
    clivas.clear()
    clivas.line('{green:fetching torrent metadata from} {bold:'+numPeers+'} {green:peers}')
  }

  if (!argv.quiet && !argv.list) {
    torrent.swarm.on('wire', updateMetadata)
    torrent.on('metadata', function () {
      torrent.swarm.removeListener('wire', updateMetadata)
    })
    updateMetadata()
  }
})

var filename, swarm, wires, server, serving

if (argv.list) torrent.once('ready', onReady)
else {
  server = torrent.createServer()
  server.listen(argv.port, function () {
    if (torrent.ready) onReady()
    else torrent.once('ready', onReady)
  }).once('connection', function () {
    serving = true
  })
}

function done () {
  if (!serving) {
    process.exit(0)
  }
}

function onReady () {
  filename = torrent.name
  swarm = torrent.swarm
  wires = torrent.swarm.wires

  if (argv.list) {
    torrent.files.forEach(function (file, i) {
      clivas.line('{3+bold:'+i+'} : {magenta:'+file.name+'} {blue:('+bytes(file.length)+')}')
    })
    return done()
  }

  torrent.on('verifying', function (data) {
    if (argv.quiet) return
    clivas.clear()
    clivas.line(
      '{green:verifying existing torrent} {bold:'+Math.floor(data.percentDone)+'%} ' +
      '({bold:'+Math.floor(data.percentVerified)+'%} {green:passed verification})'
    )
  })

  torrent.on('done', function () {
    if (!argv.quiet) {
      // TODO: expose this data from bittorrent-swarm
      var numActiveWires = torrent.swarm.wires.reduce(function (num, wire) {
        return num + (wire.downloaded > 0)
      }, 0)
      clivas.line(
        'torrent downloaded {green:successfully} from ' +
        '{bold:'+numActiveWires+'/'+torrent.swarm.wires.length+'} {green:peers} ' +
        'in {bold:'+getRuntime()+'s}!'
      )
    }
    done()
  })

  var cmd, player
  var playerName = argv.airplay ? 'Airplay'
    : argv.chromecast ? 'Chromecast'
    : argv.xbmc ? 'XBMC'
    : argv.vlc ? 'VLC'
    : argv.mplayer ? 'MPlayer'
    : argv.mpv ? 'mpv'
    : argv.omx ? 'OMXPlayer'
    : null

  // if no index specified, use largest file
  var index = (typeof argv.index === 'number')
    ? argv.index
    : torrent.files.indexOf(torrent.files.reduce(function (a, b) {
      return a.length > b.length ? a : b
    }))
  var href = 'http://' + networkAddress() + ':' + argv.port + '/' + index
  var localHref = 'http://localhost:' + argv.port + '/' + index

  if (playerName) torrent.files[index].select()
  if (argv.stdout) torrent.files[index].createReadStream().pipe(process.stdout)

  if (argv.vlc && process.platform === 'win32') {
    var registry = require('windows-no-runnable').registry
    var key
    if (process.arch === 'x64') {
      try {
        key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC')
      } catch (e) {}
    } else {
      try {
        key = registry('HKLM/Software/VideoLAN/VLC')
      } catch (err) {}
    }

    if (key) {
      var vlcPath = key.InstallDir.value + path.sep + 'vlc'
      VLC_ARGS = VLC_ARGS.split(' ')
      VLC_ARGS.unshift(localHref)
      cp.execFile(vlcPath, VLC_ARGS, function (err) {
        if (err) return errorAndExit(err)
        done()
      })
    }
  } else if (argv.vlc) {
    var root = '/Applications/VLC.app/Contents/MacOS/VLC'
    var home = (process.env.HOME || '') + root
    cmd = 'vlc ' + localHref + ' ' + VLC_ARGS + ' || ' +
      root + ' ' + localHref + ' ' + VLC_ARGS + ' || ' +
      home + ' ' + localHref + ' ' + VLC_ARGS
  } else if (argv.mplayer) {
    cmd = MPLAYER_EXEC + ' ' + localHref
  } else if (argv.mpv) {
    cmd = MPV_EXEC + ' ' + localHref
  } else if (argv.omx) {
    cmd = OMX_EXEC + ' ' + localHref
  }

  if (cmd) {
    player = cp.exec(cmd, function (err) {
      if (err) return errorAndExit(err)
      done()
    })
  }

  if (argv.airplay) {
    var airplay = require('airplay-js')
    airplay.createBrowser()
      .on('deviceOn', function (device) {
        device.play(href, 0, function () {})
      })
      .start()
    // TODO: handle case where user closes airplay. do same thing as when VLC is closed
  }

  if (argv.chromecast) {
    var chromecast = require('chromecast-js')
    new chromecast.Browser()
      .on('deviceOn', function (device) {
        device.connect()
        device.on('connected', function () {
          device.play(href)
        })
      })
  }

  if (argv.xbmc) {
    var xbmc = require('nodebmc')
    new xbmc.Browser()
      .on('deviceOn', function (device) {
          device.play(href, function () {})
      })
  }

  var hotswaps = 0
  torrent.on('hotswap', function () {
    hotswaps += 1
  })

  if (!argv.quiet) {
    process.stdout.write(new Buffer('G1tIG1sySg==', 'base64')) // clear for drawing

    setInterval(draw, 500)
  }

  function active (wire) {
    return !wire.peerChoking
  }

  function draw () {
    var unchoked = wires.filter(active)
    var linesremaining = clivas.height
    var peerslisted = 0
    var speed = swarm.downloadSpeed()
    var estimatedSecondsRemaining = Math.max(0, torrent.length - swarm.downloaded) / (speed > 0 ? speed : -1)
    var estimate = moment.duration(estimatedSecondsRemaining, 'seconds').humanize()

    clivas.clear()

    if (playerName)
      clivas.line('{green:Streaming to} {bold:' + playerName + '}')
    if (server)
      clivas.line('{green:server running at} {bold:' + href + '}')

    clivas.line('')
    clivas.line('{green:downloading:} {bold:' + filename + '}')
    clivas.line(
      '{green:speed: }{bold:' + bytes(speed) + '/s}  ' +
      '{green:downloaded:} {bold:' + bytes(swarm.downloaded) + '}' +
      '/{bold:' + bytes(torrent.length) + '}  ' +
      '{green:uploaded:} {bold:' + bytes(swarm.uploaded) + '}  ' +
      '{green:peers:} {bold:' + unchoked.length + '/' + wires.length + '}  ' +
      '{green:hotswaps:} {bold:' + hotswaps + '}'
    )
    clivas.line(
      '{green:time remaining:} {bold:' + estimate + ' remaining}  ' +
      '{green:total time:} {bold:' + getRuntime() + 's}  ' +
      '{green:queued peers:} {bold:' + swarm.numQueued + '}  ' +
      '{green:blocked:} {bold:' + torrent.numBlockedPeers + '}'
    )
    clivas.line('{80:}')
    linesremaining -= 8

    var pieces = torrent.storage.pieces
    for(var i = 0; i < pieces.length; i++) {
      var piece = pieces[i]
      if (piece.verified || piece.blocksWritten === 0) {
        continue;
      }
      var bar = ''
      for(var j = 0; j < piece.blocks.length; j++) {
        bar += piece.blocks[j] ? '{green:█}' : '{red:█}';
      }
      clivas.line('{4+cyan:' + i + '} ' + bar);
      linesremaining -= 1
    }
    clivas.line('{80:}')
    linesremaining -= 1

    wires.every(function (wire) {
      var progress = '?'
      if (torrent.parsedTorrent) {
        var bits = 0
        var piececount = Math.ceil(torrent.parsedTorrent.length / torrent.parsedTorrent.pieceLength)
        for(var i = 0; i < piececount; i++) {
          if (wire.peerPieces.get(i)) {
            bits++
          }
        }
        progress = bits === piececount ? 'S' : Math.floor(100 * bits / piececount) + '%'
      }
      var tags = []
      if (wire.peerChoking) tags.push('choked')
      var reqStats = wire.requests.map(function(req) {
          return req.piece;
      })
      clivas.line(
        '{3:' + progress + '} ' +
        '{25+magenta:' + wire.remoteAddress + '} {10:'+bytes(wire.downloaded)+'} ' +
        '{10+cyan:' + bytes(wire.downloadSpeed()) + '/s} ' +
        '{10+red:' + bytes(wire.uploadSpeed()) + '/s} ' +
        '{15+grey:' + tags.join(', ') + '}' +
        '{15+cyan:' + reqStats.join(' ') + '}'
      )
      peerslisted++
      return linesremaining - peerslisted > 4
    })
    linesremaining -= peerslisted

    if (wires.length > peerslisted) {
      clivas.line('{80:}')
      clivas.line('... and '+(wires.length - peerslisted)+' more')
    }

    clivas.line('{80:}')
    clivas.flush(true)
  }
}

function bytes (num) {
  return prettysize(num)
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var argv = require('optimist').argv;
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var dataDir = path.resolve(process.env.HOME || process.env.USERPROFILE, '.config/stream-adventure');
mkdirp.sync(dataDir);

var showMenu = require('./menu.js');
var verify = require('./verify.js');
var order = require('../data/order.json');

if (argv.h || argv.help || argv._[0] === 'help') {
    return fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
}

if (argv._[0] === 'list') {
    order.forEach(function (name) {
        console.log(name);
    });
    return;
}

if (argv._[0] === 'current') {
    var current = getData('current');
    console.log(current);
    return;
}

if (argv._[0] === 'select') {
    return onselect(argv._.slice(1).join(' '));
}

if (argv._[0] === 'verify' || argv._[0] === 'run') {
    var current = getData('current');
    if (!current) {
        console.error('ERROR: No active problem. '
            + 'Select a challenge from the menu.'
        );
        return process.exit(1);
    }
    var dir = dirFromName(current);
    var setup = require(dir + '/setup.js')({ run: argv._[0] === 'run' });
    setTimeout(function () {
        var a = argv._.slice(1)
            .concat(setup.aArgs || setup.args || [])
        ;
        var b = [ dir + '/solution.js' ]
            .concat(setup.bArgs || setup.args || [])
        ;
        var v = verify(a, b, {
            a: setup.a,
            b: setup.b,
            showStdout: setup.showStdout,
            long: setup.long,
            run: argv._[0] === 'run'
        });
        v.on('pass', onpass);
        v.on('fail', onfail);

        if (setup.stdin) {
            setup.stdin.pipe(v);
            setup.stdin.resume();
        }

        if (setup.a) setup.a.resume();
        if (setup.b) setup.b.resume();
    }, setup.wait || 1);

    function onpass () {
        console.log('# PASS');
        console.log('\nYour solution to ' + current + ' passed!');
        console.log(
            '\nHere\'s what the official solution'
            + ' is if you want to compare notes:\n'
        );
        var src = fs.readFileSync(path.join(dir, 'solution.js'), 'utf8');
        src.split('\n').forEach(function (line) {
            console.log('    ' + line);
        });

        updateData('completed', function (xs) {
            if (!xs) xs = [];
            var ix = xs.indexOf(current);
            return ix >= 0 ? xs : xs.concat(current);
        });

        var completed = getData('completed') || [];

        var remaining = order.length - completed.length;
        if (remaining === 0) {
            console.log("You've finished all the challenges! Hooray!\n");
        }
        else {
            console.log('You have ' + remaining + ' challenges left.');
            console.log('Type `stream-adventure` to show the menu.\n');
        }

        if (setup.close) setup.close();
    }

    function onfail () {
        if (setup.close) setup.close();

        console.log('# FAIL');
        console.log(
            "\nYour solution didn't match the expected output."
            + ' Try again, or run `stream-adventure run program.js` to see your solution\'s output.'
        );
    }
}
else {
  var opts = {
    completed: getData('completed') || []
  };

  if (argv.b || argv.bg){
    opts.bg = argv.b || argv.bg;
  }

  if (argv.f || argv.fg){
    opts.fg = argv.f || argv.fg;
  }

  var menu = showMenu(opts);

  menu.on('select', onselect);
  menu.on('exit', function () {
      console.log();
      process.exit(0);
  });
}

function onselect (name) {
    console.log('\n  ' + Array(70).join('#'));
    console.log(center('~~  ' + name + '  ~~'));
    console.log('  ' + Array(70).join('#') + '\n');

    var dir = dirFromName(name);
    var file = path.resolve(dir, 'problem.txt');
    updateData('current', function (c) { return name });
    var rs = fs.createReadStream(file);
    rs.on('close', function () {
        console.log(
            '\nTo verify your program, run: '
            + '`stream-adventure verify program.js`.\n'
        );
    });
    rs.pipe(process.stdout);
}

function updateData (name, fn) {
    var json = {};
    try { json = getData(name) }
    catch (e) {}
    var file = path.resolve(dataDir, name + '.json');
    fs.writeFileSync(file, JSON.stringify(fn(json)));
}

function getData (name) {
    var file = path.resolve(dataDir, name + '.json');
    try { return JSON.parse(fs.readFileSync(file, 'utf8')) }
    catch (e) {}
    return null;
}

function dirFromName (name) {
    return path.resolve(__dirname, '../problems/'
        + name.toLowerCase().replace(/\s/g, '_')
    );
}

function center (s) {
    var n = (67 - s.length) / 2;
    return '  ##' + Array(Math.floor(n)).join(' ')
        + s + Array(Math.ceil(n)).join(' ') + '##'
    ;
}
<commit_msg>add a newline<commit_after>#!/usr/bin/env node
var argv = require('optimist').argv;
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var dataDir = path.resolve(process.env.HOME || process.env.USERPROFILE, '.config/stream-adventure');
mkdirp.sync(dataDir);

var showMenu = require('./menu.js');
var verify = require('./verify.js');
var order = require('../data/order.json');

if (argv.h || argv.help || argv._[0] === 'help') {
    return fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
}

if (argv._[0] === 'list') {
    order.forEach(function (name) {
        console.log(name);
    });
    return;
}

if (argv._[0] === 'current') {
    var current = getData('current');
    console.log(current);
    return;
}

if (argv._[0] === 'select') {
    return onselect(argv._.slice(1).join(' '));
}

if (argv._[0] === 'verify' || argv._[0] === 'run') {
    var current = getData('current');
    if (!current) {
        console.error('ERROR: No active problem. '
            + 'Select a challenge from the menu.'
        );
        return process.exit(1);
    }
    var dir = dirFromName(current);
    var setup = require(dir + '/setup.js')({ run: argv._[0] === 'run' });
    setTimeout(function () {
        var a = argv._.slice(1)
            .concat(setup.aArgs || setup.args || [])
        ;
        var b = [ dir + '/solution.js' ]
            .concat(setup.bArgs || setup.args || [])
        ;
        var v = verify(a, b, {
            a: setup.a,
            b: setup.b,
            showStdout: setup.showStdout,
            long: setup.long,
            run: argv._[0] === 'run'
        });
        v.on('pass', onpass);
        v.on('fail', onfail);

        if (setup.stdin) {
            setup.stdin.pipe(v);
            setup.stdin.resume();
        }

        if (setup.a) setup.a.resume();
        if (setup.b) setup.b.resume();
    }, setup.wait || 1);

    function onpass () {
        console.log('# PASS');
        console.log('\nYour solution to ' + current + ' passed!');
        console.log(
            '\nHere\'s what the official solution'
            + ' is if you want to compare notes:\n'
        );
        var src = fs.readFileSync(path.join(dir, 'solution.js'), 'utf8');
        src.split('\n').forEach(function (line) {
            console.log('    ' + line);
        });

        updateData('completed', function (xs) {
            if (!xs) xs = [];
            var ix = xs.indexOf(current);
            return ix >= 0 ? xs : xs.concat(current);
        });

        var completed = getData('completed') || [];

        var remaining = order.length - completed.length;
        if (remaining === 0) {
            console.log("You've finished all the challenges! Hooray!\n");
        }
        else {
            console.log('You have ' + remaining + ' challenges left.');
            console.log('Type `stream-adventure` to show the menu.\n');
        }

        if (setup.close) setup.close();
    }

    function onfail () {
        if (setup.close) setup.close();

        console.log('# FAIL');
        console.log(
            "\nYour solution didn't match the expected output."
            + '\nTry again, or run `stream-adventure run program.js`'
            + ' to see your solution\'s output.'
        );
    }
}
else {
  var opts = {
    completed: getData('completed') || []
  };

  if (argv.b || argv.bg){
    opts.bg = argv.b || argv.bg;
  }

  if (argv.f || argv.fg){
    opts.fg = argv.f || argv.fg;
  }

  var menu = showMenu(opts);

  menu.on('select', onselect);
  menu.on('exit', function () {
      console.log();
      process.exit(0);
  });
}

function onselect (name) {
    console.log('\n  ' + Array(70).join('#'));
    console.log(center('~~  ' + name + '  ~~'));
    console.log('  ' + Array(70).join('#') + '\n');

    var dir = dirFromName(name);
    var file = path.resolve(dir, 'problem.txt');
    updateData('current', function (c) { return name });
    var rs = fs.createReadStream(file);
    rs.on('close', function () {
        console.log(
            '\nTo verify your program, run: '
            + '`stream-adventure verify program.js`.\n'
        );
    });
    rs.pipe(process.stdout);
}

function updateData (name, fn) {
    var json = {};
    try { json = getData(name) }
    catch (e) {}
    var file = path.resolve(dataDir, name + '.json');
    fs.writeFileSync(file, JSON.stringify(fn(json)));
}

function getData (name) {
    var file = path.resolve(dataDir, name + '.json');
    try { return JSON.parse(fs.readFileSync(file, 'utf8')) }
    catch (e) {}
    return null;
}

function dirFromName (name) {
    return path.resolve(__dirname, '../problems/'
        + name.toLowerCase().replace(/\s/g, '_')
    );
}

function center (s) {
    var n = (67 - s.length) / 2;
    return '  ##' + Array(Math.floor(n)).join(' ')
        + s + Array(Math.ceil(n)).join(' ') + '##'
    ;
}
<|endoftext|>


<commit_before>#!/usr/bin/env node

/* eslint-env node */

// Sub options for dev command
exports.builder = {
  e: {
    alias: 'environment',
    type: 'string',
    choices: ['development', 'testing', 'production'],
    describe: 'environment setting'
  },
  p: {
    alias: 'port',
    type: 'number',
    describe: 'server port to listen on'
  },
  dt: {
    alias: 'devtool',
    type: 'string',
    describe: 'webpack performance build'
  },
  sr: {
    alias: 'single-run',
    default: true,
    type: 'boolean',
    describe: 'testing single run'
  }
}

// dev command function
exports.handler = function (yargs) {
  var projectRoot = process.cwd()
  var Webpack = require('webpack')
  var WebpackDevServer = require(projectRoot + '/node_modules/webpack-dev-server/lib/Server.js')
  var webpackHotMiddleware = require('webpack-hot-middleware')
  var chalk = require('chalk')
  var ProgressBarPlugin = require('progress-bar-webpack-plugin')
  var fs = require('fs')

  // Check environment if yargs is passed set environment
  process.env.NODE_ENV = process.env.NODE_ENV || 'development'
  process.env.ENVIRONMENT = process.env.ENVIRONMENT || 'development'
  if (yargs.environment) {
    process.env.ENVIRONMENT = yargs.environment
  }

  // Set port in order of importance - fallback is 8080
  var port = process.env.E2E_PORT || yargs.port || process.env.PORT || webpackConfig.devServer.port || 8080

  // Overwrite devtool
  var devtool = yargs.devtool || false
  if (devtool) { webpackConfig.devtool = devtool }

  // Check if there is a server.js file in the test folder
  var pathToServer = projectRoot + '/test/server.js'
  try {
    fs.statSync(pathToServer)
  } catch (err) { pathToServer = false }

  // Load webpack config file
  var webpackConfig = require('./config/webpack.dev.config.js')

  // Add progress bar to webpack config
  webpackConfig.plugins.push(new ProgressBarPlugin({
    format: 'Building [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)',
    callback: function () {
      if (process.env.ENVIRONMENT !== 'production') {
        console.log(chalk.blue('Dev server started'))
        console.log(chalk.blue('http://localhost:' + port + '.....PID:' + process.pid))
      }
    }
  }))

  var compiler = Webpack(webpackConfig)
  var server = new WebpackDevServer(compiler, Object.assign({}, {
    stats: {
      colors: true
    },
    setup: function (app) {
      app.use(function (req, res, next) {
        if (process.env.ENVIRONMENT === 'development') {
          console.log('Using middleware for ' + req.url)
        }
        next()
      })

      // Add webpack hot middleware to use for error overlay
      // Quiet is set to true because well let WebpackDevServer handle console logging
      app.use(webpackHotMiddleware(compiler, {
        overlay: true,
        quiet: true
      }))

      // If there is a server.js file load it and pass app to it
      if (pathToServer) {
        require(pathToServer)(app)
      }
    }
  }, webpackConfig.devServer))

  var serverListen = server.listen(port, 'localhost', function () {})

  return {
    compiler: compiler,
    server: serverListen
  }
}
<commit_msg>dev - removed devserver port<commit_after>#!/usr/bin/env node

/* eslint-env node */

// Sub options for dev command
exports.builder = {
  e: {
    alias: 'environment',
    type: 'string',
    choices: ['development', 'testing', 'production'],
    describe: 'environment setting'
  },
  p: {
    alias: 'port',
    type: 'number',
    describe: 'server port to listen on'
  },
  dt: {
    alias: 'devtool',
    type: 'string',
    describe: 'webpack performance build'
  },
  sr: {
    alias: 'single-run',
    default: true,
    type: 'boolean',
    describe: 'testing single run'
  }
}

// dev command function
exports.handler = function (yargs) {
  var projectRoot = process.cwd()
  var Webpack = require('webpack')
  var WebpackDevServer = require(projectRoot + '/node_modules/webpack-dev-server/lib/Server.js')
  var webpackHotMiddleware = require('webpack-hot-middleware')
  var chalk = require('chalk')
  var ProgressBarPlugin = require('progress-bar-webpack-plugin')
  var fs = require('fs')

  // Check environment if yargs is passed set environment
  process.env.NODE_ENV = process.env.NODE_ENV || 'development'
  process.env.ENVIRONMENT = process.env.ENVIRONMENT || 'development'
  if (yargs.environment) {
    process.env.ENVIRONMENT = yargs.environment
  }

  // Set port in order of importance - fallback is 8080
  var port = process.env.E2E_PORT || yargs.port || process.env.PORT || 8080

  // Overwrite devtool
  var devtool = yargs.devtool || false
  if (devtool) { webpackConfig.devtool = devtool }

  // Check if there is a server.js file in the test folder
  var pathToServer = projectRoot + '/test/server.js'
  try {
    fs.statSync(pathToServer)
  } catch (err) { pathToServer = false }

  // Load webpack config file
  var webpackConfig = require('./config/webpack.dev.config.js')

  // Add progress bar to webpack config
  webpackConfig.plugins.push(new ProgressBarPlugin({
    format: 'Building [:bar] ' + chalk.green.bold(':percent') + ' (:elapsed seconds)',
    callback: function () {
      if (process.env.ENVIRONMENT !== 'production') {
        console.log(chalk.blue('Dev server started'))
        console.log(chalk.blue('http://localhost:' + port + '.....PID:' + process.pid))
      }
    }
  }))

  var compiler = Webpack(webpackConfig)
  var server = new WebpackDevServer(compiler, Object.assign({}, {
    stats: {
      colors: true
    },
    setup: function (app) {
      app.use(function (req, res, next) {
        if (process.env.ENVIRONMENT === 'development') {
          console.log('Using middleware for ' + req.url)
        }
        next()
      })

      // Add webpack hot middleware to use for error overlay
      // Quiet is set to true because well let WebpackDevServer handle console logging
      app.use(webpackHotMiddleware(compiler, {
        overlay: true,
        quiet: true
      }))

      // If there is a server.js file load it and pass app to it
      if (pathToServer) {
        require(pathToServer)(app)
      }
    }
  }, webpackConfig.devServer))

  var serverListen = server.listen(port, 'localhost', function () {})

  return {
    compiler: compiler,
    server: serverListen
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

const spawn = require('cross-spawn')
const glob = require('glob')
const fs = require('fs')
const path = require('path')
const { prompt } = require('inquirer')

let packageName = process.argv[2]
let command = process.argv[3]
const args = process.argv.slice(4)

const useYarn = fs.existsSync('../yarn.lock')

const lernaJson = requireIfExist('../lerna.json')

const packagePaths = ['node_modules/*'].concat(lernaJson && lernaJson.packages ? lernaJson.packages : [])

const packages = packagePaths.map(packagePath =>
  glob.sync(packagePath).reduce((result, packageFolder) => {
    const packageJson = requireIfExist(`../${packageFolder}/package.json`)
    if (!packageJson || !packageJson['rispa:plugin']) {
      return result
    }

    const name = packageJson['name']
    const rispaName = packageJson['rispa:name']

    if (packageName === 'all' && !(packageJson.scripts && command in packageJson.scripts)) {
      return result
    }

    const packageInfo = {
      path: packageFolder,
      alias: rispaName,
      name: name,
      commands: Object.keys(packageJson.scripts)
    }

    if (rispaName) {
      result[rispaName] = packageInfo
    }

    result[packageInfo.name] = packageInfo

    return result
  }, {})
).reduce((result, currentResult) => Object.assign(result, currentResult))

if (packageName === 'all') {
  const result = callScriptList(packages, command, args)
  process.exit(result)
} else if (!packages[packageName]) {
  console.log(`Can't find package with name: ${packageName}.\n`)

  selectPackage(packages).then(async ({ packageName }) => {
    const packageInfo = packages[packageName]

    const { command } = await selectCommand(packageInfo.commands)

    const result = callScript(packages[packageName], command, args)
    process.exit(result)
  }).catch(e => {
    console.log(e)
    process.exit(1)
  });
} else {
  const result = callScript(packages[packageName], command, args)
  process.exit(result)
}

function selectPackage(packages) {
  return prompt([{
    type: 'list',
    name: 'packageName',
    message: 'Select available package:',
    paginated: true,
    choices: [...new Set(Object.keys(packages).map((key) => packages[key]))]
  }])
}

function selectCommand(commands) {
  return prompt([{
    type: 'list',
    name: 'command',
    message: 'Select available command:',
    paginated: true,
    choices: commands
  }])
}

function callScriptList(packages, command, args) {
  return Object.values(packages)
    .reduce((result, packageInfo) => callScript(packageInfo, command, args) || result, 0)
}

function callScript(packageInfo, command, args) {
  return spawn.sync(
    useYarn ? 'yarn' : "npm",
    [...(useYarn ? [] : ["run"]), command].concat(args),
    {
      cwd: packageInfo.path,
      stdio: 'inherit',
    }
  ).status
}

function requireIfExist(id) {
  try {
    return require(id)
  } catch (e) {
    if (e instanceof Error && e.code === 'MODULE_NOT_FOUND') {
      return null
    }
    throw e;
  }
}
<commit_msg>handle error if can't find packages, fix npm\yarn choise run scripts<commit_after>#!/usr/bin/env node
'use strict';

const spawn = require('cross-spawn')
const glob = require('glob')
const fs = require('fs')
const path = require('path')
const { prompt } = require('inquirer')

let packageName = process.argv[2]
let command = process.argv[3]
const args = process.argv.slice(4)

const useYarn = fs.existsSync('./yarn.lock')

const lernaJson = requireIfExist('../lerna.json')

const packagePaths = ['node_modules/*'].concat(lernaJson && lernaJson.packages ? lernaJson.packages : [])

const packages = packagePaths.map(packagePath =>
  glob.sync(packagePath).reduce((result, packageFolder) => {
    const packageJson = requireIfExist(`../${packageFolder}/package.json`)
    if (!packageJson || !packageJson['rispa:plugin']) {
      return result
    }

    const name = packageJson['name']
    const rispaName = packageJson['rispa:name']

    if (packageName === 'all' && !(packageJson.scripts && command in packageJson.scripts)) {
      return result
    }

    const packageInfo = {
      path: packageFolder,
      alias: rispaName,
      name: name,
      commands: Object.keys(packageJson.scripts)
    }

    if (rispaName) {
      result[rispaName] = packageInfo
    }

    result[packageInfo.name] = packageInfo

    return result
  }, {})
).reduce((result, currentResult) => Object.assign(result, currentResult))

if (!Object.keys(packages).length) {
  console.log(`Can't find packages.`)
  process.exit(1)
} else if (packageName === 'all') {
  const result = callScriptList(packages, command, args)
  process.exit(result)
} else if (!packages[packageName]) {
  console.log(`Can't find package with name: ${packageName}.\n`)

  selectPackage(packages).then(async ({ packageName }) => {
    const packageInfo = packages[packageName]

    const { command } = await selectCommand(packageInfo.commands)

    const result = callScript(packages[packageName], command, args)
    process.exit(result)
  }).catch(e => {
    console.log(e)
    process.exit(1)
  });
} else {
  const result = callScript(packages[packageName], command, args)
  process.exit(result)
}

function selectPackage(packages) {
  return prompt([{
    type: 'list',
    name: 'packageName',
    message: 'Select available package:',
    paginated: true,
    choices: [...new Set(Object.keys(packages).map(key => packages[key].name))]
  }])
}

function selectCommand(commands) {
  return prompt([{
    type: 'list',
    name: 'command',
    message: 'Select available command:',
    paginated: true,
    choices: commands
  }])
}

function callScriptList(packages, command, args) {
  return Object.values(packages)
    .reduce((result, packageInfo) => callScript(packageInfo, command, args) || result, 0)
}

function callScript(packageInfo, command, args) {
  return spawn.sync(
    useYarn ? 'yarn' : 'npm',
    [...(useYarn ? [] : ['run']), command].concat(args),
    {
      cwd: packageInfo.path,
      stdio: 'inherit',
    }
  ).status
}

function requireIfExist(id) {
  try {
    return require(id)
  } catch (e) {
    if (e instanceof Error && e.code === 'MODULE_NOT_FOUND') {
      return null
    }
    throw e;
  }
}
<|endoftext|>


<commit_before>var fs = require('fs');
var async = require('async');
var _ = require('lodash');

function load(events) {
  fs.readdir('./node_modules', function(err, dirs) {
    if (err) return console.error(err);

    async.waterfall([
      function(cb) { async.filter(dirs, hasPackageJson, _.partial(cb, null)); },
      _.partial(async.map, _, parsePackageJson, _),
      function(params, cb) { async.filter(params, hasPluginField, _.partial(cb, null)); },
      _.partial(async.map, _, loadPlugin, _)
    ], function(err, plugins) {
      if (err) return console.error(err);
    });

    function hasPackageJson(dir, cb) {
      fs.stat('./node_modules/' + dir + '/package.json', function(err) {
        cb(!err);
      });
    }
    function parsePackageJson(dir, cb) {
      fs.readFile('./node_modules/' + dir + '/package.json', function(err, data) {
        if (err) return cb(err);
        try {
          cb(null, JSON.parse(data));
        } catch (e) {
          cb(e);
        }
      });
    }
    function hasPluginField(params, cb) {
      cb(params.hasOwnProperty('ethereumSandboxPlugin'));
    }
    function loadPlugin(params, cb) {
      cb(null, [
        params.ethereumSandboxPlugin,
        require(params.name).create(events)
      ]);
    }
  });
}

module.exports = {
  load: load
};
<commit_msg>Fix plugins loading<commit_after>var fs = require('fs');
var async = require('async');
var _ = require('lodash');

function load(events) {
  fs.readdir(__dirname + '/node_modules', function(err, dirs) {
    if (err) return console.error(err);

    async.waterfall([
      function(cb) { async.filter(dirs, hasPackageJson, _.partial(cb, null)); },
      _.partial(async.map, _, parsePackageJson, _),
      function(params, cb) { async.filter(params, hasPluginField, _.partial(cb, null)); },
      _.partial(async.map, _, loadPlugin, _)
    ], function(err, plugins) {
      if (err) return console.error(err);
    });

    function hasPackageJson(dir, cb) {
      fs.stat('./node_modules/' + dir + '/package.json', function(err) {
        cb(!err);
      });
    }
    function parsePackageJson(dir, cb) {
      fs.readFile('./node_modules/' + dir + '/package.json', function(err, data) {
        if (err) return cb(err);
        try {
          cb(null, JSON.parse(data));
        } catch (e) {
          cb(e);
        }
      });
    }
    function hasPluginField(params, cb) {
      cb(params.hasOwnProperty('ethereumSandboxPlugin'));
    }
    function loadPlugin(params, cb) {
      cb(null, [
        params.ethereumSandboxPlugin,
        require(params.name).create(events)
      ]);
    }
  });
}

module.exports = {
  load: load
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

const chalk = require('chalk')
const semver = require('semver')
const program = require('commander')

const pkg = require('../package')

const { generator } = require('..')

/**
 * Global error handler
 * @param {Error} err error
 * @param {Promise} promise promise
 */
const onError = (err, promise) => {
  // log error
  console.log()

  if (program.debug) {
    console.error(err)
    promise && console.error(promise)
  } else {
    console.error('💀 ', chalk.red(err instanceof Error ? err.message : err))
  }

  console.log()

  // error exit
  process.exit(1)
}

/**
 * Global exit handler
 */
const onExit = () => {
  console.log('\n\n👋  You have to cancel the init task.\n')
  process.exit(1)
}

// provide a title to the process
process.title = pkg.name
// unhandled exception & rejection
process.on('uncaughtException', onError)
process.on('unhandledRejection', onError)
process.on('SIGINT', onExit)

// istanbul ignore if
if (!semver.satisfies(process.version, pkg.engines.node)) {
  console.log(chalk.red(`You are using Node.js ${chalk.yellow(process.version)}, but this version of ${chalk.cyan(pkg.name)} requires Node.js ${chalk.green(pkg.engines.node)}.`))
  console.log(chalk.red('Please upgrade your Node.js version before this operation.'))
  // node version required
  process.exit(1)
}

// #region register commands

// `init` command
program
  .command('init <template> [project]')
  .description('generate a new project from a template')
  .option('-f, --force', 'overwrite target directory if it exists')
  .option('-o, --offline', 'offline mode, use cached template')
  .option('-s, --save', 'save the answers for the next')
  .action((template, project, { force, offline, save }) => {
    generator.init(template, project, { force, offline, save }).catch(onError)
  })
  .on('--help', () => {
    console.log()
    console.log('  Examples:')
    console.log()
    console.log(chalk.gray('    # create a new project with an official template'))
    console.log(`    $ ${program.name()} init <template> [project]`)
    console.log()
    console.log(chalk.gray('    # create a new project straight from a github template'))
    console.log(`    $ ${program.name()} init <username>/<repo> [project]`)
  })

// `list` command
program
  .command('list [username]').alias('ls')
  .description('list available official templates')
  .option('-s, --short', 'short mode')
  .action((username, { short }) => {
    generator.list(username, { short }).catch(onError)
  })

// #endregion

// #region main command

program
  .version(pkg.version)
  .usage('<command> [options]')
  .option('--debug', 'run command in debug mode')
  .action(command => {
    // output help information on unknown commands add some useful info on help
    onError(`Unknown command: '${chalk.yellow(command)}'. See '${program.name()} --help'.`)
  })
  .on('--help', () => {
    console.log()
    console.log('  Suggestions:')
    console.log()
    console.log(`    Run ${chalk.cyan(`${program.name()} <command> --help`)} for detailed usage of given command.`)
  })
// #endregion

// #region common action & help

// // clear console when sub command execute
// program.commands.forEach(item => item.action(clearConsole))

// help end padding
program.on('--help', console.log).commands.forEach(item => item.on('--help', console.log))

// #endregion

// bootstrap
program.parse(process.argv)
<commit_msg>:tada: Initial commit<commit_after>#!/usr/bin/env node

const chalk = require('chalk')
const semver = require('semver')
const program = require('commander')

const pkg = require('../package')

const { generator } = require('..')

/**
 * Global error handler
 * @param {Error} err error
 * @param {Promise} promise promise
 */
const onError = (err, promise) => {
  // log error
  console.log()

  if (program.debug) {
    console.error(err)
    promise && console.error(promise)
  } else {
    console.error('💀 ', chalk.red(err instanceof Error ? err.message : err))
  }

  console.log()

  // error exit
  process.exit(1)
}

/**
 * Global exit handler
 */
const onExit = () => {
  console.log('\n\n👋  You have to cancel the init task.\n')
  process.exit(1)
}

// provide a title to the process
process.title = pkg.name
// unhandled exception & rejection
process.on('uncaughtException', onError)
process.on('unhandledRejection', onError)
process.on('SIGINT', onExit)

// istanbul ignore if
if (!semver.satisfies(process.version, pkg.engines.node)) {
  console.log(chalk.red(`You are using Node.js ${chalk.yellow(process.version)}, but this version of ${chalk.cyan(pkg.name)} requires Node.js ${chalk.green(pkg.engines.node)}.`))
  console.log(chalk.red('Please upgrade your Node.js version before this operation.'))
  // node version required
  process.exit(1)
}

// #region register commands

// `init` command
program
  .command('init <template> [project]')
  .description('generate a new project from a template')
  .option('-f, --force', 'overwrite target directory if it exists')
  .option('-o, --offline', 'offline mode, use cached template')
  .option('-s, --save', 'save the answers for the next')
  .action((template, project, { force, offline, save }) => {
    generator.init(template, project, { force, offline, save }).catch(onError)
  })
  .on('--help', () => {
    console.log()
    console.log('  Examples:')
    console.log()
    console.log(chalk.gray('    # create a new project with an official template'))
    console.log(`    $ ${program.name()} init <template> [project]`)
    console.log()
    console.log(chalk.gray('    # create a new project straight from a github template'))
    console.log(`    $ ${program.name()} init <username>/<repo> [project]`)
  })

// `list` command
program
  .command('list [username]').alias('ls')
  .description('list available official templates')
  .option('-s, --short', 'short mode')
  .action((username, { short }) => {
    generator.list(username, { short }).catch(onError)
  })

// #endregion

// #region main command

program
  .version(pkg.version)
  .usage('<command> [options]')
  .option('--debug', 'run command in debug mode')
  .action(command => {
    // output help information on unknown commands add some useful info on help
    onError(`Unknown command: '${chalk.yellow(command)}'. See '${program.name()} --help'.`)
  })
  .on('--help', () => {
    console.log()
    console.log('  Suggestions:')
    console.log()
    console.log(`    Run ${chalk.cyan(`${program.name()} <command> --help`)} for detailed usage of given command.`)
  })
// #endregion

// #region common action & help

// // clear console when sub command execute
// program.commands.forEach(item => item.action(clearConsole))

// help end padding
program.on('--help', console.log).commands.forEach(item => item.on('--help', console.log))

// #endregion

// bootstrap
program.parse(process.argv)

program.args.length || program.help()
<|endoftext|>