diff --git a/docs/en/CLI.md b/docs/en/CLI.md index cc85f0e573..ffde52eff0 100644 --- a/docs/en/CLI.md +++ b/docs/en/CLI.md @@ -34,6 +34,7 @@ Here, is the list of all available commands before explaining their details: * **`add-package`**: Adds an ABP package to a project. * **`add-module`**: Adds a [multi-package application module](https://docs.abp.io/en/abp/latest/Modules/Index) to a solution. * **`list-modules`**: Lists names of open-source application modules. +* **`list-templates`**: Lists the names of available templates to create a solution. * **`get-source`**: Downloads the source code of a module. * **`generate-proxy`**: Generates client side proxies to use HTTP API endpoints. * **`remove-proxy`**: Removes previously generated client side proxies. diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs index 4fda075521..7aba9ae849 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs @@ -49,6 +49,7 @@ public class AbpCliCoreModule : AbpModule options.Commands[AddPackageCommand.Name] = typeof(AddPackageCommand); options.Commands[AddModuleCommand.Name] = typeof(AddModuleCommand); options.Commands[ListModulesCommand.Name] = typeof(ListModulesCommand); + options.Commands[ListTemplatesCommand.Name] = typeof(ListTemplatesCommand); options.Commands[LoginCommand.Name] = typeof(LoginCommand); options.Commands[LoginInfoCommand.Name] = typeof(LoginInfoCommand); options.Commands[LogoutCommand.Name] = typeof(LogoutCommand); diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListTemplatesCommand.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListTemplatesCommand.cs new file mode 100644 index 0000000000..7274fb641d --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/ListTemplatesCommand.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.Cli.Args; +using Volo.Abp.Cli.Commands.Templates; +using Volo.Abp.Cli.Http; +using Volo.Abp.Cli.ProjectBuilding; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; +using Volo.Abp.Threading; + +namespace Volo.Abp.Cli.Commands; + +public class ListTemplatesCommand : IConsoleCommand, ITransientDependency +{ + public const string Name = "list-templates"; + + private readonly CliHttpClientFactory _cliHttpClientFactory; + private readonly IJsonSerializer _jsonSerializer; + private readonly ICancellationTokenProvider _cancellationTokenProvider; + private readonly IRemoteServiceExceptionHandler _remoteServiceExceptionHandler; + + public ILogger Logger { get; set; } + + public ListTemplatesCommand( + CliHttpClientFactory cliHttpClientFactory, + IJsonSerializer jsonSerializer, + ICancellationTokenProvider cancellationTokenProvider, + IRemoteServiceExceptionHandler remoteServiceExceptionHandler) + { + _cliHttpClientFactory = cliHttpClientFactory; + _jsonSerializer = jsonSerializer; + _cancellationTokenProvider = cancellationTokenProvider; + _remoteServiceExceptionHandler = remoteServiceExceptionHandler; + + Logger = NullLogger.Instance; + } + + public async Task ExecuteAsync(CommandLineArgs commandLineArgs) + { + var templateNameSpaceLength = 26; + var templateDisplayNameSpaceLength = 32; + + var templates = await GetTemplatesAsync(); + + var output = new StringBuilder(Environment.NewLine + Environment.NewLine); + + output.AppendLine( + $"{"Template".PadRight(templateNameSpaceLength)}" + + $"{"Template Name".PadRight(templateDisplayNameSpaceLength)}" + + "Document Url"); + + output.AppendLine( + $"{"--------".PadRight(templateNameSpaceLength)}" + + $"{"-------------".PadRight(templateDisplayNameSpaceLength)}" + + "------------"); + + output.AppendLine(); + + foreach (var template in templates) + { + output.AppendLine( + $"{template.Name?.PadRight(templateNameSpaceLength)}" + + $"{template.DisplayName?.PadRight(templateDisplayNameSpaceLength)}" + + $"{template.DocumentUrl}"); + } + + Logger.LogInformation(output.ToString()); + } + + private async Task> GetTemplatesAsync() + { + var client = _cliHttpClientFactory.CreateClient(); + + using (var responseMessage = await client.GetAsync( + $"{CliUrls.WwwAbpIo}api/download/templates/", + _cancellationTokenProvider.Token + )) + { + await _remoteServiceExceptionHandler.EnsureSuccessfulHttpResponseAsync(responseMessage); + var result = await responseMessage.Content.ReadAsStringAsync(); + return _jsonSerializer.Deserialize>(result); + } + } + + public string GetUsageInfo() + { + var sb = new StringBuilder(); + + sb.AppendLine(""); + sb.AppendLine("Usage:"); + sb.AppendLine(" abp list-templates"); + sb.AppendLine(""); + sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); + + return sb.ToString(); + } + + public string GetShortDescription() + { + return "Lists available templates to be created."; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Templates/TemplateInfo.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Templates/TemplateInfo.cs new file mode 100644 index 0000000000..c0c269de5b --- /dev/null +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/Templates/TemplateInfo.cs @@ -0,0 +1,14 @@ +namespace Volo.Abp.Cli.Commands.Templates; + +public class TemplateInfo +{ + public string Name { get; set; } + + public string DisplayName { get; set; } + + public string ShortDescription { get; set; } + + public string DocumentUrl { get; set; } + + public bool IsPro { get; set; } +} \ No newline at end of file