From 9b24a46fd5e8faf934c3643f52bfbf6b03d5273b Mon Sep 17 00:00:00 2001 From: Virgil Date: Thu, 2 Apr 2026 06:08:44 +0000 Subject: [PATCH] feat(openapi): export runtime transport metadata Expose GraphQL, WebSocket, SSE, and debug endpoint metadata alongside the existing Swagger UI path in generated OpenAPI documents. Co-Authored-By: Virgil --- openapi.go | 16 ++++++++++++++++ spec_builder_helper_test.go | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/openapi.go b/openapi.go index 0f6ce2b..c9f4a6a 100644 --- a/openapi.go +++ b/openapi.go @@ -89,6 +89,22 @@ func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) { if swaggerPath := strings.TrimSpace(sb.SwaggerPath); swaggerPath != "" { spec["x-swagger-ui-path"] = normaliseSwaggerPath(swaggerPath) } + if graphqlPath := sb.effectiveGraphQLPath(); graphqlPath != "" { + spec["x-graphql-path"] = normaliseOpenAPIPath(graphqlPath) + spec["x-graphql-playground"] = sb.GraphQLPlayground + } + if wsPath := strings.TrimSpace(sb.WSPath); wsPath != "" { + spec["x-ws-path"] = normaliseOpenAPIPath(wsPath) + } + if ssePath := strings.TrimSpace(sb.SSEPath); ssePath != "" { + spec["x-sse-path"] = normaliseOpenAPIPath(ssePath) + } + if sb.PprofEnabled { + spec["x-pprof-enabled"] = true + } + if sb.ExpvarEnabled { + spec["x-expvar-enabled"] = true + } if sb.TermsOfService != "" { spec["info"].(map[string]any)["termsOfService"] = sb.TermsOfService diff --git a/spec_builder_helper_test.go b/spec_builder_helper_test.go index b83bc37..769a112 100644 --- a/spec_builder_helper_test.go +++ b/spec_builder_helper_test.go @@ -64,6 +64,24 @@ func TestEngine_Good_OpenAPISpecBuilderCarriesEngineMetadata(t *testing.T) { if got := spec["x-swagger-ui-path"]; got != "/docs" { t.Fatalf("expected x-swagger-ui-path=/docs, got %v", got) } + if got := spec["x-graphql-path"]; got != "/gql" { + t.Fatalf("expected x-graphql-path=/gql, got %v", got) + } + if got := spec["x-graphql-playground"]; got != true { + t.Fatalf("expected x-graphql-playground=true, got %v", got) + } + if got := spec["x-ws-path"]; got != "/socket" { + t.Fatalf("expected x-ws-path=/socket, got %v", got) + } + if got := spec["x-sse-path"]; got != "/events" { + t.Fatalf("expected x-sse-path=/events, got %v", got) + } + if got := spec["x-pprof-enabled"]; got != true { + t.Fatalf("expected x-pprof-enabled=true, got %v", got) + } + if got := spec["x-expvar-enabled"]; got != true { + t.Fatalf("expected x-expvar-enabled=true, got %v", got) + } contact, ok := info["contact"].(map[string]any) if !ok {