From 2cc9e311a38b8074fd1b30c073f3a7a506c8c75f Mon Sep 17 00:00:00 2001 From: Simon Boudrias Date: Wed, 17 Jul 2024 17:17:32 -0400 Subject: [PATCH] Fix(inquirer): Ensure no mutation of the question objects --- packages/inquirer/src/types.mts | 60 +++++++++++++++-------------- packages/inquirer/src/ui/prompt.mts | 20 ++++++++-- 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/packages/inquirer/src/types.mts b/packages/inquirer/src/types.mts index 54fb8a890..e0d0f6b56 100644 --- a/packages/inquirer/src/types.mts +++ b/packages/inquirer/src/types.mts @@ -41,43 +41,45 @@ export interface QuestionMap { } type PromptConfigMap = { - [key in keyof QuestionMap]: DistributiveMerge< - QuestionMap[keyof QuestionMap], - { - type: keyof QuestionMap; - name: KeyUnion; - when?: AsyncGetterFunction> | boolean; - askAnswered?: boolean; - message: - | Pick - | AsyncGetterFunction< - Pick, - Prettify - >; - choices?: - | Pick - | string[] - | AsyncGetterFunction< - Pick | string[], - Prettify - >; - default?: - | Pick - | AsyncGetterFunction< - Pick | string[], - Prettify - >; - } + [key in keyof QuestionMap]: Readonly< + DistributiveMerge< + QuestionMap[keyof QuestionMap], + { + type: keyof QuestionMap; + name: KeyUnion; + when?: AsyncGetterFunction> | boolean; + askAnswered?: boolean; + message: + | Pick + | AsyncGetterFunction< + Pick, + Prettify + >; + choices?: + | Pick + | string[] + | AsyncGetterFunction< + Pick | string[], + Prettify + >; + default?: + | Pick + | AsyncGetterFunction< + Pick | string[], + Prettify + >; + } + > >; }; export type Question = PromptConfigMap[keyof PromptConfigMap]; export type QuestionAnswerMap = - | { [name in KeyUnion]: Omit, 'name'> } + | Readonly<{ [name in KeyUnion]: Omit, 'name'> }> | never; -export type QuestionArray = Question[] | never; +export type QuestionArray = readonly Question[] | never; export type QuestionObservable = Observable> | never; diff --git a/packages/inquirer/src/ui/prompt.mts b/packages/inquirer/src/ui/prompt.mts index 12ccb2d89..20f2ef772 100644 --- a/packages/inquirer/src/ui/prompt.mts +++ b/packages/inquirer/src/ui/prompt.mts @@ -158,8 +158,22 @@ function setupReadlineOptions(opt: StreamOptions = {}) { }; } +function isQuestionArray( + questions: + | QuestionArray + | QuestionAnswerMap + | QuestionObservable + | Question, +): questions is QuestionArray { + return Array.isArray(questions); +} + function isQuestionMap( - questions: QuestionArray | QuestionAnswerMap | Question, + questions: + | QuestionArray + | QuestionAnswerMap + | QuestionObservable + | Question, ): questions is QuestionAnswerMap { return Object.values(questions).every( (maybeQuestion) => @@ -207,7 +221,7 @@ export default class PromptsRunner { this.answers = typeof answers === 'object' ? { ...answers } : {}; let obs: Observable>; - if (Array.isArray(questions)) { + if (isQuestionArray(questions)) { obs = from(questions); } else if (isObservable(questions)) { obs = questions; @@ -366,7 +380,7 @@ export default class PromptsRunner { setDefaultType = (question: Question): Observable> => { // Default type to input if (!this.prompts[question.type]) { - question.type = 'input'; + question = Object.assign({}, question, { type: 'input' }); } return defer(() => of(question));