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(); } }
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); }
public static CommandPipelineHandlerDelegate Next(this IMiddleware commandMiddleware, ICliContext cliContext, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken) { return(() => commandMiddleware.HandleAsync(cliContext, next, cancellationToken)); }
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); }); } }
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)); }); }
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(); }
/// <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); }
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(); }
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); } }
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)); }); }
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(); }
/// <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); } }
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}).")); } }
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(); }
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); } }
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); }); } }
/// <summary> /// Initializes an instance of <see cref="ScopeDirective"/>. /// </summary> public ScopeDirective(ICliContext cliContext) { _cliContext = (CliContext)cliContext; }
public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken) { context.ExitCode ??= Execute((CliContext)context); await next(); }
/// <summary> /// Initializes an instance of <see cref="CliApplication"/>. /// </summary> public PreviewDirective(ICliContext cliContext) { _cliContext = cliContext; }
/// <summary> /// Initializes an instance of <see cref="DefaultDirective"/>. /// </summary> public DefaultDirective(ICliContext cliContext) { _cliContext = cliContext; }
public async Task HandleAsync(ICliContext context, CommandPipelineHandlerDelegate next, CancellationToken cancellationToken) { context.Console.Output.WriteLine($"-- Log Command {_library.GetLibrary().Books.Count}"); await next(); }