From eee60623b26d94022f89cd863087b5ce8725b3e2 Mon Sep 17 00:00:00 2001 From: Zach Hamm Date: Tue, 10 Feb 2026 10:11:27 -0800 Subject: [PATCH] fix: use NewDocumentConfiguration() as default config in BuildV3Model When calling NewDocument() (without explicit configuration), BuildV3Model() was creating a bare DocumentConfiguration struct literal as the fallback. This meant all bool fields defaulted to false (Go zero values), causing TransformSiblingRefs and MergeReferencedProperties to be silently disabled. BuildV2Model() already correctly uses datamodel.NewDocumentConfiguration() as its fallback. This aligns BuildV3Model() to do the same, ensuring features like sibling $ref -> allOf transformation are enabled by default regardless of which NewDocument constructor is used. Fixes: https://github.com/pb33f/libopenapi/issues/90 Co-authored-by: Cursor --- document.go | 7 +----- document_test.go | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 6 deletions(-) diff --git a/document.go b/document.go index 7d0b537e..1b2a8c05 100644 --- a/document.go +++ b/document.go @@ -309,12 +309,7 @@ func (d *document) BuildV3Model() (*DocumentModel[v3high.Document], error) { var lowDoc *v3low.Document if d.config == nil { - d.config = &datamodel.DocumentConfiguration{ - AllowFileReferences: false, - BasePath: "", - AllowRemoteReferences: false, - BaseURL: nil, - } + d.config = datamodel.NewDocumentConfiguration() } var docErr error diff --git a/document_test.go b/document_test.go index 85f8127d..5c5cdebc 100644 --- a/document_test.go +++ b/document_test.go @@ -2034,3 +2034,60 @@ components: resolved := localSchemaComp.Schema() require.NotNil(t, resolved) } + +func TestNewDocument_DefaultConfig_EnablesSiblingRefTransform(t *testing.T) { + // Verifies that NewDocument() (without explicit configuration) uses + // NewDocumentConfiguration() defaults, which enables TransformSiblingRefs. + // See: https://github.com/pb33f/libopenapi/issues/90 + spec := `openapi: 3.1.0 +info: + title: Sibling Ref Default Config Test + version: 1.0.0 +paths: {} +components: + schemas: + Base: + type: string + enum: + - ACTIVE + - PAUSED + - DELETED + WithSiblings: + $ref: '#/components/schemas/Base' + description: "A constrained version of Base" + enum: + - ACTIVE + - PAUSED` + + doc, err := NewDocument([]byte(spec)) + require.NoError(t, err) + + model, err := doc.BuildV3Model() + require.NoError(t, err) + require.NotNil(t, model) + + // Verify the default config has TransformSiblingRefs enabled + config := doc.GetConfiguration() + require.NotNil(t, config) + assert.True(t, config.TransformSiblingRefs, + "TransformSiblingRefs should default to true even when using NewDocument()") + + // Verify the sibling $ref was converted to allOf + withSiblings := model.Model.Components.Schemas.GetOrZero("WithSiblings") + require.NotNil(t, withSiblings) + + schema := withSiblings.Schema() + require.NotNil(t, schema) + require.NotNil(t, schema.AllOf, "sibling $ref should be transformed into allOf") + assert.Len(t, schema.AllOf, 2, "allOf should have 2 items: sibling props + $ref") + + // First allOf item should contain the sibling properties + siblingSchema := schema.AllOf[0].Schema() + require.NotNil(t, siblingSchema) + assert.Equal(t, "A constrained version of Base", siblingSchema.Description) + assert.Len(t, siblingSchema.Enum, 2) + + // Second allOf item should be the $ref + refItem := schema.AllOf[1] + assert.Equal(t, "#/components/schemas/Base", refItem.GetReference()) +}