Files
budget/.plans/10-project-split.md
Spencer Twaddle 087fbdd176 Split into Budget.Core / Budget.Infrastructure / Budget.Api projects
Budget.Core: entities, DTOs, enums, FrequencyCalculator (no EF/ASP.NET deps)
Budget.Infrastructure: AppDbContext, migrations, BudgetAuthorizationService
Budget.Api: controllers, middleware, Program.cs — references both projects

EF and Npgsql packages moved to Infrastructure; Api retains only JwtBearer,
HealthChecks, and EF.Design (needed for dotnet ef CLI). Dockerfile updated
to copy all three project directories before publishing. Migration namespaces
updated from Budget.Api.Data.* to Budget.Infrastructure.Data.* and model
type strings updated to Budget.Core.Models.* in the snapshot.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 16:30:31 -05:00

91 lines
4.1 KiB
Markdown

# Plan: Core / Infrastructure / API Project Split
## Goal
Split the single `Budget.Api` project into three projects matching the stwaddle stack pattern:
- `Budget.Core` — entities, DTOs, enums. No ASP.NET or EF dependencies.
- `Budget.Infrastructure` — DbContext, EF configs, migrations, domain services.
- `Budget.Api` — controllers, middleware, Program.cs, DI wiring.
## Current state
Everything lives in `src/Budget.Api/`:
```
Models/ Budget, Income, Outgo, BudgetShare, KnownUser, enums
DTOs/ BudgetDtos, IncomeDtos, OutgoDtos, ShareDtos, SummaryDtos
Data/ AppDbContext, Migrations/
Services/ BudgetAuthorizationService, FrequencyCalculator,
KnownUserMiddleware, ErrorHandlingMiddleware, ClaimsPrincipalExtensions
Controllers/ BudgetsController, IncomesController, OutgosController,
SharesController, SummaryController
Program.cs
```
## Target state
```
src/
Budget.Core/
Models/ Budget, Income, Outgo, BudgetShare, KnownUser, enums
DTOs/ all DTO records and request types
Services/ FrequencyCalculator (pure logic, no EF/ASP.NET)
Budget.Infrastructure/
Data/ AppDbContext, Migrations/
Services/ BudgetAuthorizationService
Budget.Api/
Controllers/
Services/ KnownUserMiddleware, ErrorHandlingMiddleware,
ClaimsPrincipalExtensions
Program.cs
```
**References:** `Budget.Api``Budget.Infrastructure``Budget.Core`
## Steps
### Phase 1 — Create projects and move files
1. `dotnet new classlib -n Budget.Core -o src/Budget.Core --framework net10.0`
2. `dotnet new classlib -n Budget.Infrastructure -o src/Budget.Infrastructure --framework net10.0`
3. Add both to the solution: `dotnet sln add src/Budget.Core/Budget.Core.csproj src/Budget.Infrastructure/Budget.Infrastructure.csproj`
4. Move `Models/` and `DTOs/` to `Budget.Core`; update namespaces from `Budget.Api.*` to `Budget.Core.*`.
5. Move `FrequencyCalculator.cs` to `Budget.Core/Services/`.
6. Move `Data/` (AppDbContext + Migrations) to `Budget.Infrastructure/Data/`.
7. Move `BudgetAuthorizationService.cs` to `Budget.Infrastructure/Services/`.
### Phase 2 — Wire up project references and NuGet packages
8. Add project reference: `Budget.Infrastructure``Budget.Core`.
9. Move EF Core + Npgsql NuGet packages from `Budget.Api.csproj` to `Budget.Infrastructure.csproj`. Keep only `Microsoft.AspNetCore.Authentication.JwtBearer` and health-check packages in `Budget.Api.csproj`.
10. Add project references to `Budget.Api.csproj`: both `Budget.Core` and `Budget.Infrastructure`.
11. Add `Microsoft.EntityFrameworkCore.Design` to `Budget.Api.csproj` (needed for `dotnet ef` CLI to find the startup project).
### Phase 3 — Update namespaces and using statements
12. Global search-replace across all moved files: `namespace Budget.Api``namespace Budget.Core` or `namespace Budget.Infrastructure` as appropriate.
13. Update `using` directives in all controllers, middleware, and Program.cs to reference the new namespaces.
### Phase 4 — Update Dockerfile and EF migrations command
14. Update Dockerfile Stage 2 to copy and restore all three projects before publishing `Budget.Api`.
15. Verify `dotnet ef migrations add` command still works with `--project Budget.Infrastructure --startup-project Budget.Api`.
16. Build and confirm zero errors.
## Key decisions
- `ClaimsPrincipalExtensions` and the two middleware classes stay in `Budget.Api` — they have direct ASP.NET dependencies and are not reusable across projects.
- `BudgetAuthorizationService` goes in `Budget.Infrastructure` because it queries the DbContext.
- `FrequencyCalculator` goes in `Budget.Core` because it is pure arithmetic with no external dependencies.
- DTOs stay in `Budget.Core` (not `Budget.Api`) so `Budget.Infrastructure` can reference them if needed without creating a circular dependency.
## Files affected
- `Budget.sln`
- New: `src/Budget.Core/Budget.Core.csproj`
- New: `src/Budget.Infrastructure/Budget.Infrastructure.csproj`
- `src/Budget.Api/Budget.Api.csproj` (trim NuGet packages, add project refs)
- All `.cs` files under `src/Budget.Api/` (namespace updates)
- `Dockerfile` (Stage 2 COPY pattern)