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

v0.16.9 #300

Merged
merged 17 commits into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 10 additions & 0 deletions datamodel/high/base/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package base

import (
"encoding/json"
"github.com/pb33f/libopenapi/datamodel/high"
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
low "github.com/pb33f/libopenapi/datamodel/low/base"
Expand Down Expand Up @@ -56,6 +57,15 @@ func (e *Example) MarshalYAML() (interface{}, error) {
return nb.Render(), nil
}

// MarshalJSON will marshal this into a JSON byte slice
func (e *Example) MarshalJSON() ([]byte, error) {
var g map[string]any
nb := high.NewNodeBuilder(e, e.low)
r := nb.Render()
r.Decode(&g)
return json.Marshal(g)
}

// ExtractExamples will convert a low-level example map, into a high level one that is simple to navigate.
// no fidelity is lost, everything is still available via GoLow()
func ExtractExamples(elements *orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Example]]) *orderedmap.Map[string, *Example] {
Expand Down
16 changes: 16 additions & 0 deletions datamodel/high/base/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package base

import (
"context"
"encoding/json"
"fmt"
"strings"
"testing"
Expand Down Expand Up @@ -53,6 +54,21 @@ x-hack: code`
// render the example as YAML
rendered, _ := highExample.Render()
assert.Equal(t, yml, strings.TrimSpace(string(rendered)))

// render the example as JSON
var err error
rendered, err = json.Marshal(highExample)
assert.NoError(t, err)

var j map[string]any
_ = json.Unmarshal(rendered, &j)

assert.Equal(t, "an example", j["summary"])
assert.Equal(t, "something more", j["description"])
assert.Equal(t, "https://pb33f.io", j["externalValue"])
assert.Equal(t, "code", j["x-hack"])
assert.Equal(t, "a thing", j["value"])

}

func TestExtractExamples(t *testing.T) {
Expand Down
23 changes: 16 additions & 7 deletions datamodel/high/node_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@
if entry.LowValue != nil {
if vnut, ok := entry.LowValue.(low.HasValueNodeUntyped); ok {
vn := vnut.GetValueNode()
if vn.Kind == yaml.SequenceNode {
if vn != nil && vn.Kind == yaml.SequenceNode {
for i := range vn.Content {
if len(rawNode.Content) > i {
rawNode.Content[i].Style = vn.Content[i].Style
Expand Down Expand Up @@ -515,12 +515,21 @@
}
if !encodeSkip {
var rawNode yaml.Node
err := rawNode.Encode(value)
if err != nil {
return parent
} else {
valueNode = &rawNode
valueNode.Line = line
if value != nil {
// check if is a node and it's null
if v, ko := value.(*yaml.Node); ko {
if v.Tag == "!!null" {
return parent

Check warning on line 522 in datamodel/high/node_builder.go

View check run for this annotation

Codecov / codecov/patch

datamodel/high/node_builder.go#L522

Added line #L522 was not covered by tests
}
}

err := rawNode.Encode(value)
if err != nil {
return parent

Check warning on line 528 in datamodel/high/node_builder.go

View check run for this annotation

Codecov / codecov/patch

datamodel/high/node_builder.go#L528

Added line #L528 was not covered by tests
} else {
valueNode = &rawNode
valueNode.Line = line
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions datamodel/high/v3/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ func (c *Components) GoLow() *low.Components {
return c.low
}

// GoLowUntyped returns the low-level Components instance used to create the high-level one as an interface{}.
func (c *Components) GoLowUntyped() any {
return c.low
}

// Render will return a YAML representation of the Components object as a byte slice.
func (c *Components) Render() ([]byte, error) {
return yaml.Marshal(c)
Expand Down
1 change: 1 addition & 0 deletions datamodel/high/v3/components_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,5 @@ requestBodies:

dat, _ = r.Render()
assert.Equal(t, desired, strings.TrimSpace(string(dat)))
assert.NotNil(t, r.GoLowUntyped())
}
10 changes: 10 additions & 0 deletions datamodel/low/base/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ func (c *Contact) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.Sp
return nil
}

// GetRootNode will return the root yaml node of the Contact object
func (c *Contact) GetRootNode() *yaml.Node {
return c.RootNode
}

// GetKeyNode will return the key yaml node of the Contact object
func (c *Contact) GetKeyNode() *yaml.Node {
return c.KeyNode
}

// Hash will return a consistent SHA256 Hash of the Contact object
func (c *Contact) Hash() [32]byte {
var f []string
Expand Down
5 changes: 5 additions & 0 deletions datamodel/low/base/contact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ email: [email protected]`
_ = low.BuildModel(rNode.Content[0], &rDoc)

assert.Equal(t, lDoc.Hash(), rDoc.Hash())

c := Contact{}
c.Build(nil, &lNode, &rNode, nil)
assert.NotNil(t, c.GetRootNode())
assert.NotNil(t, c.GetKeyNode())
}
10 changes: 10 additions & 0 deletions datamodel/low/base/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ func (ex *Example) FindExtension(ext string) *low.ValueReference[*yaml.Node] {
return low.FindItemInOrderedMap[*yaml.Node](ext, ex.Extensions)
}

// GetRootNode will return the root yaml node of the Example object
func (ex *Example) GetRootNode() *yaml.Node {
return ex.RootNode
}

// GetKeyNode will return the key yaml node of the Example object
func (ex *Example) GetKeyNode() *yaml.Node {
return ex.KeyNode
}

// Hash will return a consistent SHA256 Hash of the Discriminator object
func (ex *Example) Hash() [32]byte {
var f []string
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ x-cake: hot`
var xCake string
_ = n.FindExtension("x-cake").Value.Decode(&xCake)
assert.Equal(t, "hot", xCake)
assert.NotNil(t, n.GetRootNode())
assert.Nil(t, n.GetKeyNode())
}

func TestExample_Build_Success_Simple(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions datamodel/low/base/external_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ func (ex *ExternalDoc) FindExtension(ext string) *low.ValueReference[*yaml.Node]
return low.FindItemInOrderedMap[*yaml.Node](ext, ex.Extensions)
}

// GetRootNode will return the root yaml node of the ExternalDoc object
func (ex *ExternalDoc) GetRootNode() *yaml.Node {
return ex.RootNode
}

// GetKeyNode will return the key yaml node of the ExternalDoc object
func (ex *ExternalDoc) GetKeyNode() *yaml.Node {
return ex.KeyNode
}

// Build will extract extensions from the ExternalDoc instance.
func (ex *ExternalDoc) Build(_ context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error {
ex.KeyNode = keyNode
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/external_doc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ func TestExternalDoc_FindExtension(t *testing.T) {
_ = n.FindExtension("x-fish").Value.Decode(&xFish)

assert.Equal(t, "cake", xFish)
assert.NotNil(t, n.GetRootNode())
assert.Nil(t, n.GetKeyNode())
}

func TestExternalDoc_Build(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions datamodel/low/base/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ func (i *Info) FindExtension(ext string) *low.ValueReference[*yaml.Node] {
return low.FindItemInOrderedMap(ext, i.Extensions)
}

// GetRootNode will return the root yaml node of the Info object
func (i *Info) GetRootNode() *yaml.Node {
return i.RootNode
}

// GetKeyNode will return the key yaml node of the Info object
func (i *Info) GetKeyNode() *yaml.Node {
return i.KeyNode
}

// GetExtensions returns all extensions for Info
func (i *Info) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]] {
return i.Extensions
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ x-cli-name: pizza cli`

assert.Equal(t, "pizza cli", xCliName)
assert.Equal(t, 1, orderedmap.Len(n.GetExtensions()))
assert.NotNil(t, n.GetRootNode())
assert.Nil(t, n.GetKeyNode())
}

func TestContact_Build(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions datamodel/low/base/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,16 @@ func (l *License) Build(ctx context.Context, keyNode, root *yaml.Node, idx *inde
return nil
}

// GetRootNode will return the root yaml node of the License object
func (l *License) GetRootNode() *yaml.Node {
return l.RootNode
}

// GetKeyNode will return the key yaml node of the License object
func (l *License) GetKeyNode() *yaml.Node {
return l.KeyNode
}

// Hash will return a consistent SHA256 Hash of the License object
func (l *License) Hash() [32]byte {
var f []string
Expand Down
5 changes: 5 additions & 0 deletions datamodel/low/base/license_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ description: the ranch`

assert.Equal(t, lDoc.Hash(), rDoc.Hash())

l := License{}
l.Build(nil, &lNode, &rNode, nil)
assert.NotNil(t, l.GetRootNode())
assert.NotNil(t, l.GetKeyNode())

}

func TestLicense_WithIdentifier_Hash(t *testing.T) {
Expand Down
9 changes: 8 additions & 1 deletion datamodel/low/base/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ type Schema struct {
ParentProxy *SchemaProxy

// Index is a reference to the SpecIndex that was used to build this schema.
Index *index.SpecIndex
Index *index.SpecIndex
RootNode *yaml.Node
*low.Reference
}

Expand Down Expand Up @@ -433,6 +434,11 @@ func (s *Schema) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.V
return s.Extensions
}

// GetRootNode will return the root yaml node of the Schema object
func (s *Schema) GetRootNode() *yaml.Node {
return s.RootNode
}

// Build will perform a number of operations.
// Extraction of the following happens in this method:
// - Extensions
Expand Down Expand Up @@ -465,6 +471,7 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
utils.CheckForMergeNodes(root)
s.Reference = new(low.Reference)
s.Index = idx
s.RootNode = root
if h, _, _ := utils.IsNodeRefValue(root); h {
ref, _, err, fctx := low.LocateRefNodeWithContext(ctx, root, idx)
if ref != nil {
Expand Down
2 changes: 1 addition & 1 deletion datamodel/low/base/schema_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (sp *SchemaProxy) GetKeyNode() *yaml.Node {
return sp.kn
}

// GetKeyNode will return the yaml.Node pointer that is a key for value node.
// GetContext will return the context.Context object that was passed to the SchemaProxy during build.
func (sp *SchemaProxy) GetContext() context.Context {
return sp.ctx
}
Expand Down
1 change: 1 addition & 0 deletions datamodel/low/base/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func Test_Schema(t *testing.T) {
assert.NoError(t, schErr)
assert.Equal(t, "something object", sch.Description.Value)
assert.True(t, sch.AdditionalProperties.Value.B)
assert.NotNil(t, sch.GetRootNode())

assert.Equal(t, 2, orderedmap.Len(sch.Properties.Value))
v := sch.FindProperty("somethingB")
Expand Down
10 changes: 10 additions & 0 deletions datamodel/low/base/security_requirement.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ func (s *SecurityRequirement) Build(_ context.Context, keyNode, root *yaml.Node,
return nil
}

// GetRootNode will return the root yaml node of the SecurityRequirement object
func (s *SecurityRequirement) GetRootNode() *yaml.Node {
return s.RootNode
}

// GetKeyNode will return the key yaml node of the SecurityRequirement object
func (s *SecurityRequirement) GetKeyNode() *yaml.Node {
return s.KeyNode
}

// FindRequirement will attempt to locate a security requirement string from a supplied name.
func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/security_requirement_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ one:
assert.Len(t, sr.FindRequirement("one"), 2)
assert.Equal(t, sr.Hash(), sr2.Hash())
assert.Nil(t, sr.FindRequirement("i-do-not-exist"))
assert.NotNil(t, sr.GetRootNode())
assert.Nil(t, sr.GetKeyNode())
}

func TestSecurityRequirement_TestEmptyReq(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions datamodel/low/base/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ func (t *Tag) FindExtension(ext string) *low.ValueReference[*yaml.Node] {
return low.FindItemInOrderedMap(ext, t.Extensions)
}

// GetRootNode returns the root yaml node of the Tag object
func (t *Tag) GetRootNode() *yaml.Node {
return t.RootNode
}

// GetKeyNode returns the key yaml node of the Tag object
func (t *Tag) GetKeyNode() *yaml.Node {
return t.KeyNode
}

// Build will extract extensions and external docs for the Tag.
func (t *Tag) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error {
t.KeyNode = keyNode
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/tag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ x-coffee: tasty`

assert.Equal(t, "tasty", xCoffee)
assert.Equal(t, 1, orderedmap.Len(n.GetExtensions()))
assert.NotNil(t, n.GetRootNode())
assert.Nil(t, n.GetKeyNode())
}

func TestTag_Build_Error(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ type XML struct {
Attribute low.NodeReference[bool]
Wrapped low.NodeReference[bool]
Extensions *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
RootNode *yaml.Node
*low.Reference
}

// Build will extract extensions from the XML instance.
func (x *XML) Build(root *yaml.Node, _ *index.SpecIndex) error {
root = utils.NodeAlias(root)
utils.CheckForMergeNodes(root)
x.RootNode = root
x.Reference = new(low.Reference)
x.Extensions = low.ExtractExtensions(root)
return nil
Expand Down
10 changes: 9 additions & 1 deletion datamodel/low/low.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// Copyright 2022-2004 Princess B33f Heavy Industries / Dave Shanley / Quobix
// SPDX-License-Identifier: MIT

// Package low contains a set of low-level models that represent OpenAPI 2 and 3 documents.
Expand All @@ -12,3 +12,11 @@
// Navigating maps that use a KeyReference as a key is tricky, because there is no easy way to provide a lookup.
// Convenience methods for lookup up properties in a low-level model have therefore been provided.
package low

import "gopkg.in/yaml.v3"

// HasRootNode is an interface that is used to extract the root yaml.Node from a low-level model. The root node is
// the top-level node that represents the entire object as represented in the original source file.
type HasRootNode interface {
GetRootNode() *yaml.Node
}
10 changes: 10 additions & 0 deletions datamodel/low/v3/callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ func (cb *Callback) GetExtensions() *orderedmap.Map[low.KeyReference[string], lo
return cb.Extensions
}

// GetRootNode returns the root yaml node of the Callback object
func (cb *Callback) GetRootNode() *yaml.Node {
return cb.RootNode
}

// GetKeyNode returns the key yaml node of the Callback object
func (cb *Callback) GetKeyNode() *yaml.Node {
return cb.KeyNode
}

// FindExpression will locate a string expression and return a ValueReference containing the located PathItem
func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
return low.FindItemInOrderedMap(exp, cb.Expression)
Expand Down
Loading
Loading