using Marathon.Application.Abstractions; using Marathon.Application.Storage; using Marathon.Infrastructure.Export; using Marathon.Infrastructure.Persistence.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; namespace Marathon.Infrastructure.Persistence; /// /// DI extension that wires up the persistence layer (DbContext, repositories, exporter). /// Call this from the host's DI setup — do NOT call from DependencyInjection.cs (Phase 4). /// public static class PersistenceModule { /// /// Registers EF Core DbContext, all repositories and the Excel exporter. /// Reads Storage:DatabasePath from . /// public static IServiceCollection AddMarathonPersistence( this IServiceCollection services, IConfiguration config) { services.AddOptions() .Bind(config.GetSection(StorageOptions.SectionName)) .ValidateOnStart(); services.AddDbContext((sp, opts) => { var storageOptions = sp.GetRequiredService>().Value; var dbPath = storageOptions.DatabasePath; // Ensure the directory exists var dir = Path.GetDirectoryName(dbPath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); // Configure SQLite with WAL journal mode opts.UseSqlite( $"Data Source={dbPath}", sqliteOpts => sqliteOpts.CommandTimeout(30)); }); // Register initializer — the HOST must resolve this at startup and call InitializeAsync(). // Example in Program.cs: // using var scope = app.Services.CreateScope(); // await scope.ServiceProvider.GetRequiredService().InitializeAsync(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); return services; } }