From c4fc03e9eb3a6386e8feacb67c19f0a1578dfe38 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Fri, 28 May 2021 14:44:27 -0400 Subject: [PATCH 01/10] @npmcli/arborist@2.6.1 --- node_modules/@npmcli/arborist/lib/diff.js | 20 +++++++++++++++++-- .../@npmcli/arborist/lib/shrinkwrap.js | 7 ++++++- node_modules/@npmcli/arborist/package.json | 2 +- package-lock.json | 14 ++++++------- package.json | 2 +- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/node_modules/@npmcli/arborist/lib/diff.js b/node_modules/@npmcli/arborist/lib/diff.js index 842996ba48669..dac7c81f8ecfb 100644 --- a/node_modules/@npmcli/arborist/lib/diff.js +++ b/node_modules/@npmcli/arborist/lib/diff.js @@ -110,16 +110,32 @@ const getAction = ({actual, ideal}) => { if (ideal.isRoot && actual.isRoot) return null + // if the versions don't match, it's a change no matter what + if (ideal.version !== actual.version) + return 'CHANGE' + const binsExist = ideal.binPaths.every((path) => existsSync(path)) // top nodes, links, and git deps won't have integrity, but do have resolved - if (!ideal.integrity && !actual.integrity && ideal.resolved === actual.resolved && binsExist) + // if neither node has integrity, the bins exist, and either (a) neither + // node has a resolved value or (b) they both do and match, then we can + // leave this one alone since we already know the versions match due to + // the condition above. The "neither has resolved" case (a) cannot be + // treated as a 'mark CHANGE and refetch', because shrinkwraps, bundles, + // and link deps may lack this information, and we don't want to try to + // go to the registry for something that isn't there. + const noIntegrity = !ideal.integrity && !actual.integrity + const noResolved = !ideal.resolved && !actual.resolved + const resolvedMatch = ideal.resolved && ideal.resolved === actual.resolved + if (noIntegrity && binsExist && (resolvedMatch || noResolved)) return null // otherwise, verify that it's the same bits // note that if ideal has integrity, and resolved doesn't, we treat // that as a 'change', so that it gets re-fetched and locked down. - if (!ideal.integrity || !actual.integrity || !ssri.parse(ideal.integrity).match(actual.integrity) || !binsExist) + const integrityMismatch = !ideal.integrity || !actual.integrity || + !ssri.parse(ideal.integrity).match(actual.integrity) + if (integrityMismatch || !binsExist) return 'CHANGE' return null diff --git a/node_modules/@npmcli/arborist/lib/shrinkwrap.js b/node_modules/@npmcli/arborist/lib/shrinkwrap.js index cff9f09633dfc..0a19ef93005ad 100644 --- a/node_modules/@npmcli/arborist/lib/shrinkwrap.js +++ b/node_modules/@npmcli/arborist/lib/shrinkwrap.js @@ -714,6 +714,7 @@ class Shrinkwrap { resolved, integrity, hasShrinkwrap, + version, } = this.get(node.path) const pathFixed = !resolved ? null @@ -727,8 +728,12 @@ class Shrinkwrap { node.resolved === pathFixed const integrityOk = !integrity || !node.integrity || node.integrity === integrity + const versionOk = !version || !node.version || version === node.version - if ((resolved || integrity) && resolvedOk && integrityOk) { + const allOk = (resolved || integrity || version) && + resolvedOk && integrityOk && versionOk + + if (allOk) { node.resolved = node.resolved || pathFixed || null node.integrity = node.integrity || integrity || null node.hasShrinkwrap = node.hasShrinkwrap || hasShrinkwrap || false diff --git a/node_modules/@npmcli/arborist/package.json b/node_modules/@npmcli/arborist/package.json index 8500eaadf6752..8aaa8ecdb7a4e 100644 --- a/node_modules/@npmcli/arborist/package.json +++ b/node_modules/@npmcli/arborist/package.json @@ -1,6 +1,6 @@ { "name": "@npmcli/arborist", - "version": "2.6.0", + "version": "2.6.1", "description": "Manage node_modules trees", "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", diff --git a/package-lock.json b/package-lock.json index 3e3f6a7db04c7..bc8ac92f69e81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,7 +78,7 @@ ], "license": "Artistic-2.0", "dependencies": { - "@npmcli/arborist": "^2.6.0", + "@npmcli/arborist": "^2.6.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^2.2.0", "@npmcli/run-script": "^1.8.5", @@ -712,9 +712,9 @@ } }, "node_modules/@npmcli/arborist": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.6.0.tgz", - "integrity": "sha512-6njRVuPMgGRvQUmsXwGdp1ItZtJuSdt5ouoQe4AeFTTZoMufKWLeXFDOlWj7qbMAzqw+guNEAZwBiwm04J7T2g==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.6.1.tgz", + "integrity": "sha512-OOlntFIOAo7RplEQaYXlA5U5NXE+EwZtnTCsit4Wtme5+llGiea6GBytuV8dOzdPMPlNx3fQQjBUE9E8k76yjQ==", "inBundle": true, "dependencies": { "@npmcli/installed-package-contents": "^1.0.7", @@ -10811,9 +10811,9 @@ "dev": true }, "@npmcli/arborist": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.6.0.tgz", - "integrity": "sha512-6njRVuPMgGRvQUmsXwGdp1ItZtJuSdt5ouoQe4AeFTTZoMufKWLeXFDOlWj7qbMAzqw+guNEAZwBiwm04J7T2g==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-2.6.1.tgz", + "integrity": "sha512-OOlntFIOAo7RplEQaYXlA5U5NXE+EwZtnTCsit4Wtme5+llGiea6GBytuV8dOzdPMPlNx3fQQjBUE9E8k76yjQ==", "requires": { "@npmcli/installed-package-contents": "^1.0.7", "@npmcli/map-workspaces": "^1.0.2", diff --git a/package.json b/package.json index 60637d6055154..d0b40812141a7 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "./package.json": "./package.json" }, "dependencies": { - "@npmcli/arborist": "^2.6.0", + "@npmcli/arborist": "^2.6.1", "@npmcli/ci-detect": "^1.2.0", "@npmcli/config": "^2.2.0", "@npmcli/run-script": "^1.8.5", From 598a17a2671c9e3bc204dddd6488169c9a72c6a1 Mon Sep 17 00:00:00 2001 From: Gar Date: Fri, 28 May 2021 09:23:49 -0700 Subject: [PATCH 02/10] fix(libnpmexec): don't detach output from npm The npm output function refers to this.log. libnpmexec has that passed in, which decoupled the function from the npm object. This fixes it, and sets the tests up in a way where if the output function ever becomes detached from this.npm in the same way, tests will fail. PR-URL: https://github.com/npm/cli/pull/3329 Credit: @wraithgar Close: #3329 Reviewed-by: @ruyadorno --- lib/exec.js | 2 +- lib/init.js | 7 ++- tap-snapshots/test/lib/init.js.test.cjs | 21 ++++++-- test/fixtures/mock-npm.js | 65 ++++++++++++++++--------- test/lib/exec.js | 22 ++++----- test/lib/init.js | 20 +++++--- 6 files changed, 89 insertions(+), 48 deletions(-) diff --git a/lib/exec.js b/lib/exec.js index f30746b8c50ed..8a87615d9749e 100644 --- a/lib/exec.js +++ b/lib/exec.js @@ -76,8 +76,8 @@ class Exec extends BaseCommand { localBin, log, globalBin, - output, } = this.npm + const output = (...outputArgs) => this.npm.output(...outputArgs) const scriptShell = this.npm.config.get('script-shell') || undefined const packages = this.npm.config.get('package') const yes = this.npm.config.get('yes') diff --git a/lib/init.js b/lib/init.js index bc809a15e49a9..4dd091601e191 100644 --- a/lib/init.js +++ b/lib/init.js @@ -113,8 +113,13 @@ class Init extends BaseCommand { localBin, log, globalBin, - output, } = this.npm + // this function is definitely called. But because of coverage map stuff + // it ends up both uncovered, and the coverage report doesn't even mention. + // the tests do assert that some output happens, so we know this line is + // being hit. + /* istanbul ignore next */ + const output = (...outputArgs) => this.npm.output(...outputArgs) const locationMsg = await getLocationMsg({ color, path }) const runPath = path const scriptShell = this.npm.config.get('script-shell') || undefined diff --git a/tap-snapshots/test/lib/init.js.test.cjs b/tap-snapshots/test/lib/init.js.test.cjs index 043d8b641dcce..95abbe6c1d830 100644 --- a/tap-snapshots/test/lib/init.js.test.cjs +++ b/tap-snapshots/test/lib/init.js.test.cjs @@ -6,13 +6,28 @@ */ 'use strict' exports[`test/lib/init.js TAP workspaces no args > should print helper info 1`] = ` - +Array [ + Array [ + String( + This utility will walk you through creating a package.json file. + It only covers the most common items, and tries to guess sensible defaults. + + See \`npm help init\` for definitive documentation on these fields + and exactly what they do. + + Use \`npm install \` afterwards to install a package and + save it as a dependency in the package.json file. + + Press ^C at any time to quit. + ), + ], +] ` exports[`test/lib/init.js TAP workspaces no args, existing folder > should print helper info 1`] = ` - +Array [] ` exports[`test/lib/init.js TAP workspaces with arg but missing workspace folder > should print helper info 1`] = ` - +Array [] ` diff --git a/test/fixtures/mock-npm.js b/test/fixtures/mock-npm.js index aa8d44020ee36..c972c35b31861 100644 --- a/test/fixtures/mock-npm.js +++ b/test/fixtures/mock-npm.js @@ -4,35 +4,54 @@ const realConfig = require('../../lib/utils/config') -const mockLog = { - clearProgress: () => {}, - disableProgress: () => {}, - enableProgress: () => {}, - http: () => {}, - info: () => {}, - levels: [], - notice: () => {}, - pause: () => {}, - silly: () => {}, - verbose: () => {}, - warn: () => {}, -} -const mockNpm = (base = {}) => { - const config = base.config || {} - const flatOptions = base.flatOptions || {} - return { - log: mockLog, - ...base, - flatOptions, - config: { +class MockNpm { + constructor (base = {}) { + this._mockOutputs = [] + this.isMockNpm = true + this.base = base + + const config = base.config || {} + + for (const attr in base) { + if (attr !== 'config') { + this[attr] = base[attr] + } + } + + this.flatOptions = base.flatOptions || {} + this.config = { // for now just set `find` to what config.find should return // this works cause `find` is not an existing config entry find: (k) => ({...realConfig.defaults, ...config})[k], get: (k) => ({...realConfig.defaults, ...config})[k], set: (k, v) => config[k] = v, list: [{ ...realConfig.defaults, ...config}] - }, + } + if (!this.log) { + this.log = { + clearProgress: () => {}, + disableProgress: () => {}, + enableProgress: () => {}, + http: () => {}, + info: () => {}, + levels: [], + notice: () => {}, + pause: () => {}, + silly: () => {}, + verbose: () => {}, + warn: () => {}, + } + } + } + + output(...msg) { + if (this.base.output) + return this.base.output(msg) + this._mockOutputs.push(msg) } } -module.exports = mockNpm +// TODO export MockNpm, and change tests to use new MockNpm() +module.exports = (base = {}) => { + return new MockNpm(base) +} diff --git a/test/lib/exec.js b/test/lib/exec.js index 33e30e24f84e0..4f8cc02fce7bd 100644 --- a/test/lib/exec.js +++ b/test/lib/exec.js @@ -1,8 +1,6 @@ const t = require('tap') const mockNpm = require('../fixtures/mock-npm') const { resolve, delimiter } = require('path') -const OUTPUT = [] -const output = (...msg) => OUTPUT.push(msg) const ARB_CTOR = [] const ARB_ACTUAL_TREE = {} @@ -36,6 +34,7 @@ const config = { package: [], 'script-shell': 'shell-cmd', } + const npm = mockNpm({ flatOptions, config, @@ -53,7 +52,6 @@ const npm = mockNpm({ LOG_WARN.push(args) }, }, - output, }) const RUN_SCRIPTS = [] @@ -225,7 +223,7 @@ t.test('npm exec , run interactive shell', t => { ARB_CTOR.length = 0 MKDIRPS.length = 0 ARB_REIFY.length = 0 - OUTPUT.length = 0 + npm._mockOutputs.length = 0 exec.exec([], er => { if (er) throw er @@ -256,7 +254,7 @@ t.test('npm exec , run interactive shell', t => { process.stdin.isTTY = true run(t, true, () => { t.strictSame(LOG_WARN, []) - t.strictSame(OUTPUT, [ + t.strictSame(npm._mockOutputs, [ [`\nEntering npm script environment at location:\n${process.cwd()}\nType 'exit' or ^D when finished\n`], ], 'printed message about interactive shell') t.end() @@ -270,7 +268,7 @@ t.test('npm exec , run interactive shell', t => { run(t, true, () => { t.strictSame(LOG_WARN, []) - t.strictSame(OUTPUT, [ + t.strictSame(npm._mockOutputs, [ [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m at location:\u001b[0m\n\u001b[0m\u001b[2m${process.cwd()}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`], ], 'printed message about interactive shell') t.end() @@ -282,7 +280,7 @@ t.test('npm exec , run interactive shell', t => { process.stdin.isTTY = false run(t, true, () => { t.strictSame(LOG_WARN, []) - t.strictSame(OUTPUT, [], 'no message about interactive shell') + t.strictSame(npm._mockOutputs, [], 'no message about interactive shell') t.end() }) }) @@ -294,7 +292,7 @@ t.test('npm exec , run interactive shell', t => { t.strictSame(LOG_WARN, [ ['exec', 'Interactive mode disabled in CI environment'], ]) - t.strictSame(OUTPUT, [], 'no message about interactive shell') + t.strictSame(npm._mockOutputs, [], 'no message about interactive shell') t.end() }) }) @@ -316,7 +314,7 @@ t.test('npm exec , run interactive shell', t => { ARB_CTOR.length = 0 MKDIRPS.length = 0 ARB_REIFY.length = 0 - OUTPUT.length = 0 + npm._mockOutputs.length = 0 RUN_SCRIPTS.length = 0 t.end() }) @@ -1195,7 +1193,7 @@ t.test('workspaces', t => { return rej(er) t.strictSame(LOG_WARN, []) - t.strictSame(OUTPUT, [ + t.strictSame(npm._mockOutputs, [ [`\nEntering npm script environment in workspace a@1.0.0 at location:\n${resolve(npm.localPrefix, 'packages/a')}\nType 'exit' or ^D when finished\n`], ], 'printed message about interactive shell') res() @@ -1203,14 +1201,14 @@ t.test('workspaces', t => { }) config.color = true - OUTPUT.length = 0 + npm._mockOutputs.length = 0 await new Promise((res, rej) => { exec.execWorkspaces([], ['a'], er => { if (er) return rej(er) t.strictSame(LOG_WARN, []) - t.strictSame(OUTPUT, [ + t.strictSame(npm._mockOutputs, [ [`\u001b[0m\u001b[0m\n\u001b[0mEntering npm script environment\u001b[0m\u001b[0m in workspace \u001b[32ma@1.0.0\u001b[39m at location:\u001b[0m\n\u001b[0m\u001b[2m${resolve(npm.localPrefix, 'packages/a')}\u001b[22m\u001b[0m\u001b[1m\u001b[22m\n\u001b[1mType 'exit' or ^D when finished\u001b[22m\n\u001b[1m\u001b[22m`], ], 'printed message about interactive shell') res() diff --git a/test/lib/init.js b/test/lib/init.js index 0964bb5cedde6..268b170cb4839 100644 --- a/test/lib/init.js +++ b/test/lib/init.js @@ -3,7 +3,6 @@ const { resolve } = require('path') const t = require('tap') const mockNpm = require('../fixtures/mock-npm') -let result = '' const npmLog = { disableProgress: () => null, enableProgress: () => null, @@ -19,9 +18,6 @@ const config = { const npm = mockNpm({ config, log: npmLog, - output: (...msg) => { - result += msg.join('\n') - }, }) const mocks = { '../../lib/utils/usage.js': () => 'usage instructions', @@ -33,7 +29,6 @@ const _consolelog = console.log const noop = () => {} t.afterEach(() => { - result = '' config.yes = true config.package = undefined npm.log = npmLog @@ -322,6 +317,9 @@ t.test('npm init error', t => { t.test('workspaces', t => { t.test('no args', t => { + t.teardown(() => { + npm._mockOutputs.length = 0 + }) npm.localPrefix = t.testdir({ 'package.json': JSON.stringify({ name: 'top-level', @@ -340,12 +338,15 @@ t.test('workspaces', t => { if (err) throw err - t.matchSnapshot(result, 'should print helper info') + t.matchSnapshot(npm._mockOutputs, 'should print helper info') t.end() }) }) t.test('no args, existing folder', t => { + t.teardown(() => { + npm._mockOutputs.length = 0 + }) // init-package-json prints directly to console.log // this avoids poluting test output with those logs console.log = noop @@ -369,12 +370,15 @@ t.test('workspaces', t => { if (err) throw err - t.matchSnapshot(result, 'should print helper info') + t.matchSnapshot(npm._mockOutputs, 'should print helper info') t.end() }) }) t.test('with arg but missing workspace folder', t => { + t.teardown(() => { + npm._mockOutputs.length = 0 + }) // init-package-json prints directly to console.log // this avoids poluting test output with those logs console.log = noop @@ -401,7 +405,7 @@ t.test('workspaces', t => { if (err) throw err - t.matchSnapshot(result, 'should print helper info') + t.matchSnapshot(npm._mockOutputs, 'should print helper info') t.end() }) }) From cf82ea7c0aca1a516c1315c04ea0931b743fe94f Mon Sep 17 00:00:00 2001 From: Gar Date: Wed, 26 May 2021 15:39:59 -0700 Subject: [PATCH 03/10] fix: refactor get package name renames read-local-package to read-package-name The global check needed to be moved outside this function, because it was handled differently (and will be even moreso when we implement diff workspaces) in each function. This allowed us to now pass in the prefix itself instead of the npm object, so we can reuse this function to look up package names when we refactor npm diff for workspaces. PR-URL: https://github.com/npm/cli/pull/3331 Credit: @wraithgar Close: #3331 Reviewed-by: @ruyadorno --- lib/diff.js | 8 +- lib/dist-tag.js | 14 +-- lib/owner.js | 19 +++- ...-local-package.js => read-package-name.js} | 7 +- tap-snapshots/test/lib/dist-tag.js.test.cjs | 57 ++++++++-- test/lib/diff.js | 62 ++++++----- test/lib/dist-tag.js | 14 +++ test/lib/owner.js | 100 ++++++++++++++---- ...-local-package.js => read-package-name.js} | 25 +---- 9 files changed, 203 insertions(+), 103 deletions(-) rename lib/utils/{read-local-package.js => read-package-name.js} (56%) rename test/lib/utils/{read-local-package.js => read-package-name.js} (55%) diff --git a/lib/diff.js b/lib/diff.js index 1eaceb4f2f61f..58834ca9c2674 100644 --- a/lib/diff.js +++ b/lib/diff.js @@ -8,7 +8,7 @@ const npmlog = require('npmlog') const pacote = require('pacote') const pickManifest = require('npm-pick-manifest') -const readLocalPkg = require('./utils/read-local-package.js') +const readPackageName = require('./utils/read-package-name.js') const BaseCommand = require('./base-command.js') class Diff extends BaseCommand { @@ -97,7 +97,7 @@ class Diff extends BaseCommand { let noPackageJson let pkgName try { - pkgName = await readLocalPkg(this.npm) + pkgName = await readPackageName(this.npm.prefix) } catch (e) { npmlog.verbose('diff', 'could not read project dir package.json') noPackageJson = true @@ -120,7 +120,7 @@ class Diff extends BaseCommand { let noPackageJson let pkgName try { - pkgName = await readLocalPkg(this.npm) + pkgName = await readPackageName(this.npm.prefix) } catch (e) { npmlog.verbose('diff', 'could not read project dir package.json') noPackageJson = true @@ -238,7 +238,7 @@ class Diff extends BaseCommand { if (semverA && semverB) { let pkgName try { - pkgName = await readLocalPkg(this.npm) + pkgName = await readPackageName(this.npm.prefix) } catch (e) { npmlog.verbose('diff', 'could not read project dir package.json') } diff --git a/lib/dist-tag.js b/lib/dist-tag.js index 64e8abc013745..11b1ad931e18b 100644 --- a/lib/dist-tag.js +++ b/lib/dist-tag.js @@ -4,7 +4,7 @@ const regFetch = require('npm-registry-fetch') const semver = require('semver') const otplease = require('./utils/otplease.js') -const readLocalPkgName = require('./utils/read-local-package.js') +const readPackageName = require('./utils/read-package-name.js') const getWorkspaces = require('./workspaces/get-workspaces.js') const BaseCommand = require('./base-command.js') @@ -64,7 +64,7 @@ class DistTag extends BaseCommand { // should be listing the existing tags return this.list(cmdName, opts) } else - throw this.usage + throw this.usageError() } execWorkspaces (args, filters, cb) { @@ -102,7 +102,7 @@ class DistTag extends BaseCommand { log.verbose('dist-tag add', defaultTag, 'to', spec.name + '@' + version) if (!spec.name || !version || !defaultTag) - throw this.usage + throw this.usageError() const t = defaultTag.trim() @@ -135,7 +135,7 @@ class DistTag extends BaseCommand { log.verbose('dist-tag del', tag, 'from', spec.name) if (!spec.name) - throw this.usage + throw this.usageError() const tags = await this.fetchTags(spec, opts) if (!tags[tag]) { @@ -157,9 +157,11 @@ class DistTag extends BaseCommand { async list (spec, opts) { if (!spec) { - const pkg = await readLocalPkgName(this.npm) + if (this.npm.config.get('global')) + throw this.usageError() + const pkg = await readPackageName(this.npm.prefix) if (!pkg) - throw this.usage + throw this.usageError() return this.list(pkg, opts) } diff --git a/lib/owner.js b/lib/owner.js index e57d2268d2619..311b25064e638 100644 --- a/lib/owner.js +++ b/lib/owner.js @@ -4,7 +4,7 @@ const npmFetch = require('npm-registry-fetch') const pacote = require('pacote') const otplease = require('./utils/otplease.js') -const readLocalPkg = require('./utils/read-local-package.js') +const readLocalPkgName = require('./utils/read-package-name.js') const BaseCommand = require('./base-command.js') class Owner extends BaseCommand { @@ -47,7 +47,9 @@ class Owner extends BaseCommand { // reaches registry in order to autocomplete rm if (argv[2] === 'rm') { - const pkgName = await readLocalPkg(this.npm) + if (this.npm.config.get('global')) + return [] + const pkgName = await readLocalPkgName(this.npm.prefix) if (!pkgName) return [] @@ -84,7 +86,10 @@ class Owner extends BaseCommand { async ls (pkg, opts) { if (!pkg) { - const pkgName = await readLocalPkg(this.npm) + if (this.npm.config.get('global')) + throw this.usageError() + + const pkgName = await readLocalPkgName(this.npm.prefix) if (!pkgName) throw this.usageError() @@ -113,7 +118,9 @@ class Owner extends BaseCommand { throw this.usageError() if (!pkg) { - const pkgName = await readLocalPkg(this.npm) + if (this.npm.config.get('global')) + throw this.usageError() + const pkgName = await readLocalPkgName(this.npm.prefix) if (!pkgName) throw this.usageError() @@ -131,7 +138,9 @@ class Owner extends BaseCommand { throw this.usageError() if (!pkg) { - const pkgName = await readLocalPkg(this.npm) + if (this.npm.config.get('global')) + throw this.usageError() + const pkgName = await readLocalPkgName(this.npm.prefix) if (!pkgName) throw this.usageError() diff --git a/lib/utils/read-local-package.js b/lib/utils/read-package-name.js similarity index 56% rename from lib/utils/read-local-package.js rename to lib/utils/read-package-name.js index 21506ca180a0f..7ed15987767bb 100644 --- a/lib/utils/read-local-package.js +++ b/lib/utils/read-package-name.js @@ -1,10 +1,7 @@ const { resolve } = require('path') const readJson = require('read-package-json-fast') -async function readLocalPackageName (npm) { - if (npm.config.get('global')) - return - - const filepath = resolve(npm.prefix, 'package.json') +async function readLocalPackageName (prefix) { + const filepath = resolve(prefix, 'package.json') const json = await readJson(filepath) return json.name } diff --git a/tap-snapshots/test/lib/dist-tag.js.test.cjs b/tap-snapshots/test/lib/dist-tag.js.test.cjs index 86a9c84eb1eb6..21d9331db1299 100644 --- a/tap-snapshots/test/lib/dist-tag.js.test.cjs +++ b/tap-snapshots/test/lib/dist-tag.js.test.cjs @@ -6,7 +6,8 @@ */ 'use strict' exports[`test/lib/dist-tag.js TAP add missing args > should exit usage error message 1`] = ` -npm dist-tag +Error: +Usage: npm dist-tag Modify package distribution tags @@ -21,11 +22,14 @@ Options: alias: dist-tags -Run "npm help dist-tag" for more info +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} ` exports[`test/lib/dist-tag.js TAP add missing pkg name > should exit usage error message 1`] = ` -npm dist-tag +Error: +Usage: npm dist-tag Modify package distribution tags @@ -40,7 +44,9 @@ Options: alias: dist-tags -Run "npm help dist-tag" for more info +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} ` exports[`test/lib/dist-tag.js TAP add new tag > should return success msg 1`] = ` @@ -53,7 +59,8 @@ dist-tag add 1.0.0 to @scoped/another@7.7.7 ` exports[`test/lib/dist-tag.js TAP borked cmd usage > should show usage error 1`] = ` -npm dist-tag +Error: +Usage: npm dist-tag Modify package distribution tags @@ -68,7 +75,31 @@ Options: alias: dist-tags -Run "npm help dist-tag" for more info +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} +` + +exports[`test/lib/dist-tag.js TAP ls global > should throw basic usage 1`] = ` +Error: +Usage: npm dist-tag + +Modify package distribution tags + +Usage: +npm dist-tag add @ [] +npm dist-tag rm +npm dist-tag ls [] + +Options: +[-w|--workspace [-w|--workspace ...]] +[-ws|--workspaces] + +alias: dist-tags + +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} ` exports[`test/lib/dist-tag.js TAP ls in current package > should list available tags for current package 1`] = ` @@ -78,7 +109,8 @@ latest: 1.0.0 ` exports[`test/lib/dist-tag.js TAP ls on missing name in current package > should throw usage error message 1`] = ` -npm dist-tag +Error: +Usage: npm dist-tag Modify package distribution tags @@ -93,7 +125,9 @@ Options: alias: dist-tags -Run "npm help dist-tag" for more info +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} ` exports[`test/lib/dist-tag.js TAP ls on missing package > should log no dist-tag found msg 1`] = ` @@ -133,7 +167,8 @@ exports[`test/lib/dist-tag.js TAP remove existing tag > should return success ms ` exports[`test/lib/dist-tag.js TAP remove missing pkg name > should exit usage error message 1`] = ` -npm dist-tag +Error: +Usage: npm dist-tag Modify package distribution tags @@ -148,7 +183,9 @@ Options: alias: dist-tags -Run "npm help dist-tag" for more info +Run "npm help dist-tag" for more info { + "code": "EUSAGE", +} ` exports[`test/lib/dist-tag.js TAP remove non-existing tag > should log error msg 1`] = ` diff --git a/test/lib/diff.js b/test/lib/diff.js index 355095c95786e..7a52ea5ee0ae1 100644 --- a/test/lib/diff.js +++ b/test/lib/diff.js @@ -4,7 +4,7 @@ const mockNpm = require('../fixtures/mock-npm') const noop = () => null let libnpmdiff = noop -let rlp = () => 'foo' +let rpn = () => 'foo' const config = { global: false, @@ -33,7 +33,7 @@ const mocks = { npmlog: { info: noop, verbose: noop }, libnpmdiff: (...args) => libnpmdiff(...args), 'npm-registry-fetch': async () => ({}), - '../../lib/utils/read-local-package.js': async () => rlp(), + '../../lib/utils/read-package-name.js': async (prefix) => rpn(prefix), '../../lib/utils/usage.js': () => 'usage instructions', } @@ -52,7 +52,7 @@ t.afterEach(() => { npm.globalDir = __dirname npm.prefix = '..' libnpmdiff = noop - rlp = () => 'foo' + rpn = () => 'foo' }) const Diff = t.mock('../../lib/diff.js', mocks) @@ -77,7 +77,7 @@ t.test('no args', t => { }) t.test('no args, missing package.json name in cwd', t => { - rlp = () => undefined + rpn = () => undefined diff.exec([], err => { t.match( @@ -90,7 +90,7 @@ t.test('no args', t => { }) t.test('no args, missing package.json in cwd', t => { - rlp = () => { + rpn = () => { throw new Error('ERR') } @@ -109,14 +109,17 @@ t.test('no args', t => { t.test('single arg', t => { t.test('spec using cwd package name', t => { - t.plan(3) + t.plan(4) + rpn = (prefix) => { + t.equal(prefix, path, 'read-package-name gets proper prefix') + return 'foo' + } const path = t.testdir({}) libnpmdiff = async ([a, b], opts) => { t.equal(a, 'foo@1.0.0', 'should forward single spec') t.equal(b, `file:${path}`, 'should compare to cwd') t.match(opts, npm.flatOptions, 'should forward flat options') - t.end() } config.diff = ['foo@1.0.0'] @@ -124,12 +127,13 @@ t.test('single arg', t => { diff.exec([], err => { if (err) throw err + t.end() }) }) t.test('unknown spec, no package.json', t => { const path = t.testdir({}) - rlp = () => { + rpn = () => { throw new Error('ERR') } @@ -182,7 +186,7 @@ t.test('single arg', t => { }) t.test('version, no package.json', t => { - rlp = () => { + rpn = () => { throw new Error('ERR') } @@ -273,7 +277,7 @@ t.test('single arg', t => { t.test('unknown package name, no package.json', t => { const path = t.testdir({}) - rlp = () => { + rpn = () => { throw new Error('ERR') } @@ -465,7 +469,7 @@ t.test('single arg', t => { const Diff = t.mock('../../lib/diff.js', { ...mocks, - '../../lib/utils/read-local-package.js': async () => 'my-project', + '../../lib/utils/read-package-name.js': async () => 'my-project', pacote: { packument: (spec) => { t.equal(spec.name, 'lorem', 'should have expected spec name') @@ -502,7 +506,7 @@ t.test('single arg', t => { const Diff = t.mock('../../lib/diff.js', { ...mocks, - '../../lib/utils/read-local-package.js': async () => 'my-project', + '../../lib/utils/read-package-name.js': async () => 'my-project', '@npmcli/arborist': class { constructor () { throw new Error('ERR') @@ -528,7 +532,7 @@ t.test('single arg', t => { t.plan(2) const path = t.testdir({}) - rlp = async () => undefined + rpn = async () => undefined libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@latest', 'should target latest tag of name') t.equal(b, `file:${path}`, 'should compare to cwd') @@ -547,7 +551,7 @@ t.test('single arg', t => { t.plan(2) const path = t.testdir({}) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'my-project@latest', 'should target latest tag of name') t.equal(b, `file:${path}`, 'should compare to cwd') @@ -565,7 +569,7 @@ t.test('single arg', t => { t.plan(2) const path = t.testdir({}) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'file:/path/to/other-dir', 'should target dir') t.equal(b, `file:${path}`, 'should compare to cwd') @@ -580,7 +584,7 @@ t.test('single arg', t => { }) t.test('unsupported spec type', t => { - rlp = async () => 'my-project' + rpn = async () => 'my-project' config.diff = ['git+https://github.com/user/foo'] @@ -634,7 +638,7 @@ t.test('first arg is a qualified spec', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@2.0.0', 'should set expected first spec') t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') @@ -703,7 +707,7 @@ t.test('first arg is a known dependency name', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') t.equal(b, 'bar@2.0.0', 'should set expected second spec') @@ -743,7 +747,7 @@ t.test('first arg is a known dependency name', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') t.equal(b, `bar-fork@file:${resolve(path, 'node_modules/bar-fork')}`, 'should target fork local node_modules pkg') @@ -777,7 +781,7 @@ t.test('first arg is a known dependency name', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') t.equal(b, 'bar@2.0.0', 'should use package name from first arg') @@ -811,7 +815,7 @@ t.test('first arg is a known dependency name', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') t.equal(b, 'bar-fork@latest', 'should set expected second spec') @@ -865,7 +869,7 @@ t.test('first arg is a valid semver range', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@1.0.0', 'should use name from second arg') t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should set expected second spec from nm') @@ -882,7 +886,7 @@ t.test('first arg is a valid semver range', t => { t.test('second arg is ALSO a semver version', t => { t.plan(2) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'my-project@1.0.0', 'should use name from project dir') t.equal(b, 'my-project@2.0.0', 'should use name from project dir') @@ -897,7 +901,7 @@ t.test('first arg is a valid semver range', t => { t.test('second arg is ALSO a semver version BUT cwd not a project dir', t => { const path = t.testdir({}) - rlp = () => { + rpn = () => { throw new Error('ERR') } @@ -916,7 +920,7 @@ t.test('first arg is a valid semver range', t => { t.test('second arg is an unknown dependency name', t => { t.plan(2) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar@1.0.0', 'should use name from second arg') t.equal(b, 'bar@latest', 'should compare against latest tag') @@ -940,7 +944,7 @@ t.test('first arg is a valid semver range', t => { const Diff = t.mock('../../lib/diff.js', { ...mocks, - '../../lib/utils/read-local-package.js': async () => 'my-project', + '../../lib/utils/read-package-name.js': async () => 'my-project', '@npmcli/arborist': class { constructor () { throw new Error('ERR') @@ -1003,7 +1007,7 @@ t.test('first arg is an unknown dependency name', t => { }), }) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'bar-fork@latest', 'should use latest tag') t.equal(b, `bar@file:${resolve(path, 'node_modules/bar')}`, 'should target local node_modules pkg') @@ -1051,7 +1055,7 @@ t.test('first arg is an unknown dependency name', t => { t.plan(2) const path = t.testdir({}) - rlp = () => { + rpn = () => { throw new Error('ERR') } libnpmdiff = async ([a, b], opts) => { @@ -1117,7 +1121,7 @@ t.test('various options', t => { t.plan(3) const path = t.testdir({}) - rlp = async () => 'my-project' + rpn = async () => 'my-project' libnpmdiff = async ([a, b], opts) => { t.equal(a, 'my-project@latest', 'should have default spec') t.equal(b, `file:${path}`, 'should compare to cwd') diff --git a/test/lib/dist-tag.js b/test/lib/dist-tag.js index 6bc17168cdce0..9af90c309c77c 100644 --- a/test/lib/dist-tag.js +++ b/test/lib/dist-tag.js @@ -93,6 +93,20 @@ t.test('ls in current package', (t) => { }) }) +t.test('ls global', (t) => { + t.teardown(() => { + config.global = false + }) + config.global = true + distTag.exec(['ls'], (err) => { + t.matchSnapshot( + err, + 'should throw basic usage' + ) + t.end() + }) +}) + t.test('no args in current package', (t) => { npm.prefix = t.testdir({ 'package.json': JSON.stringify({ diff --git a/test/lib/owner.js b/test/lib/owner.js index 4af8d1ebbb8fa..10ceb03030a5a 100644 --- a/test/lib/owner.js +++ b/test/lib/owner.js @@ -1,16 +1,18 @@ const t = require('tap') +const mockNpm = require('../fixtures/mock-npm.js') let result = '' -let readLocalPkgResponse = null +let readPackageNamePrefix = null +let readPackageNameResponse = null const noop = () => null -const npm = { - flatOptions: {}, +const npm = mockNpm({ output: (msg) => { result = result ? `${result}\n${msg}` : msg }, -} +}) + const npmFetch = { json: noop } const npmlog = { error: noop, info: noop, verbose: noop } const pacote = { packument: noop } @@ -20,7 +22,10 @@ const mocks = { 'npm-registry-fetch': npmFetch, pacote, '../../lib/utils/otplease.js': async (opts, fn) => fn({ otp: '123456', opts }), - '../../lib/utils/read-local-package.js': async () => readLocalPkgResponse, + '../../lib/utils/read-package-name.js': async (prefix) => { + readPackageNamePrefix = prefix + return readPackageNameResponse + }, '../../lib/utils/usage.js': () => 'usage instructions', } @@ -47,11 +52,11 @@ t.test('owner no args', t => { }) t.test('owner ls no args', t => { - t.plan(4) + t.plan(5) result = '' - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' pacote.packument = async (spec, opts) => { t.equal(spec.name, '@npmcli/map-workspaces', 'should use expect pkg name') t.match( @@ -65,14 +70,29 @@ t.test('owner ls no args', t => { return { maintainers: npmcliMaintainers } } t.teardown(() => { + npm.prefix = null result = '' pacote.packument = noop - readLocalPkgResponse = null + readPackageNameResponse = null }) + npm.prefix = 'test-npm-prefix' owner.exec(['ls'], err => { t.error(err, 'npm owner ls no args') t.matchSnapshot(result, 'should output owners of cwd package') + t.equal(readPackageNamePrefix, 'test-npm-prefix', 'read-package-name gets npm.prefix') + }) +}) + +t.test('owner ls global', t => { + t.teardown(() => { + npm.config.set('global', false) + }) + npm.config.set('global', true) + + owner.exec(['ls'], err => { + t.match(err, /usage instructions/, 'should throw usage instructions if no cwd package available') + t.end() }) }) @@ -93,7 +113,7 @@ t.test('owner ls fails to retrieve packument', t => { t.plan(4) result = '' - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' pacote.packument = () => { throw new Error('ERR') } @@ -233,7 +253,7 @@ t.test('owner add ', t => { t.test('owner add cwd package', t => { result = '' - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' npmFetch.json = async (uri, opts) => { // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') { @@ -253,7 +273,7 @@ t.test('owner add cwd package', t => { }) t.teardown(() => { result = '' - readLocalPkgResponse = null + readPackageNameResponse = null npmFetch.json = noop pacote.packument = noop }) @@ -308,7 +328,7 @@ t.test('owner add already an owner', t => { t.test('owner add fails to retrieve user', t => { result = '' - readLocalPkgResponse = + readPackageNameResponse = npmFetch.json = async (uri, opts) => { // retrieve borked user info from couchdb request if (uri === '/-/user/org.couchdb.user:foo') @@ -324,7 +344,7 @@ t.test('owner add fails to retrieve user', t => { }) t.teardown(() => { result = '' - readLocalPkgResponse = null + readPackageNameResponse = null npmFetch.json = noop pacote.packument = noop }) @@ -465,6 +485,18 @@ t.test('owner add no user', t => { }) }) +t.test('owner add no pkg global', t => { + t.teardown(() => { + npm.config.set('global', false) + }) + npm.config.set('global', true) + + owner.exec(['add', 'gar'], err => { + t.match(err, /usage instructions/, 'should throw usage instructions if user provided') + t.end() + }) +}) + t.test('owner add no cwd package', t => { result = '' t.teardown(() => { @@ -581,7 +613,7 @@ t.test('owner rm not a current owner', t => { t.test('owner rm cwd package', t => { result = '' - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' npmFetch.json = async (uri, opts) => { // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { @@ -601,7 +633,7 @@ t.test('owner rm cwd package', t => { }) t.teardown(() => { result = '' - readLocalPkgResponse = null + readPackageNameResponse = null npmFetch.json = noop pacote.packument = noop }) @@ -615,7 +647,7 @@ t.test('owner rm cwd package', t => { t.test('owner rm only user', t => { result = '' - readLocalPkgResponse = 'ipt' + readPackageNameResponse = 'ipt' npmFetch.json = async (uri, opts) => { // retrieve user info from couchdb request if (uri === '/-/user/org.couchdb.user:ruyadorno') { @@ -636,7 +668,7 @@ t.test('owner rm only user', t => { }) t.teardown(() => { result = '' - readLocalPkgResponse = null + readPackageNameResponse = null npmFetch.json = noop pacote.packument = noop }) @@ -664,6 +696,18 @@ t.test('owner rm no user', t => { }) }) +t.test('owner rm no pkg global', t => { + t.teardown(() => { + npm.config.set('global', false) + }) + npm.config.set('global', true) + + owner.exec(['rm', 'gar'], err => { + t.match(err, /usage instructions/, 'should throw usage instructions if user provided') + t.end() + }) +}) + t.test('owner rm no cwd package', t => { result = '' t.teardown(() => { @@ -693,15 +737,15 @@ t.test('completion', async t => { // npm owner rm completion is async t.test('completion npm owner rm', async t => { t.plan(2) - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' pacote.packument = async spec => { - t.equal(spec.name, readLocalPkgResponse, 'should use package spec') + t.equal(spec.name, readPackageNameResponse, 'should use package spec') return { maintainers: npmcliMaintainers, } } t.teardown(() => { - readLocalPkgResponse = null + readPackageNameResponse = null pacote.packument = noop }) @@ -718,17 +762,27 @@ t.test('completion', async t => { t.end() }) + t.test('completion npm owner rm global', async t => { + t.teardown(() => { + npm.config.set('global', false) + }) + npm.config.set('global', true) + const res = await owner.completion({ conf: { argv: { remain: ['npm', 'owner', 'rm'] } } }) + t.strictSame(res, [], 'should have no owners to autocomplete if global') + t.end() + }) + t.test('completion npm owner rm no owners found', async t => { t.plan(2) - readLocalPkgResponse = '@npmcli/map-workspaces' + readPackageNameResponse = '@npmcli/map-workspaces' pacote.packument = async spec => { - t.equal(spec.name, readLocalPkgResponse, 'should use package spec') + t.equal(spec.name, readPackageNameResponse, 'should use package spec') return { maintainers: [], } } t.teardown(() => { - readLocalPkgResponse = null + readPackageNameResponse = null pacote.packument = noop }) diff --git a/test/lib/utils/read-local-package.js b/test/lib/utils/read-package-name.js similarity index 55% rename from test/lib/utils/read-local-package.js rename to test/lib/utils/read-package-name.js index 966e74a7ab7f4..c8f88bacd4b84 100644 --- a/test/lib/utils/read-local-package.js +++ b/test/lib/utils/read-package-name.js @@ -1,13 +1,8 @@ const t = require('tap') const mockNpm = require('../../fixtures/mock-npm') +const npm = mockNpm() -const config = { - json: false, - global: false, -} -const npm = mockNpm({ config }) - -const readLocalPackageName = require('../../../lib/utils/read-local-package.js') +const readPackageName = require('../../../lib/utils/read-package-name.js') t.test('read local package.json', async (t) => { npm.prefix = t.testdir({ @@ -16,7 +11,7 @@ t.test('read local package.json', async (t) => { version: '1.0.0', }), }) - const packageName = await readLocalPackageName(npm) + const packageName = await readPackageName(npm.prefix) t.equal( packageName, 'my-local-package', @@ -31,22 +26,10 @@ t.test('read local scoped-package.json', async (t) => { version: '1.0.0', }), }) - const packageName = await readLocalPackageName(npm) + const packageName = await readPackageName(npm.prefix) t.equal( packageName, '@my-scope/my-local-package', 'should retrieve scoped package name' ) }) - -t.test('read using --global', async (t) => { - npm.prefix = t.testdir({}) - config.global = true - const packageName = await readLocalPackageName(npm) - t.equal( - packageName, - undefined, - 'should not retrieve a package name' - ) - config.global = false -}) From 66b56231b52d0389aac106fed7a90084a9b1b8c9 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Fri, 28 May 2021 16:04:15 -0400 Subject: [PATCH 04/10] chore: ignore smoke test server file coverage --- smoke-tests/server.js | 1 + 1 file changed, 1 insertion(+) diff --git a/smoke-tests/server.js b/smoke-tests/server.js index 03aacb4b8c28a..b864114af64a8 100644 --- a/smoke-tests/server.js +++ b/smoke-tests/server.js @@ -1,3 +1,4 @@ +/* istanbul ignore file */ const {join, dirname} = require('path') const {existsSync, readFileSync, writeFileSync} = require('fs') const PORT = 12345 + (+process.env.TAP_CHILD_ID || 0) From f249e784988c5f6f5c13c84bbedd7b1ba5dd49af Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 17:19:29 -0400 Subject: [PATCH 05/10] eslint-plugin-import@2.23.4 --- package-lock.json | 14 +++++++------- package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc8ac92f69e81..08c9712ace7ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -154,7 +154,7 @@ "@mdx-js/mdx": "^1.6.22", "cmark-gfm": "^0.8.5", "eslint": "^7.26.0", - "eslint-plugin-import": "^2.22.1", + "eslint-plugin-import": "^2.23.4", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-standard": "^5.0.0", @@ -2611,9 +2611,9 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.23.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.3.tgz", - "integrity": "sha512-wDxdYbSB55F7T5CC7ucDjY641VvKmlRwT0Vxh7PkY1mI4rclVRFWYfsrjDgZvwYYDZ5ee0ZtfFKXowWjqvEoRQ==", + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", "dev": true, "dependencies": { "array-includes": "^3.1.3", @@ -12286,9 +12286,9 @@ } }, "eslint-plugin-import": { - "version": "2.23.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.3.tgz", - "integrity": "sha512-wDxdYbSB55F7T5CC7ucDjY641VvKmlRwT0Vxh7PkY1mI4rclVRFWYfsrjDgZvwYYDZ5ee0ZtfFKXowWjqvEoRQ==", + "version": "2.23.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.23.4.tgz", + "integrity": "sha512-6/wP8zZRsnQFiR3iaPFgh5ImVRM1WN5NUWfTIRqwOdeiGJlBcSk82o1FEVq8yXmy4lkIzTo7YhHCIxlU/2HyEQ==", "dev": true, "requires": { "array-includes": "^3.1.3", diff --git a/package.json b/package.json index d0b40812141a7..70fa91887930d 100644 --- a/package.json +++ b/package.json @@ -183,7 +183,7 @@ "@mdx-js/mdx": "^1.6.22", "cmark-gfm": "^0.8.5", "eslint": "^7.26.0", - "eslint-plugin-import": "^2.22.1", + "eslint-plugin-import": "^2.23.4", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-standard": "^5.0.0", From 9159fa62a10dee09daef178fc7be161a02824004 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 17:25:55 -0400 Subject: [PATCH 06/10] libnpmexec@1.2.0 --- node_modules/libnpmexec/CHANGELOG.md | 17 +++++++++++++++++ node_modules/libnpmexec/README.md | 2 +- node_modules/libnpmexec/lib/index.js | 3 ++- node_modules/libnpmexec/lib/is-windows.js | 1 + node_modules/libnpmexec/package.json | 2 +- package-lock.json | 14 +++++++------- package.json | 2 +- test/lib/exec.js | 2 +- 8 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 node_modules/libnpmexec/CHANGELOG.md create mode 100644 node_modules/libnpmexec/lib/is-windows.js diff --git a/node_modules/libnpmexec/CHANGELOG.md b/node_modules/libnpmexec/CHANGELOG.md new file mode 100644 index 0000000000000..28cb71028868e --- /dev/null +++ b/node_modules/libnpmexec/CHANGELOG.md @@ -0,0 +1,17 @@ +# Changelog + +## v1.1.0 + +- Add add walk up dir lookup logic to satisfy local bins, +similar to `@npmcli/run-script` + +## v1.0.1 + +- Fix `scriptShell` option name. + +## v1.0.0 + +- Initial implementation, moves the code that used to live in the **npm cli**, +ref: https://github.com/npm/cli/blob/release/v7.10.0/lib/exec.js into this +separate module, providing a programmatic API to the **npm exec** functionality. + diff --git a/node_modules/libnpmexec/README.md b/node_modules/libnpmexec/README.md index fb7a771760019..18a26011adc76 100644 --- a/node_modules/libnpmexec/README.md +++ b/node_modules/libnpmexec/README.md @@ -39,7 +39,7 @@ await libexec({ - `packages`: A list of packages to be used (possibly fetch from the registry) **Array**, defaults to `[]` - `path`: Location to where to read local project info (`package.json`) **String**, defaults to `.` - `runPath`: Location to where to execute the script **String**, defaults to `.` - - `scriptShell`: Default shell to be used **String** + - `scriptShell`: Default shell to be used **String**, defaults to `sh` on POSIX systems, `process.env.ComSpec` OR `cmd` on Windows - `yes`: Should skip download confirmation prompt when fetching missing packages from the registry? **Boolean** - `registry`, `cache`, and more options that are forwarded to [@npmcli/arborist](https://github.com/npm/arborist/) and [pacote](https://github.com/npm/pacote/#options) **Object** diff --git a/node_modules/libnpmexec/lib/index.js b/node_modules/libnpmexec/lib/index.js index a48c654bf6a4f..8c5181f397519 100644 --- a/node_modules/libnpmexec/lib/index.js +++ b/node_modules/libnpmexec/lib/index.js @@ -16,6 +16,7 @@ const getBinFromManifest = require('./get-bin-from-manifest.js') const manifestMissing = require('./manifest-missing.js') const noTTY = require('./no-tty.js') const runScript = require('./run-script.js') +const isWindows = require('./is-windows.js') /* istanbul ignore next */ const PATH = ( @@ -34,7 +35,7 @@ const exec = async (opts) => { packages: _packages = [], path = '.', runPath = '.', - scriptShell = undefined, + scriptShell = isWindows ? process.env.ComSpec || 'cmd' : 'sh', yes = undefined, ...flatOptions } = opts diff --git a/node_modules/libnpmexec/lib/is-windows.js b/node_modules/libnpmexec/lib/is-windows.js new file mode 100644 index 0000000000000..fbece90ad7496 --- /dev/null +++ b/node_modules/libnpmexec/lib/is-windows.js @@ -0,0 +1 @@ +module.exports = process.platform === 'win32' diff --git a/node_modules/libnpmexec/package.json b/node_modules/libnpmexec/package.json index c113ac6d0a607..2b3b488cf079f 100644 --- a/node_modules/libnpmexec/package.json +++ b/node_modules/libnpmexec/package.json @@ -1,6 +1,6 @@ { "name": "libnpmexec", - "version": "1.1.1", + "version": "1.2.0", "files": [ "lib" ], diff --git a/package-lock.json b/package-lock.json index 08c9712ace7ee..f20da70ff561d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -103,7 +103,7 @@ "leven": "^3.1.0", "libnpmaccess": "^4.0.2", "libnpmdiff": "^2.0.4", - "libnpmexec": "^1.1.1", + "libnpmexec": "^1.2.0", "libnpmfund": "^1.1.0", "libnpmhook": "^6.0.2", "libnpmorg": "^2.0.2", @@ -4650,9 +4650,9 @@ } }, "node_modules/libnpmexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/libnpmexec/-/libnpmexec-1.1.1.tgz", - "integrity": "sha512-uw6H2dzC6F6fdq7lAxfzXPimHCJ3/g6ycFKcv2Q2QXuNZ94EDmNPpMO6f4mwiC5F6Lyy/WK0IL7AZwRhmSvUdQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/libnpmexec/-/libnpmexec-1.2.0.tgz", + "integrity": "sha512-LkxnH2wsMUI4thsgUK0r+EFZ5iCjKlp21J68dFY7AzD5uaaIPqO3lqVvYbyl1Umz1R4rY9t3vFa1fF3hzo6Y2Q==", "inBundle": true, "dependencies": { "@npmcli/arborist": "^2.3.0", @@ -13690,9 +13690,9 @@ } }, "libnpmexec": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/libnpmexec/-/libnpmexec-1.1.1.tgz", - "integrity": "sha512-uw6H2dzC6F6fdq7lAxfzXPimHCJ3/g6ycFKcv2Q2QXuNZ94EDmNPpMO6f4mwiC5F6Lyy/WK0IL7AZwRhmSvUdQ==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/libnpmexec/-/libnpmexec-1.2.0.tgz", + "integrity": "sha512-LkxnH2wsMUI4thsgUK0r+EFZ5iCjKlp21J68dFY7AzD5uaaIPqO3lqVvYbyl1Umz1R4rY9t3vFa1fF3hzo6Y2Q==", "requires": { "@npmcli/arborist": "^2.3.0", "@npmcli/ci-detect": "^1.3.0", diff --git a/package.json b/package.json index 70fa91887930d..0e60c184900f2 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "leven": "^3.1.0", "libnpmaccess": "^4.0.2", "libnpmdiff": "^2.0.4", - "libnpmexec": "^1.1.1", + "libnpmexec": "^1.2.0", "libnpmfund": "^1.1.0", "libnpmhook": "^6.0.2", "libnpmorg": "^2.0.2", diff --git a/test/lib/exec.js b/test/lib/exec.js index 4f8cc02fce7bd..6924783239b49 100644 --- a/test/lib/exec.js +++ b/test/lib/exec.js @@ -307,7 +307,7 @@ t.test('npm exec , run interactive shell', t => { throw er t.match(RUN_SCRIPTS, [{ - pkg: { scripts: { npx: undefined } }, + pkg: { scripts: { npx: /sh|cmd/ } }, }]) LOG_WARN.length = 0 From e5799e1e5987d841e070deb7ab30e14fd3270fdf Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 17:41:18 -0400 Subject: [PATCH 07/10] add node16 ci target --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14f362b45e305..78c2926afd6ed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: [10.x, 12.x, 14.x] + node-version: [10.x, 12.x, 14.x, 16.x] platform: - os: ubuntu-latest shell: bash @@ -83,7 +83,7 @@ jobs: strategy: fail-fast: false matrix: - node-version: ['10.1', 10.x, '12.1', 12.x, '14.1', 14.x] + node-version: ['10.1', 10.x, '12.1', 12.x, '14.1', 14.x, '16.1', 16.x] platform: - os: ubuntu-latest shell: bash From 4a8a1806861a206e874226f78d5a53f4586b58e1 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 18:06:33 -0400 Subject: [PATCH 08/10] docs: changelog for v7.15.1 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index def5daee027f2..c86373bcde2b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ +## v7.15.1 (2021-05-31) + +### BUG FIXES + +* [`598a17a26`](https://github.com/npm/cli/commit/598a17a2671c9e3bc204dddd6488169c9a72c6a1) + [#3329](https://github.com/npm/cli/issues/3329) + fix(libnpmexec): don't detach output from npm + ([@wraithgar](https://github.com/wraithgar)) + +### DEPENDENCIES + +* [`c4fc03e9e`](https://github.com/npm/cli/commit/c4fc03e9eb3a6386e8feacb67c19f0a1578dfe38) + `@npmcli/arborist@2.6.1` + * fixes reifying deps with mismatching version ranges between + actual and virtual trees +* [`9159fa62a`](https://github.com/npm/cli/commit/9159fa62a10dee09daef178fc7be161a02824004) + `libnpmexec@1.2.0` + ## v7.15.0 (2021-05-27) ### FEATURES From b72b82d6d6945948287d75d4731386126b9819af Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 18:27:30 -0400 Subject: [PATCH 09/10] update AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index f7e19d0c26b09..a8dfd8b6be682 100644 --- a/AUTHORS +++ b/AUTHORS @@ -782,3 +782,4 @@ Nariyasu Heseri rethab Spencer Wilson <5624115+spencerwilson@users.noreply.github.com> Daniel Park +Daniel Park From 73633e566661f38d78a61faa1ab43919dc5696e6 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 31 May 2021 18:27:31 -0400 Subject: [PATCH 10/10] 7.15.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index f20da70ff561d..ac1cb7e2e0d81 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "npm", - "version": "7.15.0", + "version": "7.15.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "npm", - "version": "7.15.0", + "version": "7.15.1", "bundleDependencies": [ "@npmcli/arborist", "@npmcli/ci-detect", diff --git a/package.json b/package.json index 0e60c184900f2..7df43589334ef 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "7.15.0", + "version": "7.15.1", "name": "npm", "description": "a package manager for JavaScript", "keywords": [