From 706b3d3f227de43a095263926d2eef2b4e4cf2a9 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 | 12 ++- test/lib/arborist-cmd.js | 14 +++- test/lib/commands/explain.js | 6 ++ test/lib/commands/install-ci-test.js | 6 ++ test/lib/commands/install-test.js | 6 ++ test/lib/commands/install.js | 75 +++++++++++++++++++ test/lib/commands/ls.js | 1 + test/lib/commands/set.js | 1 + 11 files changed, 148 insertions(+), 3 deletions(-) diff --git a/lib/arborist-cmd.js b/lib/arborist-cmd.js index 5007fbd9244d..29efe984d9b2 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.isDefault('audit') + && (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 9fbda9073492..0bdbcdb9efd8 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 4170dd9078c8..93a3e9ac4eeb 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 5075597b5d93..747d75b5fd4c 100644 --- a/test/index.js +++ b/test/index.js @@ -11,7 +11,17 @@ 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' + } + }, + isDefault: () => {}, + }, + }) 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 d2497efe129d..f3c1d2573d33 100644 --- a/test/lib/arborist-cmd.js +++ b/test/lib/arborist-cmd.js @@ -2,6 +2,16 @@ 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' + } + }, + isDefault: () => {}, +} + t.test('arborist-cmd', async t => { const path = t.testdir({ 'package.json': JSON.stringify({ @@ -44,7 +54,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 +106,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 c92732e904e6..71bb1752205c 100644 --- a/test/lib/commands/explain.js +++ b/test/lib/commands/explain.js @@ -8,6 +8,12 @@ const npm = { }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, + isDefault: () => {}, }, } const { resolve } = require('path') diff --git a/test/lib/commands/install-ci-test.js b/test/lib/commands/install-ci-test.js index 68b86be43a30..401113a30e18 100644 --- a/test/lib/commands/install-ci-test.js +++ b/test/lib/commands/install-ci-test.js @@ -25,6 +25,12 @@ const installCITest = new InstallCITest({ }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, + isDefault: () => {}, }, }) diff --git a/test/lib/commands/install-test.js b/test/lib/commands/install-test.js index 0e0cf47521c4..5776c7fe343b 100644 --- a/test/lib/commands/install-test.js +++ b/test/lib/commands/install-test.js @@ -25,6 +25,12 @@ const installTest = new InstallTest({ }, config: { validate: () => {}, + get: (key) => { + if (key === 'location') { + return 'project' + } + }, + isDefault: () => {}, }, }) diff --git a/test/lib/commands/install.js b/test/lib/commands/install.js index 632ca22be9e7..4c3251f52fbc 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,77 @@ 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) + }) + t.test('audit true in root config without package.json', async t => { + const { npm } = await _loadMockNpm(t, { + prefixDir: { + // no package.json + 'readme.txt': 'just a file', + other: {}, + }, + config: { + audit: { value: true, where: 'builtin' }, + }, + }) + const install = await npm.cmd('install') + t.equal(install.npm.config.get('location'), 'user') + t.equal(install.npm.config.get('audit'), true) + }) + t.test('test for warning when --global & --audit', async t => { + const { npm, logs } = await _loadMockNpm(t, { + prefixDir: { + // no package.json + 'readme.txt': 'just a file', + other: {}, + }, + config: { + audit: { value: true, where: 'cli' }, + global: { 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) + t.equal(logs.warn[0][0], 'config') + t.equal(logs.warn[0][1], 'includes both --global and --audit, which is currently unsupported.') + }) +}) diff --git a/test/lib/commands/ls.js b/test/lib/commands/ls.js index 764d95298ca1..b9278dd20688 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, diff --git a/test/lib/commands/set.js b/test/lib/commands/set.js index 9a68eaf32d45..ce59870e2fec 100644 --- a/test/lib/commands/set.js +++ b/test/lib/commands/set.js @@ -42,6 +42,7 @@ const npm = { }, config: { validate: () => {}, + isDefault: () => {}, }, }