Browse Source

Add install-libs command

pull/9145/head
liangshiwei 5 years ago
parent
commit
ab926272ed
  1. 8
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs
  2. 78
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/InstallLibsCommand.cs
  3. 9
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/IInstallLibsService.cs
  4. 189
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs
  5. 53
      framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/ResourceMapping.cs

8
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/AbpCliCoreModule.cs

@ -2,9 +2,11 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Cli.Commands;
using Volo.Abp.Cli.Http;
using Volo.Abp.Cli.LIbs;
using Volo.Abp.Domain;
using Volo.Abp.IdentityModel;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Minify;
using Volo.Abp.Modularity;
@ -25,6 +27,11 @@ namespace Volo.Abp.Cli
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.UnsupportedTypes.Add(typeof(ResourceMapping));
});
Configure<AbpCliOptions>(options =>
{
//TODO: Define constants like done for GenerateProxyCommand.Name.
@ -49,6 +56,7 @@ namespace Volo.Abp.Cli
options.Commands["build"] = typeof(BuildCommand);
options.Commands["bundle"] = typeof(BundleCommand);
options.Commands["create-migration-and-run-migrator"] = typeof(CreateMigrationAndRunMigratorCommand);
options.Commands["install-libs"] = typeof(InstallLibsCommand);
});
}
}

78
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/Commands/InstallLibsCommand.cs

@ -0,0 +1,78 @@
using System;
using System.IO;
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.LIbs;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.Commands
{
public class InstallLibsCommand : IConsoleCommand, ITransientDependency
{
public ILogger<InstallLibsCommand> Logger { get; set; }
protected IInstallLibsService InstallLibsService { get; }
public InstallLibsCommand(IInstallLibsService installLibsService)
{
InstallLibsService = installLibsService;
Logger = NullLogger<InstallLibsCommand>.Instance;
}
public async Task ExecuteAsync(CommandLineArgs commandLineArgs)
{
var workingDirectoryArg = commandLineArgs.Options.GetOrNull(
Options.WorkingDirectory.Short,
Options.WorkingDirectory.Long
);
var workingDirectory = workingDirectoryArg ?? Directory.GetCurrentDirectory();
if (!Directory.Exists(workingDirectory))
{
throw new CliUsageException(
"Specified directory does not exist." +
Environment.NewLine + Environment.NewLine +
GetUsageInfo()
);
}
await InstallLibsService.InstallLibs(workingDirectory);
}
public string GetUsageInfo()
{
var sb = new StringBuilder();
sb.AppendLine("");
sb.AppendLine("Usage:");
sb.AppendLine("");
sb.AppendLine(" abp install-libs");
sb.AppendLine("");
sb.AppendLine("Options:");
sb.AppendLine("");
sb.AppendLine("-wd|--working-directory <directory-path> (default: empty)");
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 "Bundles all third party styles and scripts required by modules and updates index.html file.";
}
public static class Options
{
public static class WorkingDirectory
{
public const string Short = "wd";
public const string Long = "working-directory";
}
}
}
}

9
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/IInstallLibsService.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Cli.LIbs
{
public interface IInstallLibsService
{
Task InstallLibs(string directory);
}
}

189
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs

@ -0,0 +1,189 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using NuGet.Versioning;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Json;
namespace Volo.Abp.Cli.LIbs
{
public class InstallLibsService : IInstallLibsService, ITransientDependency
{
public ILogger<InstallLibsService> Logger { get; set; }
private readonly IJsonSerializer _jsonSerializer;
public InstallLibsService(IJsonSerializer jsonSerializer)
{
_jsonSerializer = jsonSerializer;
Logger = NullLogger<InstallLibsService>.Instance;
}
public async Task InstallLibs(string directory)
{
var projectFiles = Directory.GetFiles(directory, "*.csproj");
if (!projectFiles.Any())
{
Logger.LogError("No project file found in the directory.");
return;
}
if (!await CanInstallLibs(directory))
{
Logger.LogWarning(
"abp install-libs command is available for MVC, Razor Page, and Blazor-Server UI types");
return;
}
if (!IsNpmInstalled())
{
Logger.LogWarning("NPM is not installed, visit https://nodejs.org/en/download/ and install NPM");
return;
}
if (IsYarnAvailable())
{
RunYarn(directory);
}
else
{
RunNpmInstall(directory);
}
await CleanAndCopyResources(directory);
}
private async Task CleanAndCopyResources(string fileDirectory)
{
var mappingFiles = Directory.GetFiles(fileDirectory, "abp.resourcemapping.js", SearchOption.AllDirectories);
var resourceMapping = new ResourceMapping
{
Clean = new List<string> {"./wwwroot/libs"}
};
foreach (var mappingFile in mappingFiles)
{
using (var reader = File.OpenText(mappingFile))
{
var mappingFileContent = await reader.ReadToEndAsync();
var mapping = _jsonSerializer.Deserialize<ResourceMapping>(mappingFileContent
.Replace("module.exports", string.Empty)
.Replace("=", string.Empty).Trim().TrimEnd(';'));
mapping.ReplaceAliases();
resourceMapping.Clean.AddRange(mapping.Clean);
mapping.Aliases.ToList().ForEach(x =>
{
resourceMapping.Aliases.AddIfNotContains(new KeyValuePair<string, string>(x.Key, x.Value));
});
mapping.Mappings.ToList().ForEach(x =>
{
resourceMapping.Mappings.AddIfNotContains(new KeyValuePair<string, string>(x.Key, x.Value));
});
}
}
CleanDirsAndFiles(fileDirectory, resourceMapping);
CopyResourcesToLibs(fileDirectory, resourceMapping);
}
private void CopyResourcesToLibs(string fileDirectory, ResourceMapping resourceMapping)
{
foreach (var mapping in resourceMapping.Mappings)
{
var sourcePath = Path.Combine(fileDirectory, mapping.Key);
var destPath = Path.Combine(fileDirectory, mapping.Value);
if (Path.HasExtension(sourcePath) && File.Exists(sourcePath))
{
Directory.CreateDirectory(Path.GetFullPath(destPath));
File.Copy(sourcePath, Path.Combine(destPath, Path.GetFileName(sourcePath)), true);
}
else
{
var files = Directory.GetFiles(fileDirectory, mapping.Key);
Directory.CreateDirectory(Path.GetFullPath(destPath));
foreach (var file in files)
{
File.Copy(file, Path.Combine(destPath, Path.GetFileName(file)), true);
}
}
}
}
private async Task<bool> CanInstallLibs(string fileDirectory)
{
var projectFiles = Directory.GetFiles(fileDirectory, "*.csproj");
using (var reader = File.OpenText(projectFiles[0]))
{
var projectFileContent = await reader.ReadToEndAsync();
return projectFileContent.Contains("Microsoft.NET.Sdk.Web");
}
}
private void CleanDirsAndFiles(string directory, ResourceMapping resourceMapping)
{
foreach (var cleanPattern in resourceMapping.Clean)
{
CleanDirsAndFiles(directory, cleanPattern);
}
}
private void CleanDirsAndFiles(string directory, string patterns)
{
foreach (var file in Directory.GetFiles(directory, patterns))
{
File.Delete(file);
}
foreach (var dir in Directory.GetDirectories(directory, patterns))
{
Directory.Delete(dir, true);
}
}
private void RunNpmInstall(string directory)
{
Logger.LogInformation($"Running npm install on {directory}");
CmdHelper.RunCmd($"cd {directory} && npm install");
}
private void RunYarn(string directory)
{
Logger.LogInformation($"Running Yarn on {directory}");
CmdHelper.RunCmd($"cd {directory} && yarn");
}
private bool IsNpmInstalled()
{
var output = CmdHelper.RunCmdAndGetOutput("npm -v").Trim();
return SemanticVersion.TryParse(output, out _);
}
private bool IsYarnAvailable()
{
var output = CmdHelper.RunCmdAndGetOutput("npm list yarn -g").Trim();
if (output.Contains("empty"))
{
return false;
}
if (!SemanticVersion.TryParse(output.Substring(output.IndexOf('@') + 1), out var version))
{
return false;
}
return version > SemanticVersion.Parse("1.20.0");
}
}
}

53
framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/ResourceMapping.cs

@ -0,0 +1,53 @@
using System.Collections.Generic;
using System.Linq;
namespace Volo.Abp.Cli.LIbs
{
public class ResourceMapping
{
public Dictionary<string, string> Aliases { get; set; }
public List<string> Clean { get; set; }
public Dictionary<string, string> Mappings { get; set; }
public ResourceMapping()
{
Aliases = new Dictionary<string, string>
{
{"@node_modules", "./node_modules"},
{"@libs", "./wwwroot/libs"},
};
Clean = new List<string>();
Mappings = new Dictionary<string, string>();
}
public void ReplaceAliases()
{
for (var i = 0; i < Mappings.Count; i++)
{
var mapping = Mappings.ElementAt(i);
Mappings.Remove(mapping.Key);
var key = mapping.Key;
var value = mapping.Value;
foreach (var alias in Aliases)
{
key = key.Replace(alias.Key, alias.Value);
value = value.Replace(alias.Key, alias.Value);
}
Mappings[key] = value;
}
for (var i = 0; i < Clean.Count; i++)
{
foreach (var alias in Aliases)
{
Clean[i] = Clean[i].Replace(alias.Key, alias.Value);
}
}
}
}
}
Loading…
Cancel
Save