mirror of https://github.com/abpframework/abp.git
491 changed files with 66439 additions and 643 deletions
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form |
||||
|
{ |
||||
|
[AttributeUsage(AttributeTargets.Property)] |
||||
|
public class DynamicFormIgnore : Attribute |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
{ |
||||
|
"iisSettings": { |
||||
|
"windowsAuthentication": false, |
||||
|
"anonymousAuthentication": true, |
||||
|
"iisExpress": { |
||||
|
"applicationUrl": "http://localhost:57333/", |
||||
|
"sslPort": 0 |
||||
|
} |
||||
|
}, |
||||
|
"profiles": { |
||||
|
"IIS Express": { |
||||
|
"commandName": "IISExpress", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
} |
||||
|
}, |
||||
|
"Volo.Abp.AspNetCore.Mvc.UI.Dashboards": { |
||||
|
"commandName": "Project", |
||||
|
"launchBrowser": true, |
||||
|
"environmentVariables": { |
||||
|
"ASPNETCORE_ENVIRONMENT": "Development" |
||||
|
}, |
||||
|
"applicationUrl": "http://localhost:57343/" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk.Web"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Dashboards</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Dashboards</PackageId> |
||||
|
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<IsPackable>true</IsPackable> |
||||
|
<OutputType>Library</OutputType> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\Components\**\*.cshtml" /> |
||||
|
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\Components\**\*.cshtml" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<Content Remove="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\_ViewImports.cshtml" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="Volo\Abp\AspNetCore\Mvc\UI\Dashboards\_ViewImports.cshtml" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Widgets\Volo.Abp.AspNetCore.Mvc.UI.Widgets.csproj" /> |
||||
|
</ItemGroup> |
||||
|
</Project> |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreMvcUiWidgetsModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreMvcUiDashboardsModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<VirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpAspNetCoreMvcUiDashboardsModule>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard |
||||
|
{ |
||||
|
public class DashboardViewComponent : AbpViewComponent |
||||
|
{ |
||||
|
public async Task<IViewComponentResult> InvokeAsync(string dashboardName, DashboardOptions dashboardOptions, WidgetOptions widgetOptions) |
||||
|
{ |
||||
|
var model = new DashboardViewModel(dashboardName, dashboardOptions, widgetOptions); |
||||
|
return View("~/Volo/Abp/AspNetCore/Mvc/UI/Dashboards/Components/Dashboard/Default.cshtml", model); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard |
||||
|
{ |
||||
|
public class DashboardViewModel |
||||
|
{ |
||||
|
public DashboardDefinition Dashboard { get; set; } |
||||
|
public DashboardOptions DashboardOptions { get; set; } |
||||
|
public WidgetOptions WidgetOptions { get; set; } |
||||
|
|
||||
|
public DashboardViewModel(string dashboardName, DashboardOptions dashboardOptions, WidgetOptions widgetOptions) |
||||
|
{ |
||||
|
Dashboard = dashboardOptions.Dashboards.Single(d => d.Name.Equals(dashboardName)); |
||||
|
DashboardOptions = dashboardOptions; |
||||
|
WidgetOptions = widgetOptions; |
||||
|
} |
||||
|
|
||||
|
public WidgetDefinition GetWidget(string name) |
||||
|
{ |
||||
|
return WidgetOptions.Widgets.Single(d => d.Name.Equals(name)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
@using Microsoft.Extensions.Localization |
||||
|
@using Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
@inject IWidgetRenderer WidgetRenderer |
||||
|
@inject IStringLocalizerFactory localizer |
||||
|
@model Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard.DashboardViewModel |
||||
|
@{ |
||||
|
} |
||||
|
<abp-row> |
||||
|
@foreach (var widgetConfiguration in Model.Dashboard.AvailableWidgets) |
||||
|
{ |
||||
|
var widgetDefinition = Model.GetWidget(widgetConfiguration.WidgetName); |
||||
|
widgetDefinition.DefaultDimensions = widgetConfiguration.Dimensions ?? widgetDefinition.DefaultDimensions ?? new WidgetDimensions(5, 5); |
||||
|
|
||||
|
<abp-column class="col-@widgetDefinition.DefaultDimensions.Width" |
||||
|
style="height: @(widgetDefinition.DefaultDimensions.Height * 100)px" |
||||
|
abp-border="Danger"> |
||||
|
|
||||
|
@await WidgetRenderer.RenderAsync(Component, widgetDefinition.Name) |
||||
|
</abp-column> |
||||
|
} |
||||
|
</abp-row> |
||||
@ -0,0 +1,49 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public class DashboardDefinition |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Unique name of the dashboard.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// A list of Widgets available for this dashboard.
|
||||
|
/// </summary>
|
||||
|
public List<DashboardWidgetConfiguration> AvailableWidgets { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display name of the widget.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public ILocalizableString DisplayName |
||||
|
{ |
||||
|
get => _displayName; |
||||
|
set => _displayName = Check.NotNull(value, nameof(value)); |
||||
|
} |
||||
|
private ILocalizableString _displayName; |
||||
|
|
||||
|
public DashboardDefinition( |
||||
|
[NotNull] string name, |
||||
|
[CanBeNull] ILocalizableString displayName) |
||||
|
{ |
||||
|
Name = Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
DisplayName = displayName ?? new FixedLocalizableString(name); |
||||
|
|
||||
|
AvailableWidgets = new List<DashboardWidgetConfiguration>(); |
||||
|
} |
||||
|
|
||||
|
public DashboardDefinition WithWidget(string widgetName, WidgetLocation location = null, WidgetDimensions dimensions = null) |
||||
|
{ |
||||
|
AvailableWidgets.Add( new DashboardWidgetConfiguration(widgetName, dimensions, location)); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public class DashboardOptions |
||||
|
{ |
||||
|
public List<DashboardDefinition> Dashboards { get; } |
||||
|
|
||||
|
public DashboardOptions() |
||||
|
{ |
||||
|
Dashboards = new List<DashboardDefinition>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Html; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Dashboards.Components.Dashboard; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public class DashboardRenderer : IDashboardRenderer |
||||
|
{ |
||||
|
public async Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, object args = null) |
||||
|
{ |
||||
|
return await componentHelper.InvokeAsync(typeof(DashboardViewComponent), args ?? new object()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Widgets; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public class DashboardWidgetConfiguration |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public string WidgetName { get; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public WidgetDimensions Dimensions { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public WidgetLocation Location { get; set; } |
||||
|
|
||||
|
public DashboardWidgetConfiguration( |
||||
|
[NotNull] string widgetName, |
||||
|
[CanBeNull] WidgetDimensions dimensions = null, |
||||
|
[CanBeNull] WidgetLocation location = null |
||||
|
) |
||||
|
{ |
||||
|
WidgetName = Check.NotNullOrWhiteSpace(widgetName, nameof(widgetName)); |
||||
|
Dimensions = dimensions; |
||||
|
Location = location; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Html; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public interface IDashboardRenderer : ITransientDependency |
||||
|
{ |
||||
|
Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, object args = null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Dashboards |
||||
|
{ |
||||
|
public class WidgetLocation |
||||
|
{ |
||||
|
public int X { get; set; } |
||||
|
|
||||
|
public int Y { get; set; } |
||||
|
|
||||
|
public WidgetLocation(int x, int y) |
||||
|
{ |
||||
|
X = x; |
||||
|
Y = y; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
||||
|
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
||||
@ -0,0 +1,16 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<AssemblyName>Volo.Abp.AspNetCore.Mvc.UI.Widgets</AssemblyName> |
||||
|
<PackageId>Volo.Abp.AspNetCore.Mvc.UI.Widgets</PackageId> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap\Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,13 @@ |
|||||
|
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreMvcUiBootstrapModule) |
||||
|
)] |
||||
|
public class AbpAspNetCoreMvcUiWidgetsModule : AbpModule |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Html; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
public interface IWidgetRenderer : ITransientDependency |
||||
|
{ |
||||
|
Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, string widgetName, object args = null); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
using System; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
public class WidgetDefinition |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Unique name of the widget.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Display name of the widget.
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public ILocalizableString DisplayName |
||||
|
{ |
||||
|
get => _displayName; |
||||
|
set => _displayName = Check.NotNull(value, nameof(value)); |
||||
|
} |
||||
|
private ILocalizableString _displayName; |
||||
|
|
||||
|
[NotNull] |
||||
|
public Type ViewComponentType { get; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public WidgetDimensions DefaultDimensions { get; set; } |
||||
|
|
||||
|
public WidgetDefinition( |
||||
|
[NotNull] string name, |
||||
|
[NotNull] Type viewComponentType, |
||||
|
[CanBeNull] ILocalizableString displayName, |
||||
|
[CanBeNull] WidgetDimensions defaultDimensions = null) |
||||
|
{ |
||||
|
DefaultDimensions = defaultDimensions; |
||||
|
Name = Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
ViewComponentType = Check.NotNull(viewComponentType, nameof(viewComponentType)); |
||||
|
DisplayName = displayName ?? new FixedLocalizableString(name); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
public class WidgetDimensions |
||||
|
{ |
||||
|
public int Width { get; } |
||||
|
|
||||
|
public int Height { get; } |
||||
|
|
||||
|
public WidgetDimensions(int width, int height) |
||||
|
{ |
||||
|
Width = width; |
||||
|
Height = height; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
public class WidgetOptions |
||||
|
{ |
||||
|
public List<WidgetDefinition> Widgets { get; } |
||||
|
|
||||
|
public WidgetOptions() |
||||
|
{ |
||||
|
Widgets = new List<WidgetDefinition>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Microsoft.AspNetCore.Html; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.UI.Widgets |
||||
|
{ |
||||
|
public class WidgetRenderer : IWidgetRenderer |
||||
|
{ |
||||
|
private readonly WidgetOptions _widgetOptions; |
||||
|
|
||||
|
public WidgetRenderer(IOptions<WidgetOptions> widgetOptions) |
||||
|
{ |
||||
|
_widgetOptions = widgetOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task<IHtmlContent> RenderAsync(IViewComponentHelper componentHelper, string widgetName, object args = null) |
||||
|
{ |
||||
|
var componentType = _widgetOptions.Widgets.Single(w=>w.Name.Equals(widgetName)).ViewComponentType; |
||||
|
|
||||
|
return await componentHelper.InvokeAsync(componentType, args ?? new object()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.Cli |
||||
|
{ |
||||
|
public class CliUsageException : Exception |
||||
|
{ |
||||
|
public CliUsageException(string message) |
||||
|
: base(message) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public CliUsageException(string message, Exception innerException) |
||||
|
: base(message, innerException) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,55 +0,0 @@ |
|||||
using Microsoft.Extensions.Logging; |
|
||||
using Microsoft.Extensions.Logging.Abstractions; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Cli.Args; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.ProjectModification; |
|
||||
|
|
||||
namespace Volo.Abp.Cli.Commands |
|
||||
{ |
|
||||
public class AddCommand : IConsoleCommand, ITransientDependency |
|
||||
{ |
|
||||
public ILogger<AddCommand> Logger { get; set; } |
|
||||
|
|
||||
protected ModuleAdder ModuleAdder { get; } |
|
||||
|
|
||||
public AddCommand(ModuleAdder moduleAdder) |
|
||||
{ |
|
||||
ModuleAdder = moduleAdder; |
|
||||
Logger = NullLogger<AddCommand>.Instance; |
|
||||
} |
|
||||
|
|
||||
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
|
||||
{ |
|
||||
if (commandLineArgs.Target == null) |
|
||||
{ |
|
||||
Logger.LogWarning("Module name is missing."); |
|
||||
AddCommandHelper.WriteUsage(Logger); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
await ModuleAdder.AddModuleAsync( |
|
||||
new AddModuleArgs( |
|
||||
commandLineArgs.Target, |
|
||||
commandLineArgs.Options.GetOrNull(Options.Solution.Short, Options.Solution.Long), |
|
||||
commandLineArgs.Options.GetOrNull(Options.Project.Short, Options.Project.Long) |
|
||||
) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
public static class Options |
|
||||
{ |
|
||||
public static class Solution |
|
||||
{ |
|
||||
public const string Short = "s"; |
|
||||
public const string Long = "solution"; |
|
||||
} |
|
||||
|
|
||||
public static class Project |
|
||||
{ |
|
||||
public const string Short = "p"; |
|
||||
public const string Long = "project"; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,121 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Text; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.ProjectModification; |
||||
|
using Volo.Abp.Cli.Utils; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class AddModuleCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<AddModuleCommand> Logger { get; set; } |
||||
|
|
||||
|
protected SolutionModuleAdder SolutionModuleAdder { get; } |
||||
|
|
||||
|
public AddModuleCommand(SolutionModuleAdder solutionModuleAdder) |
||||
|
{ |
||||
|
SolutionModuleAdder = solutionModuleAdder; |
||||
|
Logger = NullLogger<AddModuleCommand>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
if (commandLineArgs.Target == null) |
||||
|
{ |
||||
|
throw new CliUsageException("Module name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); |
||||
|
} |
||||
|
|
||||
|
var skipDbMigrations = Convert.ToBoolean( |
||||
|
commandLineArgs.Options.GetOrNull(Options.DbMigrations.Skip) ?? "false"); |
||||
|
|
||||
|
await SolutionModuleAdder.AddAsync( |
||||
|
GetSolutionFile(commandLineArgs), |
||||
|
commandLineArgs.Target, |
||||
|
skipDbMigrations |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetSolutionFile(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var providedSolutionFile = PathHelper.NormalizePath( |
||||
|
commandLineArgs.Options.GetOrNull( |
||||
|
AddPackageCommand.Options.Project.Short, |
||||
|
AddPackageCommand.Options.Project.Long |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
if (!providedSolutionFile.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return providedSolutionFile; |
||||
|
} |
||||
|
|
||||
|
var foundSolutionFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.sln"); |
||||
|
if (foundSolutionFiles.Length == 1) |
||||
|
{ |
||||
|
return foundSolutionFiles[0]; |
||||
|
} |
||||
|
|
||||
|
if (foundSolutionFiles.Length == 0) |
||||
|
{ |
||||
|
throw new CliUsageException("'abp add-module' command should be used inside a folder contaning a .sln file!"); |
||||
|
} |
||||
|
|
||||
|
//foundSolutionFiles.Length > 1
|
||||
|
|
||||
|
var sb = new StringBuilder("There are multiple solution (.sln) files in the current directory. Please specify one of the files below:"); |
||||
|
|
||||
|
foreach (var foundSolutionFile in foundSolutionFiles) |
||||
|
{ |
||||
|
sb.AppendLine("* " + foundSolutionFile); |
||||
|
} |
||||
|
|
||||
|
sb.AppendLine("Example:"); |
||||
|
sb.AppendLine($"abp add-module {commandLineArgs.Target} -p {foundSolutionFiles[0]}"); |
||||
|
|
||||
|
throw new CliUsageException(sb.ToString()); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("'add-module' command is used to add a multi-package ABP module to a solution."); |
||||
|
sb.AppendLine("It should be used in a folder containing a .sln file."); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(" abp add-module <module-name> [-s|--solution]"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(" -s|--solution <solution-file> Specify the solution file explicitly."); |
||||
|
sb.AppendLine(" --skip-db-migrations <boolean> Specify if a new migration will be added or not."); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Examples:"); |
||||
|
sb.AppendLine(" abp add-module Volo.Blogging Adds the module to the current soluton."); |
||||
|
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore Adds the module to the given soluton."); |
||||
|
sb.AppendLine(" abp add-module Volo.Blogging -s Acme.BookStore --skip-db-migrations false Adds the module to the given soluton but doesn't add-migration."); |
||||
|
sb.AppendLine(""); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
public static class Options |
||||
|
{ |
||||
|
public static class Solution |
||||
|
{ |
||||
|
public const string Short = "s"; |
||||
|
public const string Long = "solution"; |
||||
|
} |
||||
|
|
||||
|
public static class DbMigrations |
||||
|
{ |
||||
|
public const string Skip = "skip-db-migrations"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,110 @@ |
|||||
|
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.ProjectModification; |
||||
|
using Volo.Abp.Cli.Utils; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class AddPackageCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<AddPackageCommand> Logger { get; set; } |
||||
|
|
||||
|
protected ProjectNugetPackageAdder ProjectNugetPackageAdder { get; } |
||||
|
|
||||
|
public AddPackageCommand(ProjectNugetPackageAdder projectNugetPackageAdder) |
||||
|
{ |
||||
|
ProjectNugetPackageAdder = projectNugetPackageAdder; |
||||
|
Logger = NullLogger<AddPackageCommand>.Instance; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
if (commandLineArgs.Target == null) |
||||
|
{ |
||||
|
throw new CliUsageException("Package name is missing!" + Environment.NewLine + Environment.NewLine + GetUsageInfo()); |
||||
|
} |
||||
|
|
||||
|
await ProjectNugetPackageAdder.AddAsync( |
||||
|
GetProjectFile(commandLineArgs), |
||||
|
commandLineArgs.Target |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetProjectFile(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var providedProjectFile = PathHelper.NormalizePath( |
||||
|
commandLineArgs.Options.GetOrNull( |
||||
|
Options.Project.Short, |
||||
|
Options.Project.Long |
||||
|
) |
||||
|
); |
||||
|
|
||||
|
if (!providedProjectFile.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return providedProjectFile; |
||||
|
} |
||||
|
|
||||
|
var foundProjectFiles = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj"); |
||||
|
if (foundProjectFiles.Length == 1) |
||||
|
{ |
||||
|
return foundProjectFiles[0]; |
||||
|
} |
||||
|
|
||||
|
if (foundProjectFiles.Length == 0) |
||||
|
{ |
||||
|
throw new CliUsageException("'abp add-package' command should be used inside a folder contaning a .csproj file!"); |
||||
|
} |
||||
|
|
||||
|
//foundProjectFiles.Length > 1
|
||||
|
|
||||
|
var sb = new StringBuilder("There are multiple project (.csproj) files in the current directory. Please specify one of the files below:"); |
||||
|
|
||||
|
foreach (var foundProjectFile in foundProjectFiles) |
||||
|
{ |
||||
|
sb.AppendLine("* " + foundProjectFile); |
||||
|
} |
||||
|
|
||||
|
sb.AppendLine("Example:"); |
||||
|
sb.AppendLine($"abp add-package {commandLineArgs.Target} -p {foundProjectFiles[0]}"); |
||||
|
|
||||
|
throw new CliUsageException(sb.ToString()); |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("'add-package' command is used to add an ABP package to a project."); |
||||
|
sb.AppendLine("It should be used in a folder containing a .csproj file."); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(" abp add-package <package-name> [-p|--project]"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(" -p|--project <project-file> Specify the project file explicitly."); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Examples:"); |
||||
|
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation Adds the package to the current project."); |
||||
|
sb.AppendLine(" abp add-package Volo.Abp.FluentValidation -p Acme.BookStore.Application Adds the package to the given project."); |
||||
|
sb.AppendLine(""); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
public static class Options |
||||
|
{ |
||||
|
public static class Project |
||||
|
{ |
||||
|
public const string Short = "p"; |
||||
|
public const string Long = "project"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Net.Http; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.NuGet |
||||
|
{ |
||||
|
public class NuGetService : ISingletonDependency |
||||
|
{ |
||||
|
protected IJsonSerializer JsonSerializer { get; } |
||||
|
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
||||
|
|
||||
|
public NuGetService( |
||||
|
IJsonSerializer jsonSerializer, |
||||
|
ICancellationTokenProvider cancellationTokenProvider) |
||||
|
{ |
||||
|
JsonSerializer = jsonSerializer; |
||||
|
CancellationTokenProvider = cancellationTokenProvider; |
||||
|
} |
||||
|
|
||||
|
public async Task<string> GetLatestVersionOrNullAsync(string packageId, bool includePreviews = false) |
||||
|
{ |
||||
|
using (var client = new HttpClient()) |
||||
|
{ |
||||
|
client.Timeout = TimeSpan.FromSeconds(30); |
||||
|
|
||||
|
var responseMessage = await client.GetAsync( |
||||
|
$"https://api.nuget.org/v3-flatcontainer/{packageId.ToLowerInvariant()}/index.json", |
||||
|
CancellationTokenProvider.Token |
||||
|
); |
||||
|
|
||||
|
if (!responseMessage.IsSuccessStatusCode) |
||||
|
{ |
||||
|
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); |
||||
|
} |
||||
|
|
||||
|
var result = await responseMessage.Content.ReadAsStringAsync(); |
||||
|
|
||||
|
var versions = JsonSerializer.Deserialize<NuGetVersionResultDto>(result).Versions; |
||||
|
|
||||
|
if (!includePreviews) |
||||
|
{ |
||||
|
versions = versions |
||||
|
.Where(x => !x.Contains("beta") && !x.Contains("preview") && !x.Contains("alpha") && !x.Contains("rc")) |
||||
|
.ToList(); |
||||
|
} |
||||
|
|
||||
|
return versions.Count > 0 ? versions.Last() : null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class NuGetVersionResultDto |
||||
|
{ |
||||
|
[JsonProperty("versions")] |
||||
|
public List<string> Versions { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,159 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Net.Http; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http; |
||||
|
using Volo.Abp.IO; |
||||
|
using Volo.Abp.Json; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding |
||||
|
{ |
||||
|
public class AbpIoTemplateStore : ITemplateStore, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<AbpIoTemplateStore> Logger { get; set; } |
||||
|
|
||||
|
protected CliOptions Options { get; } |
||||
|
protected IJsonSerializer JsonSerializer { get; } |
||||
|
protected ICancellationTokenProvider CancellationTokenProvider { get; } |
||||
|
|
||||
|
public AbpIoTemplateStore( |
||||
|
IOptions<CliOptions> options, |
||||
|
IJsonSerializer jsonSerializer, |
||||
|
ICancellationTokenProvider cancellationTokenProvider) |
||||
|
{ |
||||
|
JsonSerializer = jsonSerializer; |
||||
|
CancellationTokenProvider = cancellationTokenProvider; |
||||
|
Options = options.Value; |
||||
|
|
||||
|
Logger = NullLogger<AbpIoTemplateStore>.Instance; |
||||
|
} |
||||
|
|
||||
|
public async Task<TemplateFile> GetAsync( |
||||
|
string name, |
||||
|
DatabaseProvider databaseProvider, |
||||
|
string projectName, |
||||
|
string version = null) |
||||
|
{ |
||||
|
if (version == null) |
||||
|
{ |
||||
|
version = await GetLatestTemplateVersionAsync(name); |
||||
|
} |
||||
|
|
||||
|
DirectoryHelper.CreateIfNotExists(CliPaths.TemplateCache); |
||||
|
|
||||
|
var localCacheFile = Path.Combine(CliPaths.TemplateCache, name + "-" + version + ".zip"); |
||||
|
if (File.Exists(localCacheFile)) |
||||
|
{ |
||||
|
Logger.LogInformation("Using cached template: " + name + ", version: " + version); |
||||
|
return new TemplateFile(File.ReadAllBytes(localCacheFile), version); |
||||
|
} |
||||
|
|
||||
|
Logger.LogInformation("Downloading template: " + name + ", version: " + version); |
||||
|
|
||||
|
var fileContent = await DownloadTemplateFileContentAsync( |
||||
|
new TemplateDownloadInputDto |
||||
|
{ |
||||
|
Name = name, |
||||
|
Version = version, |
||||
|
DatabaseProvider = databaseProvider.ToString(), |
||||
|
ProjectName = projectName |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
File.WriteAllBytes(localCacheFile, fileContent); |
||||
|
|
||||
|
return new TemplateFile(fileContent, version); |
||||
|
} |
||||
|
|
||||
|
private async Task<string> GetLatestTemplateVersionAsync(string name) |
||||
|
{ |
||||
|
var postData = JsonSerializer.Serialize(new GetLatestTemplateVersionDto { Name = name }); |
||||
|
|
||||
|
using (var client = new HttpClient()) |
||||
|
{ |
||||
|
client.Timeout = TimeSpan.FromSeconds(30); |
||||
|
|
||||
|
AddAuthentication(client); |
||||
|
|
||||
|
var responseMessage = await client.PostAsync( |
||||
|
Options.AbpIoWwwUrlRoot + "api/download/template/get-version/", |
||||
|
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), |
||||
|
CancellationTokenProvider.Token |
||||
|
); |
||||
|
|
||||
|
if (!responseMessage.IsSuccessStatusCode) |
||||
|
{ |
||||
|
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); |
||||
|
} |
||||
|
|
||||
|
var result = await responseMessage.Content.ReadAsStringAsync(); |
||||
|
return JsonSerializer.Deserialize<GetLatestTemplateVersionResultDto>(result).Version; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task<byte[]> DownloadTemplateFileContentAsync(TemplateDownloadInputDto input) |
||||
|
{ |
||||
|
var postData = JsonSerializer.Serialize(input); |
||||
|
|
||||
|
using (var client = new HttpClient()) |
||||
|
{ |
||||
|
client.Timeout = TimeSpan.FromMinutes(3); |
||||
|
|
||||
|
AddAuthentication(client); |
||||
|
|
||||
|
var responseMessage = await client.PostAsync( |
||||
|
Options.AbpIoWwwUrlRoot + "api/download/template/", |
||||
|
new StringContent(postData, Encoding.UTF8, MimeTypes.Application.Json), |
||||
|
CancellationTokenProvider.Token |
||||
|
); |
||||
|
|
||||
|
if (!responseMessage.IsSuccessStatusCode) |
||||
|
{ |
||||
|
throw new Exception("Remote server returns error! HTTP status code: " + responseMessage.StatusCode); |
||||
|
} |
||||
|
|
||||
|
return await responseMessage.Content.ReadAsByteArrayAsync(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static void AddAuthentication(HttpClient client) |
||||
|
{ |
||||
|
if (File.Exists(CliPaths.AccessToken)) |
||||
|
{ |
||||
|
var accessToken = File.ReadAllText(CliPaths.AccessToken, Encoding.UTF8); |
||||
|
if (!accessToken.IsNullOrEmpty()) |
||||
|
{ |
||||
|
client.SetBearerToken(accessToken); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class TemplateDownloadInputDto |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string Version { get; set; } |
||||
|
|
||||
|
public string DatabaseProvider { get; set; } |
||||
|
|
||||
|
public string ProjectName { get; set; } |
||||
|
} |
||||
|
|
||||
|
public class GetLatestTemplateVersionDto |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
|
|
||||
|
public class GetLatestTemplateVersionResultDto |
||||
|
{ |
||||
|
public string Version { get; set; } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,4 +1,4 @@ |
|||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public enum DatabaseProvider |
public enum DatabaseProvider |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using System; |
using System; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public class GithubRepositoryInfo |
public class GithubRepositoryInfo |
||||
{ |
{ |
||||
@ -1,8 +1,8 @@ |
|||||
using System; |
using System; |
||||
using System.Linq; |
using System.Linq; |
||||
using Volo.Abp.ProjectBuilding.Files; |
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public static class ProjectBuildContextExtensions |
public static class ProjectBuildContextExtensions |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public class ProjectBuildPipeline |
public class ProjectBuildPipeline |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.ProjectBuilding.Building.Steps; |
using Volo.Abp.Cli.ProjectBuilding.Building.Steps; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public static class ProjectBuildPipelineBuilder |
public static class ProjectBuildPipelineBuilder |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public abstract class ProjectBuildPipelineStep |
public abstract class ProjectBuildPipelineStep |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace Volo.Abp.ProjectBuilding.Building |
namespace Volo.Abp.Cli.ProjectBuilding.Building |
||||
{ |
{ |
||||
public class ProjectResult |
public class ProjectResult |
||||
{ |
{ |
||||
@ -0,0 +1,35 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
|
{ |
||||
|
public class ChangeLocalhostPortStep : ProjectBuildPipelineStep |
||||
|
{ |
||||
|
public string LaunchSettingsFilePath { get; } |
||||
|
public int[] PortNumbers { get; } |
||||
|
|
||||
|
public ChangeLocalhostPortStep( |
||||
|
string launchSettingsFilePath, |
||||
|
params int[] portNumbers) |
||||
|
{ |
||||
|
Check.NotNullOrEmpty(portNumbers, nameof(portNumbers)); |
||||
|
|
||||
|
LaunchSettingsFilePath = launchSettingsFilePath; |
||||
|
PortNumbers = portNumbers; |
||||
|
} |
||||
|
|
||||
|
public override void Execute(ProjectBuildContext context) |
||||
|
{ |
||||
|
var launchSettings = context.GetFile(LaunchSettingsFilePath); |
||||
|
var randomPort = RandomHelper.GetRandom(50001, 59990); |
||||
|
var newContent = launchSettings.Content; |
||||
|
|
||||
|
for (var i = 0; i < PortNumbers.Length; i++) |
||||
|
{ |
||||
|
newContent = newContent.Replace( |
||||
|
PortNumbers[i].ToString(), |
||||
|
(randomPort + i).ToString() |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
launchSettings.SetContent(newContent); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,8 +1,8 @@ |
|||||
using Ionic.Zip; |
using Ionic.Zip; |
||||
using Volo.Abp.ProjectBuilding.Files; |
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
using Volo.Abp.ProjectBuilding.Zipping; |
using Volo.Abp.Cli.ProjectBuilding.Zipping; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building.Steps |
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
{ |
{ |
||||
public class CreateProjectResultZipStep : ProjectBuildPipelineStep |
public class CreateProjectResultZipStep : ProjectBuildPipelineStep |
||||
{ |
{ |
||||
@ -1,9 +1,9 @@ |
|||||
using System.IO; |
using System.IO; |
||||
using Ionic.Zip; |
using Ionic.Zip; |
||||
using Volo.Abp.ProjectBuilding.Files; |
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
using Volo.Abp.ProjectBuilding.Zipping; |
using Volo.Abp.Cli.ProjectBuilding.Zipping; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building.Steps |
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
{ |
{ |
||||
public class FileEntryListReadStep : ProjectBuildPipelineStep |
public class FileEntryListReadStep : ProjectBuildPipelineStep |
||||
{ |
{ |
||||
@ -1,9 +1,9 @@ |
|||||
using System; |
using System; |
||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
using System.Linq; |
using System.Linq; |
||||
using Volo.Abp.ProjectBuilding.Files; |
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building.Steps |
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
{ |
{ |
||||
public class SolutionRenameStep : ProjectBuildPipelineStep |
public class SolutionRenameStep : ProjectBuildPipelineStep |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.ProjectBuilding.Files; |
using Volo.Abp.Cli.ProjectBuilding.Files; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Building.Steps |
namespace Volo.Abp.Cli.ProjectBuilding.Building.Steps |
||||
{ |
{ |
||||
public class TemplateCodeDeleteStep : ProjectBuildPipelineStep |
public class TemplateCodeDeleteStep : ProjectBuildPipelineStep |
||||
{ |
{ |
||||
@ -1,9 +1,9 @@ |
|||||
using System.ComponentModel.DataAnnotations; |
using System.ComponentModel.DataAnnotations; |
||||
using System.ComponentModel.DataAnnotations.Schema; |
using System.ComponentModel.DataAnnotations.Schema; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
using Volo.Abp.Domain.Entities.Auditing; |
using Volo.Abp.Domain.Entities.Auditing; |
||||
using Volo.Abp.ProjectBuilding.Building; |
|
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
[Table("Downloads")] |
[Table("Downloads")] |
||||
public class DownloadInfo : CreationAuditedAggregateRoot<int> |
public class DownloadInfo : CreationAuditedAggregateRoot<int> |
||||
@ -1,6 +1,6 @@ |
|||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Files |
namespace Volo.Abp.Cli.ProjectBuilding.Files |
||||
{ |
{ |
||||
public static class FileEntryExtensions |
public static class FileEntryExtensions |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using System.Collections.Generic; |
using System.Collections.Generic; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Files |
namespace Volo.Abp.Cli.ProjectBuilding.Files |
||||
{ |
{ |
||||
public class FileEntryList : List<FileEntry> |
public class FileEntryList : List<FileEntry> |
||||
{ |
{ |
||||
@ -1,7 +1,7 @@ |
|||||
using System; |
using System; |
||||
using Ionic.Zip; |
using Ionic.Zip; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Files |
namespace Volo.Abp.Cli.ProjectBuilding.Files |
||||
{ |
{ |
||||
public static class FileEntryListExtensions |
public static class FileEntryListExtensions |
||||
{ |
{ |
||||
@ -1,7 +1,7 @@ |
|||||
using System; |
using System; |
||||
using Newtonsoft.Json; |
using Newtonsoft.Json; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Github |
namespace Volo.Abp.Cli.ProjectBuilding.Github |
||||
{ |
{ |
||||
[JsonObject] |
[JsonObject] |
||||
public class GithubRelease |
public class GithubRelease |
||||
@ -1,6 +1,6 @@ |
|||||
using System.Threading.Tasks; |
using System.Threading.Tasks; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public interface IProjectBuilder |
public interface IProjectBuilder |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.ProjectBuilding.Building; |
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public interface ITemplateInfoProvider |
public interface ITemplateInfoProvider |
||||
{ |
{ |
||||
@ -0,0 +1,16 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectBuilding |
||||
|
{ |
||||
|
public interface ITemplateStore |
||||
|
{ |
||||
|
Task<TemplateFile> GetAsync( |
||||
|
string name, |
||||
|
DatabaseProvider databaseProvider, |
||||
|
string projectName, |
||||
|
[CanBeNull] string version = null |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,7 @@ |
|||||
using JetBrains.Annotations; |
using JetBrains.Annotations; |
||||
using Volo.Abp.ProjectBuilding.Building; |
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public class ProjectBuildArgs |
public class ProjectBuildArgs |
||||
{ |
{ |
||||
@ -1,4 +1,4 @@ |
|||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public class ProjectBuildResult |
public class ProjectBuildResult |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using System; |
using System; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public class SolutionName |
public class SolutionName |
||||
{ |
{ |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectBuilding |
||||
|
{ |
||||
|
public class TemplateFile |
||||
|
{ |
||||
|
public string Version { get; } |
||||
|
|
||||
|
public byte[] FileBytes { get; } |
||||
|
|
||||
|
public TemplateFile(byte[] fileBytes, string version) |
||||
|
{ |
||||
|
FileBytes = fileBytes; |
||||
|
Version = version; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,23 +1,23 @@ |
|||||
using System; |
using System; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
using Volo.Abp.Cli.ProjectBuilding.Templates; |
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.ProjectBuilding.Building; |
|
||||
using Volo.Abp.ProjectBuilding.Templates; |
|
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding |
namespace Volo.Abp.Cli.ProjectBuilding |
||||
{ |
{ |
||||
public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency |
public class TemplateInfoProvider : ITemplateInfoProvider, ITransientDependency |
||||
{ |
{ |
||||
public TemplateInfo GetDefault() |
public TemplateInfo GetDefault() |
||||
{ |
{ |
||||
return Get(MvcApplicationTemplate.TemplateName); |
return Get(MvcTemplate.TemplateName); |
||||
} |
} |
||||
|
|
||||
public TemplateInfo Get(string name) |
public TemplateInfo Get(string name) |
||||
{ |
{ |
||||
switch (name) |
switch (name) |
||||
{ |
{ |
||||
case MvcApplicationTemplate.TemplateName: |
case MvcTemplate.TemplateName: |
||||
return new MvcApplicationTemplate(); |
return new MvcTemplate(); |
||||
case MvcModuleTemplate.TemplateName: |
case MvcModuleTemplate.TemplateName: |
||||
return new MvcModuleTemplate(); |
return new MvcModuleTemplate(); |
||||
case ServiceTemplate.TemplateName: |
case ServiceTemplate.TemplateName: |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.ProjectBuilding.Building; |
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Templates |
namespace Volo.Abp.Cli.ProjectBuilding.Templates |
||||
{ |
{ |
||||
public class MvcModuleTemplate : TemplateInfo |
public class MvcModuleTemplate : TemplateInfo |
||||
{ |
{ |
||||
@ -1,6 +1,6 @@ |
|||||
using Volo.Abp.ProjectBuilding.Building; |
using Volo.Abp.Cli.ProjectBuilding.Building; |
||||
|
|
||||
namespace Volo.Abp.ProjectBuilding.Templates |
namespace Volo.Abp.Cli.ProjectBuilding.Templates |
||||
{ |
{ |
||||
public class ServiceTemplate : TemplateInfo |
public class ServiceTemplate : TemplateInfo |
||||
{ |
{ |
||||
@ -0,0 +1,84 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class DbContextFileBuilderConfigureAdder : ITransientDependency |
||||
|
{ |
||||
|
public ILogger<DbContextFileBuilderConfigureAdder> Logger { get; set; } |
||||
|
|
||||
|
protected UsingStatementAdder UsingStatementAdder { get; } |
||||
|
|
||||
|
public DbContextFileBuilderConfigureAdder(UsingStatementAdder usingStatementAdder) |
||||
|
{ |
||||
|
UsingStatementAdder = usingStatementAdder; |
||||
|
Logger = NullLogger<DbContextFileBuilderConfigureAdder>.Instance; |
||||
|
} |
||||
|
|
||||
|
public void Add(string path, string moduleConfiguration) |
||||
|
{ |
||||
|
var file = File.ReadAllText(path); |
||||
|
|
||||
|
file = UsingStatementAdder.Add(file, GetNamespace(moduleConfiguration)); |
||||
|
|
||||
|
var stringToAdd = GetLineToAdd(moduleConfiguration); |
||||
|
if (!file.Contains(stringToAdd)) |
||||
|
{ |
||||
|
var indexToInsert = FindIndexToInsert(file); |
||||
|
|
||||
|
if (indexToInsert <= 0 || indexToInsert >= file.Length) |
||||
|
{ |
||||
|
Logger.LogWarning($"\"OnModelCreating(ModelBuilder builder)\" method couldn't be found in {path}"); |
||||
|
return; |
||||
|
} |
||||
|
file = file.Insert(indexToInsert, " " + stringToAdd + Environment.NewLine + " "); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
File.WriteAllText(path, file); |
||||
|
} |
||||
|
|
||||
|
protected int FindIndexToInsert(string file) |
||||
|
{ |
||||
|
var indexOfMethodDeclaration = file.IndexOf("OnModelCreating(", StringComparison.Ordinal); |
||||
|
var indexOfOpeningBracket = indexOfMethodDeclaration + file.Substring(indexOfMethodDeclaration).IndexOf('{'); |
||||
|
|
||||
|
var stack = 1; |
||||
|
var index = indexOfOpeningBracket; |
||||
|
|
||||
|
while (stack > 0) |
||||
|
{ |
||||
|
index++; |
||||
|
|
||||
|
if (index >= file.Length) |
||||
|
{ |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if (file[index] == '{') |
||||
|
{ |
||||
|
stack++; |
||||
|
} |
||||
|
else if (file[index] == '}') |
||||
|
{ |
||||
|
stack--; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
protected string GetLineToAdd(string moduleConfiguration) |
||||
|
{ |
||||
|
return "builder." + moduleConfiguration.Split(':')[1] + "();"; |
||||
|
} |
||||
|
|
||||
|
protected string GetNamespace(string moduleConfiguration) |
||||
|
{ |
||||
|
return string.Join(".", moduleConfiguration.Split(':')[0]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using Microsoft.CodeAnalysis.CSharp; |
||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class DerivedClassFinder : ITransientDependency |
||||
|
{ |
||||
|
public ILogger<DerivedClassFinder> Logger { get; set; } |
||||
|
|
||||
|
public DerivedClassFinder() |
||||
|
{ |
||||
|
Logger = NullLogger<DerivedClassFinder>.Instance; |
||||
|
} |
||||
|
|
||||
|
public virtual List<string> Find(string csprojFilePath, string baseClass) |
||||
|
{ |
||||
|
var moduleFilePaths = new List<string>(); |
||||
|
var csprojFileDirectory = Path.GetDirectoryName(csprojFilePath); |
||||
|
var binFile = Path.Combine(csprojFileDirectory, "bin"); |
||||
|
var objFile = Path.Combine(csprojFileDirectory, "obj"); |
||||
|
|
||||
|
|
||||
|
var csFiles = new DirectoryInfo(csprojFileDirectory) |
||||
|
.GetFiles("*.cs", SearchOption.AllDirectories) |
||||
|
.Where(f => !f.DirectoryName.StartsWith(binFile)) |
||||
|
.Where(f => !f.DirectoryName.StartsWith(objFile)) |
||||
|
.Select(f => f.FullName) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var csFile in csFiles) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (IsDerived(csFile, baseClass)) |
||||
|
{ |
||||
|
moduleFilePaths.Add(csFile); |
||||
|
} |
||||
|
} |
||||
|
catch (Exception) |
||||
|
{ |
||||
|
Logger.LogDebug($"Couldn't parse {csFile}."); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return moduleFilePaths; |
||||
|
} |
||||
|
|
||||
|
protected bool IsDerived(string csFile, string baseClass) |
||||
|
{ |
||||
|
Logger.LogDebug(csFile); |
||||
|
var root = CSharpSyntaxTree.ParseText(File.ReadAllText(csFile)).GetRoot(); |
||||
|
var namespaceSyntax = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>().First(); |
||||
|
var classDeclaration = (namespaceSyntax.DescendantNodes().OfType<ClassDeclarationSyntax>()).First(); |
||||
|
var baseTypeList = classDeclaration.BaseList?.Types.Select(t => t.ToString()).ToList(); |
||||
|
|
||||
|
if (baseTypeList == null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
foreach (var baseType in baseTypeList) |
||||
|
{ |
||||
|
if (baseType.Contains('<') && baseType.Substring(0, baseType.IndexOf('<')) == baseClass) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
if (baseType == baseClass) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
using System; |
||||
|
using System.Diagnostics; |
||||
|
using System.IO; |
||||
|
using Volo.Abp.Cli.Utils; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class EfCoreMigrationAdder : ITransientDependency |
||||
|
{ |
||||
|
public void AddMigration(string csprojFile, string module, bool updateDatabase = true) |
||||
|
{ |
||||
|
var moduleName = ParseModuleName(module); |
||||
|
var migrationName = "Added_" + moduleName + "_Module" + GetUniquePostFix(); |
||||
|
|
||||
|
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef migrations add " + migrationName); |
||||
|
|
||||
|
if (updateDatabase) |
||||
|
{ |
||||
|
UpdateDatabase(csprojFile); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected void UpdateDatabase(string csprojFile) |
||||
|
{ |
||||
|
CmdHelper.RunCmd("cd \"" + Path.GetDirectoryName(csprojFile) + "\" & dotnet ef database update"); |
||||
|
} |
||||
|
|
||||
|
protected virtual string ParseModuleName(string fullModuleName) |
||||
|
{ |
||||
|
var words = fullModuleName?.Split('.'); |
||||
|
|
||||
|
if (words == null || words.Length <= 1) |
||||
|
{ |
||||
|
return ""; |
||||
|
} |
||||
|
|
||||
|
return words[words.Length - 1]; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetUniquePostFix() |
||||
|
{ |
||||
|
return "_" + new Random().Next(1,99999); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class ModuleClassDependcyAdder : ITransientDependency |
||||
|
{ |
||||
|
protected UsingStatementAdder UsingStatementAdder { get; } |
||||
|
|
||||
|
public ModuleClassDependcyAdder(UsingStatementAdder usingStatementAdder) |
||||
|
{ |
||||
|
UsingStatementAdder = usingStatementAdder; |
||||
|
} |
||||
|
|
||||
|
public virtual void Add(string path, string module) |
||||
|
{ |
||||
|
ParseModuleNameAndNameSpace(module, out var nameSpace, out var moduleName); |
||||
|
|
||||
|
var file = File.ReadAllText(path); |
||||
|
|
||||
|
file = UsingStatementAdder.Add(file, nameSpace); |
||||
|
|
||||
|
if (!file.Contains(moduleName) ) |
||||
|
{ |
||||
|
file = InsertDependsOnAttribute(file, moduleName); |
||||
|
} |
||||
|
|
||||
|
File.WriteAllText(path, file); |
||||
|
} |
||||
|
|
||||
|
protected virtual string InsertDependsOnAttribute(string file, string moduleName) |
||||
|
{ |
||||
|
var indexOfPublicClassDeclaration = GetIndexOfWhereDependsOnWillBeAdded(file); |
||||
|
var dependsOnAttribute = GetDependsOnAttribute(moduleName); |
||||
|
|
||||
|
return file.Insert(indexOfPublicClassDeclaration, dependsOnAttribute); |
||||
|
} |
||||
|
|
||||
|
protected virtual int GetIndexOfWhereDependsOnWillBeAdded(string file) |
||||
|
{ |
||||
|
var indexOfPublicClassDeclaration = file.IndexOf("public class", StringComparison.Ordinal); |
||||
|
|
||||
|
if (indexOfPublicClassDeclaration < 0) |
||||
|
{ |
||||
|
throw new Exception("\"public class\" declaration not found!"); |
||||
|
} |
||||
|
|
||||
|
return indexOfPublicClassDeclaration; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetDependsOnAttribute(string moduleName) |
||||
|
{ |
||||
|
return "[DependsOn(typeof(" + moduleName + "))]" + Environment.NewLine + " "; |
||||
|
} |
||||
|
|
||||
|
protected virtual string GetUsingStatement(string nameSpace) |
||||
|
{ |
||||
|
return "using " + nameSpace + ";"; |
||||
|
} |
||||
|
|
||||
|
protected virtual void ParseModuleNameAndNameSpace(string module, out string nameSpace, out string moduleName) |
||||
|
{ |
||||
|
var words = module?.Split('.'); |
||||
|
|
||||
|
if (words == null || words.Length <= 1) |
||||
|
{ |
||||
|
nameSpace = null; |
||||
|
moduleName = module; |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
moduleName = words[words.Length - 1]; |
||||
|
nameSpace = string.Join(".", words.Take(words.Length - 1)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class ModuleInfo |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public string EfCoreConfigureMethodName { get; set; } |
||||
|
|
||||
|
public List<NugetPackageInfo> NugetPackages { get; set; } |
||||
|
|
||||
|
public List<NpmPackageInfo> NpmPackages { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
[Flags] |
||||
|
public enum NpmApplicationType |
||||
|
{ |
||||
|
Mvc = 1 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class NpmPackageInfo |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public NpmApplicationType ApplicationType { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public class NugetPackageInfo |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public string ModuleClass { get; set; } |
||||
|
|
||||
|
public NuGetPackageTarget Target { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public enum NuGetPackageTarget : byte |
||||
|
{ |
||||
|
DomainShared = 1, |
||||
|
Domain = 2, |
||||
|
ApplicationContracts = 3, |
||||
|
Application = 4, |
||||
|
HttpApi = 5, |
||||
|
HttpApiClient = 6, |
||||
|
Web = 7, |
||||
|
EntityFrameworkCore = 8, |
||||
|
MongoDB = 9 |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,133 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace Volo.Abp.Cli.ProjectModification |
||||
|
{ |
||||
|
public static class ProjectFinder |
||||
|
{ |
||||
|
public static string FindNuGetTargetProjectFile(string[] projectFiles, NuGetPackageTarget target) |
||||
|
{ |
||||
|
if (!projectFiles.Any()) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var assemblyNames = GetAssemblyNames(projectFiles); |
||||
|
|
||||
|
switch (target) |
||||
|
{ |
||||
|
case NuGetPackageTarget.Web: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".Web"); |
||||
|
case NuGetPackageTarget.EntityFrameworkCore: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".EntityFrameworkCore"); |
||||
|
case NuGetPackageTarget.MongoDB: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".MongoDB"); |
||||
|
case NuGetPackageTarget.Application: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".Application") ?? |
||||
|
FindProjectEndsWith(projectFiles, assemblyNames, ".Web"); |
||||
|
case NuGetPackageTarget.ApplicationContracts: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".Application.Contracts"); |
||||
|
case NuGetPackageTarget.Domain: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".Domain") ?? |
||||
|
FindProjectEndsWith(projectFiles, assemblyNames, ".Application") ?? |
||||
|
FindProjectEndsWith(projectFiles, assemblyNames, ".Web"); |
||||
|
case NuGetPackageTarget.DomainShared: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".Domain.Shared"); |
||||
|
case NuGetPackageTarget.HttpApi: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi"); |
||||
|
case NuGetPackageTarget.HttpApiClient: |
||||
|
return FindProjectEndsWith(projectFiles, assemblyNames, ".HttpApi.Client"); |
||||
|
default: |
||||
|
throw new ApplicationException($"{nameof(NuGetPackageTarget)}.{target} has not implemented!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static string[] FindNpmTargetProjectFile(string[] projectFiles) |
||||
|
{ |
||||
|
if (!projectFiles.Any()) |
||||
|
{ |
||||
|
return Array.Empty<string>(); |
||||
|
} |
||||
|
|
||||
|
var assemblyNames = GetAssemblyNames(projectFiles); |
||||
|
|
||||
|
var projects = new List<string>(); |
||||
|
|
||||
|
var project = FindProjectEndsWith(projectFiles, assemblyNames, ".Web.Host"); |
||||
|
if (project != null) |
||||
|
{ |
||||
|
projects.Add(project); |
||||
|
} |
||||
|
|
||||
|
project = FindProjectEndsWith(projectFiles, assemblyNames, ".Host", ".HttpApi.Host"); |
||||
|
if (project != null) |
||||
|
{ |
||||
|
projects.Add(project); |
||||
|
} |
||||
|
|
||||
|
if (projects.Any()) |
||||
|
{ |
||||
|
return projects.ToArray(); |
||||
|
} |
||||
|
|
||||
|
project = FindProjectEndsWith(projectFiles, assemblyNames, ".Web"); |
||||
|
if (project != null) |
||||
|
{ |
||||
|
projects.Add(project); |
||||
|
} |
||||
|
|
||||
|
return projects.ToArray(); |
||||
|
} |
||||
|
|
||||
|
public static string[] GetProjectFiles(string solutionFile) |
||||
|
{ |
||||
|
var baseProjectFolder = GetBaseProjectFolder(solutionFile); |
||||
|
return Directory.GetFiles(baseProjectFolder, "*.csproj", SearchOption.AllDirectories); |
||||
|
} |
||||
|
|
||||
|
public static string[] GetAssemblyNames(string[] projectFiles) |
||||
|
{ |
||||
|
return projectFiles.Select(GetAssemblyName).ToArray(); |
||||
|
} |
||||
|
|
||||
|
public static string GetAssemblyName(string projectFile) |
||||
|
{ |
||||
|
return projectFile |
||||
|
.Substring(projectFile.LastIndexOf(Path.DirectorySeparatorChar) + 1) |
||||
|
.RemovePostFix(StringComparison.OrdinalIgnoreCase, ".csproj"); |
||||
|
} |
||||
|
|
||||
|
private static string FindProjectEndsWith( |
||||
|
string[] projectFiles, |
||||
|
string[] assemblyNames, |
||||
|
string postfix, |
||||
|
string excludePostfix = null) |
||||
|
{ |
||||
|
for (var i = 0; i < assemblyNames.Length; i++) |
||||
|
{ |
||||
|
var assemblyName = assemblyNames[i]; |
||||
|
if(assemblyName.EndsWith(postfix, StringComparison.OrdinalIgnoreCase) && |
||||
|
(excludePostfix == null || !assemblyName.EndsWith(excludePostfix))) |
||||
|
{ |
||||
|
return projectFiles[i]; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static string GetBaseProjectFolder(string solutionFile) |
||||
|
{ |
||||
|
var baseFolder = Path.GetDirectoryName(solutionFile); |
||||
|
var srcFolder = Path.Combine(baseFolder, "src"); |
||||
|
if (Directory.Exists(srcFolder)) |
||||
|
{ |
||||
|
baseFolder = srcFolder; |
||||
|
} |
||||
|
|
||||
|
return baseFolder; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue