Repository: remy/nodemon (js)

Issue:
nodemon .\src\server.js first second vs nodemon first second help...
- `nodemon -v`: `2.0.4`
- `node -v`: `v14.8.0`
- `OS`: Windows 10, Powershell, macOS

I have a quick question that has perplexed me since I started using nodemon. Here's the relevant section from my package.json:

```json
  "main": "./src/server.js",
  "scripts": {
    "start": "node src/server.js"
  }
```

If I execute `nodemon .\src\server.js first second` then `console.log(process.argv)` looks like:

```
[
  'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Users\\brian\\Code\\server\\src\\server.js',
  'first',
  'second'
]
```

However, if I want to take advantage of nodemon's ability to automatically run the file associated with the `main` property of my `package.json` file, and I execute `nodemon first second`, then `console.log(process.argv)` looks like:

```
[
  'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Users\\brian\\Code\\server\\src\\server.js',
  'second',
  './src/server.js'
]
```

The first argument gets eaten.

### Expected behaviour

I expect nodemon to determine that `first` isn't a Node application, so it should load the file associated with the `main` property of my `package.json` file, and then pass my `first` and `second` arguments to it. I expect `console.log(process.argv)` to look like:

```
[
  'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Users\\brian\\Code\\server\\src\\server.js',
  'first',
  'second'
]
```

### Actual behaviour

My arguments are jumbled up. My second argument appears as the first argument, my first argument doesn't appear at all, and my file associated with the `main` property of my `package.json` file appears as the second argument.

```
[
  'C:\\Program Files\\nodejs\\node.exe',
  'C:\\Users\\brian\\Code\\server\\src\\server.js',
  'second',
  './src/server.js'
]
```

### Steps to reproduce

Show above.

nodemon has been around forever and is wonderful, so I assume that I'm being an idiot and there's just something I don't understand. I want the ease of being able to enter commands like:

```
nodemon dev
```

and:

```
nodemon dev-test
```

so I can easily switch environments. I don't want to have to type in my main `.\src\server.js` every time like this:

```
nodemon .\src\server.js first second
```

Thanks!

Pull request description:
fix: package.main with -- arguments
Fixes #1758

The combination of using a package.main (which sets the script position to index zero) and using the -- stop slurp meant that the arguments had the script appended to the end instead of prepended to the start. The net result meant that when the script was forked, it would drop the first user arg.

See diff for details of the fix - a simple check against null.

Patch:
diff --git a/lib/config/load.js b/lib/config/load.js
index ddec54f..bd5a03d 100644
--- a/lib/config/load.js
+++ b/lib/config/load.js
@@ -74,7 +74,9 @@ function load(settings, options, config, callback) {
           }
           // if the script is found as a result of not being on the command
           // line, then we move any of the pre double-dash args in execArgs
-          const n = options.scriptPosition || options.args.length;
+          const n = options.scriptPosition === null ?
+            options.args.length : options.scriptPosition;
+
           options.execArgs = (options.execArgs || [])
             .concat(options.args.splice(0, n));
           options.scriptPosition = null;
diff --git a/lib/monitor/run.js b/lib/monitor/run.js
index dce4638..8dc10b3 100644
--- a/lib/monitor/run.js
+++ b/lib/monitor/run.js
@@ -97,6 +97,8 @@ function run(options) {
     utils.version.major > 4 // only fork if node version > 4
 
   if (shouldFork) {
+    // this assumes the first argument is the script and slices it out, since
+    // we're forking
     var forkArgs = cmd.args.slice(1);
     var env = utils.merge(options.execOptions.env, process.env);
     stdio.push('ipc');
diff --git a/lib/monitor/watch.js b/lib/monitor/watch.js
index be77c29..1ef1408 100644
--- a/lib/monitor/watch.js
+++ b/lib/monitor/watch.js
@@ -177,7 +177,7 @@ function filterAndRestart(files) {
 
     // if there's no matches, then test to see if the changed file is the
     // running script, if so, let's allow a restart
-    if (config.options.execOptions.script) {
+    if (config.options.execOptions && config.options.execOptions.script) {
       const script = path.resolve(config.options.execOptions.script);
       if (matched.result.length === 0 && script) {
         const length = script.length;


Test patch:
diff --git a/test/config/load.test.js b/test/config/load.test.js
index 083572d..623f2ca 100644
--- a/test/config/load.test.js
+++ b/test/config/load.test.js
@@ -298,4 +298,27 @@ describe('config load', function () {
       done();
     })
   });
+
+  it('should support pkg.main and keep user args on args', done => {
+    process.chdir(path.resolve(pwd, 'test/fixtures/packages/main-and-start'));
+    const settings = { scriptPosition: 0, script: null, args: [ 'first', 'second' ] };
+    const options = { ignore: [], watch: [], monitor: [] };
+    const config = {
+      run: false,
+      system: { cwd: '/Users/remy/dev/nodemon/issues/1758' },
+      required: false,
+      dirs: [],
+      timeout: 1000,
+      options: { ignore: [], watch: [], monitor: [] },
+      lastStarted: 0,
+      loaded: []
+    }
+
+    load(settings, options, config, res => {
+      assert.deepEqual(res.execOptions.args, ['first', 'second']);
+      done();
+    })
+  });
+
+
 });
diff --git a/test/fixtures/packages/main-and-start/index.js b/test/fixtures/packages/main-and-start/index.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/packages/main-and-start/package.json b/test/fixtures/packages/main-and-start/package.json
new file mode 100644
index 0000000..f249d17
--- /dev/null
+++ b/test/fixtures/packages/main-and-start/package.json
@@ -0,0 +1,6 @@
+{
+  "main": "./index.js",
+  "scripts": {
+    "start": "node index.js"
+  }
+}