From 569cfbb85dcf0c0a23ee3c6973d44c449b2bbb82 Mon Sep 17 00:00:00 2001 From: moarten Date: Sat, 4 Apr 2026 22:26:57 +0200 Subject: [PATCH] Added postgres docker db for local development --- Lutra/.github/copilot-instructions.md | 104 ++++++++++++++++++ Lutra/Lutra.AppHost/AppHost.cs | 10 +- Lutra/Lutra.AppHost/Lutra.AppHost.csproj | 5 +- Lutra/Lutra.AppHost/appsettings.json | 3 - .../Lutra.Infrastructure.Migrator.csproj | 5 + .../Lutra.Infrastructure.Migrator/Program.cs | 1 + .../Lutra.Infrastructure.Sql.csproj | 3 +- Lutra/Lutra.sln | 6 + 8 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 Lutra/.github/copilot-instructions.md diff --git a/Lutra/.github/copilot-instructions.md b/Lutra/.github/copilot-instructions.md new file mode 100644 index 0000000..e50f093 --- /dev/null +++ b/Lutra/.github/copilot-instructions.md @@ -0,0 +1,104 @@ +# Copilot Instructions for Lutra + +Use these standards when generating or modifying code in this repository. + +## Project overview + +- Target framework: .NET 10 (`net10.0`) +- Architecture: Clean Architecture +- Solution layers: + - `Lutra.Domain` + - `Lutra.Application` + - `Lutra.Infrastructure.Sql` + - `Lutra.API` + - `Lutra.AppHost` + - `Lutra.Infrastructure.Migrator` +- Database: PostgreSQL via EF Core +- Orchestration: .NET Aspire +- Messaging pattern: `Cortex.Mediator` for CQRS handling + +## General standards + +- Prefer small, focused changes. +- Follow existing naming, formatting, and folder conventions. +- Keep dependencies pointing inward: + - Domain depends on nothing + - Application depends on Domain + - Infrastructure depends on Application and Domain + - API depends on Application and Infrastructure + - AppHost and Migrator are host projects only +- Use nullable reference types correctly and keep implicit usings compatible with the project style. + +## Clean Architecture guidance + +Use Jason Taylor’s CleanArchitecture project as a reference for intent and structure, but adapt to this codebase’s actual implementation. + +Where the reference template uses MediatR, this project uses `Cortex.Mediator`. +Add FluentValidation, AutoMapper, NUnit, Shouldly, Moq, or Respawn only if the repository already uses them or the change clearly requires them. + +## Domain layer rules + +- Keep entities simple and focused on business state. +- Use `BaseEntity` as the shared base type when appropriate. +- Preserve the current entity style: + - `Id` as `Guid` + - audit fields like `CreatedAt`, `ModifiedAt`, `DeletedAt` + - `IsDeleted` as a derived property +- Keep validation and persistence concerns out of Domain unless they are intrinsic business rules. + +## Application layer rules + +- Put use cases in feature folders. +- Follow the existing CQRS split: + - `FeatureName.cs` as the partial entry point + - `FeatureName.Query.cs` or `FeatureName.Command.cs` + - `FeatureName.Handler.cs` + - `FeatureName.Response.cs` +- Use `Cortex.Mediator` request and handler interfaces. +- Keep handlers focused on orchestration and application logic. +- Use `ILutraDbContext` rather than referencing the concrete DbContext directly when possible. + +## Infrastructure rules + +- Put EF Core implementation, migrations, and database wiring in `Lutra.Infrastructure.Sql`. +- Keep the DbContext implementation aligned with `ILutraDbContext`. +- If package versions must be pinned for runtime compatibility, pin them explicitly in the infrastructure project. +- Be cautious with `PrivateAssets="all"` on design-time packages because they do not flow dependency constraints to downstream projects. + +## API layer rules + +- Keep controllers thin. +- Controllers should delegate to Application use cases through `IMediator`. +- Keep `Program.cs` focused on DI and middleware setup. + +## Aspire and migration rules + +- Keep `Lutra.AppHost` responsible for orchestration only. +- Preserve the persistent PostgreSQL container setup unless a change explicitly requires otherwise. +- Keep the migrator as a one-shot project that applies migrations on startup. +- Ensure migration-related changes do not break runtime assembly/version consistency. + +## Naming and code style + +- Match the existing language of the codebase; this project uses Dutch domain names in places such as `Verspakketten`, `Supermarkt`, and `Beoordeling`. +- Keep class and file names consistent with the feature name. +- Use sealed types where the project already does. +- Prefer explicit `required` members where the current codebase uses them. +- Preserve current indentation and brace style in each file. + +## Testing guidance + +- If tests exist, update or add tests alongside behavior changes. +- Follow the reference template’s intent for test coverage: + - unit tests for business logic + - integration tests for infrastructure and data access + - functional tests for API behavior +- Keep tests readable and focused on behavior. + +## When making changes + +- Read the relevant file before editing. +- Make the smallest change that solves the problem. +- Reuse existing patterns from the repo instead of inventing new ones. +- Run or request a build/test verification after changes when appropriate. +- Avoid broad refactors unless the user asks for them. diff --git a/Lutra/Lutra.AppHost/AppHost.cs b/Lutra/Lutra.AppHost/AppHost.cs index 501c50d..fe06dbc 100644 --- a/Lutra/Lutra.AppHost/AppHost.cs +++ b/Lutra/Lutra.AppHost/AppHost.cs @@ -1,9 +1,15 @@ var builder = DistributedApplication.CreateBuilder(args); -var db = builder.AddConnectionString("LutraDb"); +var postgres = builder.AddPostgres("postgres") + .WithDataVolume() + .WithLifetime(ContainerLifetime.Persistent); + +var db = postgres + .AddDatabase("LutraDb"); var migrator = builder.AddProject("dbmigrator") - .WithReference(db); + .WithReference(db) + .WaitFor(db); var apiService = builder.AddProject("apiservice") .WithHttpHealthCheck("/health") diff --git a/Lutra/Lutra.AppHost/Lutra.AppHost.csproj b/Lutra/Lutra.AppHost/Lutra.AppHost.csproj index bfb8064..73a4467 100644 --- a/Lutra/Lutra.AppHost/Lutra.AppHost.csproj +++ b/Lutra/Lutra.AppHost/Lutra.AppHost.csproj @@ -1,4 +1,4 @@ - + @@ -11,7 +11,8 @@ - + + diff --git a/Lutra/Lutra.AppHost/appsettings.json b/Lutra/Lutra.AppHost/appsettings.json index cf598e4..31c092a 100644 --- a/Lutra/Lutra.AppHost/appsettings.json +++ b/Lutra/Lutra.AppHost/appsettings.json @@ -1,7 +1,4 @@ { - "ConnectionStrings": { - "LutraDb": "Host=db.m91.nl;Username=user;Password=password;Database=Lutra" - }, "Logging": { "LogLevel": { "Default": "Information", diff --git a/Lutra/Lutra.Infrastructure.Migrator/Lutra.Infrastructure.Migrator.csproj b/Lutra/Lutra.Infrastructure.Migrator/Lutra.Infrastructure.Migrator.csproj index c6b3a7f..44bd8d9 100644 --- a/Lutra/Lutra.Infrastructure.Migrator/Lutra.Infrastructure.Migrator.csproj +++ b/Lutra/Lutra.Infrastructure.Migrator/Lutra.Infrastructure.Migrator.csproj @@ -7,6 +7,11 @@ enable + + + + + diff --git a/Lutra/Lutra.Infrastructure.Migrator/Program.cs b/Lutra/Lutra.Infrastructure.Migrator/Program.cs index 94781d4..1be687b 100644 --- a/Lutra/Lutra.Infrastructure.Migrator/Program.cs +++ b/Lutra/Lutra.Infrastructure.Migrator/Program.cs @@ -1,5 +1,6 @@ using Lutra.Infrastructure.Sql; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/Lutra/Lutra.Infrastructure/Lutra.Infrastructure.Sql.csproj b/Lutra/Lutra.Infrastructure/Lutra.Infrastructure.Sql.csproj index 17e36ef..eb0075d 100644 --- a/Lutra/Lutra.Infrastructure/Lutra.Infrastructure.Sql.csproj +++ b/Lutra/Lutra.Infrastructure/Lutra.Infrastructure.Sql.csproj @@ -12,7 +12,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + + diff --git a/Lutra/Lutra.sln b/Lutra/Lutra.sln index c6fb1c1..04a0753 100644 --- a/Lutra/Lutra.sln +++ b/Lutra/Lutra.sln @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.Infrastructure.Sql", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.AppHost", "Lutra.AppHost\Lutra.AppHost.csproj", "{B9B41350-EB18-4564-81AB-C16F3E5A0CBB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lutra.Infrastructure.Migrator", "Lutra.Infrastructure.Migrator\Lutra.Infrastructure.Migrator.csproj", "{6582486C-CEB7-78BF-D043-E0C3C0D6A923}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Debug|Any CPU.Build.0 = Debug|Any CPU {B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9B41350-EB18-4564-81AB-C16F3E5A0CBB}.Release|Any CPU.Build.0 = Release|Any CPU + {6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6582486C-CEB7-78BF-D043-E0C3C0D6A923}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE