Repository: fgnass/node-dev
Pull request #109 (2015-12-16 18:13:10)

Add support for passing options to extensions
Hello Felix, thanks for maintaining this time-saving module.

This PR adds the ability to (optionally) pass options along to any extensions by calling the function they export, if any.

Many transpilers export such a function to be called with subsequent options.

By way of example, this enhancement can be used to ensure a dependency within `node_modules` containing ES2015-only code is correctly transpiled by Babel.

The existing behaviour of providing a module name as a string is still supported.

I've added a basic test case for `extensions` - happy to add more if you feel it needs it.

Cheers,
Lovell


Patch:
diff --git a/README.md b/README.md
index 30e85e2..ba14d21 100644
--- a/README.md
+++ b/README.md
@@ -116,6 +116,23 @@ This means that if you run `node-dev foo.coffee` node-dev will do a
 __Note:__ If you want to use coffee-script < 1.7 you have to change the
 setting to `{"coffee": "coffee-script"}`.
 
+Options can be passed to a transpiler by providing an object containing
+`name` and `options` attributes:
+
+```json
+    {
+        "js": {
+            "name": "babel/register",
+            "options": {
+                "only": [
+                    "lib/**",
+                    "node_modules/es2015-only-module/**"
+                ]
+            }
+        }
+    }
+```
+
 ### Graceful restarts
 
 Node-dev sends a `SIGTERM` signal to the child-process if a restart is required.
diff --git a/lib/wrap.js b/lib/wrap.js
index bdfaf94..5236e30 100755
--- a/lib/wrap.js
+++ b/lib/wrap.js
@@ -52,7 +52,16 @@ hook(cfg, module, function(file) {
 var ext = path.extname(main).slice(1)
   , mod = cfg.extensions[ext]
 
-if (mod) require(resolve(mod, { basedir: path.dirname(main) }))
+// Support extensions where 'require' returns a function that accepts options
+if (typeof mod === 'object' && mod.name) {
+  var fn = require(resolve(mod.name, { basedir: path.dirname(main) }))
+  if (typeof fn === 'function' && mod.options) {
+    // require returned a function, call it with options
+    fn(mod.options)
+  }
+} else if (typeof mod === 'string') {
+  require(resolve(mod, { basedir: path.dirname(main) }))
+}
 
 // Execute the wrapped script
 require(main)


Test patch:
diff --git a/test/fixture/.node-dev.json b/test/fixture/.node-dev.json
index 5da1018..c60b535 100644
--- a/test/fixture/.node-dev.json
+++ b/test/fixture/.node-dev.json
@@ -2,5 +2,14 @@
   "notify": false,
   "ignore": [
     "./ignoredModule.js"
-  ]
+  ],
+  "extensions": {
+    "coffee": "coffee-script/register",
+    "js": {
+      "name": "./extension",
+      "options": {
+        "test": true
+      }
+    }
+  }
 }
diff --git a/test/fixture/extension.js b/test/fixture/extension.js
new file mode 100644
index 0000000..0529a8b
--- /dev/null
+++ b/test/fixture/extension.js
@@ -0,0 +1,9 @@
+// Example extension/transpiler with options
+module.exports = function(options) {
+  if (typeof options !== 'object') {
+    throw new Error('Expected options to be an object')
+  }
+  if (options.test !== true) {
+    throw new Error('Expected options.test to be true')
+  }
+}