diff --git a/src/utils/prompt.ts b/src/utils/prompt.ts index 94e9dbd2..285c8138 100644 --- a/src/utils/prompt.ts +++ b/src/utils/prompt.ts @@ -33,17 +33,32 @@ export async function promptText(options: { const { defaultValue, message } = options; const inquirer = await import('@clack/prompts'); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const val = await (inquirer as any).text({ - message, - default: defaultValue, - placeholder: defaultValue, - }); + const val = await (inquirer as any).text(textPromptOptions(message, defaultValue)); // @clack/prompts returns a Symbol.cancel when the user presses Ctrl+C if (typeof val === 'symbol') return undefined; return val as string; } +/** + * Build the options for a text prompt. + * + * A default value is presented as a placeholder rather than as the prompt's + * actual value, so a hint can never be submitted as input text. + * + * @clack/prompts has no `default` option (its option is `defaultValue`), so + * passing one alongside `placeholder` never had any effect. + */ +export function textPromptOptions(message: string, defaultValue?: string): { + message: string; + placeholder?: string; +} { + return { + message, + ...(defaultValue === undefined ? {} : { placeholder: defaultValue }), + }; +} + const API_KEY_VISIBLE_LENGTH = 30; export function apiKeyPreview(value: string): string { diff --git a/test/utils/prompt.test.ts b/test/utils/prompt.test.ts index f1f174ee..58f7ea68 100644 --- a/test/utils/prompt.test.ts +++ b/test/utils/prompt.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'bun:test'; -import { apiKeyPreview } from '../../src/utils/prompt'; +import { apiKeyPreview, textPromptOptions } from '../../src/utils/prompt'; describe('apiKeyPreview', () => { it('shows the total length only when the key is truncated', () => { @@ -9,3 +9,18 @@ describe('apiKeyPreview', () => { expect(apiKeyPreview('a'.repeat(125))).toBe(`${'a'.repeat(30)}.... (125 chars)`); }); }); + +describe('textPromptOptions', () => { + it('keeps the placeholder separate from the editable value', () => { + expect(textPromptOptions('Enter a value:', 'Ask Mcode')).toEqual({ + message: 'Enter a value:', + placeholder: 'Ask Mcode', + }); + }); + + it('does not pass a default value as the prompt input', () => { + expect(textPromptOptions('Enter a value:')).toEqual({ + message: 'Enter a value:', + }); + }); +});