From e25ef6db2631100990056d77a7fe9adfbc43179b Mon Sep 17 00:00:00 2001 From: "E. Cooper" Date: Wed, 11 Dec 2024 10:09:26 -0800 Subject: [PATCH] Catch all yargs validation errors in isYargsError (#504) --- src/lib/command-helpers.mjs | 82 ++++++++++++++++++------------------- src/lib/errors.mjs | 27 +++++++++--- 2 files changed, 63 insertions(+), 46 deletions(-) diff --git a/src/lib/command-helpers.mjs b/src/lib/command-helpers.mjs index 6689e817..59291f45 100644 --- a/src/lib/command-helpers.mjs +++ b/src/lib/command-helpers.mjs @@ -79,47 +79,6 @@ const COMMON_QUERY_OPTIONS = { }, }; -export const resolveFormat = (argv) => { - const logger = container.resolve("logger"); - - if (argv.json) { - logger.debug( - "--json has taken precedence over other formatting options, using JSON output", - "argv", - ); - return Format.JSON; - } - - if (argv.raw) { - logger.debug( - "--raw has taken precedence over other formatting options, using JSON output", - "argv", - ); - return Format.JSON; - } - - return argv.format; -}; - -/** - * Validate that the user has specified either a database or a secret. - * This check is not required for commands that can operate at a - * "root" level. - * - * @param {object} argv - * @param {string} argv.database - The database to use - * @param {string} argv.secret - The secret to use - * @param {boolean} argv.local - Whether to use a local Fauna container - */ -export const validateDatabaseOrSecret = (argv) => { - if (!argv.database && !argv.secret && !argv.local) { - throw new ValidationError( - "No database or secret specified. Please use either --database, --secret, or --local to connect to your desired Fauna database.", - ); - } - return true; -}; - // used for queries customers can configure const COMMON_CONFIGURABLE_QUERY_OPTIONS = { ...COMMON_QUERY_OPTIONS, @@ -182,3 +141,44 @@ export function yargsWithCommonConfigurableQueryOptions(yargs) { export function yargsWithCommonOptions(yargs, options) { return yargs.options({ ...options, ...COMMON_OPTIONS }); } + +export const resolveFormat = (argv) => { + const logger = container.resolve("logger"); + + if (argv.json) { + logger.debug( + "--json has taken precedence over other formatting options, using JSON output", + "argv", + ); + return Format.JSON; + } + + if (argv.raw) { + logger.debug( + "--raw has taken precedence over other formatting options, using JSON output", + "argv", + ); + return Format.JSON; + } + + return argv.format; +}; + +/** + * Validate that the user has specified either a database or a secret. + * This check is not required for commands that can operate at a + * "root" level. + * + * @param {object} argv + * @param {string} argv.database - The database to use + * @param {string} argv.secret - The secret to use + * @param {boolean} argv.local - Whether to use a local Fauna container + */ +export const validateDatabaseOrSecret = (argv) => { + if (!argv.database && !argv.secret && !argv.local) { + throw new ValidationError( + "No database or secret specified. Please use either --database, --secret, or --local to connect to your desired Fauna database.", + ); + } + return true; +}; diff --git a/src/lib/errors.mjs b/src/lib/errors.mjs index 9d9dffe9..339f9fc3 100644 --- a/src/lib/errors.mjs +++ b/src/lib/errors.mjs @@ -6,6 +6,26 @@ import { container } from "../cli.mjs"; const BUG_REPORT_MESSAGE = `If you believe this is a bug, please report this issue on GitHub: https://github.com/fauna/fauna-shell/issues`; +/* + * These are the error message prefixes that yargs throws during + * validation. To detect these errors, you can either parse the stack + * or the message. We've decided to parse the messages. + * + * Compiled from https://github.com/yargs/yargs/blob/main/lib/validation.ts + */ +const YARGS_STATIC_PREFIXES = [ + "Unknown argument:", + "Unknown arguments:", + "Missing required argument:", + "Missing required arguments:", + "Unknown command:", + "Unknown commands:", + "Invalid values:", + "Not enough non-option arguments:", + "Too many non-option arguments:", + "Implications failed:", +]; + /** * An error that is thrown by commands that is not a validation error, but * a known error state that should be communicated to the user. @@ -54,13 +74,10 @@ function isYargsError(error) { return true; } - // Usage errors from yargs are thrown as plain old Error. The best - // you can do is check for the message. + // Does the message look like a yargs error? if ( error.message && - (error.message.startsWith("Unknown argument") || - error.message.startsWith("Missing required argument") || - error.message.startsWith("Unknown command")) + YARGS_STATIC_PREFIXES.some((prefix) => error.message.startsWith(prefix)) ) { return true; }