export type Prompt< P extends PositionalArgument[], Q extends QuestionList, > = { /** * Show the prompt and wait for the user to answer. */ show: (options: PromptOptions) => Promise | undefined>; /** * Read the current answers from the prompt. */ read: () => FlatType>>; }; export type PositionalArgument = `<${string}>` | `[${string}]`; export type PromptOptions = { name: string; description?: string; version?: string; args?: string[]; env?: NodeJS.ProcessEnv; stdin?: NodeJS.ReadStream; stdout?: NodeJS.WriteStream; stderr?: NodeJS.WriteStream; onExit?: (code: number) => void; }; export type QuestionList = { [key in Name]: QuestionItem; }; type QuestionItem = T & { description: string; alias?: string; }; export type SelectChoice = { title?: string; description?: string; value: string; skip?: boolean | (() => boolean | Promise); }; export type Question = | TextQuestion | SelectQuestion | MultiSelectQuestion | ConfirmQuestion | TaskQuestion; export type AnswerList< P extends PositionalArgument[], Q extends QuestionList, > = FlatType< PositionalArgumentValue

& { [Key in keyof Q]: Answer ? Q : never>; } >; type PositionalArgumentValue = UnionToIntersection< { [K in T[number]]: K extends `<${infer Name}>` ? { readonly [Key in Name]: string } : K extends `[${infer Name}]` ? { readonly [Key in Name]?: string } : never; }[T[number]] >; type DefaultValue = | Value | undefined | (() => Value | undefined | Promise); type DefaultResult = T extends { default: infer D } ? D extends (...args: never[]) => infer R ? Awaited : D : never; type RequiredAnswer = T extends { required: true } ? AnswerInternal : AnswerInternal | undefined; type Answer = T extends TaskQuestion ? AnswerInternal : T extends Question ? T extends { skip: infer S } ? S extends false ? RequiredAnswer : AnswerInternal | DefaultResult | undefined : RequiredAnswer : undefined; type AnswerInternal = T extends SelectQuestion ? T['choices'][number]['value'] : T extends MultiSelectQuestion ? T['choices'][number]['value'][] : T extends ConfirmQuestion ? boolean : T extends TextQuestion ? string : T extends TaskQuestion ? Result : never; type BaseQuestion = { type: Type; message: string; validate?: (value: Value) => boolean | string; default?: DefaultValue; skip?: boolean | (() => boolean | Promise); required?: boolean; }; export type TextQuestion = BaseQuestion<'text', string>; export type SelectQuestion = BaseQuestion< 'select', Choice['value'] > & { choices: Choice[]; }; export type MultiSelectQuestion = BaseQuestion< 'multiselect', Choice['value'][] > & { choices: Choice[]; }; export type ConfirmQuestion = BaseQuestion<'confirm', boolean>; export type TaskQuestion = { type: 'task'; message: string; task: () => AsyncGenerator< { message?: string }, { value: Result; message?: string } >; }; type PromptType = 'text' | 'select' | 'multiselect' | 'confirm' | 'task'; export type QuestionOptions = { env: NodeJS.ProcessEnv; stdin: NodeJS.ReadStream; stdout: NodeJS.WriteStream; onCancel: () => void; }; type FlatType = { [K in keyof T]: T[K] } & {}; export type UnionToIntersection = ( U extends unknown ? (k: U) => void : never ) extends (k: infer I) => void ? I : never;