File: Commands\ResourceCommandHelper.cs
Web Access
Project: src\src\Aspire.Cli\Aspire.Cli.Tool.csproj (aspire)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Aspire.Cli.Backchannel;
using Aspire.Cli.Interaction;
using Microsoft.Extensions.Logging;
 
namespace Aspire.Cli.Commands;
 
/// <summary>
/// Helper for executing resource commands via the backchannel.
/// Provides common functionality for start/stop/restart/command operations.
/// </summary>
internal static class ResourceCommandHelper
{
    /// <summary>
    /// Executes a resource command and handles the response with appropriate user feedback.
    /// </summary>
    /// <param name="connection">The backchannel connection to use.</param>
    /// <param name="interactionService">The interaction service for user feedback.</param>
    /// <param name="logger">The logger for debug output.</param>
    /// <param name="resourceName">The name of the resource.</param>
    /// <param name="commandName">The command to execute (e.g., "resource-start").</param>
    /// <param name="progressVerb">The verb to display during progress (e.g., "Starting", "Stopping").</param>
    /// <param name="baseVerb">The base verb for error messages (e.g., "start", "stop").</param>
    /// <param name="pastTenseVerb">The past tense verb for success messages (e.g., "started", "stopped").</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>Exit code indicating success or failure.</returns>
    public static async Task<int> ExecuteResourceCommandAsync(
        IAppHostAuxiliaryBackchannel connection,
        IInteractionService interactionService,
        ILogger logger,
        string resourceName,
        string commandName,
        string progressVerb,
        string baseVerb,
        string pastTenseVerb,
        CancellationToken cancellationToken)
    {
        logger.LogDebug("{Verb} resource '{ResourceName}'", progressVerb, resourceName);
 
        var response = await interactionService.ShowStatusAsync(
            $"{progressVerb} resource '{resourceName}'...",
            async () => await connection.ExecuteResourceCommandAsync(resourceName, commandName, cancellationToken));
 
        return HandleResponse(response, interactionService, resourceName, progressVerb, baseVerb, pastTenseVerb);
    }
 
    /// <summary>
    /// Executes a generic command and handles the response with appropriate user feedback.
    /// </summary>
    public static async Task<int> ExecuteGenericCommandAsync(
        IAppHostAuxiliaryBackchannel connection,
        IInteractionService interactionService,
        ILogger logger,
        string resourceName,
        string commandName,
        CancellationToken cancellationToken)
    {
        logger.LogDebug("Executing command '{CommandName}' on resource '{ResourceName}'", commandName, resourceName);
 
        var response = await interactionService.ShowStatusAsync(
            $"Executing command '{commandName}' on resource '{resourceName}'...",
            async () => await connection.ExecuteResourceCommandAsync(resourceName, commandName, cancellationToken));
 
        if (response.Success)
        {
            interactionService.DisplaySuccess($"Command '{commandName}' executed successfully on resource '{resourceName}'.");
            return ExitCodeConstants.Success;
        }
        else if (response.Canceled)
        {
            interactionService.DisplayMessage("warning", $"Command '{commandName}' on '{resourceName}' was canceled.");
            return ExitCodeConstants.FailedToExecuteResourceCommand;
        }
        else
        {
            var errorMessage = GetFriendlyErrorMessage(response.ErrorMessage);
            interactionService.DisplayError($"Failed to execute command '{commandName}' on resource '{resourceName}': {errorMessage}");
            return ExitCodeConstants.FailedToExecuteResourceCommand;
        }
    }
 
    private static int HandleResponse(
        ExecuteResourceCommandResponse response,
        IInteractionService interactionService,
        string resourceName,
        string progressVerb,
        string baseVerb,
        string pastTenseVerb)
    {
        if (response.Success)
        {
            interactionService.DisplaySuccess($"Resource '{resourceName}' {pastTenseVerb} successfully.");
            return ExitCodeConstants.Success;
        }
        else if (response.Canceled)
        {
            interactionService.DisplayMessage("warning", $"{progressVerb} command for '{resourceName}' was canceled.");
            return ExitCodeConstants.FailedToExecuteResourceCommand;
        }
        else
        {
            var errorMessage = GetFriendlyErrorMessage(response.ErrorMessage);
            interactionService.DisplayError($"Failed to {baseVerb} resource '{resourceName}': {errorMessage}");
            return ExitCodeConstants.FailedToExecuteResourceCommand;
        }
    }
 
    private static string GetFriendlyErrorMessage(string? errorMessage)
    {
        return string.IsNullOrEmpty(errorMessage) ? "Unknown error occurred." : errorMessage;
    }
}