Skip to content

Commit 1b18ff5

Browse files
committed
fixup! fix: hide banner for exec and explore
1 parent 18bfc47 commit 1b18ff5

3 files changed

Lines changed: 47 additions & 32 deletions

File tree

lib/npm.js

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class Npm {
3232
updateNotification = null
3333
argv = []
3434

35+
#commandName = null
3536
#command = null
3637
#runId = new Date().toISOString().replace(/[.:]/g, '_')
3738
#title = 'npm'
@@ -94,11 +95,11 @@ class Npm {
9495

9596
async load () {
9697
return time.start('npm:load', async () => {
97-
const { exec } = await this.#load()
98+
const { exec, command, args } = await this.#load()
9899
return {
99100
exec,
100-
command: this.argv.shift(),
101-
args: this.argv,
101+
command,
102+
args,
102103
}
103104
})
104105
}
@@ -165,7 +166,26 @@ class Npm {
165166

166167
await time.start('npm:load:configload', () => this.config.load())
167168

169+
// npm --versions
170+
if (this.config.get('versions', 'cli')) {
171+
this.argv = ['version']
172+
this.config.set('usage', false, 'cli')
173+
} else {
174+
this.argv = [...this.config.parsedArgv.remain]
175+
}
176+
177+
// Remove first argv since that is our command as typed
178+
// Note that this might not be the actual name of the command
179+
// due to aliases, etc. But we use the raw form of it later
180+
// in user output so it must be preserved as is.
181+
const commandArg = this.argv.shift()
182+
183+
// This is the actual name of the command that will be run or
184+
// undefined if deref could not find a match
185+
const command = deref(commandArg)
186+
168187
await this.#display.load({
188+
command
169189
loglevel: this.config.get('loglevel'),
170190
stdoutColor: this.color,
171191
stderrColor: this.logColor,
@@ -174,9 +194,6 @@ class Npm {
174194
progress: this.flatOptions.progress,
175195
json: this.config.get('json'),
176196
heading: this.config.get('heading'),
177-
// TODO: avoid passing all of npm in. this is a quick
178-
// fix to allow display to know the currently running command
179-
npm: this,
180197
})
181198
process.env.COLOR = this.color ? '1' : '0'
182199

@@ -205,23 +222,24 @@ class Npm {
205222

206223
// note: this MUST be shorter than the actual argv length, because it
207224
// uses the same memory, so node will truncate it if it's too long.
225+
// We time this because setting process.title is slow sometimes but we
226+
// have to do it for security reasons. But still helpful to know how slow it is.
208227
time.start('npm:load:setTitle', () => {
209-
const { parsedArgv: { cooked, remain } } = this.config
210-
this.argv = remain
211228
// Secrets are mostly in configs, so title is set using only the positional args
212229
// to keep those from being leaked. We still do a best effort replaceInfo.
213-
this.#title = ['npm'].concat(replaceInfo(remain)).join(' ').trim()
230+
this.#title = ['npm'].concat(replaceInfo(this.config.parsedArgv.remain)).join(' ').trim()
214231
process.title = this.#title
215-
// The cooked argv is also logged separately for debugging purposes. It is
216-
// cleaned as a best effort by replacing known secrets like basic auth
217-
// password and strings that look like npm tokens. XXX: for this to be
218-
// safer the config should create a sanitized version of the argv as it
219-
// has the full context of what each option contains.
220-
this.#argvClean = replaceInfo(cooked)
221-
log.verbose('title', this.title)
222-
log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' '))
223232
})
224233

234+
// The cooked argv is also logged separately for debugging purposes. It is
235+
// cleaned as a best effort by replacing known secrets like basic auth
236+
// password and strings that look like npm tokens. XXX: for this to be
237+
// safer the config should create a sanitized version of the argv as it
238+
// has the full context of what each option contains.
239+
this.#argvClean = replaceInfo(this.config.parsedArgv.cooked)
240+
log.verbose('title', this.title)
241+
log.verbose('argv', this.#argvClean.map(JSON.stringify).join(' '))
242+
225243
// logFile.load returns a promise that resolves when old logs are done being cleaned.
226244
// We save this promise to an array so that we can await it in tests to ensure more
227245
// deterministic logging behavior. The process will also hang open if this were to
@@ -247,13 +265,7 @@ class Npm {
247265
log.warn('using --force', 'Recommended protections disabled.')
248266
}
249267

250-
// npm --versions
251-
if (this.config.get('versions', 'cli')) {
252-
this.argv = ['version']
253-
this.config.set('usage', false, 'cli')
254-
}
255-
256-
return { exec: true }
268+
return { exec: true, command: commandArg, args: this.argv }
257269
}
258270

259271
get isShellout () {

lib/utils/display.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,12 @@ class Display {
119119
#progress
120120

121121
// options
122+
#command
122123
#levelIndex
123124
#timing
124125
#json
125126
#heading
126127
#silent
127-
#npm
128128

129129
// display streams
130130
#stdout
@@ -160,6 +160,7 @@ class Display {
160160
}
161161

162162
async load ({
163+
command,
163164
heading,
164165
json,
165166
loglevel,
@@ -168,9 +169,8 @@ class Display {
168169
stdoutColor,
169170
timing,
170171
unicode,
171-
npm,
172172
}) {
173-
this.#npm = npm
173+
this.#command = command
174174
// get createSupportsColor from chalk directly if this lands
175175
// https://github.com/chalk/chalk/pull/600
176176
const [{ Chalk }, { createSupportsColor }] = await Promise.all([
@@ -275,10 +275,13 @@ class Display {
275275
return
276276
}
277277

278-
// HACK: if it looks like the banner and we are silent do not print it.
279-
// There's no other way to do this right now :(\
280-
const isBanner = args.length === 1 && args[0].startsWith('\n> ') && args[0].endsWith('\n')
281-
const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#npm.command)
278+
// HACK: if it looks like the banner and we are in a state where we hide the
279+
// banner then dont write any output. This hack can be replaced with proc-log.META
280+
const isBanner = args.length === 1 &&
281+
typeof args[0] === 'string' &&
282+
args[0].startsWith('\n> ') &&
283+
args[0].endsWith('\n')
284+
const hideBanner = this.#silent || ['exec', 'explore'].includes(this.#command)
282285
if (isBanner && hideBanner) {
283286
return
284287
}

test/lib/docs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ t.test('basic usage', async t => {
7474
// are generated in the following test
7575
const { npm } = await loadMockNpm(t, {
7676
mocks: {
77-
'{LIB}/utils/cmd-list.js': { commands: [] },
77+
'{LIB}/utils/cmd-list.js': { ...cmdList, commands: [] },
7878
},
7979
config: { userconfig: '/some/config/file/.npmrc' },
8080
globals: { process: { platform: 'posix' } },

0 commit comments

Comments
 (0)