fix(cli): exit after interactive secret input (#7118)

This commit is contained in:
Theodore Li
2026-08-26 12:43:53 -07:00
committed by GitHub
parent db88eca6d4
commit 437ffa3190
4 changed files with 12 additions and 10 deletions
+1 -1
View File
@@ -610,7 +610,7 @@
},
"packages/sim-cli": {
"name": "sim",
"version": "2.1.1",
"version": "2.1.2",
"bin": {
"sim": "dist/index.js",
},
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "sim",
"version": "2.1.1",
"version": "2.1.2",
"description": "Sim CLI - talk to the Sim API from your terminal",
"type": "module",
"bin": {
@@ -8,11 +8,11 @@ const ESCAPE = '\u001b'
class FakeInput extends EventEmitter {
isTTY = true
isRaw = false
paused = true
readableFlowing: boolean | null = null
readonly rawStates: boolean[] = []
isPaused(): boolean {
return this.paused
return this.readableFlowing === false
}
setRawMode(value: boolean): this {
@@ -22,12 +22,12 @@ class FakeInput extends EventEmitter {
}
resume(): this {
this.paused = false
this.readableFlowing = true
return this
}
pause(): this {
this.paused = true
this.readableFlowing = false
return this
}
}
@@ -42,9 +42,11 @@ class FakeOutput {
}
describe('promptSecret', () => {
it('masks input and restores the terminal before returning it', async () => {
it('masks input and pauses an initially idle terminal before returning', async () => {
const input = new FakeInput()
const output = new FakeOutput()
expect(input.isPaused()).toBe(false)
const result = promptSecret(input as unknown as ReadStream, output)
input.emit('keypress', 'hunter2', { name: 'h' })
@@ -53,7 +55,7 @@ describe('promptSecret', () => {
await expect(result).resolves.toBe('hunter2')
expect(output.value).toBe('Secret value: *******\n')
expect(input.rawStates).toEqual([true, false])
expect(input.paused).toBe(true)
expect(input.isPaused()).toBe(true)
})
it('handles backspace without revealing the value', async () => {
@@ -88,6 +90,7 @@ describe('promptSecret', () => {
await expect(result).rejects.toThrow('Secret input cancelled.')
await expect(result).rejects.toBeInstanceOf(SecretInputCancelledError)
expect(input.rawStates).toEqual([true, false])
expect(input.isPaused()).toBe(true)
})
it('keeps the character following a pasted escape byte', async () => {
@@ -45,7 +45,6 @@ export function promptSecret(
throw new SimApiError('Interactive secret input requires a terminal. Pass --value instead.', 0)
}
const wasPaused = input.isPaused()
const wasRaw = input.isRaw
let value = ''
let settled = false
@@ -59,7 +58,7 @@ export function promptSecret(
const cleanup = () => {
input.removeListener('keypress', onKeypress)
input.setRawMode(wasRaw)
if (wasPaused) input.pause()
input.pause()
}
const finish = (complete: () => void) => {