From 9c29072e70e37fab03e45699d318006031aa87a3 Mon Sep 17 00:00:00 2001 From: Max Black Date: Thu, 4 Dec 2025 11:34:27 -0800 Subject: [PATCH] feat: show proxy environment variables in npm config list Fixes #4170 pm config list now displays proxy-related environment variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY and their lowercase equivalents) when they are set. This helps users understand what proxy settings are being used by npm. The environment variables are shown in a separate '; environment-related config' section before the system information (node version, npm version, etc.). --- lib/commands/config.js | 17 ++++++++- test/lib/commands/config.js | 43 ++++++++++++++++++++++ workspaces/config/lib/definitions/index.js | 12 ++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/lib/commands/config.js b/lib/commands/config.js index b657029b2d2fe..5e417441d41b6 100644 --- a/lib/commands/config.js +++ b/lib/commands/config.js @@ -4,7 +4,7 @@ const { spawn } = require('node:child_process') const { EOL } = require('node:os') const localeCompare = require('@isaacs/string-locale-compare')('en') const pkgJson = require('@npmcli/package-json') -const { defaults, definitions, nerfDarts } = require('@npmcli/config/lib/definitions') +const { defaults, definitions, nerfDarts, proxyEnv } = require('@npmcli/config/lib/definitions') const { log, output } = require('proc-log') const BaseCommand = require('../base-cmd.js') const { redact } = require('@npmcli/redact') @@ -350,6 +350,21 @@ ${defData} } if (!long) { + const envVars = [] + + // Show proxy-related environment variables if they're set + for (const envVar of proxyEnv) { + if (process.env[envVar]) { + envVars.push(`; ${envVar} = ${JSON.stringify(process.env[envVar])}`) + } + } + + if (envVars.length > 0) { + msg.push('; environment-related config', '') + msg.push(...envVars) + msg.push('') + } + msg.push( `; node bin location = ${process.execPath}`, `; node version = ${process.version}`, diff --git a/test/lib/commands/config.js b/test/lib/commands/config.js index 64977c6f6c2f0..9a65e883cfebc 100644 --- a/test/lib/commands/config.js +++ b/test/lib/commands/config.js @@ -101,6 +101,49 @@ t.test('config list', async t => { t.matchSnapshot(output, 'output matches snapshot') }) +t.test('config list with proxy environment variables', async t => { + const originalHTTP = process.env.HTTP_PROXY + const originalHTTPS = process.env.HTTPS_PROXY + const originalNO = process.env.NO_PROXY + + t.teardown(() => { + if (originalHTTP !== undefined) { + process.env.HTTP_PROXY = originalHTTP + } else { + delete process.env.HTTP_PROXY + } + if (originalHTTPS !== undefined) { + process.env.HTTPS_PROXY = originalHTTPS + } else { + delete process.env.HTTPS_PROXY + } + if (originalNO !== undefined) { + process.env.NO_PROXY = originalNO + } else { + delete process.env.NO_PROXY + } + }) + + process.env.HTTP_PROXY = 'http://proxy.example.com:8080' + process.env.HTTPS_PROXY = 'https://secure-proxy.example.com:8443' + process.env.NO_PROXY = 'localhost,127.0.0.1' + + const { npm, joinedOutput } = await loadMockNpm(t, { + prefixDir: { + '.npmrc': 'test=value', + }, + }) + + await npm.exec('config', ['list']) + + const output = joinedOutput() + + t.match(output, 'HTTP_PROXY = "http://proxy.example.com:8080"') + t.match(output, 'HTTPS_PROXY = "https://secure-proxy.example.com:8443"') + t.match(output, 'NO_PROXY = "localhost,127.0.0.1"') + t.match(output, 'environment-related config') +}) + t.test('config list --long', async t => { const { npm, joinedOutput } = await loadMockNpm(t, { prefixDir: { diff --git a/workspaces/config/lib/definitions/index.js b/workspaces/config/lib/definitions/index.js index 793b71ea40d6f..6f7f48a438ade 100644 --- a/workspaces/config/lib/definitions/index.js +++ b/workspaces/config/lib/definitions/index.js @@ -71,10 +71,22 @@ const nerfDarts = [ 'username', // Does not have a config ] +// Environment variables that can affect npm's behavior but are not npm configs +// These are shown in `npm config list` to help users understand their environment +const proxyEnv = [ + 'HTTP_PROXY', + 'HTTPS_PROXY', + 'NO_PROXY', + 'http_proxy', + 'https_proxy', + 'no_proxy', +] + module.exports = { defaults: definitionProps.defaults, definitions, flatten, nerfDarts, + proxyEnv, shorthands, }