mirror of
https://github.com/simstudioai/sim.git
synced 2026-08-29 02:27:35 +08:00
fix(cli): exit after interactive secret input (#7118)
This commit is contained in:
@@ -610,7 +610,7 @@
|
||||
},
|
||||
"packages/sim-cli": {
|
||||
"name": "sim",
|
||||
"version": "2.1.1",
|
||||
"version": "2.1.2",
|
||||
"bin": {
|
||||
"sim": "dist/index.js",
|
||||
},
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user