Make mustache config self contained

This commit is contained in:
Hananiel Sarella 2019-07-17 19:07:41 -04:00
Родитель b719e93176
Коммит 5718add9a2
38 изменённых файлов: 1002 добавлений и 596 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,5 +1,6 @@
.vs
.vscode
.idea
bin
obj
node_modules

Просмотреть файл

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with NO BOM" />
</project>

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="com.jetbrains.rider.android.RiderAndroidMiscFileCreationComponent">
<option name="ENSURE_MISC_FILE_EXISTS" value="true" />
</component>
</project>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

Просмотреть файл

@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.329
MinimumVisualStudioVersion = 15.0.26124.0
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Initializr.Tests", "tests\Steeltoe.Initializr.Tests.csproj", "{E1CCB76F-904D-4B24-BF5F-B3B7DF9897C9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.Initializr", "src\Steeltoe.Initializr.csproj", "{945A8C33-08A6-4D07-A3B6-51D7802A4DC0}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{42A583D3-DB7F-49E9-A89B-58FE16391C6C}"
@ -13,20 +11,22 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{42A583
stylecop.json = stylecop.json
EndProjectSection
EndProject
Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "Steeltoe.Initializr.Tests", "tests\Steeltoe.Initializr.Tests.csproj", "{69971BFE-F4F4-42D2-8AC8-6D9723EBE09F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E1CCB76F-904D-4B24-BF5F-B3B7DF9897C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1CCB76F-904D-4B24-BF5F-B3B7DF9897C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1CCB76F-904D-4B24-BF5F-B3B7DF9897C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1CCB76F-904D-4B24-BF5F-B3B7DF9897C9}.Release|Any CPU.Build.0 = Release|Any CPU
{945A8C33-08A6-4D07-A3B6-51D7802A4DC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{945A8C33-08A6-4D07-A3B6-51D7802A4DC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{945A8C33-08A6-4D07-A3B6-51D7802A4DC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{945A8C33-08A6-4D07-A3B6-51D7802A4DC0}.Release|Any CPU.Build.0 = Release|Any CPU
{69971BFE-F4F4-42D2-8AC8-6D9723EBE09F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{69971BFE-F4F4-42D2-8AC8-6D9723EBE09F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{69971BFE-F4F4-42D2-8AC8-6D9723EBE09F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{69971BFE-F4F4-42D2-8AC8-6D9723EBE09F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -0,0 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Initializr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=steeltoe/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xunit/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

Просмотреть файл

@ -0,0 +1,13 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNotificationDisabled/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Method/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Parameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Locals/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=Property/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/AutoDetectedNamingRules/=LocalFunctions/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpNaming/ApplyAutoDetectedRules/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeStyle/Naming/CSharpAutoNaming/IsNamingAutoDetectionCompleted/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>

Просмотреть файл

@ -14,11 +14,9 @@
using Microsoft.AspNetCore.Mvc;
using Steeltoe.Initializr.Models;
using Steeltoe.Initializr.Services;
using System;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.Initializr.Services.Mustache;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http.Headers;
using System.Threading.Tasks;
@ -35,7 +33,7 @@ namespace Steeltoe.Initializr.Controllers
public TemplatesController(IEnumerable<ITemplateService> services)
{
// _templateService = services.OfType<TemplateService>().FirstOrDefault();
_sttemplateService = services.OfType<MustacheTemplateService>().FirstOrDefault(); ;
_sttemplateService = services.OfType<MustacheTemplateService>().FirstOrDefault();
}
[Route("/starter.zip")]
@ -76,24 +74,17 @@ namespace Steeltoe.Initializr.Controllers
public ActionResult<IEnumerable<TemplateViewModel>> GetTemplates([FromQuery(Name = "Mustache")] bool useMustache)
{
return _sttemplateService.GetAvailableTemplates();
//: _templateService.GetAvailableTemplates();
}
private async Task<ActionResult> GenerateProject(GeneratorModel model)
{
//var list = _sttemplateService.GetAvailableTemplates();
//if (list == null || !list.Any(x => x.ShortName.ToLower() == model.TemplateShortName.ToLower()))
//{
// return NotFound($"Template {model.TemplateShortName} was not found");
//}
//model.TemplateShortName = string.Empty;
var archiveBytes = await _sttemplateService.GenerateProjectArchive(model);
var archiveBytes = await _sttemplateService.GenerateProjectArchiveAsync(model);
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = model.ArchiveName,
};
Response.Headers.Add("Content-Disposition", cd.ToString());
return File(archiveBytes, "application/zip");
@ -101,7 +92,7 @@ namespace Steeltoe.Initializr.Controllers
private ActionResult GenerateProject2(GeneratorModel model)
{
var fileBytes = _sttemplateService.GenerateProjectArchive(model).Result;
var fileBytes = _sttemplateService.GenerateProjectArchiveAsync(model).Result;
var cd = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = (model.ProjectName ?? "SteeltoeProject") + ".zip",

Просмотреть файл

@ -21,7 +21,6 @@ namespace Steeltoe.Initializr.Models
public class GeneratorModel
{
private string[] _dependencies;
private string _templateShortName;
private string _projectName;
public string[] Dependencies
@ -30,31 +29,15 @@ namespace Steeltoe.Initializr.Models
set => _dependencies = (value == null || value.Length == 0 || value[0] == null) ? null : value[0].ToLower().Split(',');
}
public string ProjectName { get => _projectName ?? "steeltoeProject" ; set => _projectName = value; }
public string ProjectName { get => _projectName ?? "steeltoeProject"; set => _projectName = value; }
public string TemplateShortName
{
get
{
// _templateShortName = _templateShortName ?? DEFAULT_TEMPLATE;
//if (SteeltoeVersion == "3.0")
//{
// _templateShortName = "steeltoe";
//}
return _templateShortName;
}
set => _templateShortName = value;
}
public string TemplateShortName { get; set; }
public string Description { get; set; }
public string SteeltoeVersion { get; set; }
public string ArchiveName
{
get => ProjectName + ".zip";
}
public string ArchiveName => ProjectName + ".zip";
public string TargetFrameworkVersion { get; set; }
@ -64,7 +47,7 @@ namespace Steeltoe.Initializr.Models
if (!string.IsNullOrEmpty(SteeltoeVersion) && SteeltoeVersion != "3.0")
{
templateParameters.Add($"SteeltoeVersion={SteeltoeVersion}");
templateParameters?.Add($"SteeltoeVersion={SteeltoeVersion}");
}
return templateParameters ?? new List<string>();

Просмотреть файл

@ -1,20 +0,0 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Steeltoe.Initializr.Services
{
internal class IEnumerable<T1, T2>
{
}
}

Просмотреть файл

@ -1,341 +0,0 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Steeltoe.Initializr.Models;
using Stubble.Core;
using Stubble.Core.Builders;
using Stubble.Extensions.JsonNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Steeltoe.Initializr.Services
{
public class MustacheTemplateService : ITemplateService
{
private const string DEFAULT_TEMPLATE_NAME = "CSharp-WebApi-2.x";
public Dictionary<string, string> FriendlyNames { get; set; }
private StubbleVisitorRenderer _stubble;
private ILogger<MustacheTemplateService> _logger;
private string _templatePath;
private class Account
{
public string Email { get; set; }
public Func<string, object> MyLambda { get; set; }
}
public MustacheTemplateService(ILogger<MustacheTemplateService> logger, IConfiguration configuration)
: this(logger)
{
configuration.Bind(this); // Get friendlyNames
}
public MustacheTemplateService(ILogger<MustacheTemplateService> logger)
{
_stubble = new StubbleBuilder()
.Configure(settings => settings.AddJsonNet())
.Build();
_logger = logger;
_templatePath = AppDomain.CurrentDomain.BaseDirectory + "templates" + Path.DirectorySeparatorChar + "Mustache";
}
public async Task<byte[]> GenerateProjectArchive(GeneratorModel model)
{
byte[] archiveBytes;
List<KeyValuePair<string, string>> listoffiles = GenerateProjectFiles(model);
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var entry in listoffiles)
{
_logger.LogDebug(entry.Key);
var ef = archive.CreateEntry(entry.Key, CompressionLevel.Optimal);
using (var entryStream = ef.Open())
using (var fileToCompress = new MemoryStream(Encoding.UTF8.GetBytes(entry.Value)))
{
fileToCompress.CopyTo(entryStream);
}
}
}
archiveBytes = memoryStream.ToArray();
}
return archiveBytes;
}
public List<KeyValuePair<string, string>> GenerateProjectFiles(GeneratorModel model)
{
var name = string.IsNullOrEmpty(model.TemplateShortName) ? DEFAULT_TEMPLATE_NAME : model.TemplateShortName;
var templatePath = _templatePath + Path.DirectorySeparatorChar + name;
if (!Directory.Exists(templatePath))
{
throw new InvalidDataException("Template with $name doesnt exist");
}
var dataView = GetDataView(templatePath, model);
CalculatedFields(dataView, model.ProjectName);
var listoffiles = new List<KeyValuePair<string, string>>();
foreach (var file in GetFilteredSourceSets(dataView, templatePath))
{
if (file.EndsWith("mustache.json")
|| file.EndsWith("sourceExclusions.json"))
{
continue;
}
var pathPrefix = file.Replace(Path.GetFullPath(templatePath), string.Empty).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
string fileText = File.ReadAllText(file);
if (file.EndsWith(".csproj"))
{
pathPrefix = pathPrefix.Replace("ReplaceMe", model.ProjectName ?? "SteeltoeExample"); // get from model
var output = Render(file, fileText, dataView);
listoffiles.Add(new KeyValuePair<string, string>(pathPrefix, output));
}
else
{
var output = Render(file, fileText, dataView);
listoffiles.Add(new KeyValuePair<string, string>(pathPrefix, output));
}
}
return listoffiles;
}
private IEnumerable<string> GetFilteredSourceSets(Dictionary<string, string> dataView, string templatePath)
{
var files = Directory.EnumerateFiles(templatePath, "*", SearchOption.AllDirectories);
var json = File.ReadAllText(Path.Combine(templatePath, "sourceExclusions.json"));
IDictionary<string, string> allExclusions = JsonConvert.DeserializeObject<IDictionary<string, string>>(json);
var applicableExclusions = allExclusions.Where(x => !dataView.ContainsKey(x.Key) || dataView[x.Key] != "true");
var exclusionFiles = new List<string>();
foreach (string file in files)
{
var pathPrefix = file.Replace(Path.GetFullPath(templatePath), string.Empty).TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var exclusion in applicableExclusions)
{
var exclusionExpression = exclusion.Value;
if (exclusionExpression.EndsWith("**"))
{
if (pathPrefix.StartsWith(exclusionExpression.Replace("/**", string.Empty)))
{
exclusionFiles.Add(file);
}
}
else // exact Match
{
if (pathPrefix == exclusionExpression)
{
exclusionFiles.Add(file);
}
}
}
}
return files.Where(f => !exclusionFiles.Any(e => e == f));
}
private void CalculatedFields(Dictionary<string, string> dataView, string projectName)
{
// Add Calculated deps
if (dataView["Actuators"] == "true" || dataView["CloudFoundry"] == "true")
{
dataView.Add("ActuatorsOrCloudFoundry", "true");
}
if (dataView["MySql"] == "true" || dataView["MySqlEFCore"] == "true")
{
dataView.Add("MySqlOrMySqlEFCore", "true");
}
if (dataView["Actuators"] == "true" || dataView["DynamicLogger"] == "true")
{
dataView.Add("ActuatorsOrDynamicLogger", "true");
}
if (dataView["SQLServer"] == "true" || dataView["MySqlEFCore"] == "true")
{
dataView.Add("AnyEFCore", "true");
}
if (dataView["MySql"] == "true"
|| dataView["Postgres"] == "true"
|| dataView["Redis"] == "true"
|| dataView["MongoDB"] == "true"
|| dataView["OAuthConnector"] == "true")
{
dataView.Add("AnyConnector", "true");
}
if (dataView["TargetFrameworkVersion"] == "netcoreapp2.2")
{
dataView.Add("AspNetCoreVersion", "2.2.0");
dataView.Add("TargetFrameworkVersion22", "true");
}
else if (dataView["TargetFrameworkVersion"] == "netcoreapp2.1")
{
dataView.Add("AspNetCoreVersion", "2.1.1");
}
dataView.Add("ProjectNameSpace", projectName);
}
private string Render(string name, string input, object view)
{
try
{
return _stubble.Render(input, view);
}
catch (Exception ex)
{
throw new Exception("Error rendering " + name, ex);
}
}
public List<TemplateViewModel> GetAvailableTemplates()
{
return Directory
.GetDirectories(_templatePath)
.Select(path => new TemplateViewModel
{
Name = new DirectoryInfo(path).Name,
ShortName = new DirectoryInfo(path).Name,
Language = "C#",
Tags = "Web/Microservice",
})
.ToList();
}
public List<ProjectDependency> GetDependencies(string shortName)
{
shortName = string.IsNullOrEmpty(shortName) ? DEFAULT_TEMPLATE_NAME : shortName;
var list = GetAvailableTemplates();
var selectedTemplate = list.Where(x => x.ShortName == shortName).FirstOrDefault();
if (selectedTemplate == null)
{
throw new InvalidDataException($"Could not find template with name {shortName} ");
}
var templatePath = _templatePath + Path.DirectorySeparatorChar + selectedTemplate.Name;
var config = GetMustacheConfigJson(templatePath);
return config.Dependencies
.Where(p => p.Description.ToLower().Contains("steeltoe"))
.Select(p => new ProjectDependency
{
Name = GetFriendlyName(p.Name),
ShortName = p.Name,
Description = p.Description,
}).ToList();
}
private MustacheConfig GetMustacheConfigJson(string templatePath)
{
var json = File.ReadAllText(Path.Combine(templatePath, "mustache.json"));
return JsonConvert.DeserializeObject<MustacheConfig>(json);
}
private Dictionary<string, string> GetDataView(string templatePath, GeneratorModel model)
{
var mustacheConfig = GetMustacheConfigJson(templatePath);
var dataView = new Dictionary<string, string>();
if (mustacheConfig == null)
{
throw new InvalidDataException($"could not find config at {templatePath}");
}
foreach (var dep in mustacheConfig.Dependencies)
{
dataView.Add(dep.Name, dep.DefaultValue);
}
if (model.Dependencies != null)
{
foreach (var dependencyName in model.Dependencies)
{
var key = mustacheConfig.Dependencies.FirstOrDefault(k => k.Name.ToLower() == dependencyName)?.Name;
if (key != null)
{
dataView[key] = "true";
}
}
}
foreach (var version in mustacheConfig.Versions)
{
dataView.Add(version.Name, version.DefaultValue);
}
if (model.SteeltoeVersion != null)
{
var steeltoeVersionName = "SteeltoeVersion";
var steeltoVersion = mustacheConfig.Versions.FirstOrDefault(v => v.Name == steeltoeVersionName);
if (steeltoVersion.Choices.Any(choice => model.SteeltoeVersion.ToLower() == choice.Choice))
{
dataView[steeltoeVersionName] = model.SteeltoeVersion.ToLower();
}
}
if (model.TargetFrameworkVersion != null)
{
var targetFmwkName = "TargetFrameworkVersion";
var targetFmwk = mustacheConfig.Versions.FirstOrDefault(v => v.Name == targetFmwkName);
if (targetFmwk.Choices.Any(choice => model.TargetFrameworkVersion.ToLower() == choice.Choice))
{
dataView[targetFmwkName] = model.TargetFrameworkVersion;
}
}
return dataView;
}
private string GetFriendlyName(string name)
{
return FriendlyNames?.ContainsKey(name) == true ? FriendlyNames[name] : name;
}
public void ClearCache()
{
throw new NotImplementedException();
}
}
}

Просмотреть файл

@ -17,16 +17,15 @@ using Microsoft.AspNetCore.Hosting;
namespace Steeltoe.Initializr
{
public class Program
public static class Program
{
public static void Main(string[] args)
{
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
private static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
// .UseUrls("http://*:5000", "https://*:5001")
.UseStartup<Startup>();
.UseStartup<Startup>();
}
}

Просмотреть файл

@ -16,13 +16,13 @@ using Steeltoe.Initializr.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
public interface ITemplateService
{
List<KeyValuePair<string, string>> GenerateProjectFiles(GeneratorModel model);
Task<byte[]> GenerateProjectArchive(GeneratorModel model);
Task<byte[]> GenerateProjectArchiveAsync(GeneratorModel model);
List<TemplateViewModel> GetAvailableTemplates();

Просмотреть файл

@ -14,7 +14,7 @@ using Microsoft.TemplateEngine.Edge.Mount.Archive;
using Microsoft.TemplateEngine.Edge.Mount.FileSystem;
using Microsoft.TemplateEngine.Edge.Settings;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
/// <summary>
/// Copy of https://github.com/dotnet/templating/blob/stabilize/src/Microsoft.TemplateEngine.Edge/Settings/ComponentManager.cs

Просмотреть файл

@ -1,5 +1,6 @@
// <autogenerated />
// Doesnt follow stylecop rules
using System;
using System.Collections.Generic;
using System.IO;
@ -9,13 +10,11 @@ using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.Mount;
using Microsoft.TemplateEngine.Abstractions.PhysicalFileSystem;
using Microsoft.TemplateEngine.Edge;
using Microsoft.TemplateEngine.Edge.Mount.FileSystem;
using Microsoft.TemplateEngine.Edge.Settings;
using Microsoft.TemplateEngine.Utils;
using Newtonsoft.Json.Linq;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
/// <summary>
/// from: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/SettingsLoader.cs

Просмотреть файл

@ -1,5 +1,9 @@
// <autogenerated />
// Doesnt follow stylecop rules
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Edge;
using Microsoft.TemplateEngine.Edge.Settings;
@ -7,11 +11,8 @@ using Microsoft.TemplateEngine.Edge.Template;
using Microsoft.TemplateEngine.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
/// <summary>
/// From: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/TemplateCache.cs

Просмотреть файл

@ -1,12 +1,12 @@
// <autogenerated />
// Doesnt follow stylecop rules
using System;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Abstractions.Mount;
using Microsoft.TemplateEngine.Utils;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
/// <summary>
/// from: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/MountPointManager.cs

Просмотреть файл

@ -14,6 +14,7 @@
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine.Abstractions;
using Microsoft.TemplateEngine.Edge.Settings;
using Microsoft.TemplateEngine.Edge.Template;
@ -26,7 +27,7 @@ using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.DotNetTemplateEngine
{
public class TemplateService : ITemplateService
{
@ -71,17 +72,20 @@ namespace Steeltoe.Initializr.Services
private readonly string _hivePath;
private readonly string _outPath;
private IMemoryCache _memoryCache;
private ILogger<TemplateService> _logger;
public TemplateService(IConfiguration configuration, IMemoryCache memoryCache)
: this()
public TemplateService(IConfiguration configuration, IMemoryCache memoryCache, ILogger<TemplateService> logger)
: this(logger)
{
_memoryCache = memoryCache;
configuration.Bind(this); // Get friendlyNames
}
public TemplateService()
public TemplateService(ILogger<TemplateService> logger)
{
_hivePath = AppDomain.CurrentDomain.BaseDirectory + "templates" + Path.DirectorySeparatorChar + "DotNetTemplating"+ Path.DirectorySeparatorChar ;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_hivePath = AppDomain.CurrentDomain.BaseDirectory + "templates" + Path.DirectorySeparatorChar + "DotNetTemplating" + Path.DirectorySeparatorChar;
_outPath = AppDomain.CurrentDomain.BaseDirectory + "output" + Path.DirectorySeparatorChar;
Console.WriteLine("hivePath " + _hivePath);
@ -147,7 +151,6 @@ namespace Steeltoe.Initializr.Services
public List<KeyValuePair<string, string>> GenerateProjectFiles(GeneratorModel model)
{
var listOfFiles = new List<KeyValuePair<string, string>>();
var outFolder = GenerateProject(model);
@ -161,7 +164,7 @@ namespace Steeltoe.Initializr.Services
return listOfFiles;
}
public async Task<byte[]> GenerateProjectArchive(GeneratorModel model)
public async Task<byte[]> GenerateProjectArchiveAsync(GeneratorModel model)
{
var outFolder = GenerateProject(model);
@ -173,20 +176,6 @@ namespace Steeltoe.Initializr.Services
return archiveBytes;
}
private void Delete(string outFolder, string zipFile)
{
try
{
System.IO.File.Delete(zipFile);
Directory.Delete(Path.Combine(outFolder, ".."), true);
}
catch (Exception ex)
{
// Todo: log exception
// Console.WriteLine("Delete Error: " + ex.Message);
}
}
public List<TemplateViewModel> GetAvailableTemplates()
{
var list = GetAllTemplates();
@ -204,7 +193,9 @@ namespace Steeltoe.Initializr.Services
{
var list = GetAllTemplates();
var selectedTemplate = list.Where(x => x.ShortName == (shortName ?? DEFAULT_TEMPLATE)).FirstOrDefault();
shortName = string.IsNullOrEmpty(shortName) ? DEFAULT_TEMPLATE : shortName;
var selectedTemplate = list.FirstOrDefault(x => x.ShortName == shortName);
if (selectedTemplate == null)
{
@ -221,6 +212,19 @@ namespace Steeltoe.Initializr.Services
}).ToList();
}
private void Delete(string outFolder, string zipFile)
{
try
{
System.IO.File.Delete(zipFile);
Directory.Delete(Path.Combine(outFolder, ".."), true);
}
catch (Exception ex)
{
_logger.LogError("Delete Error: " + ex.Message);
}
}
private EngineEnvironmentSettings GetEngineEnvironmentSettings()
{
var envSettings = new EngineEnvironmentSettings(

Просмотреть файл

@ -0,0 +1,232 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Newtonsoft.Json;
using Steeltoe.Initializr.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Steeltoe.Initializr.Services.Mustache
{
public class MustacheConfig
{
public IEnumerable<string> GetFilteredSourceSets(Dictionary<string, object> dataView, string templatePath)
{
var files = Directory.EnumerateFiles(templatePath, "*", SearchOption.AllDirectories).ToList();
var json = File.ReadAllText(Path.Combine(templatePath, "sourceExclusions.json"));
IDictionary<string, string>
allExclusions = JsonConvert.DeserializeObject<IDictionary<string, string>>(json);
var conditionalInclusions = allExclusions.Where(x => !dataView.ContainsKey(x.Key)
|| (dataView[x.Key] is bool boolValue && !boolValue)
|| (dataView[x.Key] is string stringValue &&
stringValue != "true")).ToList();
var exclusionFiles = new List<string>();
foreach (string file in files)
{
var pathPrefix = file.Replace(Path.GetFullPath(templatePath), string.Empty)
.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var inclusion in conditionalInclusions)
{
var inclusionExpression = inclusion.Value;
if (inclusionExpression.EndsWith("**"))
{
if (pathPrefix.StartsWith(inclusionExpression.Replace("/**", string.Empty)))
{
exclusionFiles.Add(file);
}
}
else
{
// exact Match
if (pathPrefix == inclusionExpression)
{
exclusionFiles.Add(file);
}
}
}
}
return files.Where(f => exclusionFiles.All(e => e != f));
}
public MustacheConfigSchema GetMustacheConfigSchema(string templatePath)
{
var json = File.ReadAllText(Path.Combine(templatePath, "mustache.json"));
return JsonConvert.DeserializeObject<MustacheConfigSchema>(json);
}
public Dictionary<string, object> GetDataView(string templatePath, GeneratorModel model)
{
var mustacheConfig = GetMustacheConfigSchema(templatePath);
var dataView = new Dictionary<string, object>();
if (mustacheConfig == null)
{
throw new InvalidDataException($"could not find config at {templatePath}");
}
foreach (var dep in mustacheConfig.Params)
{
var defaultValue = bool.TryParse(dep.DefaultValue, out var boolDefaultValue)
? (object)boolDefaultValue
: dep.DefaultValue;
dataView.Add(dep.Name, defaultValue);
}
if (model.Dependencies != null)
{
foreach (var dependencyName in model.Dependencies)
{
var key = mustacheConfig.Params.FirstOrDefault(k => k.Name.ToLower() == dependencyName)?.Name;
if (key != null)
{
dataView[key] = true;
}
}
}
foreach (var version in mustacheConfig.Versions)
{
dataView.Add(version.Name, version.DefaultValue);
}
if (model.SteeltoeVersion != null)
{
const string steeltoeVersionName = "SteeltoeVersion";
var steeltoeVersion = mustacheConfig.Versions.FirstOrDefault(v => v.Name == steeltoeVersionName);
var validChoice =
steeltoeVersion?.Choices.Any(choice => model.SteeltoeVersion.ToLower() == choice.Choice);
if (validChoice == true)
{
dataView[steeltoeVersionName] = model.SteeltoeVersion.ToLower();
}
}
if (model.TargetFrameworkVersion != null)
{
const string targetFrameworkName = "TargetFrameworkVersion";
var targetFramework = mustacheConfig.Versions.FirstOrDefault(v => v.Name == targetFrameworkName);
var validChoice =
targetFramework?.Choices.Any(choice => model.TargetFrameworkVersion.ToLower() == choice.Choice);
if (validChoice == true)
{
dataView[targetFrameworkName] = model.TargetFrameworkVersion;
}
}
if (model.ProjectName != null)
{
const string projectNamespaceName = "ProjectNameSpace";
if (dataView.ContainsKey(projectNamespaceName))
{
dataView[projectNamespaceName] = model.ProjectName;
}
}
foreach (var calculatedParam in mustacheConfig.CalculatedParams)
{
switch (calculatedParam.ExpressionType)
{
case ExpressionTypeEnum.Lookup:
var lambda = BuildLookupLambda(calculatedParam, dataView);
EvaluateLambdaExpression<bool>(calculatedParam.Name, lambda, dataView);
break;
case ExpressionTypeEnum.Lambda:
default:
lambda = calculatedParam.Expression;
EvaluateLambdaExpression<string>(calculatedParam.Name, lambda, dataView);
break;
}
}
return dataView;
}
public string BuildLookupLambda(CalculatedParam calculatedParam, Dictionary<string, object> dataView)
{
var lambda = string.Empty;
var expressionString = calculatedParam.Expression;
var tree = SyntaxFactory.ParseExpression(expressionString);
foreach (var node in tree.DescendantTokens())
{
var key = node.ToString();
if (dataView.ContainsKey(key))
{
lambda += $"dataView[\"{key}\"]";
}
else
{
lambda += key;
}
}
return "dataView => " + lambda;
}
public void EvaluateLambdaExpression<T>(
string calculatedParamName,
string lambda,
Dictionary<string, object> dataView)
where T : IConvertible
{
try
{
var options = ScriptOptions.Default;
var evalExpression = CSharpScript
.EvaluateAsync<Func<Dictionary<string, T>, T>>(lambda, options).Result;
var typedDataView = GetTypedDictionary<T>(dataView);
var result = evalExpression(typedDataView);
if (result != null)
{
dataView.TryAdd(calculatedParamName, result);
}
}
catch (Exception ex)
{
throw new ArgumentException(lambda, ex);
}
}
private Dictionary<string, T> GetTypedDictionary<T>(Dictionary<string, object> dictionary)
where T : IConvertible
{
var result = new Dictionary<string, T>();
foreach (var (key, value) in dictionary)
{
if (value is T itemValue)
{
result.Add(key, itemValue);
}
}
return result;
}
}
}

Просмотреть файл

@ -14,18 +14,35 @@
using System.Collections.Generic;
namespace Steeltoe.Initializr.Services
namespace Steeltoe.Initializr.Services.Mustache
{
public class MustacheConfig
public class MustacheConfigSchema
{
public List<Dependency> Dependencies { get; set; }
public List<Param> Params { get; set; }
public List<CalculatedParam> CalculatedParams { get; set; }
public List<Version> Versions { get; set; }
}
#pragma warning disable SA1402 // File may only contain a single type
public class CalculatedParam
{
public string Name { get; set; }
public string Expression { get; set; }
public ExpressionTypeEnum ExpressionType { get; set; }
}
public enum ExpressionTypeEnum
{
Lookup = 0,
Lambda,
}
public class Version
#pragma warning restore SA1402 // File may only contain a single type
{
public string Name { get; set; }
@ -36,17 +53,14 @@ namespace Steeltoe.Initializr.Services
public List<ChoiceValue> Choices { get; set; }
}
#pragma warning disable SA1402 // File may only contain a single type
public class ChoiceValue
#pragma warning restore SA1402 // File may only contain a single type
{
public string Choice { get; set; }
public string Description { get; set; }
}
#pragma warning disable SA1402 // File may only contain a single type
public class Dependency
public class Param
#pragma warning restore SA1402 // File may only contain a single type
{
public string Name { get; set; }
@ -56,5 +70,7 @@ namespace Steeltoe.Initializr.Services
public string Description { get; set; }
public string FriendlyName { get; set; }
// TODO : Add param type Bool, String etc
}
}
}

Просмотреть файл

@ -0,0 +1,199 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Models;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Stubble.Core;
using Stubble.Core.Builders;
using Stubble.Extensions.JsonNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Steeltoe.Initializr.Services.Mustache
{
/// <summary>
/// An implementation of a Dotnet Template service via Mustache (Stubble).
/// </summary>
public class MustacheTemplateService : ITemplateService
{
private const string DefaultTemplateName = "CSharp-WebApi-2.x";
private Dictionary<string, string> FriendlyNames { get; set; }
private readonly StubbleVisitorRenderer _stubble;
private readonly ILogger<MustacheTemplateService> _logger;
private readonly string _templatePath;
private readonly MustacheConfig _mustacheConfig;
public MustacheTemplateService(IConfiguration configuration, ILogger<MustacheTemplateService> logger)
: this(logger)
{
configuration.Bind(this); // Get friendlyNames
}
public MustacheTemplateService(ILogger<MustacheTemplateService> logger)
{
_stubble = new StubbleBuilder()
.Configure(settings => settings.AddJsonNet())
.Build();
_logger = logger;
_templatePath = AppDomain.CurrentDomain.BaseDirectory + "templates" + Path.DirectorySeparatorChar +
"Mustache";
_mustacheConfig = new MustacheConfig();
}
public async Task<byte[]> GenerateProjectArchiveAsync(GeneratorModel model)
{
return await Task.Run(() => GenerateProjectArchive(model)).ConfigureAwait(false);
}
public List<KeyValuePair<string, string>> GenerateProjectFiles(GeneratorModel model)
{
var name = string.IsNullOrEmpty(model.TemplateShortName) ? DefaultTemplateName : model.TemplateShortName;
var templatePath = _templatePath + Path.DirectorySeparatorChar + name;
if (!Directory.Exists(templatePath))
{
throw new InvalidDataException("Template with $name doesnt exist");
}
var dataView = _mustacheConfig.GetDataView(templatePath, model);
var listOfFiles = new List<KeyValuePair<string, string>>();
foreach (var file in _mustacheConfig.GetFilteredSourceSets(dataView, templatePath))
{
if (file.EndsWith("mustache.json")
|| file.EndsWith("sourceExclusions.json"))
{
continue;
}
var pathPrefix = file.Replace(Path.GetFullPath(templatePath), string.Empty)
.TrimStart(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
string fileText = File.ReadAllText(file);
if (file.EndsWith(".csproj"))
{
pathPrefix =
pathPrefix.Replace("ReplaceMe", model.ProjectName ?? "SteeltoeExample"); // get from model
var output = Render(file, fileText, dataView);
listOfFiles.Add(new KeyValuePair<string, string>(pathPrefix, output));
}
else
{
var output = Render(file, fileText, dataView);
listOfFiles.Add(new KeyValuePair<string, string>(pathPrefix, output));
}
}
return listOfFiles;
}
public List<TemplateViewModel> GetAvailableTemplates()
{
return Directory
.GetDirectories(_templatePath)
.Select(path => new TemplateViewModel
{
Name = new DirectoryInfo(path).Name,
ShortName = new DirectoryInfo(path).Name,
Language = "C#",
Tags = "Web/Microservice",
})
.ToList();
}
public List<ProjectDependency> GetDependencies(string shortName)
{
shortName = string.IsNullOrEmpty(shortName) ? DefaultTemplateName : shortName;
var list = GetAvailableTemplates();
var selectedTemplate = list.FirstOrDefault(x => x.ShortName == shortName);
if (selectedTemplate == null)
{
throw new InvalidDataException($"Could not find template with name {shortName} ");
}
var templatePath = _templatePath + Path.DirectorySeparatorChar + selectedTemplate.Name;
var config = _mustacheConfig.GetMustacheConfigSchema(templatePath);
return config.Params
.Where(p => p.Description.ToLower().Contains("steeltoe"))
.Select(p => new ProjectDependency
{
Name = p.FriendlyName ?? GetFriendlyName(p.Name),
ShortName = p.Name,
Description = p.Description,
}).ToList();
}
public void ClearCache()
{
throw new NotImplementedException();
}
private byte[] GenerateProjectArchive(GeneratorModel model)
{
byte[] archiveBytes;
var listOfFiles = GenerateProjectFiles(model);
using (var memoryStream = new MemoryStream())
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach (var (key, value) in listOfFiles)
{
_logger.LogDebug(key);
var ef = archive.CreateEntry(key, CompressionLevel.Optimal);
using (var entryStream = ef.Open())
using (var fileToCompress = new MemoryStream(Encoding.UTF8.GetBytes(value)))
{
fileToCompress.CopyTo(entryStream);
}
}
}
archiveBytes = memoryStream.ToArray();
}
return archiveBytes;
}
private string Render(string name, string input, object view)
{
try
{
return _stubble.Render(input, view);
}
catch (Exception ex)
{
throw new Exception("Error rendering " + name, ex);
}
}
private string GetFriendlyName(string name)
{
return FriendlyNames?.ContainsKey(name) == true ? FriendlyNames[name] : name;
}
}
}

Просмотреть файл

@ -20,7 +20,8 @@ using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services;
using System.Collections.Generic;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.Initializr.Services.Mustache;
namespace Steeltoe.Initializr
{
@ -42,7 +43,6 @@ namespace Steeltoe.Initializr
services.AddMemoryCache();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// In production, the React files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
@ -50,7 +50,6 @@ namespace Steeltoe.Initializr
});
services.AddSingleton<ITemplateService, TemplateService>();
services.AddSingleton<ITemplateService, MustacheTemplateService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -68,12 +67,12 @@ namespace Steeltoe.Initializr
app.UseHsts();
}
//app.UseHttpsRedirection();
// app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseMvc();
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";

Просмотреть файл

@ -11,11 +11,6 @@
<OutputType>Exe</OutputType>
<StartupObject />
<UserSecretsId>.zip</UserSecretsId>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>C:\Users\Hananiel\projects\InitializrApi\src\InitializrApi.xml</DocumentationFile>
</PropertyGroup>
<ItemGroup>
<!-- Don't publish the SPA source files, but do show them in the project files list -->
@ -28,19 +23,11 @@
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\Mustache\CSharp-WebApi-2.x\Properties\**" />
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\Mustache\react\Properties\**" />
</ItemGroup>
<ItemGroup>
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\DotNetTemplating\CSharp-React-2.x\versions.props" />
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\DotNetTemplating\CSharp-WebApi-2.x\versions.props" />
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\Mustache\CSharp-WebApi-2.x\versions.props" />
<None Remove="C:\Users\Hananiel\projects\steeltoeoss-incubator\steetoe-initializr\src\..\templates\Mustache\react\versions.props" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.1.0" />
<PackageReference Include="Microsoft.TemplateEngine.Edge" Version="0.2.3-alpha" />
<PackageReference Include="Microsoft.TemplateEngine.Orchestrator.RunnableProjects" Version="0.2.1-alpha" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
@ -52,7 +39,17 @@
</PackageReference>
</ItemGroup>
<PropertyGroup>
<!--
Make sure any documentation comments which are included in code get checked for syntax during the build, but do
not report warnings for missing comments.
CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do)
CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
-->
<DocumentationFile>$(OutputPath)$(AssemblyName).xml</DocumentationFile>
<NoWarn>$(NoWarn),1573,1591,1712</NoWarn>
</PropertyGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
@ -95,4 +92,3 @@
</Project>

Просмотреть файл

@ -0,0 +1,38 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Steeltoe.Initializr</name>
</assembly>
<members>
<member name="T:Steeltoe.Initializr.Services.DotNetTemplateEngine.InitializrComponentManager">
<summary>
Copy of https://github.com/dotnet/templating/blob/stabilize/src/Microsoft.TemplateEngine.Edge/Settings/ComponentManager.cs
Internal class and used by <see cref="T:Steeltoe.Initializr.Services.DotNetTemplateEngine.InitializrSettingsLoader"/>
No changes made
</summary>
</member>
<member name="T:Steeltoe.Initializr.Services.DotNetTemplateEngine.InitializrSettingsLoader">
<summary>
from: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/SettingsLoader.cs
Needed a new method to rebuild Cache from settings
</summary>
</member>
<member name="T:Steeltoe.Initializr.Services.DotNetTemplateEngine.InitializrTemplateCache">
<summary>
From: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/TemplateCache.cs
Need access to the Write Template Cache methods
</summary>
</member>
<member name="T:Steeltoe.Initializr.Services.DotNetTemplateEngine.InitializrMountPointManager">
<summary>
from: https://github.com/dotnet/templating/blob/master/src/Microsoft.TemplateEngine.Edge/Settings/MountPointManager.cs
Need access to internal class
</summary>
</member>
<member name="T:Steeltoe.Initializr.Services.Mustache.MustacheTemplateService">
<summary>
An implementation of a Dotnet Template service via Mustache (Stubble).
</summary>
</member>
</members>
</doc>

Просмотреть файл

@ -1,5 +1,5 @@
{
"Dependencies": [
"Params": [
{
"Name": "Actuators",
"DefaultValue": false,
@ -14,12 +14,13 @@
"Name": "CircuitBreaker",
"DefaultValue": false,
"Description": "Steeltoe: Add Circuit Breakers",
"friendlyName": "Circuit Breakers"
"FriendlyName": "Circuit Breakers"
},
{
"Name": "CloudFoundry",
"DefaultValue": false,
"Description": "Steeltoe: Target CloudFoundry Hosting"
"Description": "Steeltoe: Target CloudFoundry Hosting",
"FriendlyName": "Cloud Foundry"
},
{
"Name": "Discovery",
@ -76,6 +77,54 @@
"DefaultValue": false,
"Description": "Steeltoe: Add Microsoft SQL Server connnectors",
"friendlyName": "SQL Server"
},
{
"Name": "ProjectNameSpace",
"DefaultValue": "SteeltoeExample",
"Description": "Change the namespace "
}
],
"CalculatedParams":
[
{
"Name": "ActuatorsOrCloudFoundry",
"Expression": "Actuators || CloudFoundry",
"ExpressionType": "Lookup"
},
{
"Name": "MySqlOrMySqlEFCore",
"Expression": "MySql || MySqlEFCore",
"ExpressionType": "Lookup"
},
{
"Name": "ActuatorsOrDynamicLogger",
"Expression": "Actuators || DynamicLogger",
"ExpressionType": "Lookup"
},
{
"Name": "AnyEFCore",
"Expression": "SQLServer || MySqlEFCore",
"ExpressionType": "Lookup"
},
{
"Name": "AnyConnector",
"Expression": "MySql || Postgres || Redis || MongoDB || OAuthConnector",
"ExpressionType": "Lookup"
},
{
"Name": "AspNetCoreVersion",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.2\"? \"2.2.0\": null",
"ExpressionType": "Lambda"
},
{
"Name": "TargetFrameworkVersion22",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.2\"? \"true\": null",
"ExpressionType": "Lambda"
},
{
"Name": "AspNetCoreVersion",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.1\"? \"2.1.1\": null",
"ExpressionType": "Lambda"
}
],
"Versions": [

Просмотреть файл

@ -1,5 +1,5 @@
{
"Dependencies": [
"Params": [
{
"Name": "Actuators",
"DefaultValue": false,
@ -14,12 +14,13 @@
"Name": "CircuitBreaker",
"DefaultValue": false,
"Description": "Steeltoe: Add Circuit Breakers",
"friendlyName": "Circuit Breakers"
"FriendlyName": "Circuit Breakers"
},
{
"Name": "CloudFoundry",
"DefaultValue": false,
"Description": "Steeltoe: Target CloudFoundry Hosting"
"Description": "Steeltoe: Target CloudFoundry Hosting",
"FriendlyName": "Cloud Foundry"
},
{
"Name": "Discovery",
@ -76,6 +77,54 @@
"DefaultValue": false,
"Description": "Steeltoe: Add Microsoft SQL Server connnectors",
"friendlyName": "SQL Server"
},
{
"Name": "ProjectNameSpace",
"DefaultValue": "SteeltoeExample",
"Description": "Change the namespace "
}
],
"CalculatedParams":
[
{
"Name": "ActuatorsOrCloudFoundry",
"Expression": "Actuators || CloudFoundry",
"ExpressionType": "Lookup"
},
{
"Name": "MySqlOrMySqlEFCore",
"Expression": "MySql || MySqlEFCore",
"ExpressionType": "Lookup"
},
{
"Name": "ActuatorsOrDynamicLogger",
"Expression": "Actuators || DynamicLogger",
"ExpressionType": "Lookup"
},
{
"Name": "AnyEFCore",
"Expression": "SQLServer || MySqlEFCore",
"ExpressionType": "Lookup"
},
{
"Name": "AnyConnector",
"Expression": "MySql || Postgres || Redis || MongoDB || OAuthConnector",
"ExpressionType": "Lookup"
},
{
"Name": "AspNetCoreVersion",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.2\"? \"2.2.0\": null",
"ExpressionType": "Lambda"
},
{
"Name": "TargetFrameworkVersion22",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.2\"? \"true\": null",
"ExpressionType": "Lambda"
},
{
"Name": "AspNetCoreVersion",
"Expression": "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.1\"? \"2.1.1\": null",
"ExpressionType": "Lambda"
}
],
"Versions": [

Просмотреть файл

@ -0,0 +1,60 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.Initializr.Services.Mustache;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Steeltoe.InitializrTests
{
public class AllImplementations : IEnumerable<object[]>
{
private readonly List<object[]> _data;
public AllImplementations()
{
var settings = new Dictionary<string, string>()
{
["FriendlyNames:CloudFoundry"] = "Cloud Foundry",
};
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(settings)
.Build();
var implementations = new ITemplateService[]
{
new TemplateService(configuration, new MemoryCache(new MemoryCacheOptions()), new LoggerFactory().CreateLogger<TemplateService>()),
new MustacheTemplateService(configuration, new LoggerFactory().CreateLogger<MustacheTemplateService>()),
};
var templateNames = new string[]
{
string.Empty, // test default
"react",
"CSharp-WebApi-2.x",
};
var data = from implementation in implementations
select new object[] { implementation };
_data = data.ToList();
}
public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

Просмотреть файл

@ -1,18 +1,33 @@
using Microsoft.Extensions.Caching.Memory;
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.Initializr.Services.Mustache;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Steeltoe.InitializrTests
namespace Steeltoe.Initializr.Tests
{
public class TestData : IEnumerable<object[]>
public class AllImplementationsAndTemplates : IEnumerable<object[]>
{
private readonly List<object[]> _data;
public TestData()
public AllImplementationsAndTemplates()
{
var settings = new Dictionary<string, string>()
{
@ -21,14 +36,15 @@ namespace Steeltoe.InitializrTests
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(settings)
.Build();
var implementations = new ITemplateService[]
{
new TemplateService(configuration, new MemoryCache(new MemoryCacheOptions())),
new MustacheTemplateService( new LoggerFactory().CreateLogger<MustacheTemplateService>(), configuration),
new TemplateService(configuration, new MemoryCache(new MemoryCacheOptions()), new LoggerFactory().CreateLogger<TemplateService>()),
new MustacheTemplateService(configuration, new LoggerFactory().CreateLogger<MustacheTemplateService>()),
};
var templateNames = new string[]
{
string.Empty, //test default
string.Empty, // test default
"react",
"CSharp-WebApi-2.x",
};

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Steeltoe.Initializr.Services.Mustache;
using System.Collections.Generic;
using Xunit;
namespace Steeltoe.Initializr.Tests
{
public class MustacheDataViewTests
{
[Fact]
public void TestExpressions()
{
var cdv = new MustacheConfig();
var dv = new Dictionary<string, object>
{
{ "A", true },
{ "B", false },
{ "C", false },
};
var calcExp = new CalculatedParam
{
Name = "testExp",
Expression = "A || B && !C ",
ExpressionType = ExpressionTypeEnum.Lookup,
};
var lambda = cdv.BuildLookupLambda(calcExp, dv);
cdv.EvaluateLambdaExpression<bool>(calcExp.Name, lambda, dv);
Assert.Contains(dv, (item) => item.Key == calcExp.Name && item.Value is bool itemValue && itemValue);
}
[Fact]
public void TestExpressionsActuators()
{
var cdv = new MustacheConfig();
var dv = new Dictionary<string, object>
{
{ "MySql", true },
{ "MySqlEFCore", false },
};
var calcExp = new CalculatedParam
{
Name = "MySqlOrMySqlEFCore",
Expression = "MySql || MySqlEFCore",
ExpressionType = ExpressionTypeEnum.Lookup,
};
var lambda = cdv.BuildLookupLambda(calcExp, dv);
cdv.EvaluateLambdaExpression<bool>(calcExp.Name, lambda, dv);
Assert.Contains(dv, (item) => item.Key == calcExp.Name && item.Value is bool itemValue && itemValue);
}
[Fact]
public void TestLambdaExpression()
{
var cdv = new MustacheConfig();
var dv = new Dictionary<string, object>
{
{ "TargetFrameworkVersion", "netcoreapp2.2" },
};
var calcExp = new CalculatedParam
{
Name = "AspNetCoreVersion",
Expression = "dataView => dataView[\"TargetFrameworkVersion\"]==\"netcoreapp2.2\"? \"2.2.0\": null",
ExpressionType = ExpressionTypeEnum.Lambda,
};
cdv.EvaluateLambdaExpression<string>(calcExp.Name, calcExp.Expression, dv);
Assert.Contains(dv, (item) => item.Key == calcExp.Name && (string)item.Value == "2.2.0");
}
}
}

Просмотреть файл

@ -1,21 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<NoWarn>SA0001</NoWarn>
</PropertyGroup>
 <Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\shared.props" />
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup>
<!--
Make sure any documentation comments which are included in code get checked for syntax during the build, but do
not report warnings for missing comments.
CS1573: Parameter 'parameter' has no matching param tag in the XML comment for 'parameter' (but other parameters do)
CS1591: Missing XML comment for publicly visible type or member 'Type_or_Member'
-->
<DocumentationFile>$(OutputPath)$(AssemblyName).xml</DocumentationFile>
<NoWarn>$(NoWarn),1573,1591,1712</NoWarn>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.2.0" />
@ -31,16 +34,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Steeltoe.Initializr.csproj" />
</ItemGroup>
<Target Name="CopyTemplates" BeforeTargets="PreBuildEvent">
<ItemGroup>
<Templates Include="$(SolutionDir)\templates\**\*.*" />
</ItemGroup>
<Copy SourceFiles="@(Templates)" DestinationFolder="$(TargetDir)\templates\%(RecursiveDir)" SkipUnchangedFiles="false" />
</Target>
</Project>

Просмотреть файл

@ -1,6 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ActiveDebugProfile>IIS Express</ActiveDebugProfile>
</PropertyGroup>
</Project>

Просмотреть файл

@ -0,0 +1,13 @@
<?xml version="1.0"?>
<doc>
<assembly>
<name>Steeltoe.Initializr.Tests</name>
</assembly>
<members>
<member name="T:Steeltoe.Initializr.Tests.TemplateControllerTests">
<summary>
Controller Tests for multiple templateService implementations.
</summary>
</member>
</members>
</doc>

Просмотреть файл

@ -14,8 +14,8 @@
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr;
using Steeltoe.Initializr.Services;
using Steeltoe.Initializr.Services.Mustache;
using Steeltoe.InitializrTests;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
@ -24,13 +24,16 @@ using System.Net.Http;
using Xunit;
using Xunit.Abstractions;
namespace Steeltoe.InitializrTests
namespace Steeltoe.Initializr.Tests
{
/// <summary>
/// Controller Tests for multiple templateService implementations.
/// </summary>
public class TemplateControllerTests : XunitLoggingBase, IClassFixture<TestWebAppFactory<Startup>>
{
private ILogger<MustacheTemplateService> _logger;
private readonly TestWebAppFactory<Startup> _factory;
private readonly HttpClient _client;
private ILogger<MustacheTemplateService> _logger;
public TemplateControllerTests(ITestOutputHelper testOutputHelper, TestWebAppFactory<Startup> factory)
: base(testOutputHelper)
@ -39,7 +42,8 @@ namespace Steeltoe.InitializrTests
_client = factory.CreateClient(new WebApplicationFactoryClientOptions
{
AllowAutoRedirect = false,
}) ;
});
var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
_logger = loggerFactory.CreateLogger<MustacheTemplateService>();
@ -64,9 +68,8 @@ namespace Steeltoe.InitializrTests
}
}
}
Assert.True(files.Count > 0);
Assert.True(files.Count > 0);
}
}
}

Просмотреть файл

@ -14,61 +14,54 @@
using DiffMatchPatch;
using Microsoft.Extensions.Logging;
using Steeltoe.Initializr.Services;
using System;
using System.Collections.Generic;
using Steeltoe.Initializr.Services.DotNetTemplateEngine;
using Steeltoe.InitializrTests;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
namespace Steeltoe.InitializrTests
namespace Steeltoe.Initializr.Tests
{
public class TemplateServiceTests : XunitLoggingBase
{
private ILogger<MustacheTemplateService> _logger;
private readonly LoggerFactory _loggerFactory;
public TemplateServiceTests(ITestOutputHelper testOutputHelper)
: base(testOutputHelper)
{
var loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
_logger = loggerFactory.CreateLogger<MustacheTemplateService>();
_loggerFactory = new LoggerFactory();
_loggerFactory.AddProvider(new XunitLoggerProvider(testOutputHelper));
}
[Theory]
[ClassData(typeof(TestData))]
public void GetAvailableTemplates_returnsTemplates(ITemplateService templateService, string templateName)
[Fact]
public void GetAvailableTemplates_returnsTemplates()
{
var templates = templateService.GetAvailableTemplates();
var templates = new TemplateService(_loggerFactory.CreateLogger<TemplateService>())
.GetAvailableTemplates();
Assert.NotNull(templates);
Assert.NotEmpty(templates);
if (templateService is TemplateService)
{
Assert.Contains(templates, x => x.ShortName == "CSharp-WebApi-2.x");
Assert.Contains(templates, x => x.ShortName == "steeltoe");
Assert.Contains(templates, x => x.ShortName == "react");
}
Assert.Contains(templates, x => x.ShortName == "CSharp-WebApi-2.x");
Assert.Contains(templates, x => x.ShortName == "steeltoe");
Assert.Contains(templates, x => x.ShortName == "react");
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void GetDependencies(ITemplateService templateService, string templateName)
{
var deps = templateService.GetDependencies(null);
var deps = templateService.GetDependencies(templateName);
Assert.NotNull(deps);
Assert.NotEmpty(deps);
Assert.Contains(deps, x => x.Name == "OAuthConnector");
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void GetDependencies_WithFriendlyNames(ITemplateService templateService, string templateName)
{
var deps = templateService.GetDependencies();
var deps = templateService.GetDependencies(templateName);
Assert.NotNull(deps);
Assert.NotEmpty(deps);
@ -77,7 +70,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_actuators(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -96,22 +89,21 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_react(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
{
ProjectName = "testProject",
TemplateShortName = templateName,
});
string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.NotEmpty(startUpContents);
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_discovery(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -128,7 +120,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_actuators_circuitbreakers(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -143,7 +135,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_MySql(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -159,7 +151,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_MySql_EFCore(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -174,7 +166,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_postgresql(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -190,7 +182,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_postgresEFCore(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -206,7 +198,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_RabbitMQ(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -222,7 +214,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_Redis(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -237,7 +229,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_MongoDB(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -252,7 +244,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_OauthConnector(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -267,7 +259,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_SqlServer(ITemplateService templateService, string templateName)
{
var steeltoeVersion = "2.3.0-rc1";
@ -282,27 +274,27 @@ namespace Steeltoe.InitializrTests
Assert.Contains(files, file => file.Key.StartsWith("Models"));
string fileContents = files.Find(x => x.Key == "testProject.csproj").Value;
var fileContents = files.Find(x => x.Key == "testProject.csproj").Value;
Assert.Contains(@"<PackageReference Include=""Microsoft.EntityFrameworkCore"" Version=""2.2.0"" />", fileContents);
Assert.Contains(@"<PackageReference Include=""Microsoft.EntityFrameworkCore.SqlServer"" Version=""2.2.0"" />", fileContents);
Assert.Contains(@"<PackageReference Include=""Steeltoe.CloudFoundry.Connector.EFCore"" Version=""" + steeltoeVersion + @""" />", fileContents);
string program = files.Find(x => x.Key == "Program.cs").Value;
var program = files.Find(x => x.Key == "Program.cs").Value;
Assert.Contains(@".InitializeDbContexts()", program);
string startup = files.Find(x => x.Key == "Startup.cs").Value;
var startup = files.Find(x => x.Key == "Startup.cs").Value;
Assert.Contains(@"using Steeltoe.CloudFoundry.Connector.SqlServer.EFCore;", startup);
Assert.Contains(@"services.AddDbContext<TestContext>(options => options.UseSqlServer(Configuration));", startup);
if (templateName != "react") //TODO: Add demo for react app
{
string valuesController = files.Find(x => x.Key.EndsWith("ValuesController.cs")).Value;
if (templateName != "react")
{ // TODO: Add demo for react app
var valuesController = files.Find(x => x.Key.EndsWith("ValuesController.cs")).Value;
Assert.Contains(@" public ValuesController(ILogger<ValuesController> logger, [FromServices] TestContext context)", valuesController);
}
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_DynamicLogger(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -322,7 +314,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_actuators_cloudFoundry(ITemplateService templateService, string templateName)
{
Assert.NotNull(templateService);
@ -340,7 +332,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_actuators_v22(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -350,14 +342,13 @@ namespace Steeltoe.InitializrTests
TemplateShortName = templateName,
});
string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.Contains("services.AddCloudFoundryActuators(Configuration, MediaTypeVersion.V2, ActuatorContext.Actuator);", startUpContents);
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_actuators_23rc1(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -367,10 +358,9 @@ namespace Steeltoe.InitializrTests
TemplateShortName = templateName,
});
string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.Contains("services.AddCloudFoundryActuators(Configuration, MediaTypeVersion.V2, ActuatorContext.Actuator);", startUpContents);
}
////[Fact]
////public void CreateTemplate_actuators_v3()
@ -391,7 +381,7 @@ namespace Steeltoe.InitializrTests
////}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_empty(ITemplateService templateService, string templateName)
{
Assert.NotNull(templateService);
@ -401,21 +391,21 @@ namespace Steeltoe.InitializrTests
TemplateShortName = templateName,
ProjectName = "Foo.Bar",
});
string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.DoesNotContain(files, file => file.Key.StartsWith("Models"));
Assert.DoesNotContain("AddCloudFoundryActuators", startUpContents);
string dockerFile = files.Find(x => x.Key == "Dockerfile").Value;
var dockerFile = files.Find(x => x.Key == "Dockerfile").Value;
Assert.NotNull(dockerFile);
Assert.Contains("Foo.Bar.dll", dockerFile);
Assert.Contains("Foo.Bar.csproj", dockerFile);
string projectFile = files.Find(x => x.Key == "Foo.Bar.csproj").Value;
var projectFile = files.Find(x => x.Key == "Foo.Bar.csproj").Value;
Assert.Contains("<TargetFramework>netcoreapp2.2</TargetFramework>", projectFile);
foreach (var file in files)
{
Assert.DoesNotContain("{{", file.Value);
@ -424,7 +414,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_targetVersion21(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -443,7 +433,7 @@ namespace Steeltoe.InitializrTests
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_targetVersion22(ITemplateService templateService, string templateName)
{
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
@ -453,24 +443,21 @@ namespace Steeltoe.InitializrTests
TargetFrameworkVersion = "netcoreapp2.2",
});
string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.Contains("services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);", startUpContents);
//string versionProps = files.Find(x => x.Key == "versions.props").Value;
//Assert.Contains("<AspNetCoreVersion>2.2.0</AspNetCoreVersion", versionProps);
string projectFile = files.Find(x => x.Key == "Foo.Bar.csproj").Value;
var projectFile = files.Find(x => x.Key == "Foo.Bar.csproj").Value;
Assert.Contains("<TargetFramework>netcoreapp2.2</TargetFramework>", projectFile);
}
[Theory]
[ClassData(typeof(TestData))]
[ClassData(typeof(AllImplementationsAndTemplates))]
public void CreateTemplate_GeneratesCorrectVersions(ITemplateService templateService, string templateName)
{
var deps = templateService.GetDependencies();
var files = templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
{
//Todo : fix this
// Todo : fix this
Dependencies = new string[] { string.Join(",", deps.Select(d => d.ShortName.ToLower()).ToArray()) },
TemplateShortName = templateName,
ProjectName = "Foo.Bar",
@ -601,19 +588,18 @@ namespace Steeltoe.InitializrTests
Assert.True(DiffIgnoreWhitespace(expected, projectFile, out string diffMessage), diffMessage);
}
public bool DiffIgnoreWhitespace(string a, string b, out string diffMessage)
private bool DiffIgnoreWhitespace(string a, string b, out string diffMessage)
{
var dmp = DiffMatchPatchModule.Default;
var a_min = a.Replace(" ", "").Replace(" ","");
var b_min = b.Replace(" ", "").Replace(" ", "");
var diffs = dmp.DiffMain(b_min, a_min , true);
var a_min = a.Replace(" ", string.Empty).Replace(" ", string.Empty);
var b_min = b.Replace(" ", string.Empty).Replace(" ", string.Empty);
var diffs = dmp.DiffMain(b_min, a_min, true);
var filtered_diffs = diffs.Where(x => x.Operation != Operation.Equal && x.Text.Any(c => !char.IsWhiteSpace(c))).Take(3);
var filtered_diffs = diffs.Where(x => x.Operation != Operation.Equal && x.Text.Any(c => !char.IsWhiteSpace(c))).Take(3).ToList();
var diffStrings = string.Join("\r\n", filtered_diffs.Select(d => (d.Operation == Operation.Insert ? '+' : '-') + $" {d.Text} "));
diffMessage = diffStrings + "in " + b;
return !filtered_diffs.Any();
}
}
}

Просмотреть файл

@ -1,7 +1,21 @@
using Microsoft.AspNetCore.Hosting;
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
namespace Steeltoe.InitializrTests
namespace Steeltoe.Initializr.Tests
{
public class TestWebAppFactory<TStartup>
: WebApplicationFactory<TStartup>

Просмотреть файл

@ -16,9 +16,8 @@ using Microsoft.Extensions.Logging;
using System;
using Xunit.Abstractions;
namespace Steeltoe.InitializrTests
namespace Steeltoe.Initializr.Tests
{
public class XunitLogger : ILogger
{
private readonly ITestOutputHelper _testOutputHelper;
@ -50,7 +49,8 @@ namespace Steeltoe.InitializrTests
public static NoopDisposable Instance = new NoopDisposable();
public void Dispose()
{ }
{
}
}
}
}

Просмотреть файл

@ -27,9 +27,10 @@ namespace Steeltoe.InitializrTests
}
public ILogger CreateLogger(string categoryName)
=> new XunitLogger(_testOutputHelper, categoryName);
=> new Initializr.Tests.XunitLogger(_testOutputHelper, categoryName);
public void Dispose()
{ }
{
}
}
}