From ccabb78bbad0dd1bea75cca8abb77e8f99b00684 Mon Sep 17 00:00:00 2001 From: Nathan Fritz Date: Sun, 30 Oct 2022 22:30:01 -0700 Subject: [PATCH] feat: set --no-audit when installing outside of a project (like --global) --- lib/arborist-cmd.js | 14 +++++++ lib/npm.js | 15 +++++++ .../test/lib/commands/config.js.test.cjs | 1 + test/index.js | 11 ++++- test/lib/arborist-cmd.js | 13 +++++- test/lib/commands/explain.js | 5 +++ test/lib/commands/install-ci-test.js | 5 +++ test/lib/commands/install-test.js | 5 +++ test/lib/commands/install.js | 42 +++++++++++++++++++ test/lib/commands/ls.js | 1 + 10 files changed, 109 insertions(+), 3 deletions(-) diff --git a/lib/arborist-cmd.js b/lib/arborist-cmd.js index 5007fbd9244d2..a78ade58e1594 100644 --- a/lib/arborist-cmd.js +++ b/lib/arborist-cmd.js @@ -1,3 +1,5 @@ +const log = require('./utils/log-shim.js') + // This is the base for all commands whose execWorkspaces just gets // a list of workspace names and passes it on to new Arborist() to // be able to run a filtered Arborist.reify() at some point. @@ -17,6 +19,18 @@ class ArboristCmd extends BaseCommand { static ignoreImplicitWorkspace = false + constructor (npm) { + super(npm) + if (!this.npm.config.get('audit', 'cli') + && (this.npm.global || this.npm.config.get('location') !== 'project') + ) { + this.npm.config.set('audit', false) + } else if (this.npm.global && this.npm.config.get('audit')) { + log.warn('config', + 'includes both --global and --audit, which is currently unsupported.') + } + } + async execWorkspaces (args, filters) { await this.setWorkspaces(filters) return this.exec(args) diff --git a/lib/npm.js b/lib/npm.js index 9fbda90734921..0bdbcdb9efd8b 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -88,6 +88,21 @@ class Npm extends EventEmitter { // would be needed to change this async cmd (cmd) { await this.load() + + // when location isn't set and global isn't true + // check for a package.json at the localPrefix + // and set the location to project if found + // TODO: this logic can move to the config module loadLocalPrefix to + // avoid double stat calls and consolidate logic + if (this.config.isDefault('location') && !this.config.get('global')) { + const hasPackageJson = await fs.stat(resolve(this.config.localPrefix, 'package.json')) + .then((st) => st.isFile()) + .catch(() => false) + if (hasPackageJson) { + this.config.set('location', 'project') + } + } + const command = this.deref(cmd) if (!command) { throw Object.assign(new Error(`Unknown command ${cmd}`), { diff --git a/tap-snapshots/test/lib/commands/config.js.test.cjs b/tap-snapshots/test/lib/commands/config.js.test.cjs index 4170dd9078c86..93a3e9ac4eebf 100644 --- a/tap-snapshots/test/lib/commands/config.js.test.cjs +++ b/tap-snapshots/test/lib/commands/config.js.test.cjs @@ -354,6 +354,7 @@ exports[`test/lib/commands/config.js TAP config list with publishConfig > output ; "cli" config from command line options cache = "{NPMDIR}/test/lib/commands/tap-testdir-config-config-list-with-publishConfig-sandbox/cache" +location = "project" prefix = "{LOCALPREFIX}" userconfig = "{HOME}/.npmrc" diff --git a/test/index.js b/test/index.js index 5075597b5d93c..e80b690767144 100644 --- a/test/index.js +++ b/test/index.js @@ -11,7 +11,16 @@ t.test('loading as main module will load the cli', t => { const cwd = t.testdir() const { spawn } = require('child_process') const LS = require('../lib/commands/ls.js') - const ls = new LS({ config: { validate: () => {} } }) + const ls = new LS({ + config: { + validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, + }, + }) const p = spawn(process.execPath, [index, 'ls', '-h', '--cache', cwd]) const out = [] p.stdout.on('data', c => out.push(c)) diff --git a/test/lib/arborist-cmd.js b/test/lib/arborist-cmd.js index d2497efe129dc..5841bbed9139d 100644 --- a/test/lib/arborist-cmd.js +++ b/test/lib/arborist-cmd.js @@ -2,6 +2,15 @@ const { resolve } = require('path') const t = require('tap') const ArboristCmd = require('../../lib/arborist-cmd.js') +const configMock = { + validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, +} + t.test('arborist-cmd', async t => { const path = t.testdir({ 'package.json': JSON.stringify({ @@ -44,7 +53,7 @@ t.test('arborist-cmd', async t => { class TestCmd extends ArboristCmd {} - const cmd = new TestCmd({ localPrefix: path, config: { validate: () => {} } }) + const cmd = new TestCmd({ localPrefix: path, config: configMock }) // check filtering for a single workspace name cmd.exec = async function (args) { @@ -96,7 +105,7 @@ t.test('handle getWorkspaces raising an error', async t => { }, }) class TestCmd extends ArboristCmd {} - const cmd = new TestCmd({ localPrefix: t.testdir(), config: { validate: () => {} } }) + const cmd = new TestCmd({ localPrefix: t.testdir(), config: configMock }) await t.rejects( cmd.execWorkspaces(['foo'], ['a']), diff --git a/test/lib/commands/explain.js b/test/lib/commands/explain.js index c92732e904e60..3e2d495f8fc73 100644 --- a/test/lib/commands/explain.js +++ b/test/lib/commands/explain.js @@ -8,6 +8,11 @@ const npm = { }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, }, } const { resolve } = require('path') diff --git a/test/lib/commands/install-ci-test.js b/test/lib/commands/install-ci-test.js index 68b86be43a30f..62ffc68466bb8 100644 --- a/test/lib/commands/install-ci-test.js +++ b/test/lib/commands/install-ci-test.js @@ -25,6 +25,11 @@ const installCITest = new InstallCITest({ }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, }, }) diff --git a/test/lib/commands/install-test.js b/test/lib/commands/install-test.js index 0e0cf47521c4e..3e3ec7732a8cc 100644 --- a/test/lib/commands/install-test.js +++ b/test/lib/commands/install-test.js @@ -25,6 +25,11 @@ const installTest = new InstallTest({ }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, }, }) diff --git a/test/lib/commands/install.js b/test/lib/commands/install.js index 632ca22be9e71..b3498593a5f5d 100644 --- a/test/lib/commands/install.js +++ b/test/lib/commands/install.js @@ -130,6 +130,7 @@ t.test('exec commands', async t => { ) t.equal(REIFY_CALLED, true, 'called reify') t.strictSame(SCRIPTS, [], 'no scripts when installing globally') + t.equal(npm.config.get('audit', 'cli'), false) }) await t.test('should not install invalid global package name', async t => { @@ -327,3 +328,44 @@ t.test('completion', async t => { t.strictSame(res, []) }) }) + +t.test('location detection and audit', async () => { + t.test('audit false without package.json', async t => { + const { npm } = await _loadMockNpm(t, { + prefixDir: { + // no package.json + 'readme.txt': 'just a file', + other: {}, + }, + }) + const install = await npm.cmd('install') + t.equal(install.npm.config.get('location'), 'user') + t.equal(install.npm.config.get('audit'), false) + }) + t.test('audit true with package.json', async t => { + const { npm } = await _loadMockNpm(t, { + prefixDir: { + 'package.json': '{ "name": "testpkg", "version": "1.0.0" }', + 'readme.txt': 'just a file', + }, + }) + const install = await npm.cmd('install') + t.equal(install.npm.config.get('location'), 'project') + t.equal(install.npm.config.get('audit'), true) + }) + t.test('audit true without package.json when set', async t => { + const { npm } = await _loadMockNpm(t, { + prefixDir: { + // no package.json + 'readme.txt': 'just a file', + other: {}, + }, + config: { + audit: { value: true, where: 'cli' }, + }, + }) + const install = await npm.cmd('install') + t.equal(install.npm.config.get('location'), 'user') + t.equal(install.npm.config.get('audit'), true) + }) +}) diff --git a/test/lib/commands/ls.js b/test/lib/commands/ls.js index 764d95298ca10..b9278dd20688d 100644 --- a/test/lib/commands/ls.js +++ b/test/lib/commands/ls.js @@ -103,6 +103,7 @@ const config = { global: false, json: false, link: false, + location: 'project', omit: [], parseable: false, 'package-lock-only': false,