feat(api): make spec builder nil-safe

This commit is contained in:
Virgil 2026-04-02 09:01:04 +00:00
parent 57ff0d2a48
commit 4fc93612e4
2 changed files with 34 additions and 0 deletions

View file

@ -63,6 +63,10 @@ const openAPIDialect = "https://spec.openapis.org/oas/3.1/dialect/base"
//
// data, err := (&api.SpecBuilder{Title: "Service", Version: "1.0.0"}).Build(engine.Groups())
func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) {
if sb == nil {
sb = &SpecBuilder{}
}
prepared := prepareRouteGroups(groups)
spec := map[string]any{
@ -214,6 +218,10 @@ func (sb *SpecBuilder) Build(groups []RouteGroup) ([]byte, error) {
//
// data, err := (&api.SpecBuilder{Title: "Service"}).BuildIter(api.RegisteredSpecGroupsIter())
func (sb *SpecBuilder) BuildIter(groups iter.Seq[RouteGroup]) ([]byte, error) {
if sb == nil {
sb = &SpecBuilder{}
}
return sb.Build(collectRouteGroups(groups))
}

View file

@ -208,6 +208,32 @@ func TestSpecBuilder_Good_EmptyGroups(t *testing.T) {
}
}
func TestSpecBuilder_Good_NilReceiverIsZeroValueSafe(t *testing.T) {
var sb *api.SpecBuilder
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)
}
if spec["openapi"] != "3.1.0" {
t.Fatalf("expected openapi=3.1.0, got %v", spec["openapi"])
}
paths, ok := spec["paths"].(map[string]any)
if !ok {
t.Fatalf("expected paths object, got %T", spec["paths"])
}
if _, ok := paths["/health"]; !ok {
t.Fatal("expected /health path to be present")
}
}
func TestSpecBuilder_Good_CustomSecuritySchemesAreMerged(t *testing.T) {
sb := &api.SpecBuilder{
Title: "Test",