param( [string]$ProjectName, [ValidateSet("slnx", "sln")] [string]$Format = "slnx", [switch]$SkipPackages = $false ) # --- 1. Setup & Validation --- if ([string]::IsNullOrWhiteSpace($ProjectName)) { $ProjectName = Read-Host "Please enter a project name" } if ([string]::IsNullOrWhiteSpace($ProjectName)) { Write-Host "โŒ Name required." -ForegroundColor Red; exit 1 } if (Test-Path $ProjectName) { Write-Host "โŒ Directory '$ProjectName' already exists. Aborting to prevent overwrite." -ForegroundColor Red; exit 1 } $SlnFile = "$ProjectName.$Format" Write-Host "๐Ÿš€ Scaffolding Clean Architecture (DDD) for: $ProjectName" -ForegroundColor Cyan # Create Root Directory New-Item -ItemType Directory -Path $ProjectName | Out-Null Set-Location $ProjectName # --- 2. Smart SDK Detection --- $LatestSdk = dotnet --list-sdks | Select-Object -Last 1 | ForEach-Object { $_.Split(' ')[0] } if ($LatestSdk) { Write-Host "โ„น๏ธ Detected SDK: $LatestSdk. Pinning global.json..." -ForegroundColor Gray dotnet new globaljson --sdk-version $LatestSdk --roll-forward latestFeature } dotnet new gitignore # --- 3. Create Solution & Fix NuGet --- if ($Format -eq "slnx") { dotnet new sln -n $ProjectName --format slnx } else { dotnet new sln -n $ProjectName } Write-Host "๐Ÿ“ฆ Configuring NuGet sources..." -ForegroundColor Cyan dotnet new nugetconfig --force $CurrentSources = dotnet nuget list source --configfile "nuget.config" if ($CurrentSources -notmatch "nuget.org") { dotnet nuget add source "https://api.nuget.org/v3/index.json" -n "nuget.org" --configfile "nuget.config" } # --- 4. Create Projects --- Write-Host "๐Ÿ”จ Creating projects..." -ForegroundColor Cyan # Source Projects dotnet new classlib -n "$ProjectName.Shared" -o "src/$ProjectName.Shared" dotnet new classlib -n "$ProjectName.Domain" -o "src/$ProjectName.Domain" # <--- CHANGED dotnet new classlib -n "$ProjectName.Application" -o "src/$ProjectName.Application" dotnet new classlib -n "$ProjectName.Infrastructure" -o "src/$ProjectName.Infrastructure" dotnet new webapi -n "$ProjectName.Api" -o "src/$ProjectName.Api" --use-controllers # Test Projects dotnet new xunit -n "$ProjectName.Domain.Tests" -o "tests/$ProjectName.Domain.Tests" # <--- CHANGED dotnet new xunit -n "$ProjectName.Application.Tests" -o "tests/$ProjectName.Application.Tests" dotnet new xunit -n "$ProjectName.IntegrationTests" -o "tests/$ProjectName.IntegrationTests" # --- 4.1 CLEANUP BOILERPLATE --- Write-Host "๐Ÿงน Removing default template files..." -ForegroundColor Cyan $FilesToRemove = @( "src/$ProjectName.Shared/Class1.cs", "src/$ProjectName.Domain/Class1.cs", # <--- CHANGED "src/$ProjectName.Application/Class1.cs", "src/$ProjectName.Infrastructure/Class1.cs", "tests/$ProjectName.Domain.Tests/UnitTest1.cs", # <--- CHANGED "tests/$ProjectName.Application.Tests/UnitTest1.cs", "tests/$ProjectName.IntegrationTests/UnitTest1.cs", "src/$ProjectName.Api/WeatherForecast.cs", "src/$ProjectName.Api/Controllers/WeatherForecastController.cs", "src/$ProjectName.Api/$ProjectName.Api.http" ) foreach ($File in $FilesToRemove) { if (Test-Path $File) { Remove-Item $File -Force } } # --- 5. Add to Solution --- Write-Host "๐Ÿ“‚ Organizing solution structure..." -ForegroundColor Cyan # Add Src dotnet sln $SlnFile add "src/$ProjectName.Shared/$ProjectName.Shared.csproj" -s "src" dotnet sln $SlnFile add "src/$ProjectName.Domain/$ProjectName.Domain.csproj" -s "src" # <--- CHANGED dotnet sln $SlnFile add "src/$ProjectName.Application/$ProjectName.Application.csproj" -s "src" dotnet sln $SlnFile add "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" -s "src" dotnet sln $SlnFile add "src/$ProjectName.Api/$ProjectName.Api.csproj" -s "src" # Add Tests dotnet sln $SlnFile add "tests/$ProjectName.Domain.Tests/$ProjectName.Domain.Tests.csproj" -s "tests" # <--- CHANGED dotnet sln $SlnFile add "tests/$ProjectName.Application.Tests/$ProjectName.Application.Tests.csproj" -s "tests" dotnet sln $SlnFile add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" -s "tests" # --- 6. Add References --- Write-Host "๐Ÿ”— Wiring up dependencies..." -ForegroundColor Cyan # Shared References (Utility/Kernel) dotnet add "src/$ProjectName.Domain/$ProjectName.Domain.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" # <--- CHANGED dotnet add "src/$ProjectName.Application/$ProjectName.Application.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" dotnet add "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" dotnet add "src/$ProjectName.Api/$ProjectName.Api.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" # Application -> Domain dotnet add "src/$ProjectName.Application/$ProjectName.Application.csproj" reference "src/$ProjectName.Domain/$ProjectName.Domain.csproj" # <--- CHANGED # Infrastructure -> Application & Domain dotnet add "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" reference "src/$ProjectName.Application/$ProjectName.Application.csproj" dotnet add "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" reference "src/$ProjectName.Domain/$ProjectName.Domain.csproj" # <--- CHANGED # API -> Application & Infrastructure dotnet add "src/$ProjectName.Api/$ProjectName.Api.csproj" reference "src/$ProjectName.Application/$ProjectName.Application.csproj" dotnet add "src/$ProjectName.Api/$ProjectName.Api.csproj" reference "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" # Tests dotnet add "tests/$ProjectName.Domain.Tests/$ProjectName.Domain.Tests.csproj" reference "src/$ProjectName.Domain/$ProjectName.Domain.csproj" # <--- CHANGED dotnet add "tests/$ProjectName.Domain.Tests/$ProjectName.Domain.Tests.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" # <--- CHANGED dotnet add "tests/$ProjectName.Application.Tests/$ProjectName.Application.Tests.csproj" reference "src/$ProjectName.Application/$ProjectName.Application.csproj" dotnet add "tests/$ProjectName.Application.Tests/$ProjectName.Application.Tests.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" # NOTE: Application tests usually need Domain too for entities dotnet add "tests/$ProjectName.Application.Tests/$ProjectName.Application.Tests.csproj" reference "src/$ProjectName.Domain/$ProjectName.Domain.csproj" # <--- ADDED dotnet add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" reference "src/$ProjectName.Api/$ProjectName.Api.csproj" dotnet add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" reference "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" dotnet add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" reference "src/$ProjectName.Application/$ProjectName.Application.csproj" dotnet add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" dotnet add "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" reference "src/$ProjectName.Domain/$ProjectName.Domain.csproj" # <--- ADDED # --- 7. Install Nuget Packages (Optional) --- if (-not $SkipPackages) { Write-Host "๐Ÿ“ฆ Installing standard Clean Architecture packages..." -ForegroundColor Cyan function Add-Package { param ($Project, $Package) Write-Host " + Adding $Package..." -ForegroundColor Gray dotnet add $Project package $Package } # Application Layer Add-Package "src/$ProjectName.Application/$ProjectName.Application.csproj" "MediatR" Add-Package "src/$ProjectName.Application/$ProjectName.Application.csproj" "FluentValidation" Add-Package "src/$ProjectName.Application/$ProjectName.Application.csproj" "FluentValidation.DependencyInjectionExtensions" Add-Package "src/$ProjectName.Application/$ProjectName.Application.csproj" "Microsoft.Extensions.Logging.Abstractions" # Infrastructure Layer Add-Package "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" "Microsoft.EntityFrameworkCore" Add-Package "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" "Microsoft.EntityFrameworkCore.SqlServer" Add-Package "src/$ProjectName.Infrastructure/$ProjectName.Infrastructure.csproj" "Microsoft.EntityFrameworkCore.Design" # API Layer Add-Package "src/$ProjectName.Api/$ProjectName.Api.csproj" "Microsoft.EntityFrameworkCore.Tools" # Test Projects $TestProjects = @( "tests/$ProjectName.Domain.Tests/$ProjectName.Domain.Tests.csproj", # <--- CHANGED "tests/$ProjectName.Application.Tests/$ProjectName.Application.Tests.csproj", "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" ) foreach ($proj in $TestProjects) { Add-Package $proj "FluentAssertions" Add-Package $proj "Moq" } Add-Package "tests/$ProjectName.IntegrationTests/$ProjectName.IntegrationTests.csproj" "Microsoft.AspNetCore.Mvc.Testing" } # --- 8. Final Verification --- Write-Host "๐Ÿ—๏ธ Verifying build..." -ForegroundColor Cyan dotnet build if ($LASTEXITCODE -eq 0) { Write-Host "โœ… $ProjectName scaffolded successfully!" -ForegroundColor Green Write-Host " ๐Ÿ‘‰ cd $ProjectName" -ForegroundColor Gray }