using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using ZB.MOM.WW.OtOpcUa.AdminUI.Hubs; using ZB.MOM.WW.OtOpcUa.AdminUI.Uns; using ZB.MOM.WW.OtOpcUa.Commons.Browsing; using ZB.MOM.WW.OtOpcUa.Core.Abstractions; using ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Browser; using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser; namespace ZB.MOM.WW.OtOpcUa.AdminUI; public static class EndpointRouteBuilderExtensions { /// /// Mounts the AdminUI Razor components and the AdminUI static asset pipeline at the root. /// Call from the fused Host's Program.cs alongside app.MapOtOpcUaAuth(). /// /// The root component type for Razor pages. /// The endpoint route builder. /// The same endpoint route builder, for chaining. public static IEndpointRouteBuilder MapAdminUI(this IEndpointRouteBuilder app) where TApp : IComponent { // Razor class library static assets (_content/ZB.MOM.WW.OtOpcUa.AdminUI/**) are // served via the Host's app.UseStaticFiles() middleware which must run BEFORE // UseAuthentication() — see Program.cs. app.MapRazorComponents() .AddInteractiveServerRenderMode(); return app; } /// /// Adds AdminUI services to the dependency injection container. /// /// The service collection. /// The same service collection, for chaining. public static IServiceCollection AddAdminUI(this IServiceCollection services) { services.AddRazorComponents().AddInteractiveServerComponents(); services.AddOtOpcUaDriverStatusServices(); // Browse pipeline — see docs/plans/2026-05-28-driver-browsers-design.md services.AddSingleton(); services.AddHostedService(); services.AddScoped(); services.AddScoped(); services.AddSingleton(); services.AddSingleton(); // Universal Discover-backed fallback browser (Wave 0). IDriverFactory is bound by the // fused Host's DriverFactoryBootstrap; a standalone AdminUI has none → NullDriverFactory // → CanBrowse false → pickers gracefully stay manual-entry (design §6). services.AddSingleton(sp => new DiscoveryDriverBrowser( sp.GetService() ?? NullDriverFactory.Instance, sp.GetRequiredService>())); // Roslyn-backed Monaco script-editor analysis (diagnostics/completions/hover/...). services.AddScoped(); services.AddScoped(); // Certificate-store actions (trust/untrust/delete) for the /certificates page. services.AddSingleton(); // Structured audit-event sink: forwards AuditEvents to the ControlPlane AuditWriter singleton. services.AddSingleton(); return services; } }