diff --git a/.eslintrc b/.eslintrc index 2064edd..230d696 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,5 +13,13 @@ "no-trailing-spaces": "error", "prefer-arrow-callback": "error", "semi": "error" - } + }, + "overrides": [ + { + "files": ["./**/*.mjs"], + "parserOptions": { + "sourceType": "module" + } + } + ] } diff --git a/lib/index.js b/lib/index.js index 7b1b795..b1383de 100644 --- a/lib/index.js +++ b/lib/index.js @@ -2,6 +2,7 @@ const { fork } = require('child_process'); const filewatcher = require('filewatcher'); const { extname } = require('path'); const semver = require('semver'); +const getPackageType = require('get-package-type'); const { clearFactory } = require('./clear'); const { configureDeps, configureIgnore } = require('./ignore'); @@ -94,7 +95,7 @@ module.exports = function ( isPaused = false; const cmd = nodeArgs.concat(wrapper, script, scriptArgs); - if (extname(script) === '.mjs') { + if (extname(script) === '.mjs' || getPackageType.sync(script) === 'module') { if (semver.satisfies(process.version, '>=10 <12.11.1')) { const resolveLoader = resolveMain(localPath('resolve-loader.mjs')); cmd.unshift('--experimental-modules', `--loader=${resolveLoader}`); diff --git a/lib/wrap.js b/lib/wrap.js index 4c61f7c..a05bd11 100755 --- a/lib/wrap.js +++ b/lib/wrap.js @@ -1,6 +1,7 @@ const { dirname, extname } = require('path'); const childProcess = require('child_process'); const { sync: resolve } = require('resolve'); +const getPackageType = require('get-package-type'); const { getConfig } = require('./cfg'); const hook = require('./hook'); @@ -67,4 +68,4 @@ if (typeof mod === 'object' && mod.name) { } // Execute the wrapped script -ext === 'mjs' ? import(main) : require(main); +ext === 'mjs' || getPackageType.sync(main) === 'module' ? import(main) : require(main); diff --git a/package.json b/package.json index 23265f8..69b9f11 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "dateformat": "^3.0.3", "dynamic-dedupe": "^0.3.0", "filewatcher": "~3.0.0", + "get-package-type": "^0.1.0", "minimist": "^1.2.5", "node-notifier": "^8.0.1", "resolve": "^1.0.0", diff --git a/test/fixture/ecma-script-module-package/.eslintrc b/test/fixture/ecma-script-module-package/.eslintrc new file mode 100644 index 0000000..bd14a19 --- /dev/null +++ b/test/fixture/ecma-script-module-package/.eslintrc @@ -0,0 +1,5 @@ +{ + "parserOptions": { + "sourceType": "module" + } +} diff --git a/test/fixture/ecma-script-module-package/.node-dev.json b/test/fixture/ecma-script-module-package/.node-dev.json new file mode 100644 index 0000000..1d4987e --- /dev/null +++ b/test/fixture/ecma-script-module-package/.node-dev.json @@ -0,0 +1,3 @@ +{ + "extensions": {} +} diff --git a/test/fixture/ecma-script-module-package/index.js b/test/fixture/ecma-script-module-package/index.js new file mode 100644 index 0000000..849423f --- /dev/null +++ b/test/fixture/ecma-script-module-package/index.js @@ -0,0 +1,6 @@ +import message from './message.js'; + +console.log(message); + +// So it doesn't immediately exit. +setTimeout(() => {}, 10000); diff --git a/test/fixture/ecma-script-module-package/message.js b/test/fixture/ecma-script-module-package/message.js new file mode 100644 index 0000000..f20016c --- /dev/null +++ b/test/fixture/ecma-script-module-package/message.js @@ -0,0 +1 @@ +export default 'Please touch ecma-script-module-package/message.js now'; diff --git a/test/fixture/ecma-script-module-package/package.json b/test/fixture/ecma-script-module-package/package.json new file mode 100644 index 0000000..3dbc1ca --- /dev/null +++ b/test/fixture/ecma-script-module-package/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/test/spawn/esmodule.js b/test/spawn/esmodule.js index bb97aff..2e6e03a 100644 --- a/test/spawn/esmodule.js +++ b/test/spawn/esmodule.js @@ -35,3 +35,19 @@ tap.test('Supports ECMAScript modules', t => { } }); }); + +tap.test('Supports ECMAScript module packages', t => { + if (process.platform === 'win32') return t.skip('ESM support on windows is broken'); + + spawn('ecma-script-module-package/index.js', out => { + if (out.match(/touch ecma-script-module-package\/message.js/)) { + touchFile('ecma-script-module-package/message.js'); + return out2 => { + if (out2.match(/Restarting/)) { + t.match(out2, /\[INFO\] \d{2}:\d{2}:\d{2} Restarting/); + return { exit: t.end.bind(t) }; + } + }; + } + }); +});