private static void PrintValidationResults(ICliContext context, ValidationException ex)
        {
            context.Console.Error.WithForegroundColor(ConsoleColor.Red, (error) => error.WriteLine("Validation failed:"));

            foreach (IGrouping <string, ValidationFailure> group in ex.Errors.GroupBy(x => x.PropertyName))
            {
                ArgumentSchema property = context.CommandSchema.GetArguments().Where(x => x.Property?.Name == group.Key).First();

                string name = group.Key;
                if (property is CommandOptionSchema option)
                {
                    name = "--" + option.Name;
                }
                else if (property is CommandParameterSchema parameter)
                {
                    name = $"Parameter {parameter.Order}";
                }

                context.Console.Error.Write(" ");
                context.Console.Error.WithForegroundColor(ConsoleColor.Cyan, (error) => error.Write(name));

                context.Console.Error.Write(" ");
                context.Console.Error.WithForegroundColor(ConsoleColor.Green, (error) => error.Write($"[{group.First().AttemptedValue}]"));
                context.Console.Error.WriteLine(" ");

                foreach (var validationError in group)
                {
                    context.Console.Error.Write("   -- ");
                    context.Console.Error.WithForegroundColor(ConsoleColor.White, (error) => error.WriteLine(validationError.ErrorMessage));
                }

                context.Console.Error.WriteLine();
            }
        }
Example #2
0
        private async Task <bool> ProcessDefinedDirectives(ICliContext context)
        {
            bool isInteractiveMode = context.IsInteractiveMode;
            IReadOnlyList <DirectiveInput> directives = context.Input.Directives;

            foreach (DirectiveInput directiveInput in directives)
            {
                // Try to get the directive matching the input or fallback to default
                DirectiveSchema directive = context.RootSchema.TryFindDirective(directiveInput.Name) ?? throw EndUserTypinExceptions.UnknownDirectiveName(directiveInput);

                if (!isInteractiveMode && directive.InteractiveModeOnly)
                {
                    throw EndUserTypinExceptions.InteractiveModeDirectiveNotAvailable(directiveInput.Name);
                }

                // Get directive instance
                IDirective instance = (IDirective)_serviceProvider.GetRequiredService(directive.Type);

                await instance.HandleAsync(context.Console);

                if (!instance.ContinueExecution)
                {
                    return(false);
                }
            }

            return(true);
        }
Example #3
0
 public static CommandPipelineHandlerDelegate Next(this IMiddleware commandMiddleware,
                                                   ICliContext cliContext,
                                                   CommandPipelineHandlerDelegate next,
                                                   CancellationToken cancellationToken)
 {
     return(() => commandMiddleware.HandleAsync(cliContext, next, cancellationToken));
 }
Example #4
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            // Get input and command schema from context
            CommandInput  input         = context.Input;
            CommandSchema commandSchema = context.CommandSchema;

            // Version option
            if (commandSchema.IsVersionOptionAvailable && input.IsVersionOptionSpecified)
            {
                context.Console.Output.WriteLine(context.Metadata.VersionText);

                context.ExitCode ??= ExitCodes.Success;
                return;
            }

            // Help option
            if ((commandSchema.IsHelpOptionAvailable && input.IsHelpOptionSpecified) ||
                (commandSchema == StubDefaultCommand.Schema && input.IsDefaultCommandOrEmpty))
            {
                _helpTextWriter.Write(commandSchema, context.CommandDefaultValues);

                context.ExitCode ??= ExitCodes.Success;
                return;
            }

            await next();
        }
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
            {
                output.WriteLine("--- Handling command '{0}' with args '{1}'",
                                 context.Input.CommandName ?? "<default>",
                                 string.Join(' ', context.Input.Arguments));
            });

            Stopwatch stopwatch = Stopwatch.StartNew();

            await next();

            stopwatch.Stop();

            int?exitCode = context.ExitCode;

            if (context.ExitCode == 0)
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
                {
                    output.WriteLine("--- Command finished successfully after {0} ms.",
                                     stopwatch.Elapsed.TotalMilliseconds);
                });
            }
            else
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
                {
                    output.WriteLine("--- Command finished with exit code ({0}) after {1} ms.",
                                     context.ExitCode ?? ExitCodes.Error,
                                     stopwatch.Elapsed.TotalMilliseconds);
                });
            }
        }
Example #6
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            if (context.Input.HasDirective("custom"))
            {
                throw new ApplicationException("custom directive detected");
            }

            await next();
        }
 private static void PrintExecutionBegin(ICliContext context)
 {
     context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
     {
         output.WriteLine("--- Handling command '{0}' with args '{1}'",
                          context.Input.CommandName ?? "<default>",
                          string.Join(' ', context.Input.Arguments));
     });
 }
Example #8
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            context.Console.Output.WriteLine("-- Handling Command");
            Stopwatch stopwatch = Stopwatch.StartNew();

            await next();

            stopwatch.Stop();
            context.Console.Output.WriteLine("-- Finished Command after {0} ms", stopwatch.Elapsed.TotalMilliseconds);
        }
        /// <inheritdoc/>
        public void HandleException(ICliContext context, Exception ex)
        {
            IConsole console = context.Console;

            WriteFatalError(console, $"Fatal error occured in {context.Metadata.ExecutableName}.");

            console.Error.WriteLine();
            WriteFatalError(console, ex.ToString());
            console.Error.WriteLine();
        }
Example #10
0
        /// <inheritdoc/>
        public void HandleCommandException(ICliContext context, CommandException ex)
        {
            WriteError(context.Console, ex.ToString());
            context.Console.Error.WriteLine();

            if (ex.ShowHelp)
            {
                PrintHelp(context);
            }
        }
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            context.Console.Output.WriteLine(ExpectedOutput0);
            Stopwatch stopwatch = Stopwatch.StartNew();

            await next();

            stopwatch.Stop();
            context.Console.Output.WriteLine($"{ExpectedOutput1} {0} ms", stopwatch.Elapsed.TotalMilliseconds);
        }
Example #12
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            // Get command instance from context
            ICommand instance = context.Command;

            // Execute command
            await instance.ExecuteAsync(context.Console);

            context.ExitCode ??= ExitCodes.Success;

            await next();
        }
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            IReadOnlyList <IPipelinedDirective> pipelinedDirectives = context.PipelinedDirectives;
            CommandPipelineHandlerDelegate      newNext             = next;

            foreach (IPipelinedDirective instance in pipelinedDirectives.Reverse())
            {
                newNext = instance.Next(context, newNext, _logger, cancellationToken);
            }

            await newNext();
        }
Example #14
0
        public static CommandPipelineHandlerDelegate Next(this IPipelinedDirective pipelineDirective,
                                                          ICliContext cliContext,
                                                          CommandPipelineHandlerDelegate next,
                                                          ILogger logger,
                                                          CancellationToken cancellationToken)
        {
            return(() =>
            {
                logger.LogDebug("Executing pipelined directive {PipelineDirectiveType}.", pipelineDirective.GetType().FullName);

                return pipelineDirective.HandleAsync(cliContext, next, cancellationToken);
            });
        }
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            try
            {
                await ValidateCurrentCommand(context, cancellationToken);

                await next();
            }
            catch (ValidationException ex)
            {
                _logger.LogError(ex, "Validation of command {CommandType} failed.", context.CommandSchema.Type.FullName);
                PrintValidationResults(context, ex);
            }
        }
Example #16
0
        public static CommandPipelineHandlerDelegate Next(this IMiddleware commandMiddleware,
                                                          ICliContext cliContext,
                                                          CommandPipelineHandlerDelegate next,
                                                          Type middlewareType,
                                                          ILogger logger,
                                                          CancellationToken cancellationToken)
        {
            return(() =>
            {
                logger.LogDebug("Executing middleware {MiddlewareType}", middlewareType.FullName);

                return new ValueTask(commandMiddleware.HandleAsync(cliContext, next, cancellationToken));
            });
        }
Example #17
0
        private async Task RunPipelineAsync(IServiceProvider serviceProvider, ICliContext context)
        {
            IReadOnlyCollection <Type> middlewareTypes = context.Configuration.MiddlewareTypes;

            CancellationToken cancellationToken = context.Console.GetCancellationToken();
            CommandPipelineHandlerDelegate next = IMiddlewareExtensions.PipelineTermination;

            foreach (Type middlewareType in middlewareTypes.Reverse())
            {
                IMiddleware instance = (IMiddleware)serviceProvider.GetRequiredService(middlewareType);
                next = instance.Next(context, next, middlewareType, _logger, cancellationToken);
            }

            await next();
        }
Example #18
0
        /// <inheritdoc/>
        public async Task <int> ExecuteCommandAsync(IEnumerable <string> commandLineArguments)
        {
            _logger.LogInformation("Executing command '{CommandLineArguments}'.", commandLineArguments);

            using (IServiceScope serviceScope = _serviceScopeFactory.CreateScope())
            {
                IServiceProvider provider     = serviceScope.ServiceProvider;
                ICliContext      cliContext   = provider.GetRequiredService <ICliContext>();
                Guid             cliContextId = cliContext.Id;

                _logger.LogDebug("New scope created with CliContext {CliContextId}.", cliContextId);

                CommandInput input = CommandInputResolver.Parse(commandLineArguments, _rootSchemaAccessor.RootSchema.GetCommandNames());
                ((CliContext)cliContext).Input = input;

                try
                {
                    // Execute middleware pipeline
                    await RunPipelineAsync(provider, cliContext);
                }
                catch (Exception ex)
                {
                    _logger.LogDebug("Exception occured. Trying to find exception handler.");

                    IEnumerable <ICliExceptionHandler> exceptionHandlers = provider.GetServices <ICliExceptionHandler>();
                    foreach (ICliExceptionHandler handler in exceptionHandlers)
                    {
                        if (handler.HandleException(ex))
                        {
                            _logger.LogDebug(ex, "Exception handled by {ExceptionHandlerType}.", handler.GetType().FullName);

                            return(ExitCodes.FromException(ex));
                        }
                    }

                    _logger.LogCritical(ex, "Unhandled exception during command execution.");

                    throw;
                }
                finally
                {
                    _logger.LogDebug("Disposed scope with CliContext {CliContextId}.", cliContextId);
                }

                return(cliContext.ExitCode ?? ExitCodes.Error);
            }
        }
Example #19
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            await next();

            int?exitCode = context.ExitCode;

            if (context.ExitCode == 0)
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.White, (output) =>
                                                           output.WriteLine($"{context.Metadata.ExecutableName}: {ExpectedOutput}."));
            }
            else
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.White, (output) =>
                                                           output.WriteLine($"{context.Metadata.ExecutableName}: Command finished with exit code ({exitCode})."));
            }
        }
Example #20
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            //Get current CLI mode and input directives
            Type currentModeType = _applicationLifetime.CurrentModeType !;
            IReadOnlyList <DirectiveInput> directives = context.Input.Directives;

            //Initialize collections
            List <IDirective>          directivesInstances          = new List <IDirective>();
            List <IPipelinedDirective> pipelinedDirectivesInstances = new List <IPipelinedDirective>();

            //Process directive input
            foreach (DirectiveInput directiveInput in directives)
            {
                // Try to get the directive matching the input or fallback to default
                DirectiveSchema directive = context.RootSchema.TryFindDirective(directiveInput.Name) ?? throw ArgumentBindingExceptions.UnknownDirectiveName(directiveInput);

                // Handle interactive directives not supported in current mode
                if (!directive.CanBeExecutedInMode(currentModeType))
                {
                    throw ModeEndUserExceptions.DirectiveExecutedInInvalidMode(directive, currentModeType);
                }

                // Get directive instance
                IDirective instance = (IDirective)_serviceProvider.GetRequiredService(directive.Type);

                //Initialize directive
                await instance.OnInitializedAsync(cancellationToken);

                //Add directive to list
                directivesInstances.Add(instance);

                if (directive.IsPipelinedDirective && instance is IPipelinedDirective pd)
                {
                    pipelinedDirectivesInstances.Add(pd);
                }
            }

            //Set directives lists in context
            CliContext internalCliContext = (CliContext)context;

            internalCliContext.Directives          = directivesInstances;
            internalCliContext.PipelinedDirectives = pipelinedDirectivesInstances;

            await next();
        }
Example #21
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            await next();

            bool isInteractive = context.IsInteractiveMode;
            int? exitCode      = context.ExitCode;

            if (context.ExitCode == 0)
            {
                context.Console.WithForegroundColor(ConsoleColor.White, () =>
                                                    context.Console.Output.WriteLine($"{context.Metadata.ExecutableName}: Command finished succesfully."));
            }
            else
            {
                context.Console.WithForegroundColor(ConsoleColor.White, () =>
                                                    context.Console.Output.WriteLine($"{context.Metadata.ExecutableName}: Command finished with exit code ({exitCode})."));
            }
        }
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            bool hasPrintPerfDirective = context.GetDirectiveInstance <PrintPerformanceDirective>() is not null;
            bool hasNoLogDirective     = context.GetDirectiveInstance <NoLoggingDirective>() is not null;

            if (hasPrintPerfDirective)
            {
                PrintExecutionBegin(context);
            }

            Stopwatch stopwatch = Stopwatch.StartNew();

            if (hasNoLogDirective)
            {
                await next();
            }
            else
            {
                DateTime startedOn = DateTime.Now;

                await next();

                stopwatch.Stop();

                PerformanceLog log = new()
                {
                    StartedOn   = startedOn,
                    CommandName = context.CommandSchema.Name,
                    Input       = context.Input.Arguments,
                    Time        = stopwatch.Elapsed
                };
                _performanceLogsRepository.Insert(log);

                _logger.LogInformation("Command '{Command}' finished with exit code {ExitCode} after {Duration} ms.",
                                       string.Join(' ', context.Input.Arguments),
                                       context.ExitCode ?? ExitCodes.Error,
                                       stopwatch.Elapsed.TotalMilliseconds);
            }

            if (hasPrintPerfDirective)
            {
                PrintExecutionFinish(context, stopwatch);
            }
        }
        private async Task ValidateCurrentCommand(ICliContext context, CancellationToken cancellationToken)
        {
            Type validatorType = typeof(IValidator <>).MakeGenericType(context.CommandSchema.Type);

            if (_serviceProvider.GetService(validatorType) is IValidator validator)
            {
                IValidationContext validationContext = new ValidationContext <ICommand>(context.Command);
                ValidationResult   validationResult  = await validator.ValidateAsync(validationContext, cancellationToken);

                if (!validationResult.IsValid)
                {
                    throw new ValidationException(validationResult.Errors);
                }
            }
            else
            {
                _logger.LogDebug("No validator for {Type}.", validatorType);
            }
        }
Example #24
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            //Get input and command schema from context
            CommandInput  input           = context.Input;
            CommandSchema commandSchema   = context.CommandSchema;
            Type          currentModeType = _applicationLifetime.CurrentModeType !;

            // Handle commands not supported in current mode
            if (!commandSchema.CanBeExecutedInMode(currentModeType))
            {
                throw ModeEndUserExceptions.CommandExecutedInInvalidMode(commandSchema, currentModeType);
            }

            // Get command instance from context and bind arguments
            ICommand instance = context.Command;

            commandSchema.BindParameters(instance, input.Parameters);
            commandSchema.BindOptions(instance, input.Options, _optionFallbackProvider);

            await next();
        }
        private static void PrintExecutionFinish(ICliContext context, Stopwatch stopwatch)
        {
            int?exitCode = context.ExitCode;

            if (context.ExitCode == 0)
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
                {
                    output.WriteLine("--- Command finished successfully after {0} ms.",
                                     stopwatch.Elapsed.TotalMilliseconds);
                });
            }
            else
            {
                context.Console.Output.WithForegroundColor(ConsoleColor.DarkGray, (output) =>
                {
                    context.Console.Output.WriteLine("--- Command finished with exit code ({0}) after {1} ms.",
                                                     context.ExitCode ?? ExitCodes.Error,
                                                     stopwatch.Elapsed.TotalMilliseconds);
                });
            }
        }
Example #26
0
 /// <summary>
 /// Initializes an instance of <see cref="ScopeDirective"/>.
 /// </summary>
 public ScopeDirective(ICliContext cliContext)
 {
     _cliContext = (CliContext)cliContext;
 }
Example #27
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            context.ExitCode ??= Execute((CliContext)context);

            await next();
        }
Example #28
0
 /// <summary>
 /// Initializes an instance of <see cref="CliApplication"/>.
 /// </summary>
 public PreviewDirective(ICliContext cliContext)
 {
     _cliContext = cliContext;
 }
Example #29
0
 /// <summary>
 /// Initializes an instance of <see cref="DefaultDirective"/>.
 /// </summary>
 public DefaultDirective(ICliContext cliContext)
 {
     _cliContext = cliContext;
 }
Example #30
0
        public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken)
        {
            context.Console.Output.WriteLine($"-- Log Command {_library.GetLibrary().Books.Count}");

            await next();
        }