Skip to content

Commit

Permalink
v5.0.0 / 2020-07-08
Browse files Browse the repository at this point in the history
  • Loading branch information
bjornstar committed Jul 8, 2020
1 parent a429a0c commit 624665a
Show file tree
Hide file tree
Showing 14 changed files with 228 additions and 141 deletions.
3 changes: 3 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"extends": [
"airbnb-base/legacy"
],
"parserOptions": {
"ecmaVersion": 9
},
"rules": {
"comma-dangle": [2, "never"],
"consistent-return": 0,
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# node-dev

## v5.0.0 / 2020-07-08

- Remove `--all-deps` and `--no-deps` CLI options, use `--deps=-1` or `--deps=0` respectively
- Unify `cli` and `cfg` logic to ensure CLI always overrides config files
- Load order for config files now matches what is in the `README`
- Add tests for notify, CLI should override config files
- All config now have clear default values
- Use more ES6 code
- Rename `resolveMain.js` to `resolve-main.js`

## v4.3.0 / 2020-07-03

- Enable `--notify` by default and add tests
Expand Down
31 changes: 21 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,20 @@ node-dev foo.js
There are a couple of command line options that can be used to control which
files are watched and what happens when they change:

* `--no-deps` Watch only the project's own files and linked modules (via `npm link`)
* `--all-deps` Watch the whole dependency tree
* `--respawn` Keep watching for changes after the script has exited
* `--dedupe` [Dedupe dynamically](https://www.npmjs.org/package/dynamic-dedupe)
* `--graceful_ipc <msg>` Send 'msg' as an IPC message instead of SIGTERM for restart/shutdown
* `--poll` Force polling for file changes (Caution! CPU-heavy!)
* `--clear` - Clear the screen on restart
* `--dedupe` - [Dedupe dynamically](https://www.npmjs.org/package/dynamic-dedupe)
* `--deps`:
* -1 - Watch the whole dependency tree
* 0 - Watch only the project's own files and linked modules (via `npm link`)
* 1 (_Default_) - Watch all first level dependencies
* `--fork` - Hook into child_process.fork
* `--graceful_ipc <msg>` - Send 'msg' as an IPC message instead of SIGTERM for restart/shutdown
* `--ignore` - A file whose changes should not cause a restart
* `--notify` - Display desktop notifications
* `--poll` - Force polling for file changes (Caution! CPU-heavy!)
* `--respawn` - Keep watching for changes after the script has exited
* `--timestamp` - The timestamp format to use for logging restarts
* `--vm` - Load files using Node's VM

By default node-dev will watch all first-level dependencies, i.e. the ones in
the project's `node_modules`folder.
Expand Down Expand Up @@ -76,13 +84,16 @@ Usually node-dev doesn't require any configuration at all, but there are some
options you can set to tweak its behaviour:

* `clear` – Whether to clear the screen upon restarts. _Default:_ `false`
* `dedupe` – Whether modules should by [dynamically deduped](https://www.npmjs.org/package/dynamic-dedupe). _Default:_ `false`
* `deps` – How many levels of dependencies should be watched. _Default:_ `1`
* `fork` – Whether to hook into [child_process.fork](http://nodejs.org/docs/latest/api/child_process.html#child_process_child_process_fork_modulepath_args_options) (required for [clustered](http://nodejs.org/docs/latest/api/cluster.html) programs). _Default:_ `true`
* `graceful_ipc` - Send the argument provided as an IPC message instead of SIGTERM during restart events. _Default:_ `""` (off)
* `ignore` - A single file or an array of files to ignore. _Default:_ `[]`
* `notify` – Whether to display desktop notifications. _Default:_ `true`
* `poll` - Force polling for file changes, this can be CPU-heavy. _Default:_ `false`
* `respawn` - Keep watching for changes after the script has exited. _Default:_ `false`
* `timestamp` – The timestamp format to use for logging restarts. _Default:_ `"HH:MM:ss"`
* `vm` – Whether to watch files loaded via Node's [VM](http://nodejs.org/docs/latest/api/vm.html) module. _Default:_ `true`
* `fork` – Whether to hook into [child_process.fork](http://nodejs.org/docs/latest/api/child_process.html#child_process_child_process_fork_modulepath_args_options) (required for [clustered](http://nodejs.org/docs/latest/api/cluster.html) programs). _Default:_ `true`
* `deps` – How many levels of dependencies should be watched. _Default:_ `1`
* `dedupe` – Whether modules should by [dynamically deduped](https://www.npmjs.org/package/dynamic-dedupe). _Default:_ `false`
* `graceful_ipc` - Send the argument provided as an IPC message instead of SIGTERM during restart events. _Default:_ `""` (off)

Upon startup node-dev looks for a `.node-dev.json` file in the following directories:
* user's HOME directory
Expand Down
79 changes: 36 additions & 43 deletions lib/cfg.js
Original file line number Diff line number Diff line change
@@ -1,51 +1,44 @@
var fs = require('fs');
var path = require('path');
const fs = require('fs');
const path = require('path');

const resolveMain = require('./resolve-main');

const defaultConfig = {
clear: false,
dedupe: false,
deps: 1,
extensions: {
coffee: 'coffeescript/register',
ls: 'LiveScript'
},
fork: true,
graceful_ipc: '',
ignore: [],
notify: true,
poll: false,
respawn: false,
timestamp: 'HH:MM:ss',
vm: true
};

function read(dir) {
var f = path.resolve(dir, '.node-dev.json');
const f = path.resolve(dir, '.node-dev.json');
return fs.existsSync(f) ? JSON.parse(fs.readFileSync(f)) : {};
}

function resolvePath(unresolvedPath) {
return path.resolve(process.cwd(), unresolvedPath);
}

module.exports = function (main, opts) {
var dir = main ? path.dirname(main) : '.';
var c = Object.assign(read(process.cwd()), read(dir));

/* eslint-disable no-proto */
c.__proto__ = read(process.env.HOME || process.env.USERPROFILE);
function getConfig(script) {
const main = resolveMain(script);
const dir = main ? path.dirname(main) : '.';

// Truthy == --all-deps, false: one level of deps
if (typeof c.deps !== 'number') c.deps = c.deps ? -1 : 1;

if (opts) {
// Overwrite with CLI opts ...
if (opts.allDeps) c.deps = -1;
if (!opts.deps) c.deps = 0;
if (opts.dedupe) c.dedupe = true;
if (opts.graceful_ipc) c.graceful_ipc = opts.graceful_ipc;
if (opts.respawn) c.respawn = true;
c.notify = opts.notify;
}

var ignore = (c.ignore || []).map(resolvePath);
return Object.assign(
defaultConfig,
read(process.env.HOME || process.env.USERPROFILE),
read(process.cwd()),
read(dir)
);
}

return {
vm: c.vm !== false,
fork: c.fork !== false,
notify: c.notify,
deps: c.deps,
timestamp: c.timestamp || (c.timestamp !== false && 'HH:MM:ss'),
clear: !!c.clear,
dedupe: !!c.dedupe,
graceful_ipc: c.graceful_ipc,
ignore: ignore,
respawn: c.respawn || false,
extensions: c.extensions || {
coffee: 'coffeescript/register',
ls: 'LiveScript'
}
};
module.exports = {
defaultConfig,
getConfig
};
26 changes: 23 additions & 3 deletions lib/cli.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
const minimist = require('minimist');
const path = require('path');

const { defaultConfig, getConfig } = require('./cfg');

const configKeys = Object.keys(defaultConfig);

function resolvePath(unresolvedPath) {
return path.resolve(process.cwd(), unresolvedPath);
}

function getFirstNonOptionArgIndex(args) {
for (let i = 2; i < args.length; i += 1) {
if (args[i][0] != '-') return i;
}

return args.length;
}

function removeValueArgs(args, names) {
let i = 0;
let removed = [];

while (i < args.length) {
if (names.includes(args[i])) {
removed = removed.concat(args.splice(i, 2));
} else {
i += 1;
}
}

return removed;
}

Expand All @@ -29,14 +41,22 @@ module.exports = function (argv) {
const devArgs = argv.slice(2, scriptIndex);

const opts = minimist(devArgs, {
boolean: ['all-deps', 'deps', 'dedupe', 'poll', 'respawn', 'notify'],
string: ['graceful_ipc'],
default: { deps: true, notify: true, graceful_ipc: '' },
boolean: ['clear', 'dedupe', 'fork', 'notify', 'poll', 'respawn', 'vm'],
string: ['graceful_ipc', 'ignore', 'timestamp'],
default: getConfig(script),
unknown: function (arg) {
const argKeys = Object.keys(minimist([arg]));

if (configKeys.some(k => argKeys.includes(k))) {
return true;
}

nodeArgs.push(arg);
}
});

opts.ignore = [...Array.isArray(opts.ignore) ? opts.ignore : [opts.ignore]].map(resolvePath);

return {
script,
scriptArgs,
Expand Down
15 changes: 7 additions & 8 deletions lib/hook.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
var vm = require('vm');

module.exports = function (cfg, wrapper, callback) {
const vm = require('vm');

module.exports = function (patchVM, wrapper, callback) {
// Hook into Node's `require(...)`
updateHooks();

// Patch the vm module to watch files executed via one of these methods:
if (cfg.vm) {
if (patchVM) {
patch(vm, 'createScript', 1);
patch(vm, 'runInThisContext', 1);
patch(vm, 'runInNewContext', 2);
Expand All @@ -18,11 +17,11 @@ module.exports = function (cfg, wrapper, callback) {
* index.
*/
function patch(obj, method, optionsArgIndex) {
var orig = obj[method];
const orig = obj[method];
if (!orig) return;
obj[method] = function () {
var opts = arguments[optionsArgIndex];
var file = null;
const opts = arguments[optionsArgIndex];
let file = null;
if (opts) {
file = typeof opts == 'string' ? opts : opts.filename;
}
Expand All @@ -36,7 +35,7 @@ module.exports = function (cfg, wrapper, callback) {
*/
function updateHooks() {
Object.keys(require.extensions).forEach(function (ext) {
var fn = require.extensions[ext];
const fn = require.extensions[ext];
if (typeof fn === 'function' && fn.name !== 'nodeDevHook') {
require.extensions[ext] = createHook(fn);
}
Expand Down
Loading

0 comments on commit 624665a

Please sign in to comment.