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.
230 lines
6.0 KiB
230 lines
6.0 KiB
/* |
|
|
|
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<string> | string} argv 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 {import('../..').NodemonSettings} options object that will be updated |
|
* @param {String} arg current argument from argv |
|
* @param {Function} eatNext 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} value 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; |
|
} |
|
|
|
|