|
|
|
@ -1,33 +1,51 @@ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Diagnostics; |
|
|
|
using System.IO; |
|
|
|
using System.Linq; |
|
|
|
using System.Net; |
|
|
|
using System.Net.Http; |
|
|
|
using System.Net.NetworkInformation; |
|
|
|
using System.Text; |
|
|
|
using System.Threading; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Microsoft.Extensions.Logging; |
|
|
|
using Microsoft.Extensions.Logging.Abstractions; |
|
|
|
using Newtonsoft.Json.Linq; |
|
|
|
using NuGet.Versioning; |
|
|
|
using Volo.Abp.Cli.Args; |
|
|
|
using Volo.Abp.Cli.Commands.Services; |
|
|
|
using Volo.Abp.Cli.Http; |
|
|
|
using Volo.Abp.Cli.NuGet; |
|
|
|
using Volo.Abp.Cli.Utils; |
|
|
|
using Volo.Abp.DependencyInjection; |
|
|
|
using Volo.Abp.Http; |
|
|
|
using Volo.Abp.Json; |
|
|
|
using Volo.Abp.Threading; |
|
|
|
|
|
|
|
namespace Volo.Abp.Cli.Commands; |
|
|
|
|
|
|
|
public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
{ |
|
|
|
public const string Name = "suite"; |
|
|
|
|
|
|
|
|
|
|
|
public ICmdHelper CmdHelper { get; } |
|
|
|
private readonly AbpNuGetIndexUrlService _nuGetIndexUrlService; |
|
|
|
private readonly NuGetService _nuGetService; |
|
|
|
private readonly CliHttpClientFactory _cliHttpClientFactory; |
|
|
|
private const string SuitePackageName = "Volo.Abp.Suite"; |
|
|
|
public ILogger<SuiteCommand> Logger { get; set; } |
|
|
|
|
|
|
|
public SuiteCommand(AbpNuGetIndexUrlService nuGetIndexUrlService, NuGetService nuGetService, ICmdHelper cmdHelper) |
|
|
|
public SuiteCommand( |
|
|
|
AbpNuGetIndexUrlService nuGetIndexUrlService, |
|
|
|
NuGetService nuGetService, |
|
|
|
ICmdHelper cmdHelper, |
|
|
|
CliHttpClientFactory cliHttpClientFactory) |
|
|
|
{ |
|
|
|
CmdHelper = cmdHelper; |
|
|
|
_nuGetIndexUrlService = nuGetIndexUrlService; |
|
|
|
_nuGetService = nuGetService; |
|
|
|
_cliHttpClientFactory = cliHttpClientFactory; |
|
|
|
Logger = NullLogger<SuiteCommand>.Instance; |
|
|
|
} |
|
|
|
|
|
|
|
@ -48,6 +66,13 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
RunSuite(); |
|
|
|
break; |
|
|
|
|
|
|
|
case "generate": |
|
|
|
await InstallSuiteIfNotInstalledAsync(); |
|
|
|
var suiteProcess = RunSuiteTemporary(); |
|
|
|
await GenerateCrudOnSuiteAsync(commandLineArgs); |
|
|
|
suiteProcess?.Kill(); |
|
|
|
break; |
|
|
|
|
|
|
|
case "install": |
|
|
|
await InstallSuiteAsync(version, preview); |
|
|
|
break; |
|
|
|
@ -63,6 +88,115 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async Task GenerateCrudOnSuiteAsync(CommandLineArgs args) |
|
|
|
{ |
|
|
|
var entityFile = args.Options.GetOrNull(Options.Crud.Entity.Short, Options.Crud.Entity.Long); |
|
|
|
var solutionFile = args.Options.GetOrNull(Options.Crud.Solution.Short, Options.Crud.Solution.Long); |
|
|
|
|
|
|
|
if (entityFile.IsNullOrEmpty() || !entityFile.EndsWith(".json") || !File.Exists(entityFile) || |
|
|
|
solutionFile.IsNullOrEmpty() || !solutionFile.EndsWith(".sln")) |
|
|
|
{ |
|
|
|
throw new UserFriendlyException("Invalid Arguments!"); |
|
|
|
} |
|
|
|
|
|
|
|
Logger.LogInformation("Generating CRUD Page..."); |
|
|
|
|
|
|
|
var client = _cliHttpClientFactory.CreateClient(false); |
|
|
|
var solutionId = await GetSolutionIdAsync(client, solutionFile); |
|
|
|
|
|
|
|
if (!solutionId.HasValue) |
|
|
|
{ |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
var entityContent = new StringContent( |
|
|
|
File.ReadAllText(entityFile), |
|
|
|
Encoding.UTF8, |
|
|
|
MimeTypes.Application.Json |
|
|
|
); |
|
|
|
|
|
|
|
var responseMessage = await client.PostAsync( |
|
|
|
$"http://localhost:3000/api/abpSuite/crudPageGenerator/{solutionId.ToString()}/save-and-generate-entity", |
|
|
|
entityContent |
|
|
|
); |
|
|
|
|
|
|
|
var response = await responseMessage.Content.ReadAsStringAsync(); |
|
|
|
|
|
|
|
if (!response.IsNullOrWhiteSpace()) |
|
|
|
{ |
|
|
|
Logger.LogError(response); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
Logger.LogInformation("CRUD page generated."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async Task<Guid?> GetSolutionIdAsync(HttpClient client, string solutionPath) |
|
|
|
{ |
|
|
|
var timeIntervals = new List<TimeSpan>(); |
|
|
|
for (var i = 0; i < 10; i++) |
|
|
|
{ |
|
|
|
timeIntervals.Add(TimeSpan.FromSeconds(5)); |
|
|
|
} |
|
|
|
|
|
|
|
var responseMessage = await client.GetHttpResponseMessageWithRetryAsync( |
|
|
|
"http://localhost:3000/api/abpSuite/solutions", |
|
|
|
_cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10)), |
|
|
|
Logger, |
|
|
|
timeIntervals.ToArray()); |
|
|
|
|
|
|
|
var response = await responseMessage.Content.ReadAsStringAsync(); |
|
|
|
JArray solutions; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
solutions = (JArray)(JObject.Parse(response)["solutions"]); |
|
|
|
} |
|
|
|
catch (Exception) |
|
|
|
{ |
|
|
|
Logger.LogError(response); |
|
|
|
return await AddSolutionToSuiteAsync(client, solutionPath); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (JObject solution in solutions) |
|
|
|
{ |
|
|
|
if (solution["path"].ToString() == solutionPath) |
|
|
|
{ |
|
|
|
return Guid.Parse(solution["id"].ToString()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return await AddSolutionToSuiteAsync(client, solutionPath); |
|
|
|
} |
|
|
|
|
|
|
|
private async Task<Guid?> AddSolutionToSuiteAsync(HttpClient client, string solutionPath) |
|
|
|
{ |
|
|
|
var entityContent = new StringContent( |
|
|
|
"{\"Path\": \"" + solutionPath.Replace("\\", "\\\\") + "\"}", |
|
|
|
Encoding.UTF8, |
|
|
|
MimeTypes.Application.Json |
|
|
|
); |
|
|
|
|
|
|
|
var responseMessage = await client.PostAsync( |
|
|
|
"http://localhost:3000/api/abpSuite/addSolution", |
|
|
|
entityContent, |
|
|
|
_cliHttpClientFactory.GetCancellationToken(TimeSpan.FromMinutes(10)) |
|
|
|
); |
|
|
|
|
|
|
|
var response = await responseMessage.Content.ReadAsStringAsync(); |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
return Guid.Parse(JObject.Parse(response)["id"].ToString()); |
|
|
|
} |
|
|
|
catch (Exception) |
|
|
|
{ |
|
|
|
Logger.LogError(response); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private async Task InstallSuiteIfNotInstalledAsync() |
|
|
|
{ |
|
|
|
var currentSuiteVersionAsString = GetCurrentSuiteVersion(); |
|
|
|
@ -132,7 +266,8 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
} |
|
|
|
|
|
|
|
CmdHelper.RunCmd( |
|
|
|
$"dotnet tool install {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", out int exitCode |
|
|
|
$"dotnet tool install {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", |
|
|
|
out int exitCode |
|
|
|
); |
|
|
|
|
|
|
|
if (exitCode == 0) |
|
|
|
@ -155,7 +290,8 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
private void ShowSuiteManualInstallCommand() |
|
|
|
{ |
|
|
|
Logger.LogInformation("You can also run the following command to install ABP Suite."); |
|
|
|
Logger.LogInformation("dotnet tool install -g Volo.Abp.Suite --add-source https://nuget.abp.io/<your-private-key>/v3/index.json"); |
|
|
|
Logger.LogInformation( |
|
|
|
"dotnet tool install -g Volo.Abp.Suite --add-source https://nuget.abp.io/<your-private-key>/v3/index.json"); |
|
|
|
} |
|
|
|
|
|
|
|
private async Task UpdateSuiteAsync(string version = null, bool preview = false) |
|
|
|
@ -202,7 +338,8 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
} |
|
|
|
|
|
|
|
CmdHelper.RunCmd( |
|
|
|
$"dotnet tool update {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", out int exitCode |
|
|
|
$"dotnet tool update {SuitePackageName}{versionOption} --add-source {nugetIndexUrl} -g", |
|
|
|
out int exitCode |
|
|
|
); |
|
|
|
|
|
|
|
if (exitCode != 0) |
|
|
|
@ -231,7 +368,8 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
private void ShowSuiteManualUpdateCommand() |
|
|
|
{ |
|
|
|
Logger.LogError("You can also run the following command to update ABP Suite."); |
|
|
|
Logger.LogError("dotnet tool update -g Volo.Abp.Suite --add-source https://nuget.abp.io/<your-private-key>/v3/index.json"); |
|
|
|
Logger.LogError( |
|
|
|
"dotnet tool update -g Volo.Abp.Suite --add-source https://nuget.abp.io/<your-private-key>/v3/index.json"); |
|
|
|
} |
|
|
|
|
|
|
|
private void RemoveSuite() |
|
|
|
@ -258,6 +396,37 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
CmdHelper.RunCmd("abp-suite"); |
|
|
|
} |
|
|
|
|
|
|
|
private Process RunSuiteTemporary() |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
if (!GlobalToolHelper.IsGlobalToolInstalled("abp-suite")) |
|
|
|
{ |
|
|
|
Logger.LogWarning( |
|
|
|
"ABP Suite is not installed! To install it you can run the command: \"abp suite install\""); |
|
|
|
return null; |
|
|
|
} |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
Logger.LogWarning("Couldn't check ABP Suite installed status: " + ex.Message); |
|
|
|
} |
|
|
|
|
|
|
|
if (IsSuiteAlreadyRunning()) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return CmdHelper.RunCmdAndGetProcess("abp-suite --no-browser"); |
|
|
|
} |
|
|
|
|
|
|
|
bool IsSuiteAlreadyRunning() |
|
|
|
{ |
|
|
|
var ipGP = IPGlobalProperties.GetIPGlobalProperties(); |
|
|
|
var endpoints = ipGP.GetActiveTcpListeners(); |
|
|
|
return endpoints.Any(e => e.Port == 3000); |
|
|
|
} |
|
|
|
|
|
|
|
public string GetUsageInfo() |
|
|
|
{ |
|
|
|
var sb = new StringBuilder(); |
|
|
|
@ -306,5 +475,20 @@ public class SuiteCommand : IConsoleCommand, ITransientDependency |
|
|
|
public const string Long = "version"; |
|
|
|
public const string Short = "v"; |
|
|
|
} |
|
|
|
|
|
|
|
public static class Crud |
|
|
|
{ |
|
|
|
public static class Solution |
|
|
|
{ |
|
|
|
public const string Long = "solution"; |
|
|
|
public const string Short = "s"; |
|
|
|
} |
|
|
|
|
|
|
|
public static class Entity |
|
|
|
{ |
|
|
|
public const string Long = "entity"; |
|
|
|
public const string Short = "e"; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |