From 45c9c61c09f44d5129f0cdfae6d062f20b7c12ef Mon Sep 17 00:00:00 2001 From: Gefferson Ferraz Date: Wed, 28 Aug 2024 14:08:48 -0300 Subject: [PATCH 1/2] feat: add server variable extensions --- datamodel/high/v3/server_variable.go | 9 ++- datamodel/high/v3/server_variable_test.go | 67 ++++++++++++++++++++++- datamodel/low/v3/server.go | 1 + datamodel/low/v3/server_test.go | 55 +++++++++++++++++++ datamodel/low/v3/server_variable.go | 12 +++- 5 files changed, 138 insertions(+), 6 deletions(-) diff --git a/datamodel/high/v3/server_variable.go b/datamodel/high/v3/server_variable.go index 160fb462..e2800533 100644 --- a/datamodel/high/v3/server_variable.go +++ b/datamodel/high/v3/server_variable.go @@ -6,6 +6,7 @@ package v3 import ( "github.com/pb33f/libopenapi/datamodel/high" low "github.com/pb33f/libopenapi/datamodel/low/v3" + "github.com/pb33f/libopenapi/orderedmap" "gopkg.in/yaml.v3" ) @@ -14,9 +15,10 @@ import ( // ServerVariable is an object representing a Server Variable for server URL template substitution. // - https://spec.openapis.org/oas/v3.1.0#server-variable-object type ServerVariable struct { - Enum []string `json:"enum,omitempty" yaml:"enum,omitempty"` - Default string `json:"default,omitempty" yaml:"default,omitempty"` - Description string `json:"description,omitempty" yaml:"description,omitempty"` + Enum []string `json:"enum,omitempty" yaml:"enum,omitempty"` + Default string `json:"default,omitempty" yaml:"default,omitempty"` + Description string `json:"description,omitempty" yaml:"description,omitempty"` + Extensions *orderedmap.Map[string, *yaml.Node] `json:"-" yaml:"-"` low *low.ServerVariable } @@ -33,6 +35,7 @@ func NewServerVariable(variable *low.ServerVariable) *ServerVariable { v.Default = variable.Default.Value v.Description = variable.Description.Value v.Enum = enums + v.Extensions = high.ExtractExtensions(variable.Extensions) return v } diff --git a/datamodel/high/v3/server_variable_test.go b/datamodel/high/v3/server_variable_test.go index 54919b05..4c5002ef 100644 --- a/datamodel/high/v3/server_variable_test.go +++ b/datamodel/high/v3/server_variable_test.go @@ -4,9 +4,12 @@ package v3 import ( - "github.com/stretchr/testify/assert" "strings" "testing" + + "github.com/pb33f/libopenapi/orderedmap" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" ) func TestServerVariable_MarshalYAML(t *testing.T) { @@ -41,3 +44,65 @@ description: money day` assert.Equal(t, desired, strings.TrimSpace(string(svarRend))) } + +func TestServerVariableExtension_MarshalYAML(t *testing.T) { + createExtension := func(value interface{}) *yaml.Node { + node := &yaml.Node{} + err := node.Encode(value) + if err != nil { + // Trate o erro conforme necessário + } + return node + } + + svar := &ServerVariable{ + Extensions: orderedmap.New[string, *yaml.Node](), + } + transform := []map[string]interface{}{ + { + "type": "translate", + "allowMissing": true, + "translations": []map[string]string{ + {"from": "pt-br", "to": "en-us"}, + }, + }, + } + svar.Extensions.Set("x-transforms", createExtension(transform)) + + desired := `x-transforms: + - allowMissing: true + translations: + - from: pt-br + to: en-us + type: translate` + + svarRend, _ := svar.Render() + + assert.Equal(t, desired, strings.TrimSpace(string(svarRend))) + + // mutate + + svar.Default = "es-mx" + transform = []map[string]interface{}{ + { + "type": "translate", + "allowMissing": true, + "translations": []map[string]string{ + {"from": "es-mx", "to": "en-us"}, + }, + }, + } + svar.Extensions.Set("x-transforms", createExtension(transform)) + + desired = `default: es-mx +x-transforms: + - allowMissing: true + translations: + - from: es-mx + to: en-us + type: translate` + + svarRend, _ = svar.Render() + + assert.Equal(t, desired, strings.TrimSpace(string(svarRend))) +} diff --git a/datamodel/low/v3/server.go b/datamodel/low/v3/server.go index 09b5705d..88764c30 100644 --- a/datamodel/low/v3/server.go +++ b/datamodel/low/v3/server.go @@ -72,6 +72,7 @@ func (s *Server) Build(ctx context.Context, keyNode, root *yaml.Node, _ *index.S variable.Reference = new(low.Reference) _ = low.BuildModel(varNode, &variable) variable.Nodes = low.ExtractNodesRecursive(ctx, varNode) + variable.Extensions = low.ExtractExtensions(varNode) if localKeyNode != nil { variable.Nodes.Store(localKeyNode.Line, localKeyNode) } diff --git a/datamodel/low/v3/server_test.go b/datamodel/low/v3/server_test.go index 2e7bde9c..f306a7cd 100644 --- a/datamodel/low/v3/server_test.go +++ b/datamodel/low/v3/server_test.go @@ -55,6 +55,61 @@ variables: for v := range n.Variables.Value.ValuesFromOldest() { assert.NotNil(t, v.Value.GetKeyNode()) assert.NotNil(t, v.Value.GetRootNode()) + assert.Nil(t, v.Value.GetExtensions()) + } +} + +func TestServerWithVariableExtension_Build(t *testing.T) { + yml := `url: https://pb33f.io +description: high quality software for developers. +variables: + var1: + default: hello + description: a var + enum: [one, two] + x-transforms: + allowMissing: true` + + var idxNode yaml.Node + _ = yaml.Unmarshal([]byte(yml), &idxNode) + idx := index.NewSpecIndex(&idxNode) + + var n Server + err := low.BuildModel(idxNode.Content[0], &n) + assert.NoError(t, err) + assert.Nil(t, n.GetRootNode()) + + err = n.Build(context.Background(), nil, idxNode.Content[0], idx) + assert.NoError(t, err) + assert.NotNil(t, n.GetRootNode()) + assert.Equal(t, "ec69dfcf68ad8988f3804e170ee6c4a7ad2e4ac51084796eea93168820827546", + low.GenerateHashString(&n)) + + assert.Equal(t, "https://pb33f.io", n.URL.Value) + assert.Equal(t, "high quality software for developers.", n.Description.Value) + + variable := n.FindVariable("var1").Value + assert.Equal(t, "hello", variable.Default.Value) + assert.Equal(t, "a var", variable.Description.Value) + + var_extensions := variable.Extensions.First() + assert.Equal(t, "x-transforms", var_extensions.Key().Value) + variable_pair := variable.Extensions.GetPair(var_extensions.Key()) + assert.Equal(t, "allowMissing", variable_pair.Value.Value.Content[0].Value) + assert.Equal(t, "true", variable_pair.Value.Value.Content[1].Value) + + // test var hash + s := n.FindVariable("var1") + assert.Equal(t, "00eef99ee4a7b746be7b4ccdece59c5a96222c6206f846fafed782c9f3f9b46b", + low.GenerateHashString(s.Value)) + + assert.Equal(t, 0, orderedmap.Len(n.GetExtensions())) + + // check nodes on variables + for v := range n.Variables.Value.ValuesFromOldest() { + assert.NotNil(t, v.Value.GetKeyNode()) + assert.NotNil(t, v.Value.GetRootNode()) + assert.NotNil(t, v.Value.GetExtensions()) } } diff --git a/datamodel/low/v3/server_variable.go b/datamodel/low/v3/server_variable.go index d85e907f..eb3bb665 100644 --- a/datamodel/low/v3/server_variable.go +++ b/datamodel/low/v3/server_variable.go @@ -3,10 +3,12 @@ package v3 import ( "crypto/sha256" "fmt" - "github.com/pb33f/libopenapi/datamodel/low" - "gopkg.in/yaml.v3" "sort" "strings" + + "github.com/pb33f/libopenapi/datamodel/low" + "github.com/pb33f/libopenapi/orderedmap" + "gopkg.in/yaml.v3" ) // ServerVariable represents a low-level OpenAPI 3+ ServerVariable object. @@ -20,6 +22,7 @@ type ServerVariable struct { Enum []low.NodeReference[string] Default low.NodeReference[string] Description low.NodeReference[string] + Extensions *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]] KeyNode *yaml.Node RootNode *yaml.Node *low.Reference @@ -36,6 +39,11 @@ func (s *ServerVariable) GetKeyNode() *yaml.Node { return s.RootNode } +// GetExtensions returns all extensions and satisfies the low.HasExtensions interface. +func (s *ServerVariable) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]] { + return s.Extensions +} + // Hash will return a consistent SHA256 Hash of the ServerVariable object func (s *ServerVariable) Hash() [32]byte { var f []string From d26b0d27d03eb1427c72419d16e9c937d52d03d6 Mon Sep 17 00:00:00 2001 From: quobix Date: Wed, 11 Sep 2024 11:14:23 -0400 Subject: [PATCH 2/2] Update datamodel/low/v3/server_test.go --- datamodel/low/v3/server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/datamodel/low/v3/server_test.go b/datamodel/low/v3/server_test.go index f306a7cd..b488b1e5 100644 --- a/datamodel/low/v3/server_test.go +++ b/datamodel/low/v3/server_test.go @@ -55,7 +55,7 @@ variables: for v := range n.Variables.Value.ValuesFromOldest() { assert.NotNil(t, v.Value.GetKeyNode()) assert.NotNil(t, v.Value.GetRootNode()) - assert.Nil(t, v.Value.GetExtensions()) + assert.Equal(t, 0, v.Value.GetExtensions().Len()) } }