using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.EntityFrameworkCore; using SVSim.Database; using SVSim.Database.Repositories.Card; using SVSim.Database.Repositories.Collectibles; using SVSim.Database.Repositories.Deck; using SVSim.Database.Repositories.Globals; using SVSim.Database.Repositories.Viewer; using SVSim.EmulatedEntrypoint.Middlewares; using SVSim.EmulatedEntrypoint.Security.SteamSessionAuthentication; using SVSim.EmulatedEntrypoint.Services; namespace SVSim.EmulatedEntrypoint; public class Program { public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers().AddJsonOptions(opt => { // Wire-format congruence: the encrypted msgpack path uses snake_case [Key("...")] // names; the plain-JSON path runs through System.Text.Json. Match them by using // SnakeCaseLower naming policy here so both paths emit identical key names — and // so the translation middleware can hand JSON keys straight through to msgpack // without per-property name remapping. opt.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; // Production omits null/optional fields entirely; the client uses // `Keys.Contains(name)` as a presence check and calls `.ToInt()` (etc.) on the // value without a null guard. Emitting `"key":null` makes Contains return true and // crashes the client. Drop nulls during serialization so missing == absent. opt.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddHttpLogging(opt => { }); #region Database Services builder.Services.AddDbContext(opt => { opt.UseNpgsql(builder.Configuration.GetConnectionString("ApplicationDb")); }); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); #endregion builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddAuthentication() .AddScheme( SteamAuthenticationConstants.SchemeName, opt => { }); var app = builder.Build(); // Update database (skipped for non-relational providers, e.g. InMemory in tests, and // skipped under the "Testing" environment where the test fixture has already called // EnsureCreated against a SQLite in-memory DB — the Postgres migrations would fail there). using (var scope = app.Services.CreateScope()) { var dbContext = scope.ServiceProvider.GetRequiredService(); if (dbContext.Database.IsRelational() && !app.Environment.IsEnvironment("Testing")) { dbContext.UpdateDatabase(); } } app.UseHttpLogging(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } //app.UseHttpsRedirection(); app.UseMiddleware(); app.UseMiddleware(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run(); } }