Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add server variable extensions #326

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions datamodel/high/v3/server_variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -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
}

Expand All @@ -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
}

Expand Down
67 changes: 66 additions & 1 deletion datamodel/high/v3/server_variable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)))
}
1 change: 1 addition & 0 deletions datamodel/low/v3/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
55 changes: 55 additions & 0 deletions datamodel/low/v3/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
daveshanley marked this conversation as resolved.
Show resolved Hide resolved
}
}

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)
daveshanley marked this conversation as resolved.
Show resolved Hide resolved

// 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())
}
}

Expand Down
12 changes: 10 additions & 2 deletions datamodel/low/v3/server_variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
Loading