Comparing version 0.3.2 to 0.4.0
132
nodemon.js
@@ -14,6 +14,9 @@ #!/usr/bin/env node | ||
monitor = null, | ||
ignoreFilePath = './nodemon-ignore', | ||
ignoreFilePath = './.nodemonignore', | ||
oldIgnoreFilePath = './nodemon-ignore', | ||
ignoreFiles = [flag, ignoreFilePath], // ignore the monitor flag by default | ||
reIgnoreFiles = null, | ||
timeout = 1000, // check every 1 second | ||
restartDelay = 0, // controlled through arg --delay 10 (for 10 seconds) | ||
restartTimer = null, | ||
// create once, reuse as needed | ||
@@ -75,13 +78,17 @@ reEscComments = /\\#/g, | ||
if (files.length) { | ||
sys.log('[nodemon] restarting due to changes...'); | ||
files.forEach(function (file) { | ||
sys.log('[nodemon] ' + file); | ||
}); | ||
sys.print('\n\n'); | ||
if (restartTimer !== null) clearTimeout(restartTimer); | ||
if (node !== null) { | ||
node.kill('SIGUSR2'); | ||
} else { | ||
startNode(); | ||
} | ||
restartTimer = setTimeout(function () { | ||
sys.log('[nodemon] restarting due to changes...'); | ||
files.forEach(function (file) { | ||
sys.log('[nodemon] ' + file); | ||
}); | ||
sys.print('\n\n'); | ||
if (node !== null) { | ||
node.kill('SIGUSR2'); | ||
} else { | ||
startNode(); | ||
} | ||
}, restartDelay); | ||
} | ||
@@ -113,2 +120,4 @@ } | ||
// remove comments and trim lines | ||
// this mess of replace methods is escaping "\#" to allow for emacs temp files | ||
if (line = line.replace(reEscComments, '^^').replace(reComments, '').replace(reUnescapeComments, '#').replace(reTrim, '')) { | ||
@@ -128,10 +137,49 @@ ignoreFiles.push(line.replace(reEscapeChars, '\\$&').replace(reAsterisk, '.*')); | ||
function controlArg(arg, label, fn) { | ||
if (arg == label || arg == '--' + label || arg == '-' + label.substr(0, 1)) { | ||
fn(); | ||
process.exit(); | ||
function controlArg(nodeArgs, label, fn) { | ||
var i; | ||
if ((i = nodeArgs.indexOf(label)) !== -1) { | ||
fn(nodeArgs[i], i); | ||
} else if ((i = nodeArgs.indexOf('-' + label.substr(1))) !== -1) { | ||
fn(nodeArgs[i], i); | ||
} else if ((i = nodeArgs.indexOf('--' + label)) !== -1) { | ||
fn(nodeArgs[i], i); | ||
} | ||
} | ||
if (!nodeArgs.length) { | ||
// attempt to shutdown the wrapped node instance and remove | ||
// the monitor file as nodemon exists | ||
function cleanup() { | ||
node && node.kill(); | ||
fs.unlink(flag); | ||
} | ||
// control arguments test for "help" or "--help" or "-h", run the callback and exit | ||
controlArg(nodeArgs, 'help', function () { | ||
usage(); | ||
process.exit(); | ||
}); | ||
controlArg(nodeArgs, 'version', function () { | ||
sys.print('v' + meta.version + '\n'); | ||
process.exit(); | ||
}); | ||
// look for delay flag | ||
controlArg(nodeArgs, 'delay', function (arg, i) { | ||
var delay = nodeArgs[i+1]; | ||
nodeArgs.splice(i, 2); // remove the delay from the arguments | ||
if (delay) { | ||
sys.log('[nodemon] Adding delay of ' + delay + ' seconds'); | ||
restartDelay = delay * 1000; // in seconds | ||
} | ||
}); | ||
controlArg(nodeArgs, '--debug', function (arg, i) { | ||
nodeArgs.splice(i, 1); | ||
app = nodeArgs[0]; | ||
nodeArgs.unshift('--debug'); // put it at the front | ||
}); | ||
if (!nodeArgs.length || !path.existsSync(app)) { | ||
// try to get the app from the package.json | ||
@@ -143,18 +191,15 @@ // doing a try/catch because we can't use the path.exist callback pattern | ||
app = JSON.parse(fs.readFileSync('./package.json').toString()).main; | ||
nodeArgs.push(app); | ||
if (nodeArgs[0] == '--debug') { | ||
nodeArgs.splice(1, 0, app); | ||
} else { | ||
nodeArgs.unshift(app); | ||
} | ||
} catch (e) { | ||
nodeArgs.push('help'); // default to help | ||
// no app found to run - so give them a tip and get the feck out | ||
usage(); | ||
process.exit(); | ||
} | ||
} | ||
// control arguments test for "help" or "--help" or "-h", run the callback and exit | ||
controlArg(nodeArgs[0], 'help', usage); | ||
controlArg(nodeArgs[0], 'version', function () { | ||
sys.print('v' + meta.version + '\n'); | ||
}); | ||
if (nodeArgs[0] == '--debug') { | ||
app = nodeArgs[1]; | ||
} | ||
sys.log('[nodemon] v' + meta.version); | ||
@@ -168,23 +213,46 @@ | ||
startNode(); | ||
setTimeout(startMonitor, timeout); | ||
path.exists(ignoreFilePath, readIgnoreFile); | ||
path.exists(ignoreFilePath, function (exists) { | ||
if (!exists) { | ||
// try the old format | ||
path.exists(oldIgnoreFilePath, function (exists) { | ||
if (exists) { | ||
sys.log('[nodemon] detected old style .nodemonignore'); | ||
ignoreFilePath = oldIgnoreFilePath; | ||
} | ||
readIgnoreFile(); | ||
}); | ||
} else { | ||
readIgnoreFile(); | ||
} | ||
}); | ||
// touch | ||
// this little bit of hoop jumping is because sometimes the file can't be | ||
// touched properly, and it send nodemon in to a loop of restarting. | ||
// this way, the .monitor file is removed entirely, and recreated with | ||
// permissions that anyone can remove it later (i.e. if you run as root | ||
// by accident and then try again later). | ||
if (path.existsSync(flag)) fs.unlinkSync(flag); | ||
fs.writeFileSync(flag, ''); | ||
fs.chmodSync(flag, '666'); | ||
// remove the flag file on exit | ||
process.on('exit', function (code) { | ||
cleanup(); | ||
sys.log('[nodemon] exiting'); | ||
fs.unlink(flag); | ||
}); | ||
// usual suspect: ctrl+c exit | ||
process.on('SIGINT', function () { | ||
cleanup(); | ||
process.exit(0); | ||
}); | ||
// on exception *inside* nodemon, shutdown wrapped node app | ||
process.on('uncaughtException', function (err) { | ||
sys.log('[nodemon] exception in nodemon killing node'); | ||
sys.error(err.stack); | ||
node.kill(); | ||
cleanup(); | ||
}); |
@@ -12,4 +12,4 @@ { | ||
"keywords": ["monitor", "development", "restart", "autoload", "reload", "terminal"], | ||
"version": "0.3.2", | ||
"version": "0.4.0", | ||
"main": "./nodemon" | ||
} |
@@ -5,3 +5,3 @@ # nodemon | ||
`nodemon` will watch all the files in the directory that nodemon was started, and if they change, it will automatically restart your node application. | ||
`nodemon` will watch all the files in the directory that `nodemon` was started, and if they change, it will automatically restart your node application. | ||
@@ -12,7 +12,7 @@ `nodemon` does **not** require *any* changes to your code or method of development. `nodemon` simply wraps your node application and keeps an eye on any files that have changed. | ||
Either through forking or: | ||
Either through forking or by using [npm](http://npmjs.org) (the recommended way): | ||
npm install nodemon | ||
npm install nodemon -g | ||
And `nodemon` will be installed in to your bin path. | ||
And `nodemon` will be installed in to your bin path. Note that as of npm v1, you must explicitly tell npm to install globally as `nodemon` is a command line utility. | ||
@@ -37,9 +37,25 @@ # Usage | ||
You can also pass the debug flag to node through the command line as you would normally: | ||
nodemon --debug ./server.js 80 | ||
Finally, if you have a `package.json` file for your app, you can omit the main script entirely and `nodemon` will read the `package.json` for the `main` property and use that value as the app. | ||
# Delaying restarting | ||
In some situations, you may want to wait until a number of files have changed. The timeout before checking for new file changes is 1 second. If you're uploading a number of files and it's taking some number of seconds, this could cause your app to restart multiple time unnecessarily. | ||
To add an extra throttle, or delay restarting, use the `--delay` command: | ||
nodemon --delay 10 server.js | ||
The delay figure is number of seconds to delay before restarting. So `nodemon` will only restart your app the given number of seconds after the *last* file change. | ||
# Ignoring files | ||
In some cases you will want to ignore some specific files, directories or file patterns, to prevent nodemon from prematurely restarting your application. | ||
In some cases you will want to ignore some specific files, directories or file patterns, to prevent `nodemon` from prematurely restarting your application. | ||
The `nodemon-ignore` file is automatically created in the directory that you run your application from, so that you can have application specific ignore lists. | ||
The `.nodemonignore` file is automatically created in the directory that you run your application from, so that you can have application specific ignore lists. | ||
You can use the [example ignore file](http://github.com/remy/nodemon/blob/master/nodemon-ignore.example) as a basis for your `nodemon`, but it's very simple to create your own: | ||
You can use the [example ignore file](http://github.com/remy/nodemon/blob/master/nodemonignore.example) as a basis for your `nodemon`, but it's very simple to create your own: | ||
@@ -46,0 +62,0 @@ # this is my ignore file with a nice comment at the top |
11640
214
76
5