LibraryService API follows a classic layered (n-tier) design with no repository layer between the service and the database. Each layer has a single responsibility: controllers handle HTTP concerns, services own all business logic and data access, and EF Core’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/marchena96/Paradigma-lab1/llms.txt
Use this file to discover all available pages before exploring further.
LibraryContext bridges the .NET object world to PostgreSQL running on Supabase.
Request flow
Every HTTP request travels through exactly three code layers before touching the database:LibraryContext. EF Core translates those into SQL and executes them against the PostgreSQL instance hosted on Supabase.
Solution structure
Layer responsibilities
| Layer | Key types | Responsibility |
|---|---|---|
| Controllers | LibrariesController, BooksController, AuthController | Parse HTTP input (route params, JSON body), call the appropriate service method, and return the correct HTTP status code (200 OK, 201 Created, 204 No Content, 404 Not Found, 401 Unauthorized) |
| Services | ILibrariesService, IBooksService, IAuthenticationService | All data-access logic — querying, inserting, updating, and deleting via LibraryContext; no HTTP knowledge |
| LibraryContext | LibraryContext : DbContext | Maps the Library and Book entities to the Libraries and Books PostgreSQL tables; owned by EF Core’s DbContext pool |
| DTOs | BookForm, User | Lightweight, camelCase JSON contract types serialized with System.Text.Json ([JsonPropertyName]); decoupled from the database entities |
Startup and hosting model
The application uses the classicProgram.cs + Startup.cs hosting model, not Minimal API. Program.cs creates the generic host and points it at Startup:
Startup.ConfigureServices registers services in the following order:
JwtSettingsbinding — reads theJwtSettingssection from configuration (or throwsInvalidOperationExceptionif absent) and registers the result as a singleton. Also registersIAuthenticationService → AuthenticationService(Scoped).- JWT Bearer authentication — configures
JwtBearerDefaults.AuthenticationSchemewith issuer/audience/key validation and zero clock-skew. - Authorization — calls
services.AddAuthorization()to enable the[Authorize]attribute on controllers. - CORS — adds a named
"Frontend"policy that allows any header and method from the Vite dev server athttp://localhost:5173. - Business-service DI — registers
ILibrariesService → LibrariesService(Transient) andIBooksService → BooksService(Transient). DbContextPool— registersLibraryContextwith Npgsql, a pool size of 20, and retry-on-failure (max 1 retry, 5-second delay).- Controllers and Swagger — calls
services.AddControllers()andservices.AddSwaggerGen().
An idempotency guard at the top of
ConfigureServices checks whether JwtSettings is already registered and returns early if so. This prevents double-registration errors (e.g., "Scheme already exists: Bearer") when WebApplicationFactory and UseStartup<Startup> both invoke ConfigureServices during integration tests.Middleware pipeline
Before the pipeline is mounted,Startup.Configure runs auto-migration: it resolves LibraryContext, checks for pending EF Core migrations, and calls db.Database.Migrate() — but only when the provider is not SQLite (SQLite is used in tests and manages its schema via EnsureCreated).
The middleware pipeline is then assembled in the following order:
| Order | Middleware | Registered via |
|---|---|---|
| 1 | Routing | app.UseRouting() |
| 2 | CORS ("Frontend" policy) | app.UseCors("Frontend") |
| 3 | Authentication (JWT Bearer) | app.UseAuthentication() |
| 4 | Authorization | app.UseAuthorization() |
| 5 | Endpoints | app.UseEndpoints(e => e.MapControllers()) |
UseDeveloperExceptionPage() is prepended, and the Swagger middleware (UseSwagger / UseSwaggerUI) serves the interactive API explorer at /swagger.