fix(config): pause progress spinner during interactive editor spawn (… · npm/cli@c0fc549 · GitHub
Skip to content

Commit c0fc549

Browse files
Zelys-DFKHclaude
andauthored
fix(config): pause progress spinner during interactive editor spawn (#9372)
Fixes #9142, Fixes #9184 When \`npm config edit\` or \`npm edit\` opens an interactive editor, the progress spinner keeps running and writes ANSI control codes into the buffer, garbling the display. Neither command called \`input.start()\` before opening the editor, though \`help.js\` and \`open-url.js\` already handle this correctly. Wrapping both editor spawns in \`input.start()\` lets the spinner step aside while the editor has control of the terminal, and closes both issues at once. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d124c08 commit c0fc549

4 files changed

Lines changed: 21 additions & 7 deletions

File tree

lib/commands/config.js

Lines changed: 3 additions & 3 deletions

lib/commands/edit.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const { resolve } = require('node:path')
22
const { lstat } = require('node:fs/promises')
33
const cp = require('node:child_process')
4+
const { input } = require('proc-log')
45
const completion = require('../utils/installed-shallow.js')
56
const BaseCommand = require('../base-cmd.js')
67

@@ -46,16 +47,17 @@ class Edit extends BaseCommand {
4647
const dir = resolve(this.npm.dir, path)
4748

4849
await lstat(dir)
49-
await new Promise((res, rej) => {
50+
await input.start(() => new Promise((res, rej) => {
5051
const [bin, ...spawnArgs] = this.npm.config.get('editor').split(/\s+/)
5152
const editor = cp.spawn(bin, [...spawnArgs, dir], { stdio: 'inherit' })
52-
editor.on('exit', async (code) => {
53+
editor.on('exit', (code) => {
5354
if (code) {
5455
return rej(new Error(`editor process exited with code: ${code}`))
5556
}
56-
await this.npm.exec('rebuild', [dir]).then(res).catch(rej)
57+
res()
5758
})
58-
})
59+
}))
60+
await this.npm.exec('rebuild', [dir])
5961
}
6062
}
6163

test/lib/commands/config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,11 @@ t.test('config edit', async t => {
574574
},
575575
})
576576

577+
const inputEvents = []
578+
const inputListener = (level) => inputEvents.push(level)
579+
process.on('input', inputListener)
580+
t.teardown(() => process.off('input', inputListener))
581+
577582
await npm.exec('config', ['edit'])
578583

579584
t.ok(editor.called, 'editor was spawned')
@@ -582,6 +587,7 @@ t.test('config edit', async t => {
582587
[join(home, '.npmrc')],
583588
'editor opened the user config file'
584589
)
590+
t.same(inputEvents.slice(0, 2), ['start', 'end'], 'progress paused and resumed around editor')
585591

586592
const contents = await fs.readFile(join(home, '.npmrc'), { encoding: 'utf8' })
587593
t.ok(contents.includes('foo=bar'), 'kept foo')

test/lib/commands/edit.js

Lines changed: 6 additions & 0 deletions

0 commit comments

Comments
 (0)