|
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 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 |
|
} else { |
|
Write-Host "β οΈ No SDK detected. Skipping global.json." -ForegroundColor Yellow |
|
} |
|
|
|
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 } |
|
|
|
# [FIX] Create a local nuget.config to ensure we can find packages |
|
Write-Host "π¦ Configuring NuGet sources..." -ForegroundColor Cyan |
|
dotnet new nugetconfig --force |
|
|
|
# Add nuget.org only if it's missing |
|
$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 (Src & Tests) --- |
|
Write-Host "π¨ Creating projects..." -ForegroundColor Cyan |
|
|
|
# Source Projects |
|
dotnet new classlib -n "$ProjectName.Shared" -o "src/$ProjectName.Shared" |
|
dotnet new classlib -n "$ProjectName.Core" -o "src/$ProjectName.Core" |
|
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.Core.Tests" -o "tests/$ProjectName.Core.Tests" |
|
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.Core/Class1.cs", |
|
"src/$ProjectName.Application/Class1.cs", |
|
"src/$ProjectName.Infrastructure/Class1.cs", |
|
"tests/$ProjectName.Core.Tests/UnitTest1.cs", |
|
"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 |
|
Write-Host " - Deleted $File" -ForegroundColor DarkGray |
|
} |
|
} |
|
|
|
# --- 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.Core/$ProjectName.Core.csproj" -s "src" |
|
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.Core.Tests/$ProjectName.Core.Tests.csproj" -s "tests" |
|
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 (Everyone depends on Shared) |
|
dotnet add "src/$ProjectName.Core/$ProjectName.Core.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" |
|
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 -> Core |
|
dotnet add "src/$ProjectName.Application/$ProjectName.Application.csproj" reference "src/$ProjectName.Core/$ProjectName.Core.csproj" |
|
|
|
# Infrastructure -> Application & Core |
|
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.Core/$ProjectName.Core.csproj" |
|
|
|
# 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.Core.Tests/$ProjectName.Core.Tests.csproj" reference "src/$ProjectName.Core/$ProjectName.Core.csproj" |
|
dotnet add "tests/$ProjectName.Core.Tests/$ProjectName.Core.Tests.csproj" reference "src/$ProjectName.Shared/$ProjectName.Shared.csproj" |
|
|
|
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" |
|
|
|
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" |
|
|
|
# --- 7. Install Nuget Packages (Optional) --- |
|
if (-not $SkipPackages) { |
|
Write-Host "π¦ Installing standard Clean Architecture packages..." -ForegroundColor Cyan |
|
|
|
# Helper function to add package safely |
|
function Add-Package { |
|
param ($Project, $Package) |
|
Write-Host " + Adding $Package..." -ForegroundColor Gray |
|
dotnet add $Project package $Package |
|
if ($LASTEXITCODE -ne 0) { |
|
Write-Host " β οΈ Failed to add $Package. Check connection." -ForegroundColor Yellow |
|
} |
|
} |
|
|
|
# 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.Core.Tests/$ProjectName.Core.Tests.csproj", |
|
"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" |
|
} |
|
|
|
# Integration Test Specifics |
|
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 (Boilerplate Removed)!" -ForegroundColor Green |
|
Write-Host " π cd $ProjectName" -ForegroundColor Gray |
|
} else { |
|
Write-Host "β οΈ Scaffolding finished, but build failed. Run 'dotnet restore' manually." -ForegroundColor Yellow |
|
} |