Skip to content

Commit

Permalink
fix: add note to RequiredArgsError when there are flags with multiple…
Browse files Browse the repository at this point in the history
…=true (#754)
  • Loading branch information
mdonnalley committed Aug 2, 2023
1 parent 7ac230c commit ed359a7
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,4 @@
"test:perf": "ts-node test/perf/parser.perf.ts"
},
"types": "lib/index.d.ts"
}
}
2 changes: 1 addition & 1 deletion src/interfaces/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export interface OclifError {

export interface PrettyPrintableError {
/**
* messsage to display related to the error
* message to display related to the error
*/
message?: string;

Expand Down
8 changes: 7 additions & 1 deletion src/parser/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,20 @@ export class InvalidArgsSpecError extends CLIParseError {
export class RequiredArgsError extends CLIParseError {
public args: Arg<any>[]

constructor({args, parse}: CLIParseErrorOptions & { args: Arg<any>[] }) {
constructor({args, parse, flagsWithMultiple}: CLIParseErrorOptions & { args: Arg<any>[]; flagsWithMultiple?: string[] }) {
let message = `Missing ${args.length} required arg${args.length === 1 ? '' : 's'}`
const namedArgs = args.filter(a => a.name)
if (namedArgs.length > 0) {
const list = renderList(namedArgs.map(a => [a.name, a.description] as [string, string]))
message += `:\n${list}`
}

if (flagsWithMultiple?.length) {
const flags = flagsWithMultiple.map(f => `--${f}`).join(', ')
message += `\n\nNote: ${flags} allow${flagsWithMultiple.length === 1 ? 's' : ''} multiple values. Because of this you need to provide all arguments before providing ${flagsWithMultiple.length === 1 ? 'that flag' : 'those flags'}.`
message += '\nAlternatively, you can use "--" to signify the end of the flags and the beginning of arguments.'
}

super({parse, message})
this.args = args
}
Expand Down
6 changes: 5 additions & 1 deletion src/parser/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ export async function validate(parse: {
}

if (missingRequiredArgs.length > 0) {
throw new RequiredArgsError({parse, args: missingRequiredArgs})
const flagsWithMultiple = Object.entries(parse.input.flags)
.filter(([_, flagDef]) => flagDef.type === 'option' && Boolean(flagDef.multiple))
.map(([name]) => name)

throw new RequiredArgsError({parse, args: missingRequiredArgs, flagsWithMultiple})
}
}

Expand Down
47 changes: 47 additions & 0 deletions test/parser/parse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,53 @@ arg3 arg3 desc
See more help with --help`)
})

it('warns about having one flag with multiple values when missing an arg', async () => {
let message = ''
try {
await parse(['--flag1', 'val1', 'arg1'], {
args: {
arg1: Args.string({required: true, description: 'arg1 desc'}),
},
flags: {
flag1: Flags.string({multiple: true}),
},
})
} catch (error: any) {
message = error.message
}

expect(message).to.include(`Missing 1 required arg:
arg1 arg1 desc
Note: --flag1 allows multiple values. Because of this you need to provide all arguments before providing that flag.
Alternatively, you can use "--" to signify the end of the flags and the beginning of arguments.
See more help with --help`)
})

it('warns about having many flags with multiple values when missing an arg', async () => {
let message = ''
try {
await parse(['--flag1', 'val1', '--flag2', 'val1', 'val2', 'arg1'], {
args: {
arg1: Args.string({required: true, description: 'arg1 desc'}),
},
flags: {
flag1: Flags.string({multiple: true}),
flag2: Flags.string({multiple: true}),
},
})
} catch (error: any) {
message = error.message
}

expect(message).to.include(`Missing 1 required arg:
arg1 arg1 desc
Note: --flag1, --flag2 allow multiple values. Because of this you need to provide all arguments before providing those flags.
Alternatively, you can use "--" to signify the end of the flags and the beginning of arguments.
See more help with --help`)
})

it('too many args', async () => {
let message = ''
try {
Expand Down

0 comments on commit ed359a7

Please sign in to comment.