Skip to content

Commit

Permalink
Require Node.js 18 and npm 9
Browse files Browse the repository at this point in the history
  • Loading branch information
sindresorhus committed Nov 4, 2023
1 parent c31c2bc commit 6c2e00e
Show file tree
Hide file tree
Showing 13 changed files with 53 additions and 75 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/main.yml
Expand Up @@ -10,12 +10,10 @@ jobs:
fail-fast: false
matrix:
node-version:
- 19
- 18
- 16
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: git config --global user.name "Github Actions"
Expand Down
32 changes: 16 additions & 16 deletions package.json
Expand Up @@ -8,8 +8,8 @@
"type": "module",
"bin": "source/cli.js",
"engines": {
"node": ">=16.6.0",
"npm": ">=7.19.0",
"node": ">=18",
"npm": ">=9",
"git": ">=2.11.0",
"yarn": ">=1.7.0"
},
Expand All @@ -33,55 +33,55 @@
"dependencies": {
"chalk": "^5.3.0",
"chalk-template": "^1.1.0",
"cosmiconfig": "^8.1.3",
"cosmiconfig": "^8.3.6",
"del": "^7.1.0",
"escape-goat": "^4.0.0",
"escape-string-regexp": "^5.0.0",
"execa": "^8.0.1",
"exit-hook": "^4.0.0",
"github-url-from-git": "^1.5.0",
"has-yarn": "^3.0.0",
"hosted-git-info": "^7.0.0",
"hosted-git-info": "^7.0.1",
"ignore-walk": "^6.0.3",
"import-local": "^3.1.0",
"inquirer": "^9.2.10",
"inquirer": "^9.2.11",
"is-installed-globally": "^0.4.0",
"is-interactive": "^2.0.0",
"is-scoped": "^3.0.0",
"issue-regex": "^4.1.0",
"listr": "^0.14.3",
"listr-input": "^0.2.1",
"log-symbols": "^5.1.0",
"log-symbols": "^6.0.0",
"meow": "^12.1.1",
"new-github-release-url": "^2.0.0",
"npm-name": "^7.1.0",
"npm-name": "^7.1.1",
"onetime": "^6.0.0",
"open": "^9.1.0",
"ow": "^1.1.1",
"p-memoize": "^7.1.1",
"p-timeout": "^6.1.2",
"path-exists": "^5.0.0",
"pkg-dir": "^7.0.0",
"read-pkg": "^8.1.0",
"read-pkg-up": "^10.1.0",
"pkg-dir": "^8.0.0",
"read-pkg": "^9.0.0",
"read-package-up": "^11.0.0",
"rxjs": "^7.8.1",
"semver": "^7.5.4",
"symbol-observable": "^4.0.0",
"terminal-link": "^3.0.0",
"update-notifier": "^6.0.2"
"update-notifier": "^7.0.0"
},
"devDependencies": {
"@sindresorhus/is": "^6.0.0",
"@types/semver": "^7.5.1",
"@sindresorhus/is": "^6.1.0",
"@types/semver": "^7.5.4",
"ava": "^5.3.1",
"common-tags": "^1.8.2",
"esmock": "^2.3.8",
"esmock": "^2.5.9",
"fs-extra": "^11.1.1",
"map-obj": "^5.0.2",
"sinon": "^15.2.0",
"sinon": "^17.0.1",
"strip-ansi": "^7.1.0",
"tempy": "^3.1.0",
"write-pkg": "^6.0.0",
"write-package": "^7.0.0",
"xo": "^0.56.0"
},
"ava": {
Expand Down
8 changes: 3 additions & 5 deletions readme.md
Expand Up @@ -54,8 +54,8 @@

## Prerequisite

- Node.js 16 or later
- npm 7.19.0 or later
- Node.js 18 or later
- npm 9 or later
- Git 2.11 or later

## Install
Expand Down Expand Up @@ -340,14 +340,12 @@ npm ERR! code E403
npm ERR! 403 Forbidden - GET https://registry.yarnpkg.com/-/package/my-awesome-package/collaborators?format=cli - Forbidden
```

…please check whether the command `npm access ls-collaborators my-awesome-package` succeeds. If it doesn't, Yarn has overwritten your registry URL. To fix this, add the correct registry URL to `package.json`:
…please check whether the command `npm access list collaborators my-awesome-package` succeeds. If it doesn't, Yarn has overwritten your registry URL. To fix this, add the correct registry URL to `package.json`:

```json
"publishConfig": {
"registry": "https://registry.npmjs.org"
}

Note: On `npm` v9+, the command has been changed to `npm access list collaborators my-awesome-package`.
```

## Maintainers
Expand Down
30 changes: 13 additions & 17 deletions source/config.js
Expand Up @@ -2,30 +2,26 @@ import os from 'node:os';
import isInstalledGlobally from 'is-installed-globally';
import {cosmiconfig} from 'cosmiconfig';

// TODO: Remove when cosmiconfig/cosmiconfig#283 lands
const loadESM = async filepath => {
const module = await import(filepath);
return module.default ?? module;
};
export default async function getConfig(rootDirectory) {
const searchDirectory = isInstalledGlobally ? os.homedir() : rootDirectory;

const searchPlaces = [
'.np-config.json',
'.np-config.js',
'.np-config.cjs',
'.np-config.mjs',
];

const getConfig = async rootDir => {
const searchDir = isInstalledGlobally ? os.homedir() : rootDir;
const searchPlaces = ['.np-config.json', '.np-config.js', '.np-config.cjs', '.np-config.mjs'];
if (!isInstalledGlobally) {
searchPlaces.push('package.json');
}

const explorer = cosmiconfig('np', {
searchPlaces,
stopDir: searchDir,
loaders: {
'.js': loadESM,
'.mjs': loadESM,
},
stopDir: searchDirectory,
});
const {config} = (await explorer.search(searchDir)) || {};

return config;
};
const {config} = (await explorer.search(searchDirectory)) ?? {};

export default getConfig;
return config;
}
11 changes: 3 additions & 8 deletions source/npm/util.js
Expand Up @@ -5,7 +5,6 @@ import pTimeout from 'p-timeout';
import ow from 'ow';
import npmName from 'npm-name';
import chalk from 'chalk-template';
import Version from '../version.js';
import * as util from '../util.js';

export const version = async () => {
Expand Down Expand Up @@ -51,18 +50,14 @@ export const collaborators = async pkg => {
const packageName = pkg.name;
ow(packageName, ow.string);

const npmVersion = await version();
// TODO: Remove old command when targeting Node.js 18
const args = new Version(npmVersion).satisfies('>=9.0.0')
? ['access', 'list', 'collaborators', packageName, '--json']
: ['access', 'ls-collaborators', packageName];
const arguments_ = ['access', 'list', 'collaborators', packageName, '--json'];

if (isExternalRegistry(pkg)) {
args.push('--registry', pkg.publishConfig.registry);
arguments_.push('--registry', pkg.publishConfig.registry);
}

try {
const {stdout} = await execa('npm', args);
const {stdout} = await execa('npm', arguments_);
return stdout;
} catch (error) {
// Ignore non-existing package error
Expand Down
2 changes: 1 addition & 1 deletion source/util.js
@@ -1,7 +1,7 @@
import process from 'node:process';
import {fileURLToPath} from 'node:url';
import path from 'node:path';
import {readPackageUp} from 'read-pkg-up';
import {readPackageUp} from 'read-package-up';
import {parsePackage} from 'read-pkg';
import issueRegex from 'issue-regex';
import terminalLink from 'terminal-link';
Expand Down
9 changes: 2 additions & 7 deletions test/npm/util/collaborators.js
Expand Up @@ -14,7 +14,6 @@ test('pkg.name not a string', async t => {
});

const npmVersionFixtures = [
{version: '8.0.0', accessCommand: 'npm access ls-collaborators np'},
{version: '9.0.0', accessCommand: 'npm access list collaborators np --json'},
];

Expand Down Expand Up @@ -66,9 +65,7 @@ for (const {version, accessCommand} of npmVersionFixtures) {
test(`npm v${version} - non-existent`, createFixture, [
npmVersionCommand,
{
command: version === '8.0.0'
? 'npm access ls-collaborators non-existent'
: 'npm access list collaborators non-existent --json',
command: 'npm access list collaborators non-existent --json',
stderr: 'npm ERR! code E404\nnpm ERR! 404 Not Found',
},
], async ({t, testedModule: {collaborators}}) => {
Expand All @@ -81,9 +78,7 @@ for (const {version, accessCommand} of npmVersionFixtures) {
test(`npm v${version} - error`, createFixture, [
npmVersionCommand,
{
command: version === '8.0.0'
? 'npm access ls-collaborators @private/pkg'
: 'npm access list collaborators @private/pkg --json',
command: 'npm access list collaborators @private/pkg --json',
stderr: 'npm ERR! code E403\nnpm ERR! 403 403 Forbidden',
},
], async ({t, testedModule: {collaborators}}) => {
Expand Down
6 changes: 3 additions & 3 deletions test/npm/util/verify-recent-npm-version.js
Expand Up @@ -6,7 +6,7 @@ const createFixture = _createFixture('../../../source/npm/util.js', import.meta.

test('satisfied', createFixture, [{
command: 'npm --version',
stdout: '7.20.0', // One higher than minimum
stdout: '99.20.0', // Higher than minimum
}], async ({t, testedModule: npm}) => {
await t.notThrowsAsync(
npm.verifyRecentNpmVersion(),
Expand All @@ -15,10 +15,10 @@ test('satisfied', createFixture, [{

test('not satisfied', createFixture, [{
command: 'npm --version',
stdout: '7.18.0', // One lower than minimum
stdout: '5.18.0', // Lower than minimum
}], async ({t, testedModule: npm}) => {
await t.throwsAsync(
npm.verifyRecentNpmVersion(),
{message: '`np` requires npm >=7.19.0'},
{message: /`np` requires npm >=/},
);
});
6 changes: 1 addition & 5 deletions test/tasks/prerequisite-tasks.js
Expand Up @@ -96,7 +96,7 @@ test.serial('should fail when user is not authenticated at npm registry', create
stdout: 'sindresorhus',
},
{
command: 'npm access ls-collaborators test',
command: 'npm access list collaborators test',
stdout: '{"sindresorhus": "read"}',
},
], async ({t, testedModule: prerequisiteTasks}) => {
Expand All @@ -117,10 +117,6 @@ test.serial('should fail when user is not authenticated at external registry', c
command: 'npm whoami --registry http://my.io',
stdout: 'sindresorhus',
},
{
command: 'npm access ls-collaborators test --registry http://my.io',
stdout: '{"sindresorhus": "read"}',
},
{
command: 'npm access list collaborators test --json --registry http://my.io',
stdout: '{"sindresorhus": "read"}',
Expand Down
2 changes: 1 addition & 1 deletion test/ui/new-files-dependencies.js
@@ -1,7 +1,7 @@
import test from 'ava';
import sinon from 'sinon';
import {execa} from 'execa';
import {removePackageDependencies, updatePackage} from 'write-pkg';
import {removePackageDependencies, updatePackage} from 'write-package';
import stripAnsi from 'strip-ansi';
import {readPackage} from 'read-pkg';
import {createIntegrationTest} from '../_helpers/integration-test.js';
Expand Down
2 changes: 1 addition & 1 deletion test/util/get-new-dependencies.js
@@ -1,5 +1,5 @@
import test from 'ava';
import {updatePackage} from 'write-pkg';
import {updatePackage} from 'write-package';
import {readPackage} from 'read-pkg';
import {_createFixture} from '../_helpers/integration-test.js';

Expand Down
2 changes: 1 addition & 1 deletion test/util/get-new-files.js
Expand Up @@ -2,7 +2,7 @@ import path from 'node:path';
import test from 'ava';
import esmock from 'esmock';
import {execa} from 'execa';
import {writePackage} from 'write-pkg';
import {writePackage} from 'write-package';
import {createIntegrationTest} from '../_helpers/integration-test.js';

const createNewFilesFixture = test.macro(async (t, input, commands) => {
Expand Down
12 changes: 6 additions & 6 deletions test/util/validate-engine-version-satisfies.js
Expand Up @@ -5,20 +5,20 @@ const testEngineRanges = test.macro((t, engine, {above, below}) => {
const range = npPkg.engines[engine];

t.notThrows(
() => validateEngineVersionSatisfies(engine, above), // One above minimum
() => validateEngineVersionSatisfies(engine, above), // Above minimum
);

t.throws(
() => validateEngineVersionSatisfies(engine, below), // One below minimum
() => validateEngineVersionSatisfies(engine, below), // Below minimum
{message: `\`np\` requires ${engine} ${range}`},
);
});

test('node', testEngineRanges, 'node', {above: '16.7.0', below: '16.5.0'});
test('node', testEngineRanges, 'node', {above: '99.7.0', below: '16.5.0'});

test('npm', testEngineRanges, 'npm', {above: '7.20.0', below: '7.18.0'});
test('npm', testEngineRanges, 'npm', {above: '99.20.0', below: '7.18.0'});

test('git', testEngineRanges, 'git', {above: '2.12.0', below: '2.10.0'});
test('git', testEngineRanges, 'git', {above: '99.12.0', below: '2.10.0'});

test('yarn', testEngineRanges, 'yarn', {above: '1.8.0', below: '1.6.0'});
test('yarn', testEngineRanges, 'yarn', {above: '99.8.0', below: '1.6.0'});

0 comments on commit 6c2e00e

Please sign in to comment.