UNPKG

@re-shell/cli

Version:

Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja

1,621 lines (1,370 loc) 51.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.aspnetHotReloadTemplate = void 0; exports.aspnetHotReloadTemplate = { id: 'aspnet-hotreload', name: 'aspnet-hotreload', displayName: 'ASP.NET Core with Hot Reload', description: 'High-productivity .NET API with dotnet watch hot reload and live development features', language: 'csharp', framework: 'aspnet-hotreload', version: '1.0.0', tags: ['aspnet', 'hotreload', 'watch', 'development', 'productivity'], port: 5000, dependencies: {}, features: ['authentication', 'database', 'validation', 'logging', 'testing'], files: { // Project file with hot reload packages '{{serviceName}}.csproj': `<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <GenerateDocumentationFile>true</GenerateDocumentationFile> <!-- Hot Reload Configuration --> <UseAppHost>true</UseAppHost> <EnableDefaultContentItems>false</EnableDefaultContentItems> <DefaultItemExcludes>$(DefaultItemExcludes);wwwroot/**</DefaultItemExcludes> </PropertyGroup> <PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <DefineConstants>DEBUG;TRACE</DefineConstants> <DebugType>portable</DebugType> <Optimize>false</Optimize> <TreatWarningsAsErrors>false</TreatWarningsAsErrors> <WarningLevel>4</WarningLevel> <!-- Enable Hot Reload --> <UseHotReload>true</UseHotReload> <SupportedOSPlatformVersion>10.0</SupportedOSPlatformVersion> </PropertyGroup> <ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.0" /> <PackageReference Include="AutoMapper" Version="12.0.1" /> <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" /> <PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" /> <PackageReference Include="Serilog.AspNetCore" Version="8.0.0" /> <PackageReference Include="Serilog.Sinks.Console" Version="5.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" /> <PackageReference Include="BCrypt.Net-Next" Version="4.0.3" /> <!-- Hot Reload Development Packages --> <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" Condition="'$(Configuration)' == 'Debug'" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" Condition="'$(Configuration)' == 'Debug'" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.0" Condition="'$(Configuration)' == 'Debug'" /> </ItemGroup> <!-- Watch Configuration for Hot Reload --> <ItemGroup> <Watch Include="**/*.cs" /> <Watch Include="**/*.cshtml" /> <Watch Include="**/*.css" /> <Watch Include="**/*.js" /> <Watch Include="**/*.json" Exclude="bin/**/*;obj/**/*" /> <Watch Include="**/*.yml" /> <Watch Include="**/*.yaml" /> <Watch Remove="bin/**/*" /> <Watch Remove="obj/**/*" /> <Watch Remove="logs/**/*" /> <Watch Remove="**/*.tmp" /> </ItemGroup> <!-- Content Files for Watch --> <ItemGroup> <Content Include="appsettings*.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> <Content Include="wwwroot/**/*" CopyToOutputDirectory="PreserveNewest" /> </ItemGroup> </Project>`, // Program.cs with hot reload optimizations 'Program.cs': `using {{serviceName}}.Data; using {{serviceName}}.Services; using {{serviceName}}.Models; using {{serviceName}}.DTOs; using {{serviceName}}.Profiles; using {{serviceName}}.Validators; using {{serviceName}}.Extensions; using Microsoft.EntityFrameworkCore; using AutoMapper; using FluentValidation; using Serilog; using Microsoft.OpenApi.Models; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Text; var builder = WebApplication.CreateBuilder(args); // Configure Serilog with Hot Reload optimizations Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(builder.Configuration) .Enrich.FromLogContext() .WriteTo.Console() .WriteTo.File("logs/log-.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); builder.Host.UseSerilog(); // Add services to the container builder.Services.AddControllers(); // Add Razor Runtime Compilation for development hot reload if (builder.Environment.IsDevelopment()) { builder.Services.AddRazorPages().AddRazorRuntimeCompilation(); builder.Services.AddMvc().AddRazorRuntimeCompilation(); } builder.Services.AddEndpointsApiExplorer(); // Configure Entity Framework with optimizations for development builder.Services.AddDbContext<ApplicationDbContext>(options => { if (builder.Environment.IsEnvironment("Testing")) { options.UseInMemoryDatabase("TestDb"); } else { var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); options.UseSqlServer(connectionString); // Enable sensitive data logging and detailed errors in development if (builder.Environment.IsDevelopment()) { options.EnableSensitiveDataLogging(); options.EnableDetailedErrors(); options.LogTo(Console.WriteLine, LogLevel.Information); } } }); // Configure AutoMapper builder.Services.AddAutoMapper(typeof(UserProfile), typeof(ProductProfile)); // Configure FluentValidation builder.Services.AddValidatorsFromAssemblyContaining<CreateUserDtoValidator>(); // Configure Swagger/OpenAPI with hot reload support builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "{{serviceName}} API", Version = "v1", Description = "High-productivity API with dotnet watch hot reload", Contact = new OpenApiContact { Name = "{{serviceName}} Team", Email = "team@{{serviceName}}.com" } }); // Include XML comments var xmlFile = $"{System.Reflection.Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); if (File.Exists(xmlPath)) { c.IncludeXmlComments(xmlPath); } // Configure JWT authentication in Swagger c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }, Scheme = "oauth2", Name = "Bearer", In = ParameterLocation.Header, }, new List<string>() } }); }); // Configure JWT Authentication var jwtSettings = builder.Configuration.GetSection("JwtSettings"); var secretKey = jwtSettings["SecretKey"]; builder.Services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings["Issuer"], ValidAudience = jwtSettings["Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey!)) }; }); // Configure CORS for development if (builder.Environment.IsDevelopment()) { builder.Services.AddCors(options => { options.AddPolicy("Development", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); } // Register application services builder.Services.AddScoped<IUserService, UserService>(); builder.Services.AddScoped<IProductService, ProductService>(); builder.Services.AddScoped<IOrderService, OrderService>(); builder.Services.AddScoped<IAuthService, AuthService>(); // Add development services if (builder.Environment.IsDevelopment()) { builder.Services.AddScoped<IDevelopmentService, DevelopmentService>(); builder.Services.AddScoped<IHotReloadService, HotReloadService>(); } var app = builder.Build(); // Configure the HTTP request pipeline with hot reload optimizations if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "{{serviceName}} API v1"); c.RoutePrefix = string.Empty; // Set Swagger UI at apps root c.DisplayRequestDuration(); c.EnableDeepLinking(); c.EnableFilter(); c.ShowExtensions(); c.EnableValidator(); }); // Enable CORS for development app.UseCors("Development"); // Add development middleware app.UseMiddleware<HotReloadMiddleware>(); } else { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); // Add development endpoints if (app.Environment.IsDevelopment()) { app.MapGet("/dev/info", () => new { Environment = app.Environment.EnvironmentName, ProcessId = Environment.ProcessId, MachineName = Environment.MachineName, WorkingSet = GC.GetTotalMemory(false), AssemblyVersion = typeof(Program).Assembly.GetName().Version?.ToString(), DotNetVersion = Environment.Version.ToString(), HotReloadEnabled = true }).WithTags("Development"); app.MapGet("/dev/reload", (IHotReloadService hotReloadService) => { return hotReloadService.TriggerReload(); }).WithTags("Development"); } // Ensure database is created (skip in testing environment) if (!app.Environment.IsEnvironment("Testing")) { using var scope = app.Services.CreateScope(); var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); context.Database.EnsureCreated(); } app.Run(); // Make the implicit Program class public for testing public partial class Program { }`, // Hot Reload Middleware 'Middleware/HotReloadMiddleware.cs': `using System.Diagnostics; namespace {{serviceName}}.Extensions; public class HotReloadMiddleware { private readonly RequestDelegate _next; private readonly ILogger<HotReloadMiddleware> _logger; private readonly IWebHostEnvironment _environment; public HotReloadMiddleware(RequestDelegate next, ILogger<HotReloadMiddleware> logger, IWebHostEnvironment environment) { _next = next; _logger = logger; _environment = environment; } public async Task InvokeAsync(HttpContext context) { if (_environment.IsDevelopment()) { var stopwatch = Stopwatch.StartNew(); // Add hot reload headers context.Response.Headers.Add("X-Hot-Reload", "enabled"); context.Response.Headers.Add("X-Process-Id", Environment.ProcessId.ToString()); try { await _next(context); } finally { stopwatch.Stop(); // Log request details for development _logger.LogInformation("Request {Method} {Path} completed in {ElapsedMs}ms", context.Request.Method, context.Request.Path, stopwatch.ElapsedMilliseconds); } } else { await _next(context); } } }`, // Hot Reload Service 'Services/IHotReloadService.cs': `namespace {{serviceName}}.Services; public interface IHotReloadService { Task<object> TriggerReload(); Task<object> GetReloadStatus(); Task<object> GetWatchedFiles(); Task ClearCache(); }`, 'Services/HotReloadService.cs': `using System.Reflection; namespace {{serviceName}}.Services; public class HotReloadService : IHotReloadService { private readonly ILogger<HotReloadService> _logger; private readonly IWebHostEnvironment _environment; private static readonly Dictionary<string, DateTime> _fileTimestamps = new(); public HotReloadService(ILogger<HotReloadService> logger, IWebHostEnvironment environment) { _logger = logger; _environment = environment; } public Task<object> TriggerReload() { _logger.LogInformation("Hot reload triggered manually"); return Task.FromResult<object>(new { Message = "Hot reload triggered", Timestamp = DateTime.UtcNow, ProcessId = Environment.ProcessId, Environment = _environment.EnvironmentName, AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString() }); } public Task<object> GetReloadStatus() { var status = new { HotReloadEnabled = _environment.IsDevelopment(), ProcessId = Environment.ProcessId, StartTime = Process.GetCurrentProcess().StartTime, Uptime = DateTime.UtcNow - Process.GetCurrentProcess().StartTime, WorkingSet = GC.GetTotalMemory(false), GCCount = GC.CollectionCount(0), Environment = _environment.EnvironmentName, ContentRoot = _environment.ContentRootPath, WebRoot = _environment.WebRootPath }; return Task.FromResult<object>(status); } public Task<object> GetWatchedFiles() { var watchedExtensions = new[] { ".cs", ".cshtml", ".css", ".js", ".json", ".yml", ".yaml" }; var watchedFiles = new List<object>(); if (Directory.Exists(_environment.ContentRootPath)) { foreach (var extension in watchedExtensions) { var files = Directory.GetFiles(_environment.ContentRootPath, $"*{extension}", SearchOption.AllDirectories) .Where(f => !f.Contains("bin") && !f.Contains("obj") && !f.Contains("logs")) .Take(50) // Limit to prevent overwhelming response .Select(f => new { Path = Path.GetRelativePath(_environment.ContentRootPath, f), LastModified = File.GetLastWriteTime(f), Size = new FileInfo(f).Length }); watchedFiles.AddRange(files); } } return Task.FromResult<object>(new { WatchedExtensions = watchedExtensions, TotalFiles = watchedFiles.Count, Files = watchedFiles.OrderByDescending(f => ((dynamic)f).LastModified).Take(20) }); } public Task ClearCache() { _fileTimestamps.Clear(); GC.Collect(); GC.WaitForPendingFinalizers(); _logger.LogInformation("Cache cleared and garbage collection triggered"); return Task.CompletedTask; } }`, // Development Service 'Services/IDevelopmentService.cs': `namespace {{serviceName}}.Services; public interface IDevelopmentService { Task<object> GetSystemInfo(); Task<object> GetDatabaseInfo(); Task<object> GetConfigurationInfo(); Task<object> GetEndpointsInfo(); Task<object> GetHealthCheck(); }`, 'Services/DevelopmentService.cs': `using Microsoft.EntityFrameworkCore; using System.Reflection; using {{serviceName}}.Data; namespace {{serviceName}}.Services; public class DevelopmentService : IDevelopmentService { private readonly ApplicationDbContext _context; private readonly IConfiguration _configuration; private readonly IWebHostEnvironment _environment; private readonly ILogger<DevelopmentService> _logger; public DevelopmentService( ApplicationDbContext context, IConfiguration configuration, IWebHostEnvironment environment, ILogger<DevelopmentService> logger) { _context = context; _configuration = configuration; _environment = environment; _logger = logger; } public Task<object> GetSystemInfo() { var systemInfo = new { Environment = _environment.EnvironmentName, MachineName = Environment.MachineName, ProcessId = Environment.ProcessId, UserName = Environment.UserName, OSVersion = Environment.OSVersion.ToString(), DotNetVersion = Environment.Version.ToString(), ProcessorCount = Environment.ProcessorCount, WorkingSet = Environment.WorkingSet, SystemPageSize = Environment.SystemPageSize, TickCount = Environment.TickCount64, AssemblyVersion = Assembly.GetExecutingAssembly().GetName().Version?.ToString(), ContentRootPath = _environment.ContentRootPath, WebRootPath = _environment.WebRootPath }; return Task.FromResult<object>(systemInfo); } public async Task<object> GetDatabaseInfo() { try { var canConnect = await _context.Database.CanConnectAsync(); var connectionString = _context.Database.GetConnectionString(); var dbInfo = new { CanConnect = canConnect, DatabaseProvider = _context.Database.ProviderName, ConnectionString = MaskConnectionString(connectionString), PendingMigrations = await _context.Database.GetPendingMigrationsAsync(), AppliedMigrations = await _context.Database.GetAppliedMigrationsAsync() }; return dbInfo; } catch (Exception ex) { _logger.LogError(ex, "Error getting database info"); return new { Error = ex.Message, CanConnect = false }; } } public Task<object> GetConfigurationInfo() { var configInfo = new { Environment = _environment.EnvironmentName, ConfigurationSources = _configuration.AsEnumerable() .Where(kvp => !IsSecretKey(kvp.Key)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value), EnvironmentVariables = Environment.GetEnvironmentVariables() .Cast<System.Collections.DictionaryEntry>() .Where(de => !IsSecretKey(de.Key?.ToString() ?? "")) .ToDictionary(de => de.Key?.ToString() ?? "", de => de.Value?.ToString() ?? "") }; return Task.FromResult<object>(configInfo); } public Task<object> GetEndpointsInfo() { // This would typically use IEndpointDataSource to get all registered endpoints var endpointsInfo = new { Message = "Endpoint discovery requires additional setup", DevelopmentEndpoints = new[] { "/dev/info", "/dev/reload", "/dev/system", "/dev/database", "/dev/config", "/dev/health", "/swagger" }, ApiEndpoints = new[] { "/api/users", "/api/products", "/api/orders" } }; return Task.FromResult<object>(endpointsInfo); } public async Task<object> GetHealthCheck() { var healthChecks = new List<object>(); // Database Health try { var canConnect = await _context.Database.CanConnectAsync(); healthChecks.Add(new { Service = "Database", Status = canConnect ? "Healthy" : "Unhealthy" }); } catch (Exception ex) { healthChecks.Add(new { Service = "Database", Status = "Unhealthy", Error = ex.Message }); } // Memory Health var workingSet = Environment.WorkingSet; var memoryStatus = workingSet < 500_000_000 ? "Healthy" : "Warning"; // 500MB threshold healthChecks.Add(new { Service = "Memory", Status = memoryStatus, WorkingSet = workingSet }); // GC Health var gen0Collections = GC.CollectionCount(0); var gen1Collections = GC.CollectionCount(1); var gen2Collections = GC.CollectionCount(2); healthChecks.Add(new { Service = "GarbageCollector", Status = "Healthy", Gen0Collections = gen0Collections, Gen1Collections = gen1Collections, Gen2Collections = gen2Collections }); return new { OverallStatus = healthChecks.All(hc => ((dynamic)hc).Status == "Healthy") ? "Healthy" : "Degraded", Timestamp = DateTime.UtcNow, Checks = healthChecks }; } private static string? MaskConnectionString(string? connectionString) { if (string.IsNullOrEmpty(connectionString)) return connectionString; // Mask password in connection string return System.Text.RegularExpressions.Regex.Replace( connectionString, @"(Password|Pwd)=([^;]*)", "$1=***", System.Text.RegularExpressions.RegexOptions.IgnoreCase); } private static bool IsSecretKey(string key) { var secretKeywords = new[] { "password", "secret", "key", "token", "connectionstring" }; return secretKeywords.Any(keyword => key.ToLowerInvariant().Contains(keyword)); } }`, // Enhanced Development Controller 'Controllers/DevelopmentController.cs': `using Microsoft.AspNetCore.Mvc; using {{serviceName}}.Services; namespace {{serviceName}}.Controllers; /// <summary> /// Development utilities and hot reload support /// </summary> [ApiController] [Route("dev")] public class DevelopmentController : ControllerBase { private readonly IDevelopmentService _developmentService; private readonly IHotReloadService _hotReloadService; private readonly IWebHostEnvironment _environment; public DevelopmentController( IDevelopmentService developmentService, IHotReloadService hotReloadService, IWebHostEnvironment environment) { _developmentService = developmentService; _hotReloadService = hotReloadService; _environment = environment; } /// <summary> /// Get system information /// </summary> [HttpGet("system")] public async Task<ActionResult<object>> GetSystemInfo() { if (!_environment.IsDevelopment()) return NotFound(); var info = await _developmentService.GetSystemInfo(); return Ok(info); } /// <summary> /// Get database information /// </summary> [HttpGet("database")] public async Task<ActionResult<object>> GetDatabaseInfo() { if (!_environment.IsDevelopment()) return NotFound(); var info = await _developmentService.GetDatabaseInfo(); return Ok(info); } /// <summary> /// Get configuration information /// </summary> [HttpGet("config")] public async Task<ActionResult<object>> GetConfigInfo() { if (!_environment.IsDevelopment()) return NotFound(); var info = await _developmentService.GetConfigurationInfo(); return Ok(info); } /// <summary> /// Get endpoints information /// </summary> [HttpGet("endpoints")] public async Task<ActionResult<object>> GetEndpointsInfo() { if (!_environment.IsDevelopment()) return NotFound(); var info = await _developmentService.GetEndpointsInfo(); return Ok(info); } /// <summary> /// Get health check information /// </summary> [HttpGet("health")] public async Task<ActionResult<object>> GetHealthCheck() { if (!_environment.IsDevelopment()) return NotFound(); var health = await _developmentService.GetHealthCheck(); return Ok(health); } /// <summary> /// Trigger hot reload /// </summary> [HttpPost("reload")] public async Task<ActionResult<object>> TriggerReload() { if (!_environment.IsDevelopment()) return NotFound(); var result = await _hotReloadService.TriggerReload(); return Ok(result); } /// <summary> /// Get hot reload status /// </summary> [HttpGet("reload/status")] public async Task<ActionResult<object>> GetReloadStatus() { if (!_environment.IsDevelopment()) return NotFound(); var status = await _hotReloadService.GetReloadStatus(); return Ok(status); } /// <summary> /// Get watched files information /// </summary> [HttpGet("watch")] public async Task<ActionResult<object>> GetWatchedFiles() { if (!_environment.IsDevelopment()) return NotFound(); var files = await _hotReloadService.GetWatchedFiles(); return Ok(files); } /// <summary> /// Clear application cache /// </summary> [HttpPost("cache/clear")] public async Task<ActionResult> ClearCache() { if (!_environment.IsDevelopment()) return NotFound(); await _hotReloadService.ClearCache(); return Ok(new { Message = "Cache cleared successfully" }); } }`, // Basic entities and services for the template 'Models/User.cs': `using System.ComponentModel.DataAnnotations; namespace {{serviceName}}.Models; public class User { public int Id { get; set; } [Required] [StringLength(100)] public string Name { get; set; } = string.Empty; [Required] [EmailAddress] [StringLength(255)] public string Email { get; set; } = string.Empty; [Required] public string PasswordHash { get; set; } = string.Empty; [StringLength(20)] public string? PhoneNumber { get; set; } public DateTime DateOfBirth { get; set; } [StringLength(500)] public string? Address { get; set; } [StringLength(100)] public string? City { get; set; } [StringLength(100)] public string? Country { get; set; } public bool IsActive { get; set; } = true; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } // Navigation properties public virtual ICollection<Order> Orders { get; set; } = new List<Order>(); }`, 'Models/Product.cs': `using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace {{serviceName}}.Models; public class Product { public int Id { get; set; } [Required] [StringLength(200)] public string Name { get; set; } = string.Empty; [StringLength(1000)] public string? Description { get; set; } [Required] [Column(TypeName = "decimal(18,2)")] public decimal Price { get; set; } [StringLength(100)] public string? Category { get; set; } [StringLength(50)] public string? Brand { get; set; } public int StockQuantity { get; set; } [StringLength(500)] public string? ImageUrl { get; set; } public bool IsActive { get; set; } = true; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } // Navigation properties public virtual ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>(); }`, 'Models/Order.cs': `using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace {{serviceName}}.Models; public class Order { public int Id { get; set; } [Required] public int UserId { get; set; } [Required] [StringLength(50)] public string OrderNumber { get; set; } = string.Empty; [Required] [Column(TypeName = "decimal(18,2)")] public decimal TotalAmount { get; set; } [Required] [StringLength(50)] public string Status { get; set; } = "Pending"; [StringLength(500)] public string? ShippingAddress { get; set; } [StringLength(500)] public string? Notes { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } // Navigation properties public virtual User User { get; set; } = null!; public virtual ICollection<OrderItem> OrderItems { get; set; } = new List<OrderItem>(); }`, 'Models/OrderItem.cs': `using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace {{serviceName}}.Models; public class OrderItem { public int Id { get; set; } [Required] public int OrderId { get; set; } [Required] public int ProductId { get; set; } [Required] public int Quantity { get; set; } [Required] [Column(TypeName = "decimal(18,2)")] public decimal UnitPrice { get; set; } [Required] [Column(TypeName = "decimal(18,2)")] public decimal TotalPrice { get; set; } // Navigation properties public virtual Order Order { get; set; } = null!; public virtual Product Product { get; set; } = null!; }`, // Data/ApplicationDbContext.cs 'Data/ApplicationDbContext.cs': `using Microsoft.EntityFrameworkCore; using {{serviceName}}.Models; namespace {{serviceName}}.Data; public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<User> Users { get; set; } public DbSet<Product> Products { get; set; } public DbSet<Order> Orders { get; set; } public DbSet<OrderItem> OrderItems { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // User configuration modelBuilder.Entity<User>(entity => { entity.HasKey(e => e.Id); entity.HasIndex(e => e.Email).IsUnique(); entity.Property(e => e.Name).IsRequired().HasMaxLength(100); entity.Property(e => e.Email).IsRequired().HasMaxLength(255); entity.Property(e => e.PasswordHash).IsRequired(); }); // Product configuration modelBuilder.Entity<Product>(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Name).IsRequired().HasMaxLength(200); entity.Property(e => e.Price).HasColumnType("decimal(18,2)"); }); // Order configuration modelBuilder.Entity<Order>(entity => { entity.HasKey(e => e.Id); entity.HasIndex(e => e.OrderNumber).IsUnique(); entity.Property(e => e.OrderNumber).IsRequired().HasMaxLength(50); entity.Property(e => e.TotalAmount).HasColumnType("decimal(18,2)"); entity.Property(e => e.Status).IsRequired().HasMaxLength(50); entity.HasOne(e => e.User) .WithMany(u => u.Orders) .HasForeignKey(e => e.UserId) .OnDelete(DeleteBehavior.Restrict); }); // OrderItem configuration modelBuilder.Entity<OrderItem>(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.UnitPrice).HasColumnType("decimal(18,2)"); entity.Property(e => e.TotalPrice).HasColumnType("decimal(18,2)"); entity.HasOne(e => e.Order) .WithMany(o => o.OrderItems) .HasForeignKey(e => e.OrderId) .OnDelete(DeleteBehavior.Cascade); entity.HasOne(e => e.Product) .WithMany(p => p.OrderItems) .HasForeignKey(e => e.ProductId) .OnDelete(DeleteBehavior.Restrict); }); // Seed data SeedData(modelBuilder); } private static void SeedData(ModelBuilder modelBuilder) { // Seed Products modelBuilder.Entity<Product>().HasData( new Product { Id = 1, Name = "Laptop Pro 15", Description = "High-performance laptop for professionals", Price = 1299.99m, Category = "Electronics", Brand = "TechCorp", StockQuantity = 50, ImageUrl = "https://example.com/laptop.jpg", IsActive = true, CreatedAt = DateTime.UtcNow }, new Product { Id = 2, Name = "Wireless Mouse", Description = "Ergonomic wireless mouse with precision tracking", Price = 49.99m, Category = "Electronics", Brand = "TechCorp", StockQuantity = 200, ImageUrl = "https://example.com/mouse.jpg", IsActive = true, CreatedAt = DateTime.UtcNow }, new Product { Id = 3, Name = "Office Chair", Description = "Comfortable ergonomic office chair", Price = 299.99m, Category = "Furniture", Brand = "ComfortPlus", StockQuantity = 30, ImageUrl = "https://example.com/chair.jpg", IsActive = true, CreatedAt = DateTime.UtcNow } ); } }`, // Basic service stubs 'Services/IUserService.cs': `using {{serviceName}}.DTOs; namespace {{serviceName}}.Services; public interface IUserService { Task<IEnumerable<UserDto>> GetAllAsync(); Task<UserDto?> GetByIdAsync(int id); }`, 'Services/UserService.cs': `using Microsoft.EntityFrameworkCore; using AutoMapper; using {{serviceName}}.Data; using {{serviceName}}.DTOs; namespace {{serviceName}}.Services; public class UserService : IUserService { private readonly ApplicationDbContext _context; private readonly IMapper _mapper; public UserService(ApplicationDbContext context, IMapper mapper) { _context = context; _mapper = mapper; } public async Task<IEnumerable<UserDto>> GetAllAsync() { var users = await _context.Users.AsNoTracking().ToListAsync(); return _mapper.Map<IEnumerable<UserDto>>(users); } public async Task<UserDto?> GetByIdAsync(int id) { var user = await _context.Users.AsNoTracking().FirstOrDefaultAsync(u => u.Id == id); return user != null ? _mapper.Map<UserDto>(user) : null; } }`, // Stub services 'Services/IProductService.cs': `namespace {{serviceName}}.Services; public interface IProductService { }`, 'Services/ProductService.cs': `namespace {{serviceName}}.Services; public class ProductService : IProductService { }`, 'Services/IOrderService.cs': `namespace {{serviceName}}.Services; public interface IOrderService { }`, 'Services/OrderService.cs': `namespace {{serviceName}}.Services; public class OrderService : IOrderService { }`, 'Services/IAuthService.cs': `namespace {{serviceName}}.Services; public interface IAuthService { }`, 'Services/AuthService.cs': `namespace {{serviceName}}.Services; public class AuthService : IAuthService { }`, // DTOs 'DTOs/UserDtos.cs': `namespace {{serviceName}}.DTOs; public class UserDto { public int Id { get; set; } public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public string? PhoneNumber { get; set; } public DateTime DateOfBirth { get; set; } public string? Address { get; set; } public string? City { get; set; } public string? Country { get; set; } public bool IsActive { get; set; } public DateTime CreatedAt { get; set; } public DateTime? UpdatedAt { get; set; } } public class CreateUserDto { public string Name { get; set; } = string.Empty; public string Email { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public string? PhoneNumber { get; set; } public DateTime DateOfBirth { get; set; } public string? Address { get; set; } public string? City { get; set; } public string? Country { get; set; } }`, // AutoMapper Profiles 'Profiles/UserProfile.cs': `using AutoMapper; using {{serviceName}}.Models; using {{serviceName}}.DTOs; namespace {{serviceName}}.Profiles; public class UserProfile : Profile { public UserProfile() { CreateMap<User, UserDto>(); CreateMap<CreateUserDto, User>() .ForMember(dest => dest.Id, opt => opt.Ignore()) .ForMember(dest => dest.PasswordHash, opt => opt.Ignore()) .ForMember(dest => dest.IsActive, opt => opt.MapFrom(src => true)) .ForMember(dest => dest.CreatedAt, opt => opt.MapFrom(src => DateTime.UtcNow)) .ForMember(dest => dest.UpdatedAt, opt => opt.Ignore()) .ForMember(dest => dest.Orders, opt => opt.Ignore()); } }`, 'Profiles/ProductProfile.cs': `using AutoMapper; namespace {{serviceName}}.Profiles; public class ProductProfile : Profile { public ProductProfile() { // Add product mappings here } }`, // Validator 'Validators/CreateUserDtoValidator.cs': `using FluentValidation; using {{serviceName}}.DTOs; namespace {{serviceName}}.Validators; public class CreateUserDtoValidator : AbstractValidator<CreateUserDto> { public CreateUserDtoValidator() { RuleFor(x => x.Name) .NotEmpty() .Length(2, 100); RuleFor(x => x.Email) .NotEmpty() .EmailAddress() .MaximumLength(255); RuleFor(x => x.Password) .NotEmpty() .MinimumLength(6) .MaximumLength(100); } }`, // Configuration files 'appsettings.json': `{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database={{serviceName}}Db;Trusted_Connection=true;MultipleActiveResultSets=true" }, "JwtSettings": { "SecretKey": "your-256-bit-secret-key-here-make-it-long-and-secure", "Issuer": "{{serviceName}}", "Audience": "{{serviceName}}Users", "ExpirationDays": 7 }, "Serilog": { "Using": ["Serilog.Sinks.Console", "Serilog.Sinks.File"], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning" } }, "WriteTo": [ { "Name": "Console", "Args": { "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {NewLine}{Exception}" } }, { "Name": "File", "Args": { "path": "logs/log-.txt", "rollingInterval": "Day", "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} {Level:u3}] {Message:lj} {NewLine}{Exception}" } } ], "Enrich": ["FromLogContext"] }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*" }`, 'appsettings.Development.json': `{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\\\mssqllocaldb;Database={{serviceName}}DevDb;Trusted_Connection=true;MultipleActiveResultSets=true" }, "Serilog": { "MinimumLevel": { "Default": "Debug", "Override": { "Microsoft": "Information", "System": "Information" } } }, "Logging": { "LogLevel": { "Default": "Debug", "Microsoft.AspNetCore": "Information" } } }`, // Hot reload scripts 'scripts/watch.ps1': `#!/usr/bin/env pwsh # Hot Reload Development Script for Windows PowerShell Write-Host "Starting {{serviceName}} with Hot Reload..." -ForegroundColor Green # Set environment for development $env:ASPNETCORE_ENVIRONMENT = "Development" $env:DOTNET_USE_POLLING_FILE_WATCHER = "true" # Start the application with hot reload try { Write-Host "Running: dotnet watch run --non-interactive" -ForegroundColor Yellow dotnet watch run --non-interactive --project {{serviceName}}.csproj } catch { Write-Host "Error starting application: $_" -ForegroundColor Red exit 1 }`, 'scripts/watch.sh': `#!/bin/bash # Hot Reload Development Script for Unix/Linux/macOS echo "Starting {{serviceName}} with Hot Reload..." # Set environment for development export ASPNETCORE_ENVIRONMENT=Development export DOTNET_USE_POLLING_FILE_WATCHER=true # Start the application with hot reload echo "Running: dotnet watch run --non-interactive" dotnet watch run --non-interactive --project {{serviceName}}.csproj`, 'scripts/build-and-watch.ps1': `#!/usr/bin/env pwsh # Build and Watch Script for Development Write-Host "Building and starting {{serviceName}} with Hot Reload..." -ForegroundColor Green # Clean previous build Write-Host "Cleaning previous build..." -ForegroundColor Yellow dotnet clean # Restore packages Write-Host "Restoring packages..." -ForegroundColor Yellow dotnet restore # Build the project Write-Host "Building project..." -ForegroundColor Yellow $buildResult = dotnet build --no-restore if ($LASTEXITCODE -ne 0) { Write-Host "Build failed. Please fix compilation errors." -ForegroundColor Red exit 1 } # Set environment for development $env:ASPNETCORE_ENVIRONMENT = "Development" $env:DOTNET_USE_POLLING_FILE_WATCHER = "true" # Start with hot reload Write-Host "Starting application with hot reload..." -ForegroundColor Green dotnet watch run --non-interactive --no-build`, 'scripts/build-and-watch.sh': `#!/bin/bash # Build and Watch Script for Development echo "Building and starting {{serviceName}} with Hot Reload..." # Clean previous build echo "Cleaning previous build..." dotnet clean # Restore packages echo "Restoring packages..." dotnet restore # Build the project echo "Building project..." if ! dotnet build --no-restore; then echo "Build failed. Please fix compilation errors." exit 1 fi # Set environment for development export ASPNETCORE_ENVIRONMENT=Development export DOTNET_USE_POLLING_FILE_WATCHER=true # Start with hot reload echo "Starting application with hot reload..." dotnet watch run --non-interactive --no-build`, // README.md 'README.md': `# {{serviceName}} - ASP.NET Core with Hot Reload High-productivity .NET 8 Web API with comprehensive dotnet watch hot reload support and live development features. ## 🚀 Hot Reload Features - **Automatic Code Reloading**: Instant application restart on C# file changes - **Configuration Hot Reload**: Live updates for appsettings.json changes - **Static File Watching**: CSS, JavaScript, and content file monitoring - **Development Middleware**: Enhanced debugging and development utilities - **Real-time Feedback**: Immediate reflection of code changes without manual restart - **Smart File Watching**: Optimized file system monitoring with exclusions - **Development Endpoints**: Built-in utilities for development and debugging ## 📋 Prerequisites - .NET 8.0 SDK - SQL Server or SQL Server LocalDB - Modern terminal (Windows Terminal, macOS Terminal, or Linux terminal) ## 🛠 Quick Start ### Using Scripts (Recommended) #### Windows PowerShell \`\`\`powershell # Simple hot reload .\\scripts\\watch.ps1 # Or build and watch .\\scripts\\build-and-watch.ps1 \`\`\` #### Unix/Linux/macOS \`\`\`bash # Make scripts executable chmod +x scripts/*.sh # Simple hot reload ./scripts/watch.sh # Or build and watch ./scripts/build-and-watch.sh \`\`\` ### Manual Commands #### Basic Hot Reload \`\`\`bash # Set environment export ASPNETCORE_ENVIRONMENT=Development export DOTNET_USE_POLLING_FILE_WATCHER=true # Start with hot reload dotnet watch run \`\`\` #### Advanced Hot Reload \`\`\`bash # With additional options dotnet watch run --non-interactive --project {{serviceName}}.csproj # With specific launch profile dotnet watch run --launch-profile Development # With verbose output dotnet watch run --verbose \`\`\` ## 🔥 Hot Reload Capabilities ### What Triggers Reload - **C# source files** (.cs): Immediate application restart - **Configuration files** (.json): Configuration refresh - **Static files** (.css, .js): Content refresh - **Razor views** (.cshtml): View compilation refresh - **Project files** (.csproj): Full rebuild and restart ### What's Excluded from Watching - Build output directories (bin/, obj/) - Log files and temporary files - Package cache and dependencies - IDE configuration files ### File Types Monitored \`\`\` *.cs - C# source files *.cshtml - Razor views *.css - Stylesheets *.js - JavaScript files *.json - Configuration files *.yml/*.yaml - YAML configuration \`\`\` ## 🛠 Development Workflow ### 1. Start Development Server \`\`\`bash # Navigate to project directory cd {{serviceName}} # Start hot reload dotnet watch run \`\`\` ### 2. Make Code Changes - Edit any C# file in your IDE - Save the file - Watch the terminal for reload notification - Application automatically restarts with changes ### 3. View Changes - Open browser to \`https://localhost:5001\` - Navigate to Swagger UI for API testing - Changes are immediately reflected ### 4. Development Endpoints When running in Development mode, access these utilities: \`\`\` GET /dev/info - Application information GET /dev/system - System information GET /dev/database - Database status GET /dev/config - Configuration details GET /dev/endpoints - Available endpoints GET /dev/health - Health check status POST /dev/reload - Manual reload trigger GET /dev/reload/status - Hot reload status GET /dev/watch - Watched files info POST /dev/cache/clear - Clear application cache \`\`\` ## ⚡ Performance Optimizations ### Fast Rebuild Configuration The project is optimized for fast rebuilds: \`\`\`xml <PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <UseHotReload>true</UseHotReload> <DebugType>portable</DebugType> <Optimize>false</Optimize> </PropertyGroup> \`\`\` ### Smart File Watching \`\`\`xml <ItemGroup> <Watch Include="**/*.cs" /> <Watch Include="**/*.cshtml" /> <Watch Include="**/*.css" /> <Watch Include="**/*.js" /> <Watch Include="**/*.json" Exclude="bin/**/*;obj/**/*" /> <Watch Remove="bin/**/*" /> <Watch Remove="obj/**/*" /> <Watch Remove="logs/**/*" /> </ItemGroup> \`\`\` ### Development Dependencies Hot reload packages are only included in Debug builds: \`\`\`xml <PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="8.0.0" Condition="'$(Configuration)' == 'Debug'" /> \`\`\` ## 🐛 Troubleshooting ### Hot Reload Not Working 1. **Check .NET Version** \`\`\`bash dotnet --version # Should be 8.0+ \`\`\` 2. **Verify Environment** \`\`\`bash echo $ASPNETCORE_ENVIRONMENT # Should be 'Development' \`\`\` 3. **Enable Polling (if needed)** \`\`\`bash export DOTNET_USE_POLLING_FILE_WATCHER=true \`\`\` 4. **Check File Permissions** \`\`\`bash # Ensure files are writable chmod 644 **/*.cs \`\`\` ### Common Issues #### "Failed to restart the application" - Check for compilation errors - Verify all dependencies are restored - Ensure no syntax errors in code #### "File watcher reached the maximum number of files" - Exclude more directories from watching - Increase system file watcher limits #### "Hot reload not detecting changes" - Enable polling file watcher - Check antivirus software interference - Verify file system permissions ### Debug Hot Reload \`\`\`bash # Run with verbose output dotnet watch run --verbose # Check what files are being watched dotnet watch run --list \`\`\` ## 🔧 Configuration ### Environment Variables \`\`\`bash # Essential for hot reload ASPNETCORE_ENVIRONMENT=Development # Enable polling if file events don't work DOTNET_USE_POLLING_FILE_WATCHER=true # Customize polling interval (milliseconds) DOTNET_POLLING_FILE_WATCHER_INTERVAL=1000 # Disable hot reload if needed DOTNET_WATCH_RESTART_ON_RUDE_EDIT=false \`\`\` ### Project Configuration \`\`\`xml <!-- Enable hot reload features --> <UseHotReload>true</UseHotReload> <!-- Enable runtime compilation for views --> <MvcRazorCompileOnPublish>false</MvcRazorCompileOnPublish> <!-- Exclude files from content --> <EnableDefaultContentItems>false</EnableDefaultContentItems> \`\`\` ## 🚀 Advanced Features ### Custom File Watch