Skip to content

Convert codebase to ESM, mostly #183

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:
with:
node-version: ${{ matrix.node }}
- run: npm i
- run: npm run test
- run: npm run test:node-test
- uses: codecov/codecov-action@v5
if: ${{ github.event_name == 'pull_request' }}
with:
Expand Down
2 changes: 1 addition & 1 deletion .knip.jsonc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://unpkg.com/knip@5/schema.json",
"entry": ["lib/index.js", "bin/*/*.js", "test-workspace/tasks/*.js"],
"entry": ["lib/cjs.cjs", "lib/esm.mjs", "bin/*/*.js", "test-workspace/tasks/*.cjs"],
"ignoreDependencies": ["yarn", "spec"]
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ $ npm install npm-run-all2 --save-dev
$ yarn add npm-run-all2 --dev
```

- It requires `Node@>=14`. It may work on older versions of Node, but no guarantees are given.
- It requires `Node@>=22`. It may work on older versions of Node, but no guarantees are given.
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README states Node@>=22, but package.json engines allow ^20.5.0. Update the README to match the supported Node versions (>=20.5.0).

Copilot uses AI. Check for mistakes.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>=22 is a very strict requirement, I thought we were doing >=20?


## 📖 Usage

Expand Down
21 changes: 13 additions & 8 deletions bin/common/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,38 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------------------

module.exports = function bootstrap (name) {
export default async function bootstrap (name) {
const argv = process.argv.slice(2)

switch (argv[0]) {
case undefined:
case '-h':
case '--help':
return require(`../${name}/help`)(process.stdout)
case '--help': {
const help = await import(`../${name}/help.js`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I would do this instead:

Suggested change
const help = await import(`../${name}/help.js`)
const { default: help } = await import(`../${name}/help.js`)

Makes it more clear that it's only the default that we are interested in

return help.default(process.stdout)
}

case '-v':
case '--version':
return require('./version')(process.stdout)
case '--version': {
const version = await import('./version.js')
return version.default(process.stdout)
}

default:
default: {
// https://github.com/mysticatea/npm-run-all/issues/105
// Avoid MaxListenersExceededWarnings.
process.stdout.setMaxListeners(0)
process.stderr.setMaxListeners(0)
process.stdin.setMaxListeners(0)

// Main
return require(`../${name}/main`)(
const main = await import(`../${name}/main.js`)
return main.default(
argv,
process.stdout,
process.stderr
Expand All @@ -44,5 +48,6 @@ module.exports = function bootstrap (name) {
process.exit(1)
}
)
}
}
}
3 changes: 1 addition & 2 deletions bin/common/parse-cli-args.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -238,6 +237,6 @@ function parseCLIArgsCore (set, args) {
* @param {boolean} options.singleMode - The flag to be single group mode.
* @returns {ArgumentSet} The parsed CLI arguments.
*/
module.exports = function parseCLIArgs (args, initialValues, options) {
export default function parseCLIArgs (args, initialValues, options) {
return parseCLIArgsCore(new ArgumentSet(initialValues, options), args)
}
15 changes: 12 additions & 3 deletions bin/common/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
// ------------------------------------------------------------------------------

import { readFile } from 'fs/promises'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would do node: to highlight that they are built in

Suggested change
import { readFile } from 'fs/promises'
import { readFile } from 'node:fs/promises'

import { fileURLToPath } from 'url'
import { dirname, resolve } from 'path'

const __filename = fileURLToPath(import.meta.url)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use import.meta.dirname and import.meta.filename instead: https://nodejs.org/api/esm.html#importmetadirname

const __dirname = dirname(__filename)

/**
* Print a version text.
*
* @param {stream.Writable} output - A writable stream to print.
* @returns {Promise} Always a fulfilled promise.
* @private
*/
module.exports = function printVersion (output) {
const version = require('../../package.json').version
export default async function printVersion (output) {
const packageJson = JSON.parse(
await readFile(resolve(__dirname, '../../package.json'), 'utf8')
)
const version = packageJson.version

output.write(`v${version}\n`)

Expand Down
3 changes: 1 addition & 2 deletions bin/npm-run-all/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @copyright 2015 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -16,7 +15,7 @@
* @returns {Promise} Always a fulfilled promise.
* @private
*/
module.exports = function printHelp (output) {
export default function printHelp (output) {
output.write(`
Usage:
$ npm-run-all [--help | -h | --version | -v]
Expand Down
5 changes: 3 additions & 2 deletions bin/npm-run-all/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* @copyright 2015 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Main
// ------------------------------------------------------------------------------

require('../common/bootstrap')('npm-run-all')
import bootstrap from '../common/bootstrap.js'

bootstrap('npm-run-all')
7 changes: 3 additions & 4 deletions bin/npm-run-all/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
* @copyright 2015 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const runAll = require('../../lib')
const parseCLIArgs = require('../common/parse-cli-args')
import runAll from 'npm-run-all2'
import parseCLIArgs from '../common/parse-cli-args.js'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -25,7 +24,7 @@ const parseCLIArgs = require('../common/parse-cli-args')
* @returns {Promise} A promise which comes to be fulfilled when all npm-scripts are completed.
* @private
*/
module.exports = function npmRunAll (args, stdout, stderr) {
export default function npmRunAll (args, stdout, stderr) {
try {
const stdin = process.stdin
const argv = parseCLIArgs(args)
Expand Down
3 changes: 1 addition & 2 deletions bin/run-p/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -16,7 +15,7 @@
* @returns {Promise} Always a fulfilled promise.
* @private
*/
module.exports = function printHelp (output) {
export default function printHelp (output) {
output.write(`
Usage:
$ run-p [--help | -h | --version | -v]
Expand Down
5 changes: 3 additions & 2 deletions bin/run-p/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* @copyright 2015 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Main
// ------------------------------------------------------------------------------

require('../common/bootstrap')('run-p')
import bootstrap from '../common/bootstrap.js'

bootstrap('run-p')
7 changes: 3 additions & 4 deletions bin/run-p/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const runAll = require('../../lib')
const parseCLIArgs = require('../common/parse-cli-args')
import runAll from 'npm-run-all2'
import parseCLIArgs from '../common/parse-cli-args.js'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -25,7 +24,7 @@ const parseCLIArgs = require('../common/parse-cli-args')
* @returns {Promise} A promise which comes to be fulfilled when all npm-scripts are completed.
* @private
*/
module.exports = function npmRunAll (args, stdout, stderr) {
export default function npmRunAll (args, stdout, stderr) {
try {
const stdin = process.stdin
const argv = parseCLIArgs(args, { parallel: true }, { singleMode: true })
Expand Down
3 changes: 1 addition & 2 deletions bin/run-s/help.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -16,7 +15,7 @@
* @returns {Promise} Always a fulfilled promise.
* @private
*/
module.exports = function printHelp (output) {
export default function printHelp (output) {
output.write(`
Usage:
$ run-s [--help | -h | --version | -v]
Expand Down
5 changes: 3 additions & 2 deletions bin/run-s/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
* @copyright 2015 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Main
// ------------------------------------------------------------------------------

require('../common/bootstrap')('run-s')
import bootstrap from '../common/bootstrap.js'

bootstrap('run-s')
7 changes: 3 additions & 4 deletions bin/run-s/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const runAll = require('../../lib')
const parseCLIArgs = require('../common/parse-cli-args')
import runAll from 'npm-run-all2'
import parseCLIArgs from '../common/parse-cli-args.js'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -25,7 +24,7 @@ const parseCLIArgs = require('../common/parse-cli-args')
* @returns {Promise} A promise which comes to be fulfilled when all npm-scripts are completed.
* @private
*/
module.exports = function npmRunAll (args, stdout, stderr) {
export default function npmRunAll (args, stdout, stderr) {
try {
const stdin = process.stdin
const argv = parseCLIArgs(args, { parallel: false }, { singleMode: true })
Expand Down
9 changes: 4 additions & 5 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict'
import neostandard from 'neostandard'

module.exports = [
...require('neostandard')({
env: ['node', 'mocha'],
ignores: require('neostandard').resolveIgnoresFromGitignore(),
export default [
...neostandard({
ignores: neostandard.resolveIgnoresFromGitignore(),
ts: true,
}),
]
10 changes: 10 additions & 0 deletions lib/cjs.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { default: npmRunAll } = require('./esm.mjs')

// Didn't manage to get this ito the last breaking change, so adding a cjs as the primary export
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the spelling of 'ito' to 'into'.

Suggested change
// Didn't manage to get this ito the last breaking change, so adding a cjs as the primary export
// Didn't manage to get this into the last breaking change, so adding a cjs as the primary export

Copilot uses AI. Check for mistakes.

// maintiains a compatible layer for cjs consumers. If we export esm by default, the best cjs can
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the typo 'maintiains' to 'maintains'.

Suggested change
// maintiains a compatible layer for cjs consumers. If we export esm by default, the best cjs can
// maintains a compatible layer for cjs consumers. If we export esm by default, the best cjs can

Copilot uses AI. Check for mistakes.

// get is a default exoport field (breaking).
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct the spelling of 'exoport' to 'export'.

Suggested change
// get is a default exoport field (breaking).
// get is a default export field (breaking).

Copilot uses AI. Check for mistakes.

//
// TODO: Next breaking change, drop this file in favor of a named ESM export.
//
// ESM consumers can import 'npm-run-all2/esm.js' directly if they want to bypass this indirect.
module.exports = npmRunAll
3 changes: 1 addition & 2 deletions lib/create-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Public Interface
Expand All @@ -20,7 +19,7 @@
* @param {boolean} isTTY - The flag to color the header.
* @returns {string} The header of a given task.
*/
module.exports = function createHeader (nameAndArgs, packageInfo, isTTY, ansiStyles) {
export default function createHeader (nameAndArgs, packageInfo, isTTY, ansiStyles) {
if (!packageInfo) {
return `\n> ${nameAndArgs}\n\n`
}
Expand Down
5 changes: 2 additions & 3 deletions lib/create-prefix-transform-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
* @copyright 2016 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
'use strict'

// ------------------------------------------------------------------------------
// Requirements
// ------------------------------------------------------------------------------

const stream = require('stream')
import stream from 'stream'

// ------------------------------------------------------------------------------
// Helpers
Expand Down Expand Up @@ -86,6 +85,6 @@ class PrefixTransform extends stream.Transform {
* @param {boolean} state.lastIsLinebreak -The flag to check whether the last output is a line break or not.
* @returns {stream.Transform} The created transform stream.
*/
module.exports = function createPrefixTransform (prefix, state) {
export default function createPrefixTransform (prefix, state) {
return new PrefixTransform(prefix, state)
}
Loading