using AyCode.Core.Loggers; using AyCode.Core.Serializers.Binaries; using AyCode.Services.SignalRs; using FruitBank.Common; using FruitBank.Common.Loggers; using FruitBank.Common.Models; using FruitBank.Common.Services; using FruitBankHybrid.Shared.Databases; using FruitBankHybrid.Shared.Services; using FruitBankHybrid.Shared.Services.Loggers; using FruitBankHybrid.Shared.Services.SignalRs; using FruitBankHybrid.Web.Client.Services; using FruitBankHybrid.Web.Client.Services.Loggers; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.AspNetCore.SignalR.Client; using Microsoft.Extensions.Options; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.Services.AddDevExpressBlazor(configure => configure.SizeMode = DevExpress.Blazor.SizeMode.Medium); // Add device-specific services used by the FruitBankHybrid.Shared project builder.Services.AddSingleton(); builder.Services.AddSingleton(); #if DEBUG builder.Services.AddSingleton(); #endif builder.Services.AddSingleton(); builder.Services.AddSingleton(sp => new LoggedInModel(sp.GetRequiredService())); // Bind SignalR options from wwwroot/appsettings.json (loaded automatically by WebAssemblyHostBuilder) — // single Configure call per options type, combining section Bind with runtime overrides. builder.Services.Configure(opts => builder.Configuration.GetSection("AcHubConnection").Bind(opts)); builder.Services.Configure(opts => { builder.Configuration.GetSection("AcBinaryHubProtocol").Bind(opts); // WASM safety net: AsyncSegment send-path is unsupported here — Validate() would throw. // Downgrade if appsettings.json accidentally specifies it. if (opts.ProtocolMode == BinaryProtocolMode.AsyncSegment) opts.ProtocolMode = BinaryProtocolMode.Segment; }); // Logger options + framework factory. LoggerClient instances are created per caller category, // with AppType+LogLevel from appsettings and writers resolved from DI via IAcLogWriterClientBase. builder.Services.Configure(builder.Configuration.GetSection("AyCode:Logger")); builder.Services.AddAcLoggerFactory(); // HubConnectionBuilder — transient so each consumer gets a fresh builder to Build(). // All connection and protocol configuration flows from appsettings.json via IOptions; // AddAcDefaults (framework) applies AcHubConnectionOptions and bridges the provided logger into SignalR's internal pipeline. // NOTE: AcBinaryHubProtocolOptions is resolved from the OUTER service provider and passed // explicitly — HubConnectionBuilder's inner DI cannot see outer services.Configure() registrations. builder.Services.AddTransient(sp => { var loggerFactory = sp.GetRequiredService>(); var connectionOpts = sp.GetRequiredService>().Value; var protocolOpts = sp.GetRequiredService>().Value; var logger = loggerFactory(nameof(FruitBankSignalRClient)); var hubBuilder = new HubConnectionBuilder().AddAcDefaults(logger, connectionOpts); hubBuilder.AddAcBinaryProtocol(protocolOpts); return hubBuilder; }); builder.Services.AddSingleton(); builder.Services.AddSingleton(); #if DEBUG if (FruitBankConstClient.SignalRSerializerDiagnosticLog) { //SignalResponseDataMessage.DiagnosticLogger = message => { Console.WriteLine(message); }; } #endif await builder.Build().RunAsync();