From 8fde22a145bdcde21d18911c554bda9ddaca6945 Mon Sep 17 00:00:00 2001 From: Jayden Seric Date: Sun, 14 Jun 2020 15:27:21 +1000 Subject: [PATCH] Support native ESM in Node.js. --- changelog.md | 2 + cli/coverage-node.js | 12 ++-- lib/coverageSupportedMinNodeVersion.js | 14 ----- package.json | 18 +++++- {lib => private}/childProcessPromise.js | 0 {lib => private}/errorConsole.js | 4 +- {lib => private}/semver.js | 0 {lib => private}/sourceRange.js | 0 {lib => public}/analyseCoverage.js | 16 ++++- {lib => public}/coverageSupported.js | 16 ++++- public/coverageSupportedMinNodeVersion.js | 26 ++++++++ {lib => public}/index.js | 0 public/index.mjs | 4 ++ {lib => public}/reportCoverage.js | 16 ++++- readme.md | 64 ++++++++++++++++++-- test/cli/coverage-node.test.js | 4 +- test/index.js | 6 +- test/{lib => private}/semver.test.js | 2 +- test/{lib => private}/sourceRange.test.js | 2 +- test/{lib => public}/analyseCoverage.test.js | 4 +- 20 files changed, 166 insertions(+), 44 deletions(-) delete mode 100644 lib/coverageSupportedMinNodeVersion.js rename {lib => private}/childProcessPromise.js (100%) rename {lib => private}/errorConsole.js (80%) rename {lib => private}/semver.js (100%) rename {lib => private}/sourceRange.js (100%) rename {lib => public}/analyseCoverage.js (89%) rename {lib => public}/coverageSupported.js (60%) create mode 100644 public/coverageSupportedMinNodeVersion.js rename {lib => public}/index.js (100%) create mode 100644 public/index.mjs rename {lib => public}/reportCoverage.js (82%) rename test/{lib => private}/semver.test.js (91%) rename test/{lib => private}/sourceRange.test.js (98%) rename test/{lib => public}/analyseCoverage.test.js (97%) diff --git a/changelog.md b/changelog.md index 533619a..61c5093 100644 --- a/changelog.md +++ b/changelog.md @@ -6,10 +6,12 @@ - Updated supported Node.js versions to `^10.17.0 || ^12.0.0 || >= 13.7.0`. - Updated dependencies, some of which require newer Node.js versions than were previously supported. +- Added a [package `exports` field](https://nodejs.org/api/esm.html#esm_package_entry_points) with [conditional exports](https://nodejs.org/api/esm.html#esm_conditional_exports) to support native ESM in Node.js and keep internal code private, [whilst avoiding the dual package hazard](https://nodejs.org/api/esm.html#esm_approach_1_use_an_es_module_wrapper). Published files have been reorganized, so previously undocumented deep imports will need to be rewritten according to the newly documented paths. ### Patch - Updated Prettier config and scripts. +- Added ESM related keywords to the package `keywords` field. - Updated ESLint config to match the new Node.js version support. - Moved reading `process.argv` into the `coverageNode` function scope. - Improved a JSDoc return type. diff --git a/cli/coverage-node.js b/cli/coverage-node.js index d462f7c..e2b8432 100755 --- a/cli/coverage-node.js +++ b/cli/coverage-node.js @@ -5,12 +5,12 @@ const { spawn } = require('child_process'); const { disposableDirectory } = require('disposable-directory'); const kleur = require('kleur'); -const analyseCoverage = require('../lib/analyseCoverage'); -const childProcessPromise = require('../lib/childProcessPromise'); -const coverageSupported = require('../lib/coverageSupported'); -const minNodeVersion = require('../lib/coverageSupportedMinNodeVersion'); -const errorConsole = require('../lib/errorConsole'); -const reportCoverage = require('../lib/reportCoverage'); +const childProcessPromise = require('../private/childProcessPromise'); +const errorConsole = require('../private/errorConsole'); +const analyseCoverage = require('../public/analyseCoverage'); +const coverageSupported = require('../public/coverageSupported'); +const minNodeVersion = require('../public/coverageSupportedMinNodeVersion'); +const reportCoverage = require('../public/reportCoverage'); /** * Powers the `coverage-node` CLI. Runs Node.js with the given arguments and diff --git a/lib/coverageSupportedMinNodeVersion.js b/lib/coverageSupportedMinNodeVersion.js deleted file mode 100644 index fcc9739..0000000 --- a/lib/coverageSupportedMinNodeVersion.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -/** - * Minimum Node.js version supported for code coverage. Although Node.js v10+ - * supports coverage, only v13.3+ produces coverage data reliable enough to use. - * @kind constant - * @name coverageSupportedMinNodeVersion - * @type {SemanticVersion} - * @example How to import. - * ```js - * const { coverageSupportedMinNodeVersion } = require('coverage-node'); - * ``` - */ -module.exports = { major: 13, minor: 3, patch: 0 }; diff --git a/package.json b/package.json index c2a3897..5877ff5 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,25 @@ "check", "report", "code", - "coverage" + "coverage", + "esm", + "mjs" ], "files": [ "cli", - "lib" + "private", + "public" ], - "main": "lib", + "main": "public", + "exports": { + ".": { + "import": "./public/index.mjs", + "require": "./public/index.js" + }, + "./public/": "./public/", + "./package": "./package.json", + "./package.json": "./package.json" + }, "bin": { "coverage-node": "cli/coverage-node.js" }, diff --git a/lib/childProcessPromise.js b/private/childProcessPromise.js similarity index 100% rename from lib/childProcessPromise.js rename to private/childProcessPromise.js diff --git a/lib/errorConsole.js b/private/errorConsole.js similarity index 80% rename from lib/errorConsole.js rename to private/errorConsole.js index b5deeee..b320e8b 100644 --- a/lib/errorConsole.js +++ b/private/errorConsole.js @@ -3,8 +3,8 @@ const { Console } = require('console'); /* - * The `console` API, but all output is to `stderr`. This allows - * `console.group` to be used with `console.error`. + * The `console` API, but all output is to `stderr`. This allows `console.group` + * to be used with `console.error`. */ module.exports = new Console({ stdout: process.stderr, diff --git a/lib/semver.js b/private/semver.js similarity index 100% rename from lib/semver.js rename to private/semver.js diff --git a/lib/sourceRange.js b/private/sourceRange.js similarity index 100% rename from lib/sourceRange.js rename to private/sourceRange.js diff --git a/lib/analyseCoverage.js b/public/analyseCoverage.js similarity index 89% rename from lib/analyseCoverage.js rename to public/analyseCoverage.js index 1033b42..395e122 100644 --- a/lib/analyseCoverage.js +++ b/public/analyseCoverage.js @@ -4,7 +4,7 @@ const fs = require('fs'); const { join } = require('path'); const { fileURLToPath } = require('url'); const { mergeProcessCovs } = require('@bcoe/v8-coverage'); -const sourceRange = require('./sourceRange'); +const sourceRange = require('../private/sourceRange'); /** * Analyzes [Node.js generated V8 JavaScript code coverage data](https://nodejs.org/api/cli.html#cli_node_v8_coverage_dir) @@ -13,10 +13,22 @@ const sourceRange = require('./sourceRange'); * @name analyseCoverage * @param {string} coverageDirPath Code coverage data directory path. * @returns {Promise} Resolves the coverage analysis. - * @example How to import. + * @example Ways to `import`. + * ```js + * import { analyseCoverage } from 'coverage-node'; + * ``` + * + * ```js + * import analyseCoverage from 'coverage-node/public/analyseCoverage.js'; + * ``` + * @example Ways to `require`. * ```js * const { analyseCoverage } = require('coverage-node'); * ``` + * + * ```js + * const analyseCoverage = require('coverage-node/public/analyseCoverage'); + * ``` */ module.exports = async function analyseCoverage(coverageDirPath) { const coverageDirFileNames = await fs.promises.readdir(coverageDirPath); diff --git a/lib/coverageSupported.js b/public/coverageSupported.js similarity index 60% rename from lib/coverageSupported.js rename to public/coverageSupported.js index 3aeda86..080da6b 100644 --- a/lib/coverageSupported.js +++ b/public/coverageSupported.js @@ -1,11 +1,11 @@ 'use strict'; +const semver = require('../private/semver'); const { major: minMajor, minor: minMinor, patch: minPatch, } = require('./coverageSupportedMinNodeVersion'); -const semver = require('./semver'); const { major, minor, patch } = semver(process.versions.node); @@ -15,10 +15,22 @@ const { major, minor, patch } = semver(process.versions.node); * @kind constant * @name coverageSupported * @type {boolean} - * @example How to import. + * @example Ways to `import`. + * ```js + * import { coverageSupported } from 'coverage-node'; + * ``` + * + * ```js + * import coverageSupported from 'coverage-node/public/coverageSupported.js'; + * ``` + * @example Ways to `require`. * ```js * const { coverageSupported } = require('coverage-node'); * ``` + * + * ```js + * const coverageSupported = require('coverage-node/public/coverageSupported'); + * ``` */ module.exports = // coverage ignore next line diff --git a/public/coverageSupportedMinNodeVersion.js b/public/coverageSupportedMinNodeVersion.js new file mode 100644 index 0000000..d9eb039 --- /dev/null +++ b/public/coverageSupportedMinNodeVersion.js @@ -0,0 +1,26 @@ +'use strict'; + +/** + * Minimum Node.js version supported for code coverage. Although Node.js v10+ + * supports coverage, only v13.3+ produces coverage data reliable enough to use. + * @kind constant + * @name coverageSupportedMinNodeVersion + * @type {SemanticVersion} + * @example Ways to `import`. + * ```js + * import { coverageSupportedMinNodeVersion } from 'coverage-node'; + * ``` + * + * ```js + * import coverageSupportedMinNodeVersion from 'coverage-node/public/coverageSupportedMinNodeVersion.js'; + * ``` + * @example Ways to `require`. + * ```js + * const { coverageSupportedMinNodeVersion } = require('coverage-node'); + * ``` + * + * ```js + * const coverageSupportedMinNodeVersion = require('coverage-node/public/coverageSupportedMinNodeVersion'); + * ``` + */ +module.exports = { major: 13, minor: 3, patch: 0 }; diff --git a/lib/index.js b/public/index.js similarity index 100% rename from lib/index.js rename to public/index.js diff --git a/public/index.mjs b/public/index.mjs new file mode 100644 index 0000000..71a5b7c --- /dev/null +++ b/public/index.mjs @@ -0,0 +1,4 @@ +export { default as coverageSupported } from './coverageSupported.js'; +export { default as coverageSupportedMinNodeVersion } from './coverageSupportedMinNodeVersion.js'; +export { default as analyseCoverage } from './analyseCoverage.js'; +export { default as reportCoverage } from './reportCoverage.js'; diff --git a/lib/reportCoverage.js b/public/reportCoverage.js similarity index 82% rename from lib/reportCoverage.js rename to public/reportCoverage.js index fa4dbbc..757ad53 100644 --- a/lib/reportCoverage.js +++ b/public/reportCoverage.js @@ -2,17 +2,29 @@ const { relative } = require('path'); const kleur = require('kleur'); -const errorConsole = require('./errorConsole'); +const errorConsole = require('../private/errorConsole'); /** * Reports a code coverage analysis to the console. * @kind function * @name reportCoverage * @param {CoverageAnalysis} coverageAnalysis Coverage analysis from [`analyseCoverage`]{@link analyseCoverage}. - * @example How to import. + * @example Ways to `import`. + * ```js + * import { reportCoverage } from 'coverage-node'; + * ``` + * + * ```js + * import reportCoverage from 'coverage-node/public/reportCoverage.js'; + * ``` + * @example Ways to `require`. * ```js * const { reportCoverage } = require('coverage-node'); * ``` + * + * ```js + * const reportCoverage = require('coverage-node/public/reportCoverage'); + * ``` */ module.exports = function reportCoverage({ filesCount, diff --git a/readme.md b/readme.md index 78a7597..e50f6d3 100644 --- a/readme.md +++ b/readme.md @@ -89,11 +89,25 @@ Analyzes [Node.js generated V8 JavaScript code coverage data](https://nodejs.org #### Examples -_How to import._ +_Ways to `import`._ + +> ```js +> import { analyseCoverage } from 'coverage-node'; +> ``` +> +> ```js +> import analyseCoverage from 'coverage-node/public/analyseCoverage.js'; +> ``` + +_Ways to `require`._ > ```js > const { analyseCoverage } = require('coverage-node'); > ``` +> +> ```js +> const analyseCoverage = require('coverage-node/public/analyseCoverage'); +> ``` --- @@ -107,11 +121,25 @@ Reports a code coverage analysis to the console. #### Examples -_How to import._ +_Ways to `import`._ + +> ```js +> import { reportCoverage } from 'coverage-node'; +> ``` +> +> ```js +> import reportCoverage from 'coverage-node/public/reportCoverage.js'; +> ``` + +_Ways to `require`._ > ```js > const { reportCoverage } = require('coverage-node'); > ``` +> +> ```js +> const reportCoverage = require('coverage-node/public/reportCoverage'); +> ``` --- @@ -123,11 +151,25 @@ Is the process Node.js version greater at least [the minimum required to support #### Examples -_How to import._ +_Ways to `import`._ + +> ```js +> import { coverageSupported } from 'coverage-node'; +> ``` +> +> ```js +> import coverageSupported from 'coverage-node/public/coverageSupported.js'; +> ``` + +_Ways to `require`._ > ```js > const { coverageSupported } = require('coverage-node'); > ``` +> +> ```js +> const coverageSupported = require('coverage-node/public/coverageSupported'); +> ``` --- @@ -139,11 +181,25 @@ Minimum Node.js version supported for code coverage. Although Node.js v10+ suppo #### Examples -_How to import._ +_Ways to `import`._ + +> ```js +> import { coverageSupportedMinNodeVersion } from 'coverage-node'; +> ``` +> +> ```js +> import coverageSupportedMinNodeVersion from 'coverage-node/public/coverageSupportedMinNodeVersion.js'; +> ``` + +_Ways to `require`._ > ```js > const { coverageSupportedMinNodeVersion } = require('coverage-node'); > ``` +> +> ```js +> const coverageSupportedMinNodeVersion = require('coverage-node/public/coverageSupportedMinNodeVersion'); +> ``` --- diff --git a/test/cli/coverage-node.test.js b/test/cli/coverage-node.test.js index fcf282c..98c579c 100644 --- a/test/cli/coverage-node.test.js +++ b/test/cli/coverage-node.test.js @@ -4,8 +4,8 @@ const { strictEqual } = require('assert'); const fs = require('fs'); const { join, relative } = require('path'); const { disposableDirectory } = require('disposable-directory'); -const coverageSupported = require('../../lib/coverageSupported'); -const minNodeVersion = require('../../lib/coverageSupportedMinNodeVersion'); +const coverageSupported = require('../../public/coverageSupported'); +const minNodeVersion = require('../../public/coverageSupportedMinNodeVersion'); const execFilePromise = require('../execFilePromise'); const stripStackTraces = require('../stripStackTraces'); diff --git a/test/index.js b/test/index.js index fd1edb2..e999d76 100644 --- a/test/index.js +++ b/test/index.js @@ -5,8 +5,8 @@ const { TestDirector } = require('test-director'); const tests = new TestDirector(); require('./cli/coverage-node.test')(tests); -require('./lib/analyseCoverage.test')(tests); -require('./lib/semver.test')(tests); -require('./lib/sourceRange.test')(tests); +require('./private/semver.test')(tests); +require('./private/sourceRange.test')(tests); +require('./public/analyseCoverage.test')(tests); tests.run(); diff --git a/test/lib/semver.test.js b/test/private/semver.test.js similarity index 91% rename from test/lib/semver.test.js rename to test/private/semver.test.js index 9379093..560c2e5 100644 --- a/test/lib/semver.test.js +++ b/test/private/semver.test.js @@ -1,7 +1,7 @@ 'use strict'; const { deepStrictEqual } = require('assert'); -const semver = require('../../lib/semver'); +const semver = require('../../private/semver'); module.exports = (tests) => { tests.add('`semver` with a simple version.', () => { diff --git a/test/lib/sourceRange.test.js b/test/private/sourceRange.test.js similarity index 98% rename from test/lib/sourceRange.test.js rename to test/private/sourceRange.test.js index f0fb3fe..c92e7f2 100644 --- a/test/lib/sourceRange.test.js +++ b/test/private/sourceRange.test.js @@ -1,7 +1,7 @@ 'use strict'; const { deepStrictEqual } = require('assert'); -const sourceRange = require('../../lib/sourceRange'); +const sourceRange = require('../../private/sourceRange'); module.exports = (tests) => { tests.add('`sourceRange` with a single char line.', () => { diff --git a/test/lib/analyseCoverage.test.js b/test/public/analyseCoverage.test.js similarity index 97% rename from test/lib/analyseCoverage.test.js rename to test/public/analyseCoverage.test.js index 8ba5ad3..744d887 100644 --- a/test/lib/analyseCoverage.test.js +++ b/test/public/analyseCoverage.test.js @@ -5,8 +5,8 @@ const { spawn } = require('child_process'); const fs = require('fs'); const { join } = require('path'); const { disposableDirectory } = require('disposable-directory'); -const analyseCoverage = require('../../lib/analyseCoverage'); -const childProcessPromise = require('../../lib/childProcessPromise'); +const childProcessPromise = require('../../private/childProcessPromise'); +const analyseCoverage = require('../../public/analyseCoverage'); module.exports = (tests) => { tests.add(