diff --git a/openapi.go b/openapi.go index 22866f3..c2631fe 100644 --- a/openapi.go +++ b/openapi.go @@ -11,6 +11,8 @@ import ( ) // SpecBuilder constructs an OpenAPI 3.1 specification from registered RouteGroups. +// Title, Description, Version, and optional licence metadata populate the +// OpenAPI info block. // // Example: // @@ -21,6 +23,8 @@ type SpecBuilder struct { Description string Version string Servers []string + LicenseName string + LicenseURL string } // Build generates the complete OpenAPI 3.1 JSON spec. @@ -47,6 +51,16 @@ func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) { }, } + if sb.LicenseName != "" { + license := map[string]any{ + "name": sb.LicenseName, + } + if sb.LicenseURL != "" { + license["url"] = sb.LicenseURL + } + spec["info"].(map[string]any)["license"] = license + } + if servers := normaliseServers(sb.Servers); len(servers) > 0 { out := make([]map[string]any, 0, len(servers)) for _, server := range servers { diff --git a/openapi_test.go b/openapi_test.go index 7967f02..01aeffa 100644 --- a/openapi_test.go +++ b/openapi_test.go @@ -146,6 +146,38 @@ func TestSpecBuilder_Good_EmptyGroups(t *testing.T) { } } +func TestSpecBuilder_Good_InfoIncludesLicenseMetadata(t *testing.T) { + sb := &api.SpecBuilder{ + Title: "Test", + Description: "Licensed test API", + Version: "1.2.3", + LicenseName: "EUPL-1.2", + LicenseURL: "https://eupl.eu/1.2/en/", + } + + data, err := sb.Build(nil) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var spec map[string]any + if err := json.Unmarshal(data, &spec); err != nil { + t.Fatalf("invalid JSON: %v", err) + } + + info := spec["info"].(map[string]any) + license, ok := info["license"].(map[string]any) + if !ok { + t.Fatal("expected license metadata in spec info") + } + if license["name"] != "EUPL-1.2" { + t.Fatalf("expected license name EUPL-1.2, got %v", license["name"]) + } + if license["url"] != "https://eupl.eu/1.2/en/" { + t.Fatalf("expected license url to be preserved, got %v", license["url"]) + } +} + func TestSpecBuilder_Good_WithDescribableGroup(t *testing.T) { sb := &api.SpecBuilder{ Title: "Test",