@@ -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 ( ) {
0 commit comments