diff --git a/packages/inquirer/inquirer.test.mts b/packages/inquirer/inquirer.test.mts index 1a45eb6022..b24c0f5673 100644 --- a/packages/inquirer/inquirer.test.mts +++ b/packages/inquirer/inquirer.test.mts @@ -783,7 +783,7 @@ describe('AbortSignal support', () => { await expect(promise).rejects.toThrow(AbortPromptError); }); - it('legacy prompts can be aborted', async () => { + it('legacy prompts can be aborted by module signal', async () => { const abortController = new AbortController(); const localPrompt = inquirer.createPromptModule({ signal: abortController.signal, @@ -795,21 +795,7 @@ describe('AbortSignal support', () => { await expect(promise).rejects.toThrow(AbortPromptError); }); - it('legacy prompts can be aborted passing signal', async () => { - const abortController = new AbortController(); - const localPrompt = inquirer.createPromptModule(); - localPrompt.registerPrompt('stub', StubEventualyFailingPrompt); - - const promise = localPrompt( - { type: 'stub', name: 'q1', message: 'message' }, - {}, - { signal: abortController.signal }, - ); - abortController.abort(); - await expect(promise).rejects.toThrow(AbortPromptError); - }); - - it('modern prompts can be aborted', async () => { + it('modern prompts can be aborted by module signal', async () => { const abortController = new AbortController(); const localPrompt = inquirer.createPromptModule({ signal: abortController.signal, @@ -835,23 +821,6 @@ describe('AbortSignal support', () => { promise.ui.close(); await expect(promise).rejects.toThrow(AbortPromptError); }); - - it('modern prompts can be aborted passing signals', async () => { - const abortController = new AbortController(); - const localPrompt = inquirer.createPromptModule(); - localPrompt.registerPrompt( - 'stub', - createPrompt(() => 'dummy prompt'), - ); - - const promise = localPrompt( - { type: 'stub', name: 'q1', message: 'message' }, - {}, - { signal: abortController.signal }, - ); - abortController.abort(); - await expect(promise).rejects.toThrow(AbortPromptError); - }); }); describe('Non-TTY checks', () => { diff --git a/packages/inquirer/src/index.mts b/packages/inquirer/src/index.mts index 68058b7a20..4da48ff1bc 100644 --- a/packages/inquirer/src/index.mts +++ b/packages/inquirer/src/index.mts @@ -35,7 +35,7 @@ import { Observable } from 'rxjs'; export type { QuestionMap } from './types.mjs'; -const defaultPrompts: PromptCollection = { +const builtInPrompts: PromptCollection = { input, select, /** @deprecated `list` is now named `select` */ @@ -70,7 +70,6 @@ export function createPromptModule< >( questions: NamedQuestion>[], answers?: PrefilledAnswers, - opts?: { signal?: AbortSignal }, ): PromptReturnType>; function promptModule< const A extends Answers, @@ -80,7 +79,6 @@ export function createPromptModule< [name in keyof A]: Question>; }, answers?: PrefilledAnswers, - opts?: { signal?: AbortSignal }, ): PromptReturnType>>>; function promptModule< const A extends Answers, @@ -88,7 +86,6 @@ export function createPromptModule< >( questions: Observable>>, answers?: PrefilledAnswers, - opts?: { signal?: AbortSignal }, ): PromptReturnType>; function promptModule< const A extends Answers, @@ -96,20 +93,18 @@ export function createPromptModule< >( questions: NamedQuestion, answers?: PrefilledAnswers, - opts?: { signal?: AbortSignal }, ): PromptReturnType; function promptModule( questions: PromptSession, answers?: Partial, - opts: { signal?: AbortSignal } = {}, ): PromptReturnType { const runner = new PromptsRunner(promptModule.prompts, opt); - const promptPromise = runner.run(questions, answers, opts); + const promptPromise = runner.run(questions, answers); return Object.assign(promptPromise, { ui: runner }); } - promptModule.prompts = { ...defaultPrompts }; + promptModule.prompts = { ...builtInPrompts }; /** * Register a prompt type @@ -126,7 +121,7 @@ export function createPromptModule< * Register the defaults provider prompts */ promptModule.restoreDefaultPrompts = function () { - promptModule.prompts = { ...defaultPrompts }; + promptModule.prompts = { ...builtInPrompts }; }; return promptModule; diff --git a/packages/inquirer/src/ui/prompt.mts b/packages/inquirer/src/ui/prompt.mts index 791d7e357c..34b33874b5 100644 --- a/packages/inquirer/src/ui/prompt.mts +++ b/packages/inquirer/src/ui/prompt.mts @@ -198,11 +198,7 @@ export default class PromptsRunner { this.prompts = prompts; } - async run( - questions: PromptSession, - answers?: Partial, - opts: { signal?: AbortSignal } = {}, - ): Promise { + async run(questions: PromptSession, answers?: Partial): Promise { // Keep global reference to the answers this.answers = typeof answers === 'object' ? { ...answers } : {}; @@ -223,9 +219,7 @@ export default class PromptsRunner { obs = from([questions]); } - this.process = obs.pipe( - concatMap((question) => this.processQuestion(question, opts)), - ); + this.process = obs.pipe(concatMap((question) => this.processQuestion(question))); return lastValueFrom( this.process.pipe( @@ -239,7 +233,7 @@ export default class PromptsRunner { .finally(() => this.close()); } - processQuestion(question: AnyQuestion, opts: { signal?: AbortSignal } = {}) { + processQuestion(question: AnyQuestion) { question = { ...question }; return defer(() => { const obs = of(question); @@ -274,12 +268,12 @@ export default class PromptsRunner { return of(question); }), - concatMap((question) => this.fetchAnswer(question, opts)), + concatMap((question) => this.fetchAnswer(question)), ); }); } - fetchAnswer(question: AnyQuestion, opts: { signal?: AbortSignal } = {}) { + fetchAnswer(question: AnyQuestion) { const prompt = this.prompts[question.type]; if (prompt == null) { @@ -337,30 +331,28 @@ export default class PromptsRunner { }) : prompt; - const isSignal = (signal: AbortSignal | undefined): signal is AbortSignal => - signal !== undefined; - - const otherSignals = [opts.signal, this.opt.signal].filter(isSignal); - const abortedSignal = otherSignals.find((signal) => signal.aborted); let signal: AbortSignal; let cleanupSignal = () => {}; + const { signal: moduleSignal } = this.opt; - if (abortedSignal) { - signal = AbortSignal.abort(abortedSignal.reason); + if (moduleSignal?.aborted) { + signal = AbortSignal.abort(moduleSignal.reason); } else { const abortController = new AbortController(); this.abortController = abortController; signal = abortController.signal; const abort = (reason: unknown) => this.abortController?.abort(reason); - otherSignals.forEach((signal) => signal.addEventListener('abort', abort)); - cleanupSignal = () => { - otherSignals.forEach((signal) => signal.removeEventListener('abort', abort)); - }; + if (moduleSignal) { + moduleSignal.addEventListener('abort', abort); + cleanupSignal = () => { + moduleSignal.removeEventListener('abort', abort); + }; + } } return defer(() => from( - promptFn(question, { ...this.opt, ...opts, signal }) + promptFn(question, { ...this.opt, signal }) .then((answer: unknown) => ({ name: question.name, answer })) .finally(() => { cleanupSignal();