diff --git a/src/cli/Commands/GenerationCommander.cs b/src/cli/Commands/GenerationCommander.cs new file mode 100644 index 00000000..7d7581b1 --- /dev/null +++ b/src/cli/Commands/GenerationCommander.cs @@ -0,0 +1,73 @@ +using cli.Model; +using Microsoft.Extensions.CommandLineUtils; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.AspNet.Hosting; +using Microsoft.Extensions.OptionsModel; + +using cli.Services; +using cli.Settings; + +namespace cli.Commands +{ + public class GenerationCommander : ICommander + { + + public GenerationCommander() + { + } + + public CommandLineApplication Integrate(CommandLineApplication rootApp) + { + CommandArgument nsarg=null; + CommandArgument mdClass=null; + CommandArgument ctrlName=null; + CommandArgument rPath=null; + CommandArgument dbCtx=null; + + var cmd = rootApp.Command("mvc", config => { + config.FullName = "mvc controller"; + config.Description = "generates an mvc controller"; + nsarg = config.Argument("ns","default name space"); + mdClass = config.Argument("mc","Model class name"); + ctrlName = config.Argument("cn", "Controller name"); + rPath = config.Argument("rp", "Relative path"); + config.HelpOption("-? | -h | --help"); + }); + cmd.OnExecute(() => { + var host = new WebHostBuilder(); + var hostengnine = host.UseEnvironment("Development") + .UseServer("cli") + .UseStartup() + .Build(); + var app = hostengnine.Start(); + var mailer = app.Services.GetService(); + var loggerFactory = app.Services.GetService(); + var logger = loggerFactory.CreateLogger(); + var options = app.Services.GetService>(); + + MvcGenerator generator = app.Services.GetService(); + + var modelFullName = mdClass?.Value ?? options?.Value.ModelFullName; + var nameSpace = nsarg?.Value?? options?.Value.NameSpace; + var dbContext = dbCtx?.Value?? options?.Value.DbContextFullName; + var controllerName = ctrlName?.Value?? options?.Value.ControllerName; + var relativePath = rPath?.Value ?? options?.Value.RelativePath; + + logger.LogInformation("Starting generation"); + logger.LogInformation($"Using parameters : modelFullName:{modelFullName} nameSpace:{nameSpace} dbContext:{dbContext} controllerName:{controllerName} relativePath:{relativePath}"); + + generator.Generate(modelFullName, + nameSpace, + dbContext, + controllerName, + relativePath); + + logger.LogInformation("Finished generation"); + + return 0; + }); + return cmd; + } + } +} \ No newline at end of file diff --git a/src/cli/Commands/SendMailCommand.cs b/src/cli/Commands/SendMailCommand.cs index caace732..fd763418 100644 --- a/src/cli/Commands/SendMailCommand.cs +++ b/src/cli/Commands/SendMailCommand.cs @@ -46,6 +46,7 @@ public class SendMailCommandProvider : ICommander { else { sendMailCommandApp.ShowHelp(); + return 1; } return 0; }); diff --git a/src/cli/Helpers/ConsoleHelpers.cs b/src/cli/Helpers/ConsoleHelpers.cs index b896dff7..b17cdea8 100644 --- a/src/cli/Helpers/ConsoleHelpers.cs +++ b/src/cli/Helpers/ConsoleHelpers.cs @@ -1,11 +1,8 @@ using System; -using System.Collections.Generic; using System.Text; -using System.Threading.Tasks; using cli.Model; using Microsoft.Extensions.CommandLineUtils; using Yavsc.Authentication; -using static OAuth.AspNet.AuthServer.Constants; namespace cli.Helpers { @@ -31,6 +28,7 @@ namespace cli.Helpers settings.Scope, new Uri(settings.AuthorizeUrl), new Uri(settings.RedirectUrl), new Uri(settings.AccessTokenUrl)); } + /* TODO add OAut console client public static async Task> GetAuthFromPass( string login, @@ -41,7 +39,7 @@ namespace cli.Helpers query[Parameters.Password] = pass; query[Parameters.GrantType] = GrantTypes.Password; return await OAuthorInstance.RequestAccessTokenAsync(query); - } + } */ public static string GetPassword() { diff --git a/src/cli/Program.cs b/src/cli/Program.cs index 88748467..6945cf83 100644 --- a/src/cli/Program.cs +++ b/src/cli/Program.cs @@ -1,6 +1,7 @@  using System; using cli.Commands; +using cli.Services; using Microsoft.Extensions.CommandLineUtils; namespace cli @@ -24,6 +25,7 @@ namespace cli (new GenerateJsonSchema()).Integrate(cliapp); (new AuthCommander()).Integrate(cliapp); (new CiBuildCommand()).Integrate(cliapp); + (new GenerationCommander()).Integrate(cliapp); if (args.Length == 0) { diff --git a/src/cli/Services/EMailer.cs b/src/cli/Services/EMailer.cs index c99e54ed..47030185 100644 --- a/src/cli/Services/EMailer.cs +++ b/src/cli/Services/EMailer.cs @@ -172,7 +172,7 @@ namespace cli.Services else if (!mailSentInfo.Sent) logger.LogError($"{mailSentInfo.ErrorMessage}"); else - logger.LogInformation($"mailId:{mailSentInfo.MessageId} \nto:{user.UserName}"); + logger.LogInformation($"mailId:{mailSentInfo?.MessageId} \nto:{user.UserName}"); diff --git a/src/cli/Services/MvcGenerator.cs b/src/cli/Services/MvcGenerator.cs new file mode 100644 index 00000000..0517036e --- /dev/null +++ b/src/cli/Services/MvcGenerator.cs @@ -0,0 +1,30 @@ +using System; +using Microsoft.Extensions.CodeGenerators.Mvc.Controller; + +namespace cli.Services +{ + + public class MvcGenerator : CommandLineGenerator + { + CommandLineGeneratorModel _model; + public MvcGenerator (IServiceProvider services): base (services) + { + _model = new CommandLineGeneratorModel(); + } + + public async void Generate( + string modelClass, + string ns, + string dbContextFullName, + string controllerName, + string relativeFolderPath + ) + { + _model.ControllerName = controllerName; + _model.ModelClass = modelClass; + _model.DataContextClass = dbContextFullName; + _model.RelativeFolderPath = relativeFolderPath; + await GenerateCode(_model); + } + } +} \ No newline at end of file diff --git a/src/cli/Settings/GenMvcSettings.cs b/src/cli/Settings/GenMvcSettings.cs new file mode 100644 index 00000000..0a64f295 --- /dev/null +++ b/src/cli/Settings/GenMvcSettings.cs @@ -0,0 +1,16 @@ +namespace cli.Settings +{ + public class GenMvcSettings + { + public string NameSpace { get; set; } + public string ModelFullName { get; set; } + public string ControllerName { get; set; } + public string AppBase { get; set; } + public string RelativePath { get; set; } + public string DbContextFullName { get; set; } + + // FIXME this appears to be dropped soon ... as all configuration should be concerned + public string ConfigurationName { get; set; } = "Development"; + + } +} \ No newline at end of file diff --git a/src/cli/Startup.cs b/src/cli/Startup.cs index ffae7f54..cb4bcbce 100644 --- a/src/cli/Startup.cs +++ b/src/cli/Startup.cs @@ -9,10 +9,24 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.OptionsModel; using Microsoft.Extensions.PlatformAbstractions; using Microsoft.Extensions.WebEncoders; +using Microsoft.Dnx.Compilation; using Yavsc; using Yavsc.Models; using Yavsc.Services; using cli.Services; +using cli.Settings; +using Microsoft.Extensions.CodeGeneration; +using Microsoft.Dnx.Runtime.Compilation; +using Microsoft.Dnx.Runtime; +using Microsoft.Dnx.Compilation.Caching; +using Microsoft.Dnx.Host; +using System.IO; +using System.Runtime.Versioning; +using System; +using System.Collections.Generic; +using Microsoft.Extensions.CodeGeneration.EntityFramework; +using Microsoft.Extensions.CodeGeneration.Templating.Compilation; +using System.Linq; namespace cli { @@ -20,34 +34,38 @@ namespace cli { public string ConnectionString { - get ; set; + get; set; } public static ConnectionSettings Settings { get; private set; } public static IConfiguration Configuration { get; set; } public static string HostingFullName { get; private set; } - - ILogger logger; + + public static IServiceCollection Services { get; private set; } + + + + Microsoft.Extensions.Logging.ILogger logger; public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) { - var devtag = env.IsDevelopment()?"D":""; - var prodtag = env.IsProduction()?"P":""; - var stagetag = env.IsStaging()?"S":""; + var devtag = env.IsDevelopment() ? "D" : ""; + var prodtag = env.IsProduction() ? "P" : ""; + var stagetag = env.IsStaging() ? "S" : ""; HostingFullName = $"{appEnv.RuntimeFramework.FullName} [{env.EnvironmentName}:{prodtag}{devtag}{stagetag}]"; // Set up configuration sources. - + var builder = new ConfigurationBuilder() .AddEnvironmentVariables() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); - + Configuration = builder.Build(); - ConnectionString = Configuration["Data:DefaultConnection:ConnectionString"]; + ConnectionString = Configuration["ConnectionStrings:Default"]; } - public void ConfigureServices (IServiceCollection services) + public void ConfigureServices(IServiceCollection services) { services.AddOptions(); var cxSettings = Configuration.GetSection("Connection"); @@ -55,24 +73,26 @@ namespace cli var smtpSettingsconf = Configuration.GetSection("Smtp"); services.Configure(smtpSettingsconf); + services.Configure(Configuration.GetSection("gen_mvc")); services.AddInstance(typeof(ILoggerFactory), new LoggerFactory()); services.AddTransient(typeof(IEmailSender), typeof(MailSender)); services.AddTransient(typeof(RazorEngineHost), typeof(YaRazorEngineHost)); - services.AddEntityFramework().AddNpgsql().AddDbContext(); + services.AddTransient(typeof(MvcGenerator), typeof(MvcGenerator)); + services.AddEntityFramework().AddNpgsql().AddDbContext( + db => db.UseNpgsql(ConnectionString) + ); + services.AddTransient((s) => new RazorTemplateEngine(s.GetService())); + services.AddTransient(typeof(IModelTypesLocator), typeof(ModelTypesLocator)); + services.AddTransient(typeof(ILibraryExporter), typeof(RuntimeLibraryExporter)); services.AddLogging(); services.AddTransient(); services.AddLocalization(options => { options.ResourcesPath = "Resources"; }); - - services.AddEntityFramework() - .AddNpgsql() - .AddDbContext( - db => db.UseNpgsql(ConnectionString) - ); - services.Configure(options => + + services.Configure(options => { options.SignInScheme = "Bearer"; }); @@ -81,9 +101,120 @@ namespace cli services.AddAuthentication(); + services.AddSingleton(typeof(IApplicationEnvironment), svs => PlatformServices.Default.Application); + services.AddSingleton(typeof(IRuntimeEnvironment), svs => PlatformServices.Default.Runtime); + services.AddSingleton(typeof(IAssemblyLoadContextAccessor), svs => PlatformServices.Default.AssemblyLoadContextAccessor); + services.AddSingleton(typeof(IAssemblyLoaderContainer), svs => PlatformServices.Default.AssemblyLoaderContainer); + services.AddSingleton(typeof(ILibraryManager), svs => PlatformServices.Default.LibraryManager); + + services.AddSingleton(typeof(BootstrapperContext), + svs => new BootstrapperContext + { + RuntimeDirectory = Path.GetDirectoryName(typeof(BootstrapperContext).Assembly.Location), + ApplicationBase = Configuration["gen_mvc:AppBase"], + // NOTE(anurse): Mono is always "dnx451" (for now). + TargetFramework = new FrameworkName("DNX", new Version(4, 5, 1)), + RuntimeType = "Mono" + } + ); + + + services.AddTransient(typeof(CompilationEngine), + svs => { + var logger = svs.GetService().CreateLogger(); + var project = svs.GetService(); + var env = new ApplicationEnvironment(project, + PlatformServices.Default.Application.RuntimeFramework, + PlatformServices.Default.Application.Configuration, + PlatformServices.Default.Application + ); + logger.LogInformation("app name: "+env.ApplicationName); + + return new CompilationEngine( + new CompilationEngineContext(PlatformServices.Default.Application, + PlatformServices.Default.Runtime, + PlatformServices.Default.AssemblyLoadContextAccessor.Default, new CompilationCache())); + }); + services.AddTransient(typeof(IFrameworkReferenceResolver), + svs => new FrameworkReferenceResolver()); + + services.AddTransient( + typeof(Project), svs => + { + Project project = null; + var diag = new List(); + var settings = svs.GetService>(); + if (Project.TryGetProject(settings.Value.AppBase, out project, diag)) + { + return project; + } + return null; + } + ); + + services.AddTransient( + typeof(ILibraryExporter), + svs => + { + var settings = svs.GetService>(); + var compilationEngine = svs.GetService(); + var bootstrappercontext = svs.GetService(); + var project = svs.GetService(); + if (settings == null) + throw new Exception("settings are missing to generate some server code (GenMvcSettings) "); + + return + new RuntimeLibraryExporter( + () => compilationEngine.CreateProjectExporter + (project, bootstrappercontext.TargetFramework, settings.Value.ConfigurationName)); + + } + + ); + services.AddTransient(typeof(IEntityFrameworkService), typeof(EntityFrameworkServices)); + services.AddTransient(typeof(IDbContextEditorServices), typeof(DbContextEditorServices)); + services.AddTransient(typeof(IFilesLocator), typeof(FilesLocator)); + services.AddTransient(typeof( + Microsoft.Extensions.CodeGeneration.Templating.ITemplating), typeof( + Microsoft.Extensions.CodeGeneration.Templating.RazorTemplating)); + services.AddTransient( + typeof(Microsoft.Extensions.CodeGeneration.Templating.Compilation.ICompilationService), + typeof(Microsoft.Extensions.CodeGeneration.Templating.Compilation.RoslynCompilationService)); + +services.AddTransient( + typeof( +Microsoft.Extensions.CodeGeneration.ICodeGeneratorActionsService), + typeof(Microsoft.Extensions.CodeGeneration.CodeGeneratorActionsService)); + + + services.AddTransient(typeof(Microsoft.Dnx.Compilation.ICompilerOptionsProvider), + svs => + { + var bsContext = svs.GetService(); + var compileEngine = svs.GetService(); + + var applicationHostContext = new ApplicationHostContext + { + ProjectDirectory = bsContext.ApplicationBase, + RuntimeIdentifiers = new string[] { "dnx451" }, + TargetFramework = bsContext.TargetFramework + }; + + var libraries = ApplicationHostContext.GetRuntimeLibraries(applicationHostContext, throwOnInvalidLockFile: true); + var projects = libraries.Where(p => p.Type == LibraryTypes.Project) + .ToDictionary(p => p.Identity.Name, p => (ProjectDescription)p); + + return new CompilerOptionsProvider(projects); + }); + services.AddMvc(); + services.AddTransient(typeof(IPackageInstaller),typeof(PackageInstaller)); + services.AddTransient(typeof(Microsoft.Extensions.CodeGeneration.ILogger),typeof(Microsoft.Extensions.CodeGeneration.ConsoleLogger)); + + Services = services; + } - public void Configure (IApplicationBuilder app, IHostingEnvironment env, + public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions siteSettings, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(Configuration.GetSection("Logging")); diff --git a/src/cli/appsettings.Development.json b/src/cli/appsettings.Development.json index 20e8e469..98021872 100644 --- a/src/cli/appsettings.Development.json +++ b/src/cli/appsettings.Development.json @@ -18,9 +18,15 @@ "Microsoft": "Warning" } }, - "Data": { - "DefaultConnection": { - "ConnectionString": "Server=localhost;Port=5432;Database=YavscDev;Username=yavscdev;Password=admin;" - } + "ConnectionStrings": { + "Default":"Server=localhost;Port=5432;Database=YavscDev;Username=yavscdev;Password=admin;" + }, + "gen_mvc" : { + "NameSpace": "Yavsc", + "AppBase": "../Yavsc", + "RelativePath": "Controllers/Generated", + "DbContextFullName": "Yavsc.Models.ApplicationDbContext", + "ControllerName": "LiveFlowController", + "ModelFullName": "Yavsc.Models.Streaming.LiveFlow" } } \ No newline at end of file diff --git a/src/cli/appsettings.json b/src/cli/appsettings.json index d6b3aaf4..c55fb993 100644 --- a/src/cli/appsettings.json +++ b/src/cli/appsettings.json @@ -22,9 +22,15 @@ "Microsoft": "Warning" } }, - "Data": { - "DefaultConnection": { - "ConnectionString": "[sbConStr]" - } + "ConnectionStrings": { + "Default":"[your default connection string]" + }, + "gen_mvc" : { + "NameSpace": "Yavsc", + "AppBase": "../Yavsc", + "RelativePath": "../Yavsc/Controllers/Generated", + "DbContextFullName": "Yavsc.Models.ApplicationDbContext", + "ControllerName": "LiveFlowController", + "ModelFullName": "Yavsc.Models.Streaming.LiveFlow" } } diff --git a/src/cli/project.json b/src/cli/project.json index c8471919..10226fed 100644 --- a/src/cli/project.json +++ b/src/cli/project.json @@ -26,7 +26,8 @@ "Microsoft.AspNet.Mvc": "6.0.0-rc1-*", "Microsoft.AspNet.SignalR.Client": "2.2.1", "Microsoft.CodeAnalysis": "1.1.0-rc1-20151109-01", - "Microsoft.Extensions.CodeGeneration": "1.0.0-rc1-final", + "Microsoft.Extensions.CodeGeneration": "1.0.0-beta5", + "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final", "Microsoft.Extensions.Configuration.Abstractions": "1.0.0-rc1-final", "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final", "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final", @@ -58,12 +59,14 @@ "version": "1.0.5-rc22", "target": "package" }, - "Yavsc.Lib.Portable": "1.0.2", - "OAuth.AspNet.AuthServer": { "target": "project" } + "Microsoft.Dnx.Host": "1.0.0-rc1-final", + "Microsoft.Dnx.Runtime": "1.0.0-rc1-final", + "Microsoft.Dnx.DesignTimeHost": "1.0.0-rc1-final" }, "frameworks": { "dnx451": { - "System.Net": "4.0.0" + "System.Net": "4.0.0.0", + "System.Xml": "4.0.0.0" } } -} +} \ No newline at end of file