123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- /*
- nodemon is a utility for node, and replaces the use of the executable
- node. So the user calls `nodemon foo.js` instead.
- nodemon can be run in a number of ways:
- `nodemon` - tries to use package.json#main property to run
- `nodemon` - if no package, looks for index.js
- `nodemon app.js` - runs app.js
- `nodemon --arg app.js --apparg` - eats arg1, and runs app.js with apparg
- `nodemon --apparg` - as above, but passes apparg to package.json#main (or
- index.js)
- `nodemon --debug app.js
- */
- var fs = require('fs');
- var path = require('path');
- var existsSync = fs.existsSync || path.existsSync;
- module.exports = parse;
- /**
- * Parses the command line arguments `process.argv` and returns the
- * nodemon options, the user script and the executable script.
- *
- * @param {Array} full process arguments, including `node` leading arg
- * @return {Object} { options, script, args }
- */
- function parse(argv) {
- if (typeof argv === 'string') {
- argv = argv.split(' ');
- }
- var eat = function (i, args) {
- if (i <= args.length) {
- return args.splice(i + 1, 1).pop();
- }
- };
- var args = argv.slice(2);
- var script = null;
- var nodemonOptions = { scriptPosition: null };
- var nodemonOpt = nodemonOption.bind(null, nodemonOptions);
- var lookForArgs = true;
- // move forward through the arguments
- for (var i = 0; i < args.length; i++) {
- // if the argument looks like a file, then stop eating
- if (!script) {
- if (args[i] === '.' || existsSync(args[i])) {
- script = args.splice(i, 1).pop();
- // we capture the position of the script because we'll reinsert it in
- // the right place in run.js:command (though I'm not sure we should even
- // take it out of the array in the first place, but this solves passing
- // arguments to the exec process for now).
- nodemonOptions.scriptPosition = i;
- i--;
- continue;
- }
- }
- if (lookForArgs) {
- // respect the standard way of saying: hereafter belongs to my script
- if (args[i] === '--') {
- args.splice(i, 1);
- nodemonOptions.scriptPosition = i;
- // cycle back one argument, as we just ate this one up
- i--;
- // ignore all further nodemon arguments
- lookForArgs = false;
- // move to the next iteration
- continue;
- }
- if (nodemonOpt(args[i], eat.bind(null, i, args)) !== false) {
- args.splice(i, 1);
- // cycle back one argument, as we just ate this one up
- i--;
- }
- }
- }
- nodemonOptions.script = script;
- nodemonOptions.args = args;
- return nodemonOptions;
- }
- /**
- * Given an argument (ie. from process.argv), sets nodemon
- * options and can eat up the argument value
- *
- * @param {Object} options object that will be updated
- * @param {Sting} current argument from argv
- * @param {Function} the callback to eat up the next argument in argv
- * @return {Boolean} false if argument was not a nodemon arg
- */
- function nodemonOption(options, arg, eatNext) {
- // line separation on purpose to help legibility
- if (arg === '--help' || arg === '-h' || arg === '-?') {
- var help = eatNext();
- options.help = help ? help : true;
- } else
- if (arg === '--version' || arg === '-v') {
- options.version = true;
- } else
- if (arg === '--no-update-notifier') {
- options.noUpdateNotifier = true;
- } else
- if (arg === '--spawn') {
- options.spawn = true;
- } else
- if (arg === '--dump') {
- options.dump = true;
- } else
- if (arg === '--verbose' || arg === '-V') {
- options.verbose = true;
- } else
- if (arg === '--legacy-watch' || arg === '-L') {
- options.legacyWatch = true;
- } else
- if (arg === '--polling-interval' || arg === '-P') {
- options.pollingInterval = parseInt(eatNext(), 10);
- } else
- // Depricated as this is "on" by default
- if (arg === '--js') {
- options.js = true;
- } else
- if (arg === '--quiet' || arg === '-q') {
- options.quiet = true;
- } else
- if (arg === '--config') {
- options.configFile = eatNext();
- } else
- if (arg === '--watch' || arg === '-w') {
- if (!options.watch) { options.watch = []; }
- options.watch.push(eatNext());
- } else
- if (arg === '--ignore' || arg === '-i') {
- if (!options.ignore) { options.ignore = []; }
- options.ignore.push(eatNext());
- } else
- if (arg === '--exitcrash') {
- options.exitcrash = true;
- } else
- if (arg === '--delay' || arg === '-d') {
- options.delay = parseDelay(eatNext());
- } else
- if (arg === '--exec' || arg === '-x') {
- options.exec = eatNext();
- } else
- if (arg === '--no-stdin' || arg === '-I') {
- options.stdin = false;
- } else
- if (arg === '--on-change-only' || arg === '-C') {
- options.runOnChangeOnly = true;
- } else
- if (arg === '--ext' || arg === '-e') {
- options.ext = eatNext();
- } else
- if (arg === '--no-colours' || arg === '--no-colors') {
- options.colours = false;
- } else
- if (arg === '--signal' || arg === '-s') {
- options.signal = eatNext();
- } else
- if (arg === '--cwd') {
- options.cwd = eatNext();
- // go ahead and change directory. This is primarily for nodemon tools like
- // grunt-nodemon - we're doing this early because it will affect where the
- // user script is searched for.
- process.chdir(path.resolve(options.cwd));
- } else {
- // this means we didn't match
- return false;
- }
- }
- /**
- * Given an argument (ie. from nodemonOption()), will parse and return the
- * equivalent millisecond value or 0 if the argument cannot be parsed
- *
- * @param {String} argument value given to the --delay option
- * @return {Number} millisecond equivalent of the argument
- */
- function parseDelay(value) {
- var millisPerSecond = 1000;
- var millis = 0;
- if (value.match(/^\d*ms$/)) {
- // Explicitly parse for milliseconds when using ms time specifier
- millis = parseInt(value, 10);
- } else {
- // Otherwise, parse for seconds, with or without time specifier then convert
- millis = parseFloat(value) * millisPerSecond;
- }
- return isNaN(millis) ? 0 : millis;
- }
|