Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/utils/prompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
17 changes: 16 additions & 1 deletion test/utils/prompt.test.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand All @@ -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:',
});
});
});