Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: support implicit filename extension #1198

Merged
merged 4 commits into from
Dec 29, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
```
Expand Down Expand Up @@ -324,12 +324,6 @@ 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)! 🙏
Expand Down
12 changes: 11 additions & 1 deletion faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ $ 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, [email protected] 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.
Expand Down Expand Up @@ -103,7 +113,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

Expand Down
2 changes: 1 addition & 1 deletion lib/config/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ function command(settings) {
executable: executable,
args: args,
};
}
}
33 changes: 24 additions & 9 deletions lib/config/exec.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,43 @@ 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 (!nodemonOptions.exec && !nodemonOptions.script) {
if (!options.exec && !options.script) {
var found = execFromPackage();
if (found !== null) {
if (found.exec) {
nodemonOptions.exec = found.exec;
options.exec = found.exec;
}
if (!nodemonOptions.script) {
nodemonOptions.script = found.script;
if (!options.script) {
options.script = found.script;
}
if (Array.isArray(nodemonOptions.args) &&
nodemonOptions.scriptPosition === null) {
nodemonOptions.scriptPosition = nodemonOptions.args.length;
if (Array.isArray(options.args) &&
options.scriptPosition === null) {
options.scriptPosition = options.args.length;
}
}
}

var options = utils.clone(nodemonOptions || {});
var script = path.basename(options.script || '');
// var options = utils.clone(nodemonOptions || {});
script = path.basename(options.script || '');

var scriptExt = path.extname(script).slice(1);

Expand Down
41 changes: 24 additions & 17 deletions lib/config/load.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ var exec = require('./exec');
var defaults = require('./defaults');

module.exports = load;
module.exports.mutateExecOptions = mutateExecOptions;

var existsSync = fs.existsSync || path.existsSync;

Expand Down Expand Up @@ -72,23 +73,7 @@ function load(settings, options, config, callback) {
}
}

// 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;
mutateExecOptions(options);

if (options.quiet) {
utils.quiet();
Expand Down Expand Up @@ -229,3 +214,25 @@ function loadPackageJSON(config, ready) {
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;
}
3 changes: 1 addition & 2 deletions lib/monitor/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,7 @@ function run(options) {

if (code === 2) {
// something wrong with parsed command
utils.log.error('failed to start process, possible issue with exec ' +
'arguments');
utils.log.error('process failed, unhandled exit code (2)');
bus.emit('error', code);
process.exit();
}
Expand Down
3 changes: 3 additions & 0 deletions lib/nodemon.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ 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');
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"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": {
Expand Down
36 changes: 24 additions & 12 deletions test/cli/parse.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ 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();
}
Expand All @@ -26,6 +28,7 @@ function parse(cmd) {
});

return parsed;
return mutateExecOptions(cli.parse(cmd));
}

function commandToString(command) {
Expand Down Expand Up @@ -97,18 +100,6 @@ 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
Expand Down Expand Up @@ -274,6 +265,27 @@ 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"'));
Expand Down