#!/bin/bash # Usage: ./scaffold.sh MyProjectName [slnx|sln] [true|false for packages] # Example: ./scaffold.sh MyCleanApp slnx # --- 1. Setup & Validation --- if [ -z "$1" ]; then echo "โŒ Please provide a project name." echo "Usage: ./scaffold.sh MyProjectName [slnx|sln]" exit 1 fi PROJECT_NAME=$1 FORMAT=${2:-slnx} INSTALL_PACKAGES=${3:-true} # Default to true SLN_FILE="$PROJECT_NAME.$FORMAT" # Check if directory exists to avoid overwriting if [ -d "$PROJECT_NAME" ]; then echo "โŒ Directory '$PROJECT_NAME' already exists. Aborting." exit 1 fi echo "๐Ÿš€ Scaffolding $FORMAT solution for: $PROJECT_NAME (Clean Architecture + DDD)" # Create Root Directory and enter it mkdir "$PROJECT_NAME" cd "$PROJECT_NAME" || exit # --- 2. Smart SDK Detection --- # Get the latest installed SDK version (e.g. 10.0.102) LATEST_SDK=$(dotnet --list-sdks | tail -n 1 | awk '{print $1}') if [ -n "$LATEST_SDK" ]; then echo "โ„น๏ธ Detected SDK: $LATEST_SDK. Pinning global.json..." dotnet new globaljson --sdk-version "$LATEST_SDK" --roll-forward latestFeature else echo "โš ๏ธ No SDK detected. Skipping global.json." fi dotnet new gitignore # --- 3. Create Solution & Fix NuGet --- if [ "$FORMAT" == "slnx" ]; then dotnet new sln -n "$PROJECT_NAME" --format slnx else dotnet new sln -n "$PROJECT_NAME" fi # [FIX] Create a local nuget.config to ensure we can find packages echo "๐Ÿ“ฆ Configuring NuGet sources..." dotnet new nugetconfig --force # Check if nuget.org is already there if ! dotnet nuget list source --configfile "nuget.config" | grep -q "nuget.org"; then dotnet nuget add source "https://api.nuget.org/v3/index.json" -n "nuget.org" --configfile "nuget.config" fi # --- 4. Create Projects --- echo "๐Ÿ”จ Creating projects..." dotnet new classlib -n "$PROJECT_NAME.Shared" -o "src/$PROJECT_NAME.Shared" dotnet new classlib -n "$PROJECT_NAME.Domain" -o "src/$PROJECT_NAME.Domain" # <--- CHANGED dotnet new classlib -n "$PROJECT_NAME.Application" -o "src/$PROJECT_NAME.Application" dotnet new classlib -n "$PROJECT_NAME.Infrastructure" -o "src/$PROJECT_NAME.Infrastructure" dotnet new webapi -n "$PROJECT_NAME.Api" -o "src/$PROJECT_NAME.Api" --use-controllers mkdir -p tests dotnet new xunit -n "$PROJECT_NAME.Domain.Tests" -o "tests/$PROJECT_NAME.Domain.Tests" # <--- CHANGED dotnet new xunit -n "$PROJECT_NAME.Application.Tests" -o "tests/$PROJECT_NAME.Application.Tests" dotnet new xunit -n "$PROJECT_NAME.IntegrationTests" -o "tests/$PROJECT_NAME.IntegrationTests" # --- 4.1 CLEANUP BOILERPLATE --- echo "๐Ÿงน Removing default template files..." # Define array of files to remove relative to solution root FILES_TO_REMOVE=( "src/$PROJECT_NAME.Shared/Class1.cs" "src/$PROJECT_NAME.Domain/Class1.cs" # <--- CHANGED "src/$PROJECT_NAME.Application/Class1.cs" "src/$PROJECT_NAME.Infrastructure/Class1.cs" "tests/$PROJECT_NAME.Domain.Tests/UnitTest1.cs" # <--- CHANGED "tests/$PROJECT_NAME.Application.Tests/UnitTest1.cs" "tests/$PROJECT_NAME.IntegrationTests/UnitTest1.cs" "src/$PROJECT_NAME.Api/WeatherForecast.cs" "src/$PROJECT_NAME.Api/Controllers/WeatherForecastController.cs" "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.http" ) for file in "${FILES_TO_REMOVE[@]}"; do if [ -f "$file" ]; then rm "$file" echo " - Deleted $file" fi done # --- 5. Add to Solution (With Visual Folders) --- echo "๐Ÿ“‚ Organizing solution structure..." # Source dotnet sln "$SLN_FILE" add "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" -s "src" dotnet sln "$SLN_FILE" add "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" -s "src" # <--- CHANGED dotnet sln "$SLN_FILE" add "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" -s "src" dotnet sln "$SLN_FILE" add "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" -s "src" dotnet sln "$SLN_FILE" add "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" -s "src" # Tests dotnet sln "$SLN_FILE" add "tests/$PROJECT_NAME.Domain.Tests/$PROJECT_NAME.Domain.Tests.csproj" -s "tests" # <--- CHANGED dotnet sln "$SLN_FILE" add "tests/$PROJECT_NAME.Application.Tests/$PROJECT_NAME.Application.Tests.csproj" -s "tests" dotnet sln "$SLN_FILE" add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" -s "tests" # --- 6. Add References --- echo "๐Ÿ”— Wiring up dependencies..." # Shared References (Utility/Kernel) dotnet add "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" # <--- CHANGED dotnet add "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" dotnet add "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" dotnet add "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" # Application -> Domain dotnet add "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" reference "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" # <--- CHANGED # Infrastructure -> Application AND Domain dotnet add "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" reference "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" dotnet add "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" reference "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" # <--- CHANGED # API -> Application AND Infrastructure dotnet add "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" reference "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" dotnet add "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" reference "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" # Tests dotnet add "tests/$PROJECT_NAME.Domain.Tests/$PROJECT_NAME.Domain.Tests.csproj" reference "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" # <--- CHANGED dotnet add "tests/$PROJECT_NAME.Domain.Tests/$PROJECT_NAME.Domain.Tests.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" # <--- CHANGED dotnet add "tests/$PROJECT_NAME.Application.Tests/$PROJECT_NAME.Application.Tests.csproj" reference "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" dotnet add "tests/$PROJECT_NAME.Application.Tests/$PROJECT_NAME.Application.Tests.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" dotnet add "tests/$PROJECT_NAME.Application.Tests/$PROJECT_NAME.Application.Tests.csproj" reference "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" # <--- ADDED (Application tests need Entities) dotnet add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" reference "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" dotnet add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" reference "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" dotnet add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" reference "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" dotnet add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" reference "src/$PROJECT_NAME.Shared/$PROJECT_NAME.Shared.csproj" dotnet add "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" reference "src/$PROJECT_NAME.Domain/$PROJECT_NAME.Domain.csproj" # <--- ADDED # --- 7. Install Nuget Packages (Optional) --- if [ "$INSTALL_PACKAGES" = true ]; then echo "๐Ÿ“ฆ Installing standard Clean Architecture packages..." # Helper function to add packages safely add_package() { local proj=$1 local pkg=$2 echo " + Adding $pkg..." dotnet add "$proj" package "$pkg" > /dev/null 2>&1 if [ $? -ne 0 ]; then echo " โš ๏ธ Failed to add $pkg. Check connection." fi } # Application Layer add_package "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" "MediatR" add_package "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" "FluentValidation" add_package "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" "FluentValidation.DependencyInjectionExtensions" add_package "src/$PROJECT_NAME.Application/$PROJECT_NAME.Application.csproj" "Microsoft.Extensions.Logging.Abstractions" # Infrastructure Layer add_package "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" "Microsoft.EntityFrameworkCore" add_package "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" "Microsoft.EntityFrameworkCore.SqlServer" add_package "src/$PROJECT_NAME.Infrastructure/$PROJECT_NAME.Infrastructure.csproj" "Microsoft.EntityFrameworkCore.Design" # API Layer add_package "src/$PROJECT_NAME.Api/$PROJECT_NAME.Api.csproj" "Microsoft.EntityFrameworkCore.Tools" # Tests TEST_PROJECTS=( "tests/$PROJECT_NAME.Domain.Tests/$PROJECT_NAME.Domain.Tests.csproj" # <--- CHANGED "tests/$PROJECT_NAME.Application.Tests/$PROJECT_NAME.Application.Tests.csproj" "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" ) for proj in "${TEST_PROJECTS[@]}"; do add_package "$proj" "FluentAssertions" add_package "$proj" "Moq" done add_package "tests/$PROJECT_NAME.IntegrationTests/$PROJECT_NAME.IntegrationTests.csproj" "Microsoft.AspNetCore.Mvc.Testing" fi # --- 8. Final Verification --- echo "๐Ÿ—๏ธ Verifying build..." dotnet build if [ $? -eq 0 ]; then echo "โœ… $PROJECT_NAME scaffolded successfully!" echo "๐Ÿ‘‰ cd $PROJECT_NAME" else echo "โš ๏ธ Scaffolding finished, but build failed. Run 'dotnet restore' manually." fi