Skip to content

Commit 40be7bb

Browse files
author
Max Black
committed
feat: show proxy environment variables in npm config list
Adds proxy-related environment variables to npm config list output to help users understand their proxy configuration. Variables are checked case-insensitively to match the agent library behavior. Closes #4170
1 parent bc9a4c2 commit 40be7bb

File tree

3 files changed

+82
-1
lines changed

3 files changed

+82
-1
lines changed

lib/commands/config.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const { spawn } = require('node:child_process')
44
const { EOL } = require('node:os')
55
const localeCompare = require('@isaacs/string-locale-compare')('en')
66
const pkgJson = require('@npmcli/package-json')
7-
const { defaults, definitions, nerfDarts } = require('@npmcli/config/lib/definitions')
7+
const { defaults, definitions, nerfDarts, proxyEnv } = require('@npmcli/config/lib/definitions')
88
const { log, output } = require('proc-log')
99
const BaseCommand = require('../base-cmd.js')
1010
const { redact } = require('@npmcli/redact')
@@ -350,6 +350,23 @@ ${defData}
350350
}
351351

352352
if (!long) {
353+
const envVars = []
354+
355+
const foundEnvVars = new Set()
356+
for (const key of Object.keys(process.env)) {
357+
const lowerKey = key.toLowerCase()
358+
if (proxyEnv.includes(lowerKey) && !foundEnvVars.has(lowerKey)) {
359+
foundEnvVars.add(lowerKey)
360+
envVars.push(`; ${key} = ${JSON.stringify(process.env[key])}`)
361+
}
362+
}
363+
364+
if (envVars.length > 0) {
365+
msg.push('; environment-related config', '')
366+
msg.push(...envVars)
367+
msg.push('')
368+
}
369+
353370
msg.push(
354371
`; node bin location = ${process.execPath}`,
355372
`; node version = ${process.version}`,

tap-snapshots/test/lib/commands/config.js.test.cjs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
2323
"before": null,
2424
"bin-links": true,
2525
"browser": null,
26+
"bypass-2fa": false,
2627
"ca": null,
2728
"cache-max": null,
2829
"cache-min": 0,
@@ -48,6 +49,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
4849
"engine-strict": false,
4950
"expect-result-count": null,
5051
"expect-results": null,
52+
"expires": null,
5153
"fetch-retries": 2,
5254
"fetch-retry-factor": 10,
5355
"fetch-retry-maxtimeout": 60000,
@@ -97,6 +99,7 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
9799
"logs-dir": null,
98100
"logs-max": 10,
99101
"long": false,
102+
"name": null,
100103
"maxsockets": 15,
101104
"message": "%s",
102105
"node-gyp": "{CWD}/node_modules/node-gyp/bin/node-gyp.js",
@@ -108,13 +111,15 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
108111
"omit": [],
109112
"omit-lockfile-registry-resolved": false,
110113
"only": null,
114+
"orgs": null,
111115
"optional": null,
112116
"os": null,
113117
"otp": null,
114118
"package": [],
115119
"package-lock": true,
116120
"package-lock-only": false,
117121
"pack-destination": ".",
122+
"packages": [],
118123
"parseable": false,
119124
"prefer-dedupe": false,
120125
"prefer-offline": false,
@@ -141,6 +146,11 @@ exports[`test/lib/commands/config.js TAP config list --json > output matches sna
141146
"sbom-format": null,
142147
"sbom-type": "library",
143148
"scope": "",
149+
"scopes": null,
150+
"packages-all": false,
151+
"packages-and-scopes-permission": null,
152+
"orgs-permission": null,
153+
"token-description": null,
144154
"script-shell": null,
145155
"searchexclude": "",
146156
"searchlimit": 20,
@@ -187,6 +197,7 @@ auth-type = "web"
187197
before = null
188198
bin-links = true
189199
browser = null
200+
bypass-2fa = false
190201
ca = null
191202
; cache = "{CACHE}" ; overridden by cli
192203
cache-max = null
@@ -214,6 +225,7 @@ editor = "{EDITOR}"
214225
engine-strict = false
215226
expect-result-count = null
216227
expect-results = null
228+
expires = null
217229
fetch-retries = 2
218230
fetch-retry-factor = 10
219231
fetch-retry-maxtimeout = 60000
@@ -266,6 +278,7 @@ logs-max = 10
266278
; long = false ; overridden by cli
267279
maxsockets = 15
268280
message = "%s"
281+
name = null
269282
node-gyp = "{CWD}/node_modules/node-gyp/bin/node-gyp.js"
270283
node-options = null
271284
noproxy = [""]
@@ -275,13 +288,19 @@ omit = []
275288
omit-lockfile-registry-resolved = false
276289
only = null
277290
optional = null
291+
orgs = null
292+
orgs-permission = null
278293
os = null
279294
otp = null
280295
pack-destination = "."
281296
package = []
282297
package-lock = true
283298
package-lock-only = false
299+
packages = []
300+
packages-all = false
301+
packages-and-scopes-permission = null
284302
parseable = false
303+
password = (protected)
285304
prefer-dedupe = false
286305
prefer-offline = false
287306
prefer-online = false
@@ -307,6 +326,7 @@ save-prod = false
307326
sbom-format = null
308327
sbom-type = "library"
309328
scope = ""
329+
scopes = null
310330
script-shell = null
311331
searchexclude = ""
312332
searchlimit = 20
@@ -321,6 +341,7 @@ strict-ssl = true
321341
tag = "latest"
322342
tag-version-prefix = "v"
323343
timing = false
344+
token-description = null
324345
umask = 0
325346
unicode = false
326347
update-notifier = true

test/lib/commands/config.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,49 @@ t.test('config list', async t => {
101101
t.matchSnapshot(output, 'output matches snapshot')
102102
})
103103

104+
t.test('config list with proxy environment variables', async t => {
105+
const originalHTTP = process.env.HTTP_PROXY
106+
const originalHTTPS = process.env.HTTPS_PROXY
107+
const originalNO = process.env.NO_PROXY
108+
109+
t.teardown(() => {
110+
if (originalHTTP !== undefined) {
111+
process.env.HTTP_PROXY = originalHTTP
112+
} else {
113+
delete process.env.HTTP_PROXY
114+
}
115+
if (originalHTTPS !== undefined) {
116+
process.env.HTTPS_PROXY = originalHTTPS
117+
} else {
118+
delete process.env.HTTPS_PROXY
119+
}
120+
if (originalNO !== undefined) {
121+
process.env.NO_PROXY = originalNO
122+
} else {
123+
delete process.env.NO_PROXY
124+
}
125+
})
126+
127+
process.env.HTTP_PROXY = 'http://proxy.example.com:8080'
128+
process.env.HTTPS_PROXY = 'https://secure-proxy.example.com:8443'
129+
process.env.NO_PROXY = 'localhost,127.0.0.1'
130+
131+
const { npm, joinedOutput } = await loadMockNpm(t, {
132+
prefixDir: {
133+
'.npmrc': 'test=value',
134+
},
135+
})
136+
137+
await npm.exec('config', ['list'])
138+
139+
const output = joinedOutput()
140+
141+
t.match(output, 'HTTP_PROXY = "http://proxy.example.com:8080"')
142+
t.match(output, 'HTTPS_PROXY = "https://secure-proxy.example.com:8443"')
143+
t.match(output, 'NO_PROXY = "localhost,127.0.0.1"')
144+
t.match(output, 'environment-related config')
145+
})
146+
104147
t.test('config list --long', async t => {
105148
const { npm, joinedOutput } = await loadMockNpm(t, {
106149
prefixDir: {

0 commit comments

Comments
 (0)