@@ -2,6 +2,8 @@ import chalk from 'chalk';
22
33import { cachedStdinInput } from '../../entrypoints/_shared.js' ;
44import { useCLIMetadata } from '../hooks/useCLIMetadata.js' ;
5+ import type { BuiltApifyCommand } from './apify-command.js' ;
6+ import { selectiveRenderHelpForCommand } from './help.js' ;
57
68export enum CommandErrorCode {
79 NODEJS_ERR_PARSE_ARGS_INVALID_OPTION_VALUE ,
@@ -23,6 +25,10 @@ export enum CommandErrorCode {
2325 * Used when a flag is required but not provided
2426 */
2527 APIFY_MISSING_FLAG ,
28+ /**
29+ * Used when a flag is provided, but it is exclusive with another flag
30+ */
31+ APIFY_FLAG_IS_EXCLUSIVE_WITH_ANOTHER_FLAG ,
2632 APIFY_UNKNOWN_ERROR ,
2733}
2834
@@ -31,22 +37,25 @@ export interface FlagData {
3137 expectsValue : boolean ;
3238 ambiguousFlag ?: string ;
3339 ambiguousMessage ?: string ;
40+ unknownOptionSuggestion ?: string ;
3441}
3542export interface CommandErrorOptions {
3643 code : CommandErrorCode ;
44+ command : typeof BuiltApifyCommand ;
3745 message ?: string ;
3846 metadata ?: CommandError [ 'metadata' ] ;
3947}
4048
4149export class CommandError extends Error {
4250 public readonly code : CommandErrorCode ;
51+ public readonly command : typeof BuiltApifyCommand ;
52+ public readonly metadata : Record < string , unknown > ;
4353
44- public readonly metadata : Record < string , string | string [ ] | boolean > ;
45-
46- public constructor ( { code, message = '' , metadata = { } } : CommandErrorOptions ) {
54+ public constructor ( { code, message = '' , metadata = { } , command } : CommandErrorOptions ) {
4755 super ( message || String ( CommandErrorCode [ code ] ) ) ;
4856 this . code = code ;
4957 this . metadata = metadata ;
58+ this . command = command ;
5059 }
5160
5261 public extractFlagNameFromMessage ( ) : FlagData {
@@ -74,6 +83,25 @@ export class CommandError extends Error {
7483
7584 return flagData ;
7685 }
86+
87+ case CommandErrorCode . NODEJS_ERR_PARSE_ARGS_UNKNOWN_OPTION : {
88+ const match = / U n k n o w n o p t i o n ' - - (?< optionName > [ a - z A - Z 0 - 9 ] + ) ' \. (?< nodeSuggestion > .* ) / gi. exec (
89+ this . message ,
90+ ) ;
91+
92+ if ( ! match ) {
93+ throw new Error (
94+ `Encountered unparsable error message from argument parser: ${ this . message } .\n\nPlease report this issue at https://github.com/apify/apify-cli/issues` ,
95+ ) ;
96+ }
97+
98+ return {
99+ name : match . groups ! . optionName ,
100+ expectsValue : false ,
101+ unknownOptionSuggestion : match . groups ! . nodeSuggestion ,
102+ } ;
103+ }
104+
77105 default : {
78106 throw new Error ( 'Not implemented' ) ;
79107 }
@@ -88,6 +116,25 @@ export class CommandError extends Error {
88116 return CommandError . buildMessageFromFlagData ( flagData ) ;
89117 }
90118
119+ case CommandErrorCode . NODEJS_ERR_PARSE_ARGS_UNKNOWN_OPTION : {
120+ const flagData = this . extractFlagNameFromMessage ( ) ;
121+
122+ const helpMessage = selectiveRenderHelpForCommand ( this . command , {
123+ showUsageString : true ,
124+ } ) ;
125+
126+ return [
127+ chalk . gray ( `Unknown flag provided: ${ chalk . white . bold ( `--${ flagData . name } ` ) } ` ) ,
128+ flagData . unknownOptionSuggestion
129+ ? chalk . gray ( ` ${ flagData . unknownOptionSuggestion . trim ( ) } ` )
130+ : null ,
131+ '' ,
132+ helpMessage ,
133+ ]
134+ . filter ( ( v ) => v !== null )
135+ . join ( '\n' ) ;
136+ }
137+
91138 case CommandErrorCode . APIFY_FLAG_PROVIDED_MULTIPLE_TIMES : {
92139 const flagName = `--${ this . metadata . flag } ` ;
93140
@@ -122,7 +169,27 @@ export class CommandError extends Error {
122169 ) ;
123170 }
124171
125- return chalk . gray ( `Flag '${ flagName } ' is required, but was not provided.` ) ;
172+ return chalk . gray ( `Flag ${ flagName } is required, but was not provided.` ) ;
173+ }
174+
175+ case CommandErrorCode . APIFY_FLAG_IS_EXCLUSIVE_WITH_ANOTHER_FLAG : {
176+ const { flagPairs } = this . metadata as { flagPairs : [ string , string ] [ ] } ;
177+
178+ const messageParts = [ chalk . gray ( `The following errors occurred:` ) ] ;
179+
180+ const redArrow = chalk . red ( ' > ' ) ;
181+
182+ for ( const [ a , b ] of flagPairs ) {
183+ messageParts . push (
184+ chalk . gray (
185+ `${ redArrow } ${ chalk . white . bold ( a ) } cannot also be provided when using ${ chalk . white . bold ( b ) } ` ,
186+ ) ,
187+ ) ;
188+ }
189+
190+ messageParts . push ( chalk . gray ( `${ redArrow } See more help with ${ chalk . white . bold ( '--help' ) } ` ) ) ;
191+
192+ return messageParts . join ( '\n' ) ;
126193 }
127194
128195 default : {
@@ -168,7 +235,7 @@ export class CommandError extends Error {
168235 return base . map ( ( part ) => chalk . gray ( part ) ) . join ( ' ' ) ;
169236 }
170237
171- static into ( error : unknown ) : CommandError {
238+ static into ( error : unknown , command : typeof BuiltApifyCommand ) : CommandError {
172239 if ( error instanceof CommandError ) {
173240 return error ;
174241 }
@@ -181,24 +248,28 @@ export class CommandError extends Error {
181248 return new CommandError ( {
182249 code : CommandErrorCode . NODEJS_ERR_PARSE_ARGS_INVALID_OPTION_VALUE ,
183250 message : casted . message ,
251+ command,
184252 } ) ;
185253 }
186254 case 'ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL' : {
187255 return new CommandError ( {
188256 code : CommandErrorCode . NODEJS_ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL ,
189257 message : casted . message ,
258+ command,
190259 } ) ;
191260 }
192261 case 'ERR_PARSE_ARGS_UNKNOWN_OPTION' : {
193262 return new CommandError ( {
194263 code : CommandErrorCode . NODEJS_ERR_PARSE_ARGS_UNKNOWN_OPTION ,
195264 message : casted . message ,
265+ command,
196266 } ) ;
197267 }
198268 default : {
199269 return new CommandError ( {
200270 code : CommandErrorCode . APIFY_UNKNOWN_ERROR ,
201271 message : `Unknown error: ${ error instanceof Error ? error . message : String ( error ) } ` ,
272+ command,
202273 } ) ;
203274 }
204275 }
@@ -207,6 +278,7 @@ export class CommandError extends Error {
207278 return new CommandError ( {
208279 code : CommandErrorCode . APIFY_UNKNOWN_ERROR ,
209280 message : `Unknown error: ${ error instanceof Error ? error . message : String ( error ) } ` ,
281+ command,
210282 } ) ;
211283 }
212284}
0 commit comments