using Web.Api.Common; using Microsoft.OpenApi; using SharedKernel; namespace Web.Api; public static class DependencyInjection { public static IServiceCollection AddPresentation(this IServiceCollection services, AppSettings settings) { services.AddExceptionHandler(); services.AddProblemDetails(); services.AddEndpointsApiExplorer(); services.AddSwaggerGen(options => { // Nested type (예: GoogleLogin.Request, ForgotPassword.Request 등) // 이 short name `Request` 로 schemaId 충돌 → FullName 으로 unique 보장 (`+` 를 `.` 로 치환해 가독성). options.CustomSchemaIds(t => t.FullName?.Replace('+', '.') ?? t.Name); // internal: 기존 /api/* (대시보드 전용) options.SwaggerDoc("internal", new OpenApiInfo { Title = "ANTOOZA Internal API", Version = "v1", Description = "사용자/관리자 페이지 전용. 외부 노출 안 됨." }); options.DocInclusionPredicate((docName, apiDesc) => { var groupName = apiDesc.GroupName ?? "internal"; return docName == groupName; }); options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Type = SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", Description = "JWT access_token 을 입력하세요." }); options.AddSecurityRequirement(document => new() { [new OpenApiSecuritySchemeReference("Bearer", document)] = [] }); // OpenAPI 3.x servers field — Scalar / Swagger UI 의 server selector + "Try it out" base URL. // 환경별 (PROD=api.antooza.com / DEV=dev-api.antooza.com / LOCAL=localhost:4000) 로 자동 채워짐. options.AddServer(new OpenApiServer { Url = settings.App.ApiURL, Description = $"{settings.App.Name} ({settings.App.ApiURL})" }); }); return services; } }