Skip to content

Commit 31e7b7e

Browse files
committed
chore: fin i hope
1 parent 68f9a35 commit 31e7b7e

File tree

5 files changed

+177
-74
lines changed

5 files changed

+177
-74
lines changed

src/commands/_register.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import type { BuiltApifyCommand } from '../lib/command-framework/apify-command.js';
2-
import { FlagTest } from './_FlagTests.js';
32
import { ActorIndexCommand } from './actor/_index.js';
43
import { ActorChargeCommand } from './actor/charge.js';
54
import { ActorGetInputCommand } from './actor/get-input.js';
@@ -58,7 +57,9 @@ export const apifyCommands = [
5857
RunCommand,
5958
ValidateInputSchemaCommand,
6059
HelpCommand,
61-
FlagTest,
60+
61+
// test commands
62+
// (await import('./_testCommands/_FlagTests.js')).FlagTest,
6263
] as const satisfies (typeof BuiltApifyCommand)[];
6364

6465
export const actorCommands = [
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
import { ApifyCommand } from '../lib/command-framework/apify-command.js';
2-
import { Flags } from '../lib/command-framework/flags.js';
1+
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
2+
import { Flags } from '../../lib/command-framework/flags.js';
33

44
export class FlagTest extends ApifyCommand<typeof FlagTest> {
55
static override name = '_flag';
66

77
static override flags = {
88
foo: Flags.string({
99
description: 'Foo flag',
10-
required: true,
10+
// required: true,
1111
}),
1212
bar: Flags.string({
1313
description: 'Bar flag',
@@ -25,7 +25,19 @@ export class FlagTest extends ApifyCommand<typeof FlagTest> {
2525
choices: ['1', '2', '3'],
2626
}),
2727
int: Flags.integer({
28-
default: 1,
28+
exclusive: ['foo'],
29+
}),
30+
'space me': Flags.string({
31+
description: 'Space message flag',
32+
exclusive: ['lines-in'],
33+
}),
34+
'lines-in': Flags.integer({
35+
description: 'Lines in flag',
36+
exclusive: ['space me'],
37+
}),
38+
fooBar2: Flags.boolean({
39+
description: 'Foo bar flag',
40+
exclusive: ['lines-in'],
2941
}),
3042
};
3143

src/entrypoints/_shared.ts

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -197,68 +197,10 @@ export async function runCLI(entrypoint: string) {
197197

198198
cliDebugPrint('CommandArgsResult', commandResult);
199199
} catch (err) {
200-
const commandError = CommandError.into(err);
200+
const commandError = CommandError.into(err, FinalCommand);
201201

202202
error({ message: commandError.getPrettyMessage() });
203203

204204
process.exit(1);
205205
}
206-
207-
// await cli.parse(process.argv.slice(2), {}, (rawError, parsed) => {
208-
// if (rawError && parsed._.length > 0) {
209-
// cliDebugPrint('RunCLIError', { type: 'parsed', error: rawError?.message, parsed });
210-
211-
// const errorMessageSplit = rawError.message.split(' ').map((part) => part.trim());
212-
213-
// const commandFlags = Object.entries(command.flags ?? {})
214-
// .filter(([, flag]) => typeof flag !== 'string')
215-
// .map(([flagName, flag]) => {
216-
// const castedFlag = flag as TaggedFlagBuilder<FlagTag, string[] | null, unknown, unknown>;
217-
218-
// const flagKey = kebabCaseString(camelCaseToKebabCase(flagName)).toLowerCase();
219-
220-
// return {
221-
// flagKey,
222-
// char: castedFlag.char,
223-
// aliases: castedFlag.aliases?.map((alias) =>
224-
// kebabCaseString(camelCaseToKebabCase(alias)).toLowerCase(),
225-
// ),
226-
// matches(otherFlagKey: string) {
227-
// return (
228-
// this.flagKey === otherFlagKey ||
229-
// this.char === otherFlagKey ||
230-
// this.aliases?.some((aliasedFlag) => aliasedFlag === otherFlagKey)
231-
// );
232-
// },
233-
// };
234-
// });
235-
236-
// case 'ARGUMENTS_ARE_MUTUALLY_EXCLUSIVE_INPUT': {
237-
// const args = JSON.parse(errorMessageSplit[1]) as string[];
238-
239-
// error({
240-
// message: [
241-
// `The following errors occurred:`,
242-
// ...args
243-
// .sort((a, b) => a.localeCompare(b))
244-
// .map((arg) => {
245-
// const value = parsed[arg];
246-
247-
// const isBoolean = typeof value === 'boolean';
248-
249-
// const argRepresentation = isBoolean ? `--${arg}` : `--${arg}=${value}`;
250-
251-
// return ` ${chalk.red('>')} ${chalk.gray(
252-
// `${argRepresentation} cannot also be provided when using ${args
253-
// .filter((a) => a !== arg)
254-
// .map((a) => `--${a}`)
255-
// .join(', ')}`,
256-
// )}`;
257-
// }),
258-
// ` ${chalk.red('>')} See more help with --help`,
259-
// ].join('\n'),
260-
// });
261-
262-
// break;
263-
// }
264206
}

src/lib/command-framework/CommandError.ts

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import chalk from 'chalk';
22

33
import { cachedStdinInput } from '../../entrypoints/_shared.js';
44
import { useCLIMetadata } from '../hooks/useCLIMetadata.js';
5+
import type { BuiltApifyCommand } from './apify-command.js';
6+
import { selectiveRenderHelpForCommand } from './help.js';
57

68
export 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
}
3542
export interface CommandErrorOptions {
3643
code: CommandErrorCode;
44+
command: typeof BuiltApifyCommand;
3745
message?: string;
3846
metadata?: CommandError['metadata'];
3947
}
4048

4149
export 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 = /Unknown option '--(?<optionName>[a-zA-Z0-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

Comments
 (0)