Repository: remy/nodemon
Pull request #1200 (2017-12-29 11:06:57)

fix: don't use fork with `node inspect`
Fixes: #1191


Patch:
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 32d9248..fbd5222 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -15,4 +15,4 @@
 
 ---
 
-If applicable, please append the `--dump` flag on your command and include the output here **ensuring to remove any sensitive/personal details or tokens**.
+If applicable, please append the `--dump` flag on your command and include the output here **ensuring to remove any sensitive/personal details or tokens.
diff --git a/README.md b/README.md
index dab4ee4..3a5e05c 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ Simply specify the config in the same format as you would for a config file but
   "...": "... other standard package.json values",
   "nodemonConfig": {
     "ignore": ["test/*", "docs/*"],
-    "delay": "2500"
+"delay": "2500"
   }
 }
 ```
@@ -324,6 +324,12 @@ Nodemon is not perfect, and CLI arguments has sprawled beyond where I'm complete
 
 See the [FAQ](https://github.com/remy/nodemon/blob/master/faq.md) and please add your own questions if you think they would help others.
 
+## Contributors
+
+This project exists thanks to all the people who [contribute](https://github.com/remy/nodemon/blob/master/.github/CONTRIBUTING.md).
+[![nodemon contributors](https://opencollective.com/nodemon/contributors.svg?width=890)](https://opencollective.com/nodemon#backer)
+
+
 ## Backers
 
 Thank you to all [our backers](https://opencollective.com/nodemon#backer)! 🙏
@@ -334,8 +340,6 @@ Thank you to all [our backers](https://opencollective.com/nodemon#backer)! 🙏
 
 Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Sponsor this project today ❤️](https://opencollective.com/nodemon#sponsor)
 
-[<img src="website/sparkpost.svg" width="200">](https://sparkpo.st/nodemon)
-
 # License
 
 MIT [http://rem.mit-license.org](http://rem.mit-license.org)
diff --git a/bin/nodemon.js b/bin/nodemon.js
index 31aff34..4676707 100755
--- a/bin/nodemon.js
+++ b/bin/nodemon.js
@@ -1,16 +1,16 @@
 #!/usr/bin/env node
-
-const cli = require('../lib/cli');
-const nodemon = require('../lib/');
-const options = cli.parse(process.argv);
+'use strict';
+var cli = require('../lib/cli');
+var nodemon = require('../lib/');
+var options = cli.parse(process.argv);
 
 nodemon(options);
 
-const fs = require('fs');
+var fs = require('fs');
 
 // checks for available update and returns an instance
-const pkg = JSON.parse(fs.readFileSync(__dirname + '/../package.json'));
+var pkg = JSON.parse(fs.readFileSync(__dirname + '/../package.json'));
 
-if (pkg.version.indexOf('0.0.0') !== 0 && options.noUpdateNotifier !== true) {
+if (pkg.version.indexOf('0.0.0') !== 0) {
   require('update-notifier')({ pkg }).notify();
 }
diff --git a/doc/cli/options.txt b/doc/cli/options.txt
index ab6561a..7d28440 100644
--- a/doc/cli/options.txt
+++ b/doc/cli/options.txt
@@ -7,7 +7,6 @@ Configuration
   --signal <signal> ........ use specified kill signal instead of default (ex. SIGTERM)
   -w, --watch dir........... watch directory "dir" or files. use once for each
                              directory or file to watch
-  --no-update-notifier ..... opt-out of update version check
 
 Execution
   -C, --on-change-only ..... execute script on change only, not startup
diff --git a/website/index.html b/docs/index.html
similarity index 100%
rename from website/index.html
rename to docs/index.html
diff --git a/docs/index.js b/docs/index.js
new file mode 100644
index 0000000..78a75c6
--- /dev/null
+++ b/docs/index.js
@@ -0,0 +1,12 @@
+'use strict';
+var http = require('http'),
+    fs = require('fs');
+
+var page = fs.readFileSync(__dirname + '/index.html', 'utf8');
+
+var server = http.createServer(function (req, res) {
+  res.writeHead(200, { 'content-type': 'text/html' });
+  res.end(page);
+}).listen(process.env.PORT || 0, function () {
+  console.log('Listening on http://localhost:' + server.address().port);
+});
\ No newline at end of file
diff --git a/website/nodemon.svg b/docs/nodemon.svg
similarity index 100%
rename from website/nodemon.svg
rename to docs/nodemon.svg
diff --git a/faq.md b/faq.md
index efbd349..ecb1d90 100644
--- a/faq.md
+++ b/faq.md
@@ -26,16 +26,6 @@ $ nodemon app.js -- -L -opt2 -opt3
 
 nodemon will ignore all script arguments after `--` and pass them to your script.
 
-# Error: "process failed, unhandled exit code (2)"
-
-Nodemon will look for exit signals from the child process it runs. When the exit code is `2`, nodemon throws an error. Typically this is because the arguments are bad for the executing program, but it can also be due other reasons.
-
-For example, mocha@3.x will exit with `2` on failing tests. To handle the exit code in a way that nodemon can consume, manually exit the process, i.e.:
-
-```bash
-nodemon -x 'mocha test/bad.test.js || exit 1'
-```
-
 # Can't install nodemon: permission issue
 
 You may need to install nodemon using `sudo` (which isn't recommended, but I understand it's unavoidable in some environemnts). If the install fails with this appearing in the npm error log, then you need the following workaround.
@@ -113,7 +103,7 @@ A workaround is to make sure that `node` binary exists in the `PATH`:
 sudo ln -s /usr/bin/nodejs /usr/local/bin/node
 ```
 
-Alternatively the `--exec nodejs` option can be used.
+Alternatively the `--exec nodejs` option can be used. 
 
 Fedora and Ubuntu pakage node as nodejs, because node.dpkg is
 
diff --git a/lib/cli/parse.js b/lib/cli/parse.js
index 4c0fa8f..789fe6e 100644
--- a/lib/cli/parse.js
+++ b/lib/cli/parse.js
@@ -113,11 +113,6 @@ function nodemonOption(options, arg, eatNext) {
     options.version = true;
   } else
 
-  if (arg === '--no-update-notifier') {
-    options.noUpdateNotifier = true;
-  } else
-
-
   if (arg === '--dump') {
     options.dump = true;
   } else
diff --git a/lib/config/command.js b/lib/config/command.js
index 9839b5c..2ce4634 100644
--- a/lib/config/command.js
+++ b/lib/config/command.js
@@ -40,4 +40,4 @@ function command(settings) {
     executable: executable,
     args: args,
   };
-}
+}
\ No newline at end of file
diff --git a/lib/config/exec.js b/lib/config/exec.js
index 3a4f7f7..852186f 100644
--- a/lib/config/exec.js
+++ b/lib/config/exec.js
@@ -73,43 +73,28 @@ function exec(nodemonOptions, execMap) {
     execMap = {};
   }
 
-  var options = utils.clone(nodemonOptions || {});
-  var script;
-
-  // if there's no script passed, try to get it from the first argument
-  if (!options.script && (options.args || []).length) {
-    script = expandScript(options.args[0],
-      options.ext && ('.' + (options.ext || 'js').split(',')[0]));
-
-    // if the script was found, shift it off our args
-    if (script !== options.args[0]) {
-      options.script = script;
-      options.args.shift();
-    }
-  }
-
   // if there's no exec found yet, then try to read it from the local
   // package.json this logic used to sit in the cli/parse, but actually the cli
   // should be parsed first, then the user options (via nodemon.json) then
   // finally default down to pot shots at the directory via package.json
-  if (!options.exec && !options.script) {
+  if (!nodemonOptions.exec && !nodemonOptions.script) {
     var found = execFromPackage();
     if (found !== null) {
       if (found.exec) {
-        options.exec = found.exec;
+        nodemonOptions.exec = found.exec;
       }
-      if (!options.script) {
-        options.script = found.script;
+      if (!nodemonOptions.script) {
+        nodemonOptions.script = found.script;
       }
-      if (Array.isArray(options.args) &&
-        options.scriptPosition === null) {
-        options.scriptPosition = options.args.length;
+      if (Array.isArray(nodemonOptions.args) &&
+        nodemonOptions.scriptPosition === null) {
+        nodemonOptions.scriptPosition = nodemonOptions.args.length;
       }
     }
   }
 
-  // var options = utils.clone(nodemonOptions || {});
-  script = path.basename(options.script || '');
+  var options = utils.clone(nodemonOptions || {});
+  var script = path.basename(options.script || '');
 
   var scriptExt = path.extname(script).slice(1);
 
diff --git a/lib/config/load.js b/lib/config/load.js
index 39b1d05..06ec801 100644
--- a/lib/config/load.js
+++ b/lib/config/load.js
@@ -9,7 +9,6 @@ var exec = require('./exec');
 var defaults = require('./defaults');
 
 module.exports = load;
-module.exports.mutateExecOptions = mutateExecOptions;
 
 var existsSync = fs.existsSync || path.existsSync;
 
@@ -73,7 +72,23 @@ function load(settings, options, config, callback) {
         }
       }
 
-      mutateExecOptions(options);
+      // work out the execOptions based on the final config we have
+      options.execOptions = exec({
+        script: options.script,
+        exec: options.exec,
+        args: options.args,
+        scriptPosition: options.scriptPosition,
+        nodeArgs: options.nodeArgs,
+        execArgs: options.execArgs,
+        ext: options.ext,
+        env: options.env,
+      }, options.execMap);
+
+      // clean up values that we don't need at the top level
+      delete options.scriptPosition;
+      delete options.script;
+      delete options.args;
+      delete options.ext;
 
       if (options.quiet) {
         utils.quiet();
@@ -205,35 +220,12 @@ function loadPackageJSON(config, ready) {
     ready = function () { };
   }
 
+  utils.log.detail('Looking in package.json for nodemonConfig');
+
   var dir = process.cwd();
   var filename = path.join(dir, 'package.json');
   var packageLoadOptions = { configFile: filename };
   return loadFile(packageLoadOptions, config, dir, function (settings) {
-    if (settings.nodemonConfig) {
-      utils.log.detail('using config in package.json');
-    }
     ready(settings.nodemonConfig || {});
   });
 }
-
-function mutateExecOptions(options) {
-  // work out the execOptions based on the final config we have
-  options.execOptions = exec({
-    script: options.script,
-    exec: options.exec,
-    args: options.args,
-    scriptPosition: options.scriptPosition,
-    nodeArgs: options.nodeArgs,
-    execArgs: options.execArgs,
-    ext: options.ext,
-    env: options.env,
-  }, options.execMap);
-
-  // clean up values that we don't need at the top level
-  delete options.scriptPosition;
-  delete options.script;
-  delete options.args;
-  delete options.ext;
-
-  return options;
-}
diff --git a/lib/monitor/run.js b/lib/monitor/run.js
index cc14913..53f2cd3 100644
--- a/lib/monitor/run.js
+++ b/lib/monitor/run.js
@@ -78,10 +78,13 @@ function run(options) {
     });
   }
 
+  const firstArg = cmd.args[0] || '';
+
   if (
     // this is a hack to avoid forking if there's a node argument being passed
     // it's a short term fix, and I'm not 100% sure that `fork` is the right way
-    (cmd.args[0] || '').indexOf('-') === -1 &&
+    firstArg.indexOf('-') === -1 &&
+    firstArg !== 'inspect' &&
     executable === 'node' &&
     utils.version.major > 4
   ) {
@@ -143,7 +146,8 @@ function run(options) {
 
     if (code === 2) {
       // something wrong with parsed command
-      utils.log.error('process failed, unhandled exit code (2)');
+      utils.log.error('failed to start process, possible issue with exec ' +
+        'arguments');
       bus.emit('error', code);
       process.exit();
     }
diff --git a/lib/monitor/watch.js b/lib/monitor/watch.js
index 7becd47..67aba74 100644
--- a/lib/monitor/watch.js
+++ b/lib/monitor/watch.js
@@ -108,8 +108,13 @@ function watch() {
   });
 
   return Promise.all(promises).then(function (res) {
-    utils.log.detail(`watching ${watchedFiles.length} file${
-      watchedFiles.length === 1 ? '' : 's'}`);
+    var total = res.reduce(function (acc, curr) {
+      acc += curr;
+      return acc;
+    }, 0);
+
+    var count = total.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
+    utils.log.detail('watching ' + count + ' files');
     return watchedFiles;
   });
 }
diff --git a/lib/nodemon.js b/lib/nodemon.js
index c71e2e6..c2f8973 100644
--- a/lib/nodemon.js
+++ b/lib/nodemon.js
@@ -138,9 +138,6 @@ function nodemon(settings) {
     if (!config.required) {
       const restartSignal = config.options.signal === 'SIGUSR2' ? 'SIGHUP' : 'SIGUSR2';
       process.on(restartSignal, nodemon.restart);
-      utils.bus.on('error', () => {
-        utils.log.fail((new Error().stack));
-      });
       utils.log.detail((config.options.restartable ? 'or ' : '') + 'send ' +
         restartSignal + ' to ' + process.pid + ' to restart');
     }
diff --git a/package.json b/package.json
index d96deab..158eab6 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,6 @@
     "clean": "rm -rf test/fixtures/test*.js test/fixtures/test*.md",
     "web": "node web",
     "semantic-release": "semantic-release pre && npm publish && semantic-release post",
-    "prepush": "npm run lint",
     "postinstall": "node -e \"console.log('\\u001b[32mLove nodemon? You can now support the project via the open collective:\\u001b[22m\\u001b[39m\\n > \\u001b[96m\\u001b[1mhttps://opencollective.com/nodemon/donate\\u001b[0m\\n')\""
   },
   "devDependencies": {
diff --git a/website/sparkpost.svg b/website/sparkpost.svg
deleted file mode 100644
index 2c754c5..0000000
--- a/website/sparkpost.svg
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.0" id="_x32_-Color_Gray__x2B__Orange"
-	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 500 130"
-	 enable-background="new 0 0 500 130" xml:space="preserve">
-<g>
-	<g>
-		<g>
-			<path fill="#55555A" d="M1.899,115.584l7.79-9.333c5.398,4.452,11.049,7.278,17.896,7.278c5.398,0,8.651-2.141,8.651-5.651
-				v-0.171c0-3.34-2.057-5.053-12.074-7.621C12.088,97.002,4.297,93.663,4.297,81.761V81.59c0-10.875,8.733-18.069,20.978-18.069
-				c8.733,0,16.182,2.74,22.263,7.621l-6.85,9.934c-5.309-3.682-10.533-5.909-15.584-5.909c-5.053,0-7.708,2.313-7.708,5.224v0.171
-				c0,3.939,2.569,5.224,12.929,7.879c12.163,3.167,19.01,7.535,19.01,17.982v0.171c0,11.903-9.075,18.581-22.004,18.581
-				C18.251,125.174,9.091,122.007,1.899,115.584z"/>
-			<path fill="#55555A" d="M57.427,64.377h24.49c14.299,0,22.947,8.478,22.947,20.724v0.171c0,13.872-10.79,21.065-24.231,21.065
-				H70.615v17.982H57.427V64.377z M81.06,94.605c6.594,0,10.445-3.939,10.445-9.078v-0.171c0-5.909-4.107-9.076-10.701-9.076H70.615
-				v18.325H81.06z"/>
-			<path fill="#55555A" d="M123.528,63.95h12.16l25.69,60.369h-13.786l-5.48-13.444h-25.345l-5.48,13.444H97.838L123.528,63.95z
-				 M137.403,99.228l-7.967-19.437l-7.961,19.437H137.403z"/>
-			<path fill="#55555A" d="M167.616,64.377h27.402c7.622,0,13.53,2.142,17.469,6.08c3.338,3.34,5.139,8.05,5.139,13.701v0.172
-				c0,9.676-5.224,15.756-12.846,18.581l14.644,21.407H204.01l-12.846-19.181h-10.36v19.181h-13.188V64.377z M194.163,93.492
-				c6.42,0,10.103-3.425,10.103-8.477v-0.172c0-5.651-3.939-8.562-10.362-8.562h-13.1v17.211H194.163z"/>
-			<g>
-				<path fill="#55555A" d="M287.733,64.377h21.747c13.188,0,22.266,6.765,22.266,18.325v0.172
-					c0,12.587-10.875,19.094-23.377,19.094h-16.185v22.35h-4.452V64.377z M308.626,97.858c11.132,0,18.665-5.822,18.665-14.728
-					V82.96c0-9.505-7.363-14.473-18.153-14.473h-16.954v29.371H308.626z"/>
-				<path fill="#55555A" d="M403.064,115.584l2.911-3.34c6.594,6.08,12.672,8.906,21.491,8.906c8.992,0,15.159-5.052,15.159-11.902
-					v-0.171c0-6.338-3.341-10.019-16.957-12.759c-14.384-2.911-20.209-7.792-20.209-16.87v-0.171
-					c0-8.906,8.135-15.756,19.267-15.756c8.736,0,14.473,2.398,20.554,7.279l-2.829,3.511c-5.651-4.881-11.302-6.765-17.896-6.765
-					c-8.819,0-14.641,5.052-14.641,11.304v0.171c0,6.336,3.253,10.19,17.466,13.101c13.875,2.826,19.697,7.792,19.697,16.526v0.171
-					c0,9.677-8.306,16.355-19.868,16.355C417.619,125.174,410.256,122.007,403.064,115.584z"/>
-				<path fill="#55555A" d="M472.756,68.487H451.86v-4.11h46.241v4.11h-20.893v55.831h-4.452V68.487z"/>
-			</g>
-			<g>
-				<path fill="#55555A" d="M239.82,89.595l20.752-25.218h16.096l-24.343,28.473l26.096,31.471h-16.957L239.82,97.559v26.76h-13.185
-					V64.378h13.185V89.595z"/>
-			</g>
-		</g>
-		<path fill="#FA6423" d="M389.368,50.717c-6.677,5.037-7.969,13.926-8.166,19.934c-10.553-12.204,19.544-48.109-14.656-70.299
-			c21.171,27.397-30.123,54.332-30.123,94.693c0,15.821,9.886,29.764,31.6,34.604c21.3-4.535,31.81-18.783,31.81-34.603
-			C399.833,71.456,385.147,63.563,389.368,50.717z M368.066,116.715c-11.597,0-20.998-9.401-20.998-20.998
-			c0-11.597,9.401-20.998,20.998-20.998c11.597,0,20.998,9.401,20.998,20.998C389.064,107.314,379.663,116.715,368.066,116.715z"/>
-	</g>
-</g>
-</svg>


Test patch:
diff --git a/test/cli/parse.test.js b/test/cli/parse.test.js
index 636feb5..15e16d7 100644
--- a/test/cli/parse.test.js
+++ b/test/cli/parse.test.js
@@ -7,8 +7,6 @@ var cli = require('../../lib/cli/'),
   command = require('../../lib/config/command'),
   utils = require('../../lib/utils');
 
-const mutateExecOptions = require('../../lib/config/load').mutateExecOptions;
-
 function asCLI(cmd) {
   return ('node nodemon ' + (cmd || '')).trim();
 }
@@ -28,7 +26,6 @@ function parse(cmd) {
   });
 
   return parsed;
-    return mutateExecOptions(cli.parse(cmd));
 }
 
 function commandToString(command) {
@@ -100,6 +97,18 @@ describe('nodemon CLI parser', function () {
     assert(cmd === 'node --harmony app.js', 'command is ' + cmd);
   });
 
+  // it('should put the script at the end if found in package.scripts.start', function () {
+  //   var pwd = process.cwd();
+  //   process.chdir('test/fixtures/packages/start'); // allows us to load text/fixtures/package.json
+  //   var settings = parse(asCLI('--harmony')),
+  //       cmd = commandToString(command(settings));
+
+  //   process.chdir(pwd);
+  //   console.log(settings, cmd);
+
+  //   assert(cmd === 'node --harmony app.js', 'command is ' + cmd);
+  // });
+
   it('should support default express4 format', function () {
     var pwd = process.cwd();
     process.chdir('test/fixtures/packages/express4'); // allows us to load text/fixtures/package.json
@@ -265,27 +274,6 @@ describe('nodemon respects custom "ext" and "execMap"', function () {
   });
 });
 
-describe('nodemon should support implicit extensions', () => {
-  it('should expand script to script.js', () => {
-    const cwd = process.cwd();
-    process.chdir('test/fixtures/');
-    const settings = parse(asCLI('env'));
-    process.chdir(cwd);
-    var cmd = commandToString(command(settings));
-    assert.equal(cmd, 'node env.js', 'implicit extension added');
-  });
-
-  it('should support non-js', () => {
-    const cwd = process.cwd();
-    process.chdir('test/fixtures/');
-    const settings = parse(asCLI('hello --ext py'));
-    process.chdir(cwd);
-    var cmd = commandToString(command(settings));
-    assert.equal(cmd, 'node hello.py', 'implicit extension added');
-  });
-
-});
-
 describe('nodemon should slurp properly', () => {
   it('should read quotes as a single entity', () => {
     const settings = parse(asCLI('notindex.js -- -b "hello - world"'));