UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

102 lines (90 loc) 4.14 kB
// SPDX-License-Identifier: Apache-2.0 import {SoloError} from './core/errors/solo-error.js'; import {SilentBreak} from './core/errors/silent-break.js'; import {Flags as flags} from './commands/flags.js'; import {type Middlewares} from './core/middlewares.js'; import {InjectTokens} from './core/dependency-injection/inject-tokens.js'; import {type HelpRenderer} from './core/help-renderer.js'; import {container} from 'tsyringe-neo'; import {type SoloLogger} from './core/logging/solo-logger.js'; import yargs from 'yargs'; import {hideBin} from 'yargs/helpers'; import {type AnyObject} from './types/aliases.js'; export class ArgumentProcessor { public static async process(argv: string[]): Promise<AnyObject> { const logger: SoloLogger = container.resolve<SoloLogger>(InjectTokens.SoloLogger); const middlewares: Middlewares = container.resolve(InjectTokens.Middlewares); const helpRenderer: HelpRenderer = container.resolve(InjectTokens.HelpRenderer); const commands: AnyObject = container.resolve(InjectTokens.Commands); const rawArguments: string[] = hideBin(argv); logger.debug('Initializing commands'); const rootCmd: AnyObject = yargs(rawArguments) .scriptName('') .usage('Usage:\n solo <command> [options]') .alias('h', 'help') .alias('v', 'version') .help(false) // disable default help to enable custom help renderer .command(commands.getCommandDefinitions()) .strict() .demand(1, 'Select a command'); rootCmd.middleware( [ middlewares.detectLocalSoloPackages(), middlewares.printCustomHelp(rootCmd), middlewares.setLoggerDevFlag(), // @ts-expect-error - TS2322: To assign middlewares middlewares.processArgumentsAndDisplayHeader(), middlewares.initSystemFiles(), ], false, // applyBeforeValidate is false as otherwise middleware is called twice ); // Expand the terminal width to the maximum available rootCmd.wrap(rootCmd.terminalWidth()); rootCmd.fail((message, error): void => { if (message) { const usedHelpShorthand: boolean = rawArguments.includes('help') && !rawArguments.includes('--help') && !rawArguments.includes('-h'); const usedHelpFlag: boolean = rawArguments.includes('--help') || rawArguments.includes('-h'); if (usedHelpShorthand || usedHelpFlag) { rootCmd.showHelp((output): void => { helpRenderer.render(rootCmd, output); }); throw new SilentBreak('Help displayed'); } if ( message.includes('Unknown argument') || message.includes('Missing required argument') || message.toLowerCase().includes('select') ) { if (message.toLowerCase().includes('select')) { // Show what subcommands are available then exit normally rootCmd.showHelp((output): void => { helpRenderer.render(rootCmd, output); }); // Use SilentBreak to exit cleanly without error display throw new SilentBreak('No subcommand provided, help displayed'); } // For unknown/missing arguments, show message and help logger.showUser(message); rootCmd.showHelp((output): void => { helpRenderer.render(rootCmd, output); }); // Throw error to propagate through async call chains if given unknown argument if (!rootCmd.parsed.argv.help) { // Set exit code but don't exit immediately - allows I/O buffers to flush process.exitCode = 1; throw new SoloError(message, error); } } else { logger.showUserError(new SoloError(`Error running Solo CLI, failure occurred: ${message ?? ''}`)); throw new SoloError(message, error); } } }); logger.debug('Setting up flags'); // set root level flags flags.setOptionalCommandFlags(rootCmd, flags.devMode, flags.forcePortForward); logger.debug('Parsing root command (executing the commands)'); return await rootCmd.parseAsync(); } }