From 7d521b2350e488bf5c1570f8f82bf7a582eea0d8 Mon Sep 17 00:00:00 2001 From: Mike Donnalley Date: Mon, 12 Feb 2024 13:40:25 -0700 Subject: [PATCH] fix: allow long text in ux.prompt --- src/cli-ux/prompt.ts | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/src/cli-ux/prompt.ts b/src/cli-ux/prompt.ts index 84f25dc21..495593523 100644 --- a/src/cli-ux/prompt.ts +++ b/src/cli-ux/prompt.ts @@ -1,4 +1,5 @@ import chalk from 'chalk' +import readline from 'node:readline' import * as Errors from '../errors' import {config} from './config' @@ -26,29 +27,36 @@ interface IPromptConfig { function normal(options: IPromptConfig, retries = 100): Promise { if (retries < 0) throw new Error('no input') + const ac = new AbortController() + const {signal} = ac + return new Promise((resolve, reject) => { - let timer: NodeJS.Timeout - if (options.timeout) { - timer = setTimeout(() => { - process.stdin.pause() - reject(new Error('Prompt timeout')) - }, options.timeout) - timer.unref() - } + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }) - process.stdin.setEncoding('utf8') - process.stderr.write(options.prompt) - process.stdin.resume() - process.stdin.once('data', (b) => { - if (timer) clearTimeout(timer) - process.stdin.pause() - const data: string = (typeof b === 'string' ? b : b.toString()).trim() + rl.question(options.prompt, {signal}, (answer) => { + rl.close() + const data = answer.trim() if (!options.default && options.required && data === '') { resolve(normal(options, retries - 1)) } else { resolve(data || (options.default as string)) } }) + + if (options.timeout) { + signal.addEventListener( + 'abort', + () => { + reject(new Error('Prompt timeout')) + }, + {once: true}, + ) + + setTimeout(() => ac.abort(), options.timeout) + } }) }