Skip to content

Commit bdda7bf

Browse files
committed
feat: prompt.validate error support
1 parent 4c98bd2 commit bdda7bf

File tree

3 files changed

+35
-26
lines changed

3 files changed

+35
-26
lines changed

.changeset/moody-hairs-learn.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@clack/prompts': patch
3+
'@clack/core': patch
4+
---
5+
6+
Add Error support for validate function

packages/core/src/prompts/prompt.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export interface PromptOptions<Self extends Prompt> {
1313
render(this: Omit<Self, 'prompt'>): string | undefined;
1414
placeholder?: string;
1515
initialValue?: any;
16-
validate?: ((value: any) => string | undefined) | undefined;
16+
validate?: ((value: any) => string | Error | undefined) | undefined;
1717
input?: Readable;
1818
output?: Writable;
1919
debug?: boolean;
@@ -183,7 +183,7 @@ export default class Prompt {
183183
if (this.opts.validate) {
184184
const problem = this.opts.validate(this.value);
185185
if (problem) {
186-
this.error = problem;
186+
this.error = problem instanceof Error ? problem.message : problem;
187187
this.state = 'error';
188188
this.rl.write(this.value);
189189
}

packages/prompts/src/index.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export interface TextOptions {
100100
placeholder?: string;
101101
defaultValue?: string;
102102
initialValue?: string;
103-
validate?: (value: string) => string | undefined;
103+
validate?: (value: string) => string | Error | undefined;
104104
}
105105
export const text = (opts: TextOptions) => {
106106
return new TextPrompt({
@@ -117,9 +117,9 @@ export const text = (opts: TextOptions) => {
117117

118118
switch (this.state) {
119119
case 'error':
120-
return `${title.trim()}\n${color.yellow(S_BAR)} ${value}\n${color.yellow(
121-
S_BAR_END
122-
)} ${color.yellow(this.error)}\n`;
120+
return `${title.trim()}\n${color.yellow(
121+
S_BAR
122+
)} ${value}\n${color.yellow(S_BAR_END)} ${color.yellow(this.error)}\n`;
123123
case 'submit':
124124
return `${title}${color.gray(S_BAR)} ${color.dim(this.value || opts.placeholder)}`;
125125
case 'cancel':
@@ -136,7 +136,7 @@ export const text = (opts: TextOptions) => {
136136
export interface PasswordOptions {
137137
message: string;
138138
mask?: string;
139-
validate?: (value: string) => string | undefined;
139+
validate?: (value: string) => string | Error | undefined;
140140
}
141141
export const password = (opts: PasswordOptions) => {
142142
return new PasswordPrompt({
@@ -149,15 +149,15 @@ export const password = (opts: PasswordOptions) => {
149149

150150
switch (this.state) {
151151
case 'error':
152-
return `${title.trim()}\n${color.yellow(S_BAR)} ${masked}\n${color.yellow(
153-
S_BAR_END
154-
)} ${color.yellow(this.error)}\n`;
152+
return `${title.trim()}\n${color.yellow(
153+
S_BAR
154+
)} ${masked}\n${color.yellow(S_BAR_END)} ${color.yellow(this.error)}\n`;
155155
case 'submit':
156156
return `${title}${color.gray(S_BAR)} ${color.dim(masked)}`;
157157
case 'cancel':
158-
return `${title}${color.gray(S_BAR)} ${color.strikethrough(color.dim(masked ?? ''))}${
159-
masked ? `\n${color.gray(S_BAR)}` : ''
160-
}`;
158+
return `${title}${color.gray(S_BAR)} ${color.strikethrough(
159+
color.dim(masked ?? '')
160+
)}${masked ? `\n${color.gray(S_BAR)}` : ''}`;
161161
default:
162162
return `${title}${color.cyan(S_BAR)} ${value}\n${color.cyan(S_BAR_END)}\n`;
163163
}
@@ -279,9 +279,9 @@ export const selectKey = <Value extends string>(opts: SelectOptions<Value>) => {
279279
option.hint ? color.dim(`(${option.hint})`) : ''
280280
}`;
281281
}
282-
return `${color.gray(color.bgWhite(color.inverse(` ${option.value} `)))} ${label} ${
283-
option.hint ? color.dim(`(${option.hint})`) : ''
284-
}`;
282+
return `${color.gray(
283+
color.bgWhite(color.inverse(` ${option.value} `))
284+
)} ${label} ${option.hint ? color.dim(`(${option.hint})`) : ''}`;
285285
};
286286

287287
return new SelectKeyPrompt({
@@ -297,9 +297,10 @@ export const selectKey = <Value extends string>(opts: SelectOptions<Value>) => {
297297
'selected'
298298
)}`;
299299
case 'cancel':
300-
return `${title}${color.gray(S_BAR)} ${opt(this.options[0], 'cancelled')}\n${color.gray(
301-
S_BAR
302-
)}`;
300+
return `${title}${color.gray(S_BAR)} ${opt(
301+
this.options[0],
302+
'cancelled'
303+
)}\n${color.gray(S_BAR)}`;
303304
default: {
304305
return `${title}${color.cyan(S_BAR)} ${this.options
305306
.map((option, i) => opt(option, i === this.cursor ? 'active' : 'inactive'))
@@ -465,9 +466,9 @@ export const groupMultiselect = <Value>(opts: GroupMultiSelectOptions<Value>) =>
465466
return `${color.strikethrough(color.dim(label))}`;
466467
}
467468
if (state === 'active-selected') {
468-
return `${color.dim(prefix)}${color.green(S_CHECKBOX_SELECTED)} ${label} ${
469-
option.hint ? color.dim(`(${option.hint})`) : ''
470-
}`;
469+
return `${color.dim(prefix)}${color.green(
470+
S_CHECKBOX_SELECTED
471+
)} ${label} ${option.hint ? color.dim(`(${option.hint})`) : ''}`;
471472
}
472473
if (state === 'submitted') {
473474
return `${color.dim(label)}`;
@@ -583,9 +584,9 @@ export const note = (message = '', title = '') => {
583584
const msg = lines
584585
.map(
585586
(ln) =>
586-
`${color.gray(S_BAR)} ${color.dim(ln)}${' '.repeat(len - strip(ln).length)}${color.gray(
587-
S_BAR
588-
)}`
587+
`${color.gray(S_BAR)} ${color.dim(ln)}${' '.repeat(
588+
len - strip(ln).length
589+
)}${color.gray(S_BAR)}`
589590
)
590591
.join('\n');
591592
process.stdout.write(
@@ -759,7 +760,9 @@ export interface PromptGroupOptions<T> {
759760
* Control how the group can be canceled
760761
* if one of the prompts is canceled.
761762
*/
762-
onCancel?: (opts: { results: Prettify<Partial<PromptGroupAwaitedReturn<T>>> }) => void;
763+
onCancel?: (opts: {
764+
results: Prettify<Partial<PromptGroupAwaitedReturn<T>>>;
765+
}) => void;
763766
}
764767

765768
type Prettify<T> = {

0 commit comments

Comments
 (0)