You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					231 lines
				
				5.9 KiB
			
		
		
			
		
	
	
					231 lines
				
				5.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								/*
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								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;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 |