mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 04:20:11 +00:00
Monster refactor of map to orderedmap.Map data type.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/base"
|
low "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,10 +58,10 @@ func (e *Example) MarshalYAML() (interface{}, error) {
|
|||||||
|
|
||||||
// ExtractExamples will convert a low-level example map, into a high level one that is simple to navigate.
|
// 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()
|
// no fidelity is lost, everything is still available via GoLow()
|
||||||
func ExtractExamples(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Example]) map[string]*Example {
|
func ExtractExamples(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Example]]) orderedmap.Map[string, *Example] {
|
||||||
extracted := make(map[string]*Example)
|
extracted := orderedmap.New[string, *Example]()
|
||||||
for k, v := range elements {
|
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||||
extracted[k.Value] = NewExample(v.Value)
|
extracted.Set(pair.Key().Value, NewExample(pair.Value().Value))
|
||||||
}
|
}
|
||||||
return extracted
|
return extracted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ package base
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewExample(t *testing.T) {
|
func TestNewExample(t *testing.T) {
|
||||||
@@ -61,14 +63,13 @@ func TestExtractExamples(t *testing.T) {
|
|||||||
|
|
||||||
_ = lowExample.Build(nil, cNode.Content[0], nil)
|
_ = lowExample.Build(nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
examplesMap := make(map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*lowbase.Example])
|
examplesMap := orderedmap.New[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.Example]]()
|
||||||
examplesMap[lowmodel.KeyReference[string]{
|
examplesMap.Set(
|
||||||
Value: "green",
|
lowmodel.KeyReference[string]{Value: "green"},
|
||||||
}] = lowmodel.ValueReference[*lowbase.Example]{
|
lowmodel.ValueReference[*lowbase.Example]{Value: &lowExample},
|
||||||
Value: &lowExample,
|
)
|
||||||
}
|
|
||||||
|
|
||||||
assert.Equal(t, "herbs", ExtractExamples(examplesMap)["green"].Summary)
|
assert.Equal(t, "herbs", ExtractExamples(examplesMap).GetOrZero("green").Summary)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,8 +57,8 @@ type Schema struct {
|
|||||||
If *SchemaProxy `json:"if,omitempty" yaml:"if,omitempty"`
|
If *SchemaProxy `json:"if,omitempty" yaml:"if,omitempty"`
|
||||||
Else *SchemaProxy `json:"else,omitempty" yaml:"else,omitempty"`
|
Else *SchemaProxy `json:"else,omitempty" yaml:"else,omitempty"`
|
||||||
Then *SchemaProxy `json:"then,omitempty" yaml:"then,omitempty"`
|
Then *SchemaProxy `json:"then,omitempty" yaml:"then,omitempty"`
|
||||||
DependentSchemas map[string]*SchemaProxy `json:"dependentSchemas,omitempty" yaml:"dependentSchemas,omitempty"`
|
DependentSchemas orderedmap.Map[string, *SchemaProxy] `json:"dependentSchemas,omitempty" yaml:"dependentSchemas,omitempty"`
|
||||||
PatternProperties map[string]*SchemaProxy `json:"patternProperties,omitempty" yaml:"patternProperties,omitempty"`
|
PatternProperties orderedmap.Map[string, *SchemaProxy] `json:"patternProperties,omitempty" yaml:"patternProperties,omitempty"`
|
||||||
PropertyNames *SchemaProxy `json:"propertyNames,omitempty" yaml:"propertyNames,omitempty"`
|
PropertyNames *SchemaProxy `json:"propertyNames,omitempty" yaml:"propertyNames,omitempty"`
|
||||||
UnevaluatedItems *SchemaProxy `json:"unevaluatedItems,omitempty" yaml:"unevaluatedItems,omitempty"`
|
UnevaluatedItems *SchemaProxy `json:"unevaluatedItems,omitempty" yaml:"unevaluatedItems,omitempty"`
|
||||||
|
|
||||||
@@ -73,7 +74,7 @@ type Schema struct {
|
|||||||
|
|
||||||
// Compatible with all versions
|
// Compatible with all versions
|
||||||
Not *SchemaProxy `json:"not,omitempty" yaml:"not,omitempty"`
|
Not *SchemaProxy `json:"not,omitempty" yaml:"not,omitempty"`
|
||||||
Properties map[string]*SchemaProxy `json:"properties,omitempty" yaml:"properties,omitempty"`
|
Properties orderedmap.Map[string, *SchemaProxy] `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||||
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
||||||
Maximum *float64 `json:"maximum,omitempty" yaml:"maximum,omitempty"`
|
Maximum *float64 `json:"maximum,omitempty" yaml:"maximum,omitempty"`
|
||||||
@@ -356,14 +357,13 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
|
|
||||||
// props async
|
// props async
|
||||||
buildProps := func(k lowmodel.KeyReference[string], v lowmodel.ValueReference[*base.SchemaProxy],
|
buildProps := func(k lowmodel.KeyReference[string], v lowmodel.ValueReference[*base.SchemaProxy],
|
||||||
props map[string]*SchemaProxy, sw int,
|
props orderedmap.Map[string, *SchemaProxy], sw int,
|
||||||
) {
|
) {
|
||||||
props[k.Value] = NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
props.Set(k.Value, NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||||
Value: v.Value,
|
Value: v.Value,
|
||||||
KeyNode: k.KeyNode,
|
KeyNode: k.KeyNode,
|
||||||
ValueNode: v.ValueNode,
|
ValueNode: v.ValueNode,
|
||||||
},
|
}))
|
||||||
)
|
|
||||||
|
|
||||||
switch sw {
|
switch sw {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -375,18 +375,18 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
props := make(map[string]*SchemaProxy)
|
props := orderedmap.New[string, *SchemaProxy]()
|
||||||
for k, v := range schema.Properties.Value {
|
for pair := orderedmap.First(schema.Properties.Value); pair != nil; pair = pair.Next() {
|
||||||
buildProps(k, v, props, 0)
|
buildProps(pair.Key(), pair.Value(), props, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
dependents := make(map[string]*SchemaProxy)
|
dependents := orderedmap.New[string, *SchemaProxy]()
|
||||||
for k, v := range schema.DependentSchemas.Value {
|
for pair := orderedmap.First(schema.DependentSchemas.Value); pair != nil; pair = pair.Next() {
|
||||||
buildProps(k, v, dependents, 1)
|
buildProps(pair.Key(), pair.Value(), dependents, 1)
|
||||||
}
|
}
|
||||||
patternProps := make(map[string]*SchemaProxy)
|
patternProps := orderedmap.New[string, *SchemaProxy]()
|
||||||
for k, v := range schema.PatternProperties.Value {
|
for pair := orderedmap.First(schema.PatternProperties.Value); pair != nil; pair = pair.Next() {
|
||||||
buildProps(k, v, patternProps, 2)
|
buildProps(pair.Key(), pair.Value(), patternProps, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
var allOf []*SchemaProxy
|
var allOf []*SchemaProxy
|
||||||
|
|||||||
@@ -303,8 +303,8 @@ $anchor: anchor`
|
|||||||
assert.Equal(t, "string", compiled.If.Schema().Type[0])
|
assert.Equal(t, "string", compiled.If.Schema().Type[0])
|
||||||
assert.Equal(t, "integer", compiled.Else.Schema().Type[0])
|
assert.Equal(t, "integer", compiled.Else.Schema().Type[0])
|
||||||
assert.Equal(t, "boolean", compiled.Then.Schema().Type[0])
|
assert.Equal(t, "boolean", compiled.Then.Schema().Type[0])
|
||||||
assert.Equal(t, "string", compiled.PatternProperties["patternOne"].Schema().Type[0])
|
assert.Equal(t, "string", compiled.PatternProperties.GetOrZero("patternOne").Schema().Type[0])
|
||||||
assert.Equal(t, "string", compiled.DependentSchemas["schemaOne"].Schema().Type[0])
|
assert.Equal(t, "string", compiled.DependentSchemas.GetOrZero("schemaOne").Schema().Type[0])
|
||||||
assert.Equal(t, "string", compiled.PropertyNames.Schema().Type[0])
|
assert.Equal(t, "string", compiled.PropertyNames.Schema().Type[0])
|
||||||
assert.Equal(t, "boolean", compiled.UnevaluatedItems.Schema().Type[0])
|
assert.Equal(t, "boolean", compiled.UnevaluatedItems.Schema().Type[0])
|
||||||
assert.Equal(t, "integer", compiled.UnevaluatedProperties.A.Schema().Type[0])
|
assert.Equal(t, "integer", compiled.UnevaluatedProperties.A.Schema().Type[0])
|
||||||
@@ -500,9 +500,9 @@ required: [cake, fish]`
|
|||||||
assert.Nil(t, schemaProxy.GetBuildError())
|
assert.Nil(t, schemaProxy.GetBuildError())
|
||||||
|
|
||||||
assert.True(t, compiled.ExclusiveMaximum.A)
|
assert.True(t, compiled.ExclusiveMaximum.A)
|
||||||
assert.Equal(t, float64(123), compiled.Properties["somethingB"].Schema().ExclusiveMinimum.B)
|
assert.Equal(t, float64(123), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMinimum.B)
|
||||||
assert.Equal(t, float64(334), compiled.Properties["somethingB"].Schema().ExclusiveMaximum.B)
|
assert.Equal(t, float64(334), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMaximum.B)
|
||||||
assert.Len(t, compiled.Properties["somethingB"].Schema().Properties["somethingBProp"].Schema().Type, 2)
|
assert.Len(t, compiled.Properties.GetOrZero("somethingB").Schema().Properties.GetOrZero("somethingBProp").Schema().Type, 2)
|
||||||
|
|
||||||
assert.Equal(t, "nice", compiled.AdditionalProperties.(*SchemaProxy).Schema().Description)
|
assert.Equal(t, "nice", compiled.AdditionalProperties.(*SchemaProxy).Schema().Description)
|
||||||
|
|
||||||
@@ -734,7 +734,7 @@ properties:
|
|||||||
highSchema := NewSchema(&lowSchema)
|
highSchema := NewSchema(&lowSchema)
|
||||||
|
|
||||||
// print out the description of 'aProperty'
|
// print out the description of 'aProperty'
|
||||||
fmt.Print(highSchema.Properties["aProperty"].Schema().Description)
|
fmt.Print(highSchema.Properties.GetOrZero("aProperty").Schema().Description)
|
||||||
// Output: this is an integer property
|
// Output: this is an integer property
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -765,7 +765,7 @@ properties:
|
|||||||
})
|
})
|
||||||
|
|
||||||
// print out the description of 'aProperty'
|
// print out the description of 'aProperty'
|
||||||
fmt.Print(highSchema.Schema().Properties["aProperty"].Schema().Description)
|
fmt.Print(highSchema.Schema().Properties.GetOrZero("aProperty").Schema().Description)
|
||||||
// Output: this is an integer property
|
// Output: this is an integer property
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SecurityRequirement is a high-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.
|
// SecurityRequirement is a high-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.
|
||||||
@@ -19,7 +21,7 @@ import (
|
|||||||
// The name used for each property MUST correspond to a security scheme declared in the Security Definitions
|
// The name used for each property MUST correspond to a security scheme declared in the Security Definitions
|
||||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||||
type SecurityRequirement struct {
|
type SecurityRequirement struct {
|
||||||
Requirements map[string][]string `json:"-" yaml:"-"`
|
Requirements orderedmap.Map[string, []string] `json:"-" yaml:"-"`
|
||||||
low *base.SecurityRequirement
|
low *base.SecurityRequirement
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,14 +29,14 @@ type SecurityRequirement struct {
|
|||||||
func NewSecurityRequirement(req *base.SecurityRequirement) *SecurityRequirement {
|
func NewSecurityRequirement(req *base.SecurityRequirement) *SecurityRequirement {
|
||||||
r := new(SecurityRequirement)
|
r := new(SecurityRequirement)
|
||||||
r.low = req
|
r.low = req
|
||||||
values := make(map[string][]string)
|
values := orderedmap.New[string, []string]()
|
||||||
// to keep things fast, avoiding copying anything - makes it a little hard to read.
|
// to keep things fast, avoiding copying anything - makes it a little hard to read.
|
||||||
for reqK := range req.Requirements.Value {
|
for pair := orderedmap.First(req.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
var vals []string
|
var vals []string
|
||||||
for valK := range req.Requirements.Value[reqK].Value {
|
for valK := range pair.Value().Value {
|
||||||
vals = append(vals, req.Requirements.Value[reqK].Value[valK].Value)
|
vals = append(vals, pair.Value().Value[valK].Value)
|
||||||
}
|
}
|
||||||
values[reqK.Value] = vals
|
values.Set(pair.Key().Value, vals)
|
||||||
}
|
}
|
||||||
r.Requirements = values
|
r.Requirements = values
|
||||||
return r
|
return r
|
||||||
@@ -67,24 +69,23 @@ func (s *SecurityRequirement) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
m := utils.CreateEmptyMapNode()
|
m := utils.CreateEmptyMapNode()
|
||||||
keys := make([]*req, len(s.Requirements))
|
keys := make([]*req, orderedmap.Len(s.Requirements))
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
for k := range s.Requirements {
|
for pair := orderedmap.First(s.Requirements); pair != nil; pair = pair.Next() {
|
||||||
keys[i] = &req{key: k, val: s.Requirements[k]}
|
keys[i] = &req{key: pair.Key(), val: pair.Value()}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
i = 0
|
i = 0
|
||||||
if s.low != nil {
|
if s.low != nil {
|
||||||
for o := range keys {
|
for o := range keys {
|
||||||
kv := keys[o].key
|
kv := keys[o].key
|
||||||
for k := range s.low.Requirements.Value {
|
for pair := orderedmap.First(s.low.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
if k.Value == kv {
|
if pair.Key().Value == kv {
|
||||||
gh := s.low.Requirements.Value[k]
|
keys[o].line = pair.Key().KeyNode.Line
|
||||||
keys[o].line = k.KeyNode.Line
|
keys[o].lowKey = pair.KeyPtr()
|
||||||
keys[o].lowKey = &k
|
keys[o].lowVal = pair.ValuePtr()
|
||||||
keys[o].lowVal = &gh
|
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,12 +4,14 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewSecurityRequirement(t *testing.T) {
|
func TestNewSecurityRequirement(t *testing.T) {
|
||||||
@@ -32,11 +34,11 @@ cake:
|
|||||||
|
|
||||||
highExt := NewSecurityRequirement(&lowExt)
|
highExt := NewSecurityRequirement(&lowExt)
|
||||||
|
|
||||||
assert.Len(t, highExt.Requirements["pizza"], 2)
|
assert.Len(t, highExt.Requirements.GetOrZero("pizza"), 2)
|
||||||
assert.Len(t, highExt.Requirements["cake"], 2)
|
assert.Len(t, highExt.Requirements.GetOrZero("cake"), 2)
|
||||||
|
|
||||||
wentLow := highExt.GoLow()
|
wentLow := highExt.GoLow()
|
||||||
assert.Len(t, wentLow.Requirements.Value, 2)
|
assert.Equal(t, 2, orderedmap.Len(wentLow.Requirements.Value))
|
||||||
assert.NotNil(t, highExt.GoLowUntyped())
|
assert.NotNil(t, highExt.GoLowUntyped())
|
||||||
|
|
||||||
// render the high-level object as YAML
|
// render the high-level object as YAML
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ package high
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NodeEntry represents a single node used by NodeBuilder.
|
// NodeEntry represents a single node used by NodeBuilder.
|
||||||
@@ -659,12 +660,12 @@ func (n *NodeBuilder) extractLowMapKeys(fg reflect.Value, x string, found bool,
|
|||||||
return found, orderedCollection
|
return found, orderedCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
// Renderable is an interface that can be implemented by types that provide a custom MarshaYAML method.
|
// Renderable is an interface that can be implemented by types that provide a custom MarshalYAML method.
|
||||||
type Renderable interface {
|
type Renderable interface {
|
||||||
MarshalYAML() (interface{}, error)
|
MarshalYAML() (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderableInline is an interface that can be implemented by types that provide a custom MarshaYAML method.
|
// RenderableInline is an interface that can be implemented by types that provide a custom MarshalYAML method.
|
||||||
type RenderableInline interface {
|
type RenderableInline interface {
|
||||||
MarshalYAMLInline() (interface{}, error)
|
MarshalYAMLInline() (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|||||||
6
datamodel/high/v2/asyncresult.go
Normal file
6
datamodel/high/v2/asyncresult.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
type asyncResult[T any] struct {
|
||||||
|
key string
|
||||||
|
result T
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Definitions is a high-level represents of a Swagger / OpenAPI 2 Definitions object, backed by a low-level one.
|
// Definitions is a high-level represents of a Swagger / OpenAPI 2 Definitions object, backed by a low-level one.
|
||||||
@@ -16,7 +17,7 @@ import (
|
|||||||
// arrays or models.
|
// arrays or models.
|
||||||
// - https://swagger.io/specification/v2/#definitionsObject
|
// - https://swagger.io/specification/v2/#definitionsObject
|
||||||
type Definitions struct {
|
type Definitions struct {
|
||||||
Definitions map[string]*highbase.SchemaProxy
|
Definitions orderedmap.Map[string, *highbase.SchemaProxy]
|
||||||
low *low.Definitions
|
low *low.Definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,12 +25,20 @@ type Definitions struct {
|
|||||||
func NewDefinitions(definitions *low.Definitions) *Definitions {
|
func NewDefinitions(definitions *low.Definitions) *Definitions {
|
||||||
rd := new(Definitions)
|
rd := new(Definitions)
|
||||||
rd.low = definitions
|
rd.low = definitions
|
||||||
defs := make(map[string]*highbase.SchemaProxy)
|
defs := orderedmap.New[string, *highbase.SchemaProxy]()
|
||||||
for k := range definitions.Schemas {
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.SchemaProxy]]) (asyncResult[*highbase.SchemaProxy], error) {
|
||||||
defs[k.Value] = highbase.NewSchemaProxy(&lowmodel.NodeReference[*lowbase.SchemaProxy]{
|
return asyncResult[*highbase.SchemaProxy]{
|
||||||
Value: definitions.Schemas[k].Value,
|
key: pair.Key().Value,
|
||||||
})
|
result: highbase.NewSchemaProxy(&lowmodel.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: pair.Value().Value,
|
||||||
|
}),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
resultFunc := func(value asyncResult[*highbase.SchemaProxy]) error {
|
||||||
|
defs.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_ = orderedmap.TranslateMapParallel(definitions.Schemas, translateFunc, resultFunc)
|
||||||
rd.Definitions = defs
|
rd.Definitions = defs
|
||||||
return rd
|
return rd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,16 @@
|
|||||||
|
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
import (
|
||||||
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
)
|
||||||
|
|
||||||
// Example represents a high-level Swagger / OpenAPI 2 Example object, backed by a low level one.
|
// Example represents a high-level Swagger / OpenAPI 2 Example object, backed by a low level one.
|
||||||
// Allows sharing examples for operation responses
|
// Allows sharing examples for operation responses
|
||||||
// - https://swagger.io/specification/v2/#exampleObject
|
// - https://swagger.io/specification/v2/#exampleObject
|
||||||
type Example struct {
|
type Example struct {
|
||||||
Values map[string]any
|
Values orderedmap.Map[string, any]
|
||||||
low *low.Examples
|
low *low.Examples
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -17,10 +20,10 @@ type Example struct {
|
|||||||
func NewExample(examples *low.Examples) *Example {
|
func NewExample(examples *low.Examples) *Example {
|
||||||
e := new(Example)
|
e := new(Example)
|
||||||
e.low = examples
|
e.low = examples
|
||||||
if len(examples.Values) > 0 {
|
if orderedmap.Len(examples.Values) > 0 {
|
||||||
values := make(map[string]any)
|
values := orderedmap.New[string, any]()
|
||||||
for k := range examples.Values {
|
for pair := orderedmap.First(examples.Values); pair != nil; pair = pair.Next() {
|
||||||
values[k.Value] = examples.Values[k].Value
|
values.Set(pair.Key().Value, pair.Value().Value)
|
||||||
}
|
}
|
||||||
e.Values = values
|
e.Values = values
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
import (
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
)
|
||||||
|
|
||||||
// ParameterDefinitions is a high-level representation of a Swagger / OpenAPI 2 Parameters Definitions object
|
// ParameterDefinitions is a high-level representation of a Swagger / OpenAPI 2 Parameters Definitions object
|
||||||
// that is backed by a low-level one.
|
// that is backed by a low-level one.
|
||||||
@@ -12,7 +16,7 @@ import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
|||||||
// referenced to the ones defined here. It does not define global operation parameters
|
// referenced to the ones defined here. It does not define global operation parameters
|
||||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||||
type ParameterDefinitions struct {
|
type ParameterDefinitions struct {
|
||||||
Definitions map[string]*Parameter
|
Definitions orderedmap.Map[string, *Parameter]
|
||||||
low *low.ParameterDefinitions
|
low *low.ParameterDefinitions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,26 +25,18 @@ type ParameterDefinitions struct {
|
|||||||
func NewParametersDefinitions(parametersDefinitions *low.ParameterDefinitions) *ParameterDefinitions {
|
func NewParametersDefinitions(parametersDefinitions *low.ParameterDefinitions) *ParameterDefinitions {
|
||||||
pd := new(ParameterDefinitions)
|
pd := new(ParameterDefinitions)
|
||||||
pd.low = parametersDefinitions
|
pd.low = parametersDefinitions
|
||||||
params := make(map[string]*Parameter)
|
params := orderedmap.New[string, *Parameter]()
|
||||||
var buildParam = func(name string, param *low.Parameter, rChan chan<- asyncResult[*Parameter]) {
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Parameter]]) (asyncResult[*Parameter], error) {
|
||||||
rChan <- asyncResult[*Parameter]{
|
return asyncResult[*Parameter]{
|
||||||
key: name,
|
key: pair.Key().Value,
|
||||||
result: NewParameter(param),
|
result: NewParameter(pair.Value().Value),
|
||||||
}
|
}, nil
|
||||||
}
|
|
||||||
resChan := make(chan asyncResult[*Parameter])
|
|
||||||
for k := range parametersDefinitions.Definitions {
|
|
||||||
go buildParam(k.Value, parametersDefinitions.Definitions[k].Value, resChan)
|
|
||||||
}
|
|
||||||
totalParams := len(parametersDefinitions.Definitions)
|
|
||||||
completedParams := 0
|
|
||||||
for completedParams < totalParams {
|
|
||||||
select {
|
|
||||||
case r := <-resChan:
|
|
||||||
completedParams++
|
|
||||||
params[r.key] = r.result
|
|
||||||
}
|
}
|
||||||
|
resultFunc := func(value asyncResult[*Parameter]) error {
|
||||||
|
params.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.TranslateMapParallel(parametersDefinitions.Definitions, translateFunc, resultFunc)
|
||||||
pd.Definitions = params
|
pd.Definitions = params
|
||||||
return pd
|
return pd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Response is a representation of a high-level Swagger / OpenAPI 2 Response object, backed by a low-level one.
|
// Response is a representation of a high-level Swagger / OpenAPI 2 Response object, backed by a low-level one.
|
||||||
@@ -15,7 +16,7 @@ import (
|
|||||||
type Response struct {
|
type Response struct {
|
||||||
Description string
|
Description string
|
||||||
Schema *base.SchemaProxy
|
Schema *base.SchemaProxy
|
||||||
Headers map[string]*Header
|
Headers orderedmap.Map[string, *Header]
|
||||||
Examples *Example
|
Examples *Example
|
||||||
Extensions map[string]any
|
Extensions map[string]any
|
||||||
low *low.Response
|
low *low.Response
|
||||||
@@ -33,9 +34,9 @@ func NewResponse(response *low.Response) *Response {
|
|||||||
r.Schema = base.NewSchemaProxy(&response.Schema)
|
r.Schema = base.NewSchemaProxy(&response.Schema)
|
||||||
}
|
}
|
||||||
if !response.Headers.IsEmpty() {
|
if !response.Headers.IsEmpty() {
|
||||||
headers := make(map[string]*Header)
|
headers := orderedmap.New[string, *Header]()
|
||||||
for k := range response.Headers.Value {
|
for pair := orderedmap.First(response.Headers.Value); pair != nil; pair = pair.Next() {
|
||||||
headers[k.Value] = NewHeader(response.Headers.Value[k].Value)
|
headers.Set(pair.Key().Value, NewHeader(pair.Value().Value))
|
||||||
}
|
}
|
||||||
r.Headers = headers
|
r.Headers = headers
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Responses is a high-level representation of a Swagger / OpenAPI 2 Responses object, backed by a low level one.
|
// Responses is a high-level representation of a Swagger / OpenAPI 2 Responses object, backed by a low level one.
|
||||||
type Responses struct {
|
type Responses struct {
|
||||||
Codes map[string]*Response
|
Codes orderedmap.Map[string, *Response]
|
||||||
Default *Response
|
Default *Response
|
||||||
Extensions map[string]any
|
Extensions map[string]any
|
||||||
low *low.Responses
|
low *low.Responses
|
||||||
@@ -22,36 +24,26 @@ func NewResponses(responses *low.Responses) *Responses {
|
|||||||
r.low = responses
|
r.low = responses
|
||||||
r.Extensions = high.ExtractExtensions(responses.Extensions)
|
r.Extensions = high.ExtractExtensions(responses.Extensions)
|
||||||
|
|
||||||
// async function.
|
|
||||||
var buildPath = func(code string, pi *low.Response, rChan chan<- asyncResult[*Response]) {
|
|
||||||
rChan <- asyncResult[*Response]{
|
|
||||||
key: code,
|
|
||||||
result: NewResponse(pi),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !responses.Default.IsEmpty() {
|
if !responses.Default.IsEmpty() {
|
||||||
r.Default = NewResponse(responses.Default.Value)
|
r.Default = NewResponse(responses.Default.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// run everything async. lots of responses with lots of data are possible.
|
if orderedmap.Len(responses.Codes) > 0 {
|
||||||
if len(responses.Codes) > 0 {
|
resp := orderedmap.New[string, *Response]()
|
||||||
resultChan := make(chan asyncResult[*Response])
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
||||||
for k := range responses.Codes {
|
return asyncResult[*Response]{
|
||||||
go buildPath(k.Value, responses.Codes[k].Value, resultChan)
|
key: pair.Key().Value,
|
||||||
}
|
result: NewResponse(pair.Value().Value),
|
||||||
resp := make(map[string]*Response)
|
}, nil
|
||||||
totalResponses := len(responses.Codes)
|
|
||||||
completedResponses := 0
|
|
||||||
for completedResponses < totalResponses {
|
|
||||||
select {
|
|
||||||
case res := <-resultChan:
|
|
||||||
completedResponses++
|
|
||||||
resp[res.key] = res.result
|
|
||||||
}
|
}
|
||||||
|
resultFunc := func(value asyncResult[*Response]) error {
|
||||||
|
resp.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.TranslateMapParallel(responses.Codes, translateFunc, resultFunc)
|
||||||
r.Codes = resp
|
r.Codes = resp
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
import (
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
)
|
||||||
|
|
||||||
// ResponsesDefinitions is a high-level representation of a Swagger / OpenAPI 2 Responses Definitions object.
|
// ResponsesDefinitions is a high-level representation of a Swagger / OpenAPI 2 Responses Definitions object.
|
||||||
// that is backed by a low-level one.
|
// that is backed by a low-level one.
|
||||||
@@ -12,7 +16,7 @@ import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
|||||||
// referenced to the ones defined here. It does not define global operation responses
|
// referenced to the ones defined here. It does not define global operation responses
|
||||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||||
type ResponsesDefinitions struct {
|
type ResponsesDefinitions struct {
|
||||||
Definitions map[string]*Response
|
Definitions orderedmap.Map[string, *Response]
|
||||||
low *low.ResponsesDefinitions
|
low *low.ResponsesDefinitions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,28 +24,19 @@ type ResponsesDefinitions struct {
|
|||||||
func NewResponsesDefinitions(responsesDefinitions *low.ResponsesDefinitions) *ResponsesDefinitions {
|
func NewResponsesDefinitions(responsesDefinitions *low.ResponsesDefinitions) *ResponsesDefinitions {
|
||||||
rd := new(ResponsesDefinitions)
|
rd := new(ResponsesDefinitions)
|
||||||
rd.low = responsesDefinitions
|
rd.low = responsesDefinitions
|
||||||
|
responses := orderedmap.New[string, *Response]()
|
||||||
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
||||||
|
return asyncResult[*Response]{
|
||||||
|
key: pair.Key().Value,
|
||||||
|
result: NewResponse(pair.Value().Value),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
resultFunc := func(value asyncResult[*Response]) error {
|
||||||
|
responses.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// build everything async.
|
_ = orderedmap.TranslateMapParallel(responsesDefinitions.Definitions, translateFunc, resultFunc)
|
||||||
responses := make(map[string]*Response)
|
|
||||||
var buildResp = func(name string, resp *low.Response, rChan chan<- asyncResult[*Response]) {
|
|
||||||
rChan <- asyncResult[*Response]{
|
|
||||||
key: name,
|
|
||||||
result: NewResponse(resp),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resChan := make(chan asyncResult[*Response])
|
|
||||||
for k := range responsesDefinitions.Definitions {
|
|
||||||
go buildResp(k.Value, responsesDefinitions.Definitions[k].Value, resChan)
|
|
||||||
}
|
|
||||||
totalResponses := len(responsesDefinitions.Definitions)
|
|
||||||
completedResponses := 0
|
|
||||||
for completedResponses < totalResponses {
|
|
||||||
select {
|
|
||||||
case r := <-resChan:
|
|
||||||
completedResponses++
|
|
||||||
responses[r.key] = r.result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rd.Definitions = responses
|
rd.Definitions = responses
|
||||||
return rd
|
return rd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scopes is a high-level representation of a Swagger / OpenAPI 2 OAuth2 Scopes object, that is backed by a low-level one.
|
// Scopes is a high-level representation of a Swagger / OpenAPI 2 OAuth2 Scopes object, that is backed by a low-level one.
|
||||||
@@ -12,7 +13,7 @@ import (
|
|||||||
// Scopes lists the available scopes for an OAuth2 security scheme.
|
// Scopes lists the available scopes for an OAuth2 security scheme.
|
||||||
// - https://swagger.io/specification/v2/#scopesObject
|
// - https://swagger.io/specification/v2/#scopesObject
|
||||||
type Scopes struct {
|
type Scopes struct {
|
||||||
Values map[string]string
|
Values orderedmap.Map[string, string]
|
||||||
low *low.Scopes
|
low *low.Scopes
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,9 +21,9 @@ type Scopes struct {
|
|||||||
func NewScopes(scopes *low.Scopes) *Scopes {
|
func NewScopes(scopes *low.Scopes) *Scopes {
|
||||||
s := new(Scopes)
|
s := new(Scopes)
|
||||||
s.low = scopes
|
s.low = scopes
|
||||||
scopeValues := make(map[string]string)
|
scopeValues := orderedmap.New[string, string]()
|
||||||
for k := range scopes.Values {
|
for pair := orderedmap.First(scopes.Values); pair != nil; pair = pair.Next() {
|
||||||
scopeValues[k.Value] = scopes.Values[k].Value
|
scopeValues.Set(pair.Key().Value, pair.Value().Value)
|
||||||
}
|
}
|
||||||
s.Values = scopeValues
|
s.Values = scopeValues
|
||||||
return s
|
return s
|
||||||
|
|||||||
@@ -3,7 +3,11 @@
|
|||||||
|
|
||||||
package v2
|
package v2
|
||||||
|
|
||||||
import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
import (
|
||||||
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
)
|
||||||
|
|
||||||
// SecurityDefinitions is a high-level representation of a Swagger / OpenAPI 2 Security Definitions object, that
|
// SecurityDefinitions is a high-level representation of a Swagger / OpenAPI 2 Security Definitions object, that
|
||||||
// is backed by a low-level one.
|
// is backed by a low-level one.
|
||||||
@@ -12,7 +16,7 @@ import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
|||||||
// schemes on the operations and only serves to provide the relevant details for each scheme
|
// schemes on the operations and only serves to provide the relevant details for each scheme
|
||||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||||
type SecurityDefinitions struct {
|
type SecurityDefinitions struct {
|
||||||
Definitions map[string]*SecurityScheme
|
Definitions orderedmap.Map[string, *SecurityScheme]
|
||||||
low *low.SecurityDefinitions
|
low *low.SecurityDefinitions
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20,10 +24,23 @@ type SecurityDefinitions struct {
|
|||||||
func NewSecurityDefinitions(definitions *low.SecurityDefinitions) *SecurityDefinitions {
|
func NewSecurityDefinitions(definitions *low.SecurityDefinitions) *SecurityDefinitions {
|
||||||
sd := new(SecurityDefinitions)
|
sd := new(SecurityDefinitions)
|
||||||
sd.low = definitions
|
sd.low = definitions
|
||||||
schemes := make(map[string]*SecurityScheme)
|
schemes := orderedmap.New[string, *SecurityScheme]()
|
||||||
for k := range definitions.Definitions {
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.SecurityScheme]]) (asyncResult[*SecurityScheme], error) {
|
||||||
schemes[k.Value] = NewSecurityScheme(definitions.Definitions[k].Value)
|
return asyncResult[*SecurityScheme]{
|
||||||
|
key: pair.Key().Value,
|
||||||
|
result: NewSecurityScheme(pair.Value().Value),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
resultFunc := func(value asyncResult[*SecurityScheme]) error {
|
||||||
|
schemes.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_ = orderedmap.TranslateMapParallel(definitions.Definitions, translateFunc, resultFunc)
|
||||||
|
|
||||||
|
// schemes := make(map[string]*SecurityScheme)
|
||||||
|
// for k := range definitions.Definitions {
|
||||||
|
// schemes[k.Value] = NewSecurityScheme(definitions.Definitions[k].Value)
|
||||||
|
// }
|
||||||
sd.Definitions = schemes
|
sd.Definitions = schemes
|
||||||
return sd
|
return sd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,9 +173,3 @@ func NewSwaggerDocument(document *low.Swagger) *Swagger {
|
|||||||
func (s *Swagger) GoLow() *low.Swagger {
|
func (s *Swagger) GoLow() *low.Swagger {
|
||||||
return s.low
|
return s.low
|
||||||
}
|
}
|
||||||
|
|
||||||
// everything is build async, this little gem holds the results.
|
|
||||||
type asyncResult[T any] struct {
|
|
||||||
key string
|
|
||||||
result T
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -80,17 +81,17 @@ func TestNewSwaggerDocument_Parameters(t *testing.T) {
|
|||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
params := highDoc.Parameters
|
params := highDoc.Parameters
|
||||||
assert.Len(t, params.Definitions, 1)
|
assert.Equal(t, 1, orderedmap.Len(params.Definitions))
|
||||||
assert.Equal(t, "query", params.Definitions["simpleParam"].In)
|
assert.Equal(t, "query", params.Definitions.GetOrZero("simpleParam").In)
|
||||||
assert.Equal(t, "simple", params.Definitions["simpleParam"].Name)
|
assert.Equal(t, "simple", params.Definitions.GetOrZero("simpleParam").Name)
|
||||||
assert.Equal(t, "string", params.Definitions["simpleParam"].Type)
|
assert.Equal(t, "string", params.Definitions.GetOrZero("simpleParam").Type)
|
||||||
assert.Equal(t, "nuggets", params.Definitions["simpleParam"].Extensions["x-chicken"])
|
assert.Equal(t, "nuggets", params.Definitions.GetOrZero("simpleParam").Extensions["x-chicken"])
|
||||||
|
|
||||||
wentLow := params.GoLow()
|
wentLow := params.GoLow()
|
||||||
assert.Equal(t, 20, wentLow.FindParameter("simpleParam").ValueNode.Line)
|
assert.Equal(t, 20, wentLow.FindParameter("simpleParam").ValueNode.Line)
|
||||||
assert.Equal(t, 5, wentLow.FindParameter("simpleParam").ValueNode.Column)
|
assert.Equal(t, 5, wentLow.FindParameter("simpleParam").ValueNode.Column)
|
||||||
|
|
||||||
wentLower := params.Definitions["simpleParam"].GoLow()
|
wentLower := params.Definitions.GetOrZero("simpleParam").GoLow()
|
||||||
assert.Equal(t, 21, wentLower.Name.ValueNode.Line)
|
assert.Equal(t, 21, wentLower.Name.ValueNode.Line)
|
||||||
assert.Equal(t, 11, wentLower.Name.ValueNode.Column)
|
assert.Equal(t, 11, wentLower.Name.ValueNode.Column)
|
||||||
|
|
||||||
@@ -100,7 +101,7 @@ func TestNewSwaggerDocument_Security(t *testing.T) {
|
|||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
assert.Len(t, highDoc.Security, 1)
|
assert.Len(t, highDoc.Security, 1)
|
||||||
assert.Len(t, highDoc.Security[0].Requirements["global_auth"], 2)
|
assert.Len(t, highDoc.Security[0].Requirements.GetOrZero("global_auth"), 2)
|
||||||
|
|
||||||
wentLow := highDoc.Security[0].GoLow()
|
wentLow := highDoc.Security[0].GoLow()
|
||||||
assert.Equal(t, 25, wentLow.Requirements.ValueNode.Line)
|
assert.Equal(t, 25, wentLow.Requirements.ValueNode.Line)
|
||||||
@@ -111,23 +112,23 @@ func TestNewSwaggerDocument_Security(t *testing.T) {
|
|||||||
func TestNewSwaggerDocument_Definitions_Security(t *testing.T) {
|
func TestNewSwaggerDocument_Definitions_Security(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
assert.Len(t, highDoc.SecurityDefinitions.Definitions, 3)
|
assert.Equal(t, 3, orderedmap.Len(highDoc.SecurityDefinitions.Definitions))
|
||||||
assert.Equal(t, "oauth2", highDoc.SecurityDefinitions.Definitions["petstore_auth"].Type)
|
assert.Equal(t, "oauth2", highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Type)
|
||||||
assert.Equal(t, "https://petstore.swagger.io/oauth/authorize",
|
assert.Equal(t, "https://petstore.swagger.io/oauth/authorize",
|
||||||
highDoc.SecurityDefinitions.Definitions["petstore_auth"].AuthorizationUrl)
|
highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").AuthorizationUrl)
|
||||||
assert.Equal(t, "implicit", highDoc.SecurityDefinitions.Definitions["petstore_auth"].Flow)
|
assert.Equal(t, "implicit", highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Flow)
|
||||||
assert.Len(t, highDoc.SecurityDefinitions.Definitions["petstore_auth"].Scopes.Values, 2)
|
assert.Equal(t, 2, orderedmap.Len(highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Scopes.Values))
|
||||||
|
|
||||||
goLow := highDoc.SecurityDefinitions.GoLow()
|
goLow := highDoc.SecurityDefinitions.GoLow()
|
||||||
|
|
||||||
assert.Equal(t, 661, goLow.FindSecurityDefinition("petstore_auth").ValueNode.Line)
|
assert.Equal(t, 661, goLow.FindSecurityDefinition("petstore_auth").ValueNode.Line)
|
||||||
assert.Equal(t, 5, goLow.FindSecurityDefinition("petstore_auth").ValueNode.Column)
|
assert.Equal(t, 5, goLow.FindSecurityDefinition("petstore_auth").ValueNode.Column)
|
||||||
|
|
||||||
goLower := highDoc.SecurityDefinitions.Definitions["petstore_auth"].GoLow()
|
goLower := highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").GoLow()
|
||||||
assert.Equal(t, 664, goLower.Scopes.KeyNode.Line)
|
assert.Equal(t, 664, goLower.Scopes.KeyNode.Line)
|
||||||
assert.Equal(t, 5, goLower.Scopes.KeyNode.Column)
|
assert.Equal(t, 5, goLower.Scopes.KeyNode.Column)
|
||||||
|
|
||||||
goLowest := highDoc.SecurityDefinitions.Definitions["petstore_auth"].Scopes.GoLow()
|
goLowest := highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Scopes.GoLow()
|
||||||
assert.Equal(t, 665, goLowest.FindScope("read:pets").ValueNode.Line)
|
assert.Equal(t, 665, goLowest.FindScope("read:pets").ValueNode.Line)
|
||||||
assert.Equal(t, 18, goLowest.FindScope("read:pets").ValueNode.Column)
|
assert.Equal(t, 18, goLowest.FindScope("read:pets").ValueNode.Column)
|
||||||
}
|
}
|
||||||
@@ -135,34 +136,34 @@ func TestNewSwaggerDocument_Definitions_Security(t *testing.T) {
|
|||||||
func TestNewSwaggerDocument_Definitions_Responses(t *testing.T) {
|
func TestNewSwaggerDocument_Definitions_Responses(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
assert.Len(t, highDoc.Responses.Definitions, 2)
|
assert.Equal(t, 2, orderedmap.Len(highDoc.Responses.Definitions))
|
||||||
|
|
||||||
defs := highDoc.Responses.Definitions
|
defs := highDoc.Responses.Definitions
|
||||||
assert.Equal(t, "morning", defs["200"].Extensions["x-coffee"])
|
assert.Equal(t, "morning", defs.GetOrZero("200").Extensions["x-coffee"])
|
||||||
assert.Equal(t, "OK", defs["200"].Description)
|
assert.Equal(t, "OK", defs.GetOrZero("200").Description)
|
||||||
assert.Equal(t, "a generic API response object",
|
assert.Equal(t, "a generic API response object",
|
||||||
defs["200"].Schema.Schema().Description)
|
defs.GetOrZero("200").Schema.Schema().Description)
|
||||||
assert.Len(t, defs["200"].Examples.Values, 3)
|
assert.Equal(t, 3, orderedmap.Len(defs.GetOrZero("200").Examples.Values))
|
||||||
|
|
||||||
exp := defs["200"].Examples.Values["application/json"]
|
exp := defs.GetOrZero("200").Examples.Values.GetOrZero("application/json")
|
||||||
assert.Len(t, exp.(map[string]interface{}), 2)
|
assert.Len(t, exp.(map[string]interface{}), 2)
|
||||||
assert.Equal(t, "two", exp.(map[string]interface{})["one"])
|
assert.Equal(t, "two", exp.(map[string]interface{})["one"])
|
||||||
|
|
||||||
exp = defs["200"].Examples.Values["text/xml"]
|
exp = defs.GetOrZero("200").Examples.Values.GetOrZero("text/xml")
|
||||||
assert.Len(t, exp.([]interface{}), 3)
|
assert.Len(t, exp.([]interface{}), 3)
|
||||||
assert.Equal(t, "two", exp.([]interface{})[1])
|
assert.Equal(t, "two", exp.([]interface{})[1])
|
||||||
|
|
||||||
exp = defs["200"].Examples.Values["text/plain"]
|
exp = defs.GetOrZero("200").Examples.Values.GetOrZero("text/plain")
|
||||||
assert.Equal(t, "something else.", exp)
|
assert.Equal(t, "something else.", exp)
|
||||||
|
|
||||||
expWentLow := defs["200"].Examples.GoLow()
|
expWentLow := defs.GetOrZero("200").Examples.GoLow()
|
||||||
assert.Equal(t, 702, expWentLow.FindExample("application/json").ValueNode.Line)
|
assert.Equal(t, 702, expWentLow.FindExample("application/json").ValueNode.Line)
|
||||||
assert.Equal(t, 9, expWentLow.FindExample("application/json").ValueNode.Column)
|
assert.Equal(t, 9, expWentLow.FindExample("application/json").ValueNode.Column)
|
||||||
|
|
||||||
wentLow := highDoc.Responses.GoLow()
|
wentLow := highDoc.Responses.GoLow()
|
||||||
assert.Equal(t, 669, wentLow.FindResponse("200").ValueNode.Line)
|
assert.Equal(t, 669, wentLow.FindResponse("200").ValueNode.Line)
|
||||||
|
|
||||||
y := defs["500"].Headers["someHeader"]
|
y := defs.GetOrZero("500").Headers.GetOrZero("someHeader")
|
||||||
assert.Len(t, y.Enum, 2)
|
assert.Len(t, y.Enum, 2)
|
||||||
x := y.Items
|
x := y.Items
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ func TestNewSwaggerDocument_Definitions(t *testing.T) {
|
|||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
|
|
||||||
assert.Len(t, highDoc.Definitions.Definitions, 6)
|
assert.Equal(t, 6, orderedmap.Len(highDoc.Definitions.Definitions))
|
||||||
|
|
||||||
wentLow := highDoc.Definitions.GoLow()
|
wentLow := highDoc.Definitions.GoLow()
|
||||||
assert.Equal(t, 848, wentLow.FindSchema("User").ValueNode.Line)
|
assert.Equal(t, 848, wentLow.FindSchema("User").ValueNode.Line)
|
||||||
@@ -202,7 +203,7 @@ func TestNewSwaggerDocument_Definitions(t *testing.T) {
|
|||||||
func TestNewSwaggerDocument_Paths(t *testing.T) {
|
func TestNewSwaggerDocument_Paths(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
assert.Len(t, highDoc.Paths.PathItems, 15)
|
assert.Equal(t, 15, orderedmap.Len(highDoc.Paths.PathItems))
|
||||||
|
|
||||||
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage")
|
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage")
|
||||||
assert.Equal(t, "man", upload.Extensions["x-potato"])
|
assert.Equal(t, "man", upload.Extensions["x-potato"])
|
||||||
@@ -264,9 +265,9 @@ func TestNewSwaggerDocument_Responses(t *testing.T) {
|
|||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage").Post
|
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage").Post
|
||||||
|
|
||||||
assert.Len(t, upload.Responses.Codes, 1)
|
assert.Equal(t, 1, orderedmap.Len(upload.Responses.Codes))
|
||||||
|
|
||||||
OK := upload.Responses.Codes["200"]
|
OK := upload.Responses.Codes.GetOrZero("200")
|
||||||
assert.Equal(t, "successful operation", OK.Description)
|
assert.Equal(t, "successful operation", OK.Description)
|
||||||
assert.Equal(t, "a generic API response object", OK.Schema.Schema().Description)
|
assert.Equal(t, "a generic API response object", OK.Schema.Schema().Description)
|
||||||
|
|
||||||
|
|||||||
6
datamodel/high/v3/asyncresult.go
Normal file
6
datamodel/high/v3/asyncresult.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package v3
|
||||||
|
|
||||||
|
type asyncResult[T any] struct {
|
||||||
|
key string
|
||||||
|
result T
|
||||||
|
}
|
||||||
@@ -4,11 +4,13 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Callback represents a high-level Callback object for OpenAPI 3+.
|
// Callback represents a high-level Callback object for OpenAPI 3+.
|
||||||
@@ -19,7 +21,7 @@ import (
|
|||||||
// that identifies a URL to use for the callback operation.
|
// that identifies a URL to use for the callback operation.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
||||||
type Callback struct {
|
type Callback struct {
|
||||||
Expression map[string]*PathItem `json:"-" yaml:"-"`
|
Expression orderedmap.Map[string, *PathItem] `json:"-" yaml:"-"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Callback
|
low *low.Callback
|
||||||
}
|
}
|
||||||
@@ -28,9 +30,9 @@ type Callback struct {
|
|||||||
func NewCallback(lowCallback *low.Callback) *Callback {
|
func NewCallback(lowCallback *low.Callback) *Callback {
|
||||||
n := new(Callback)
|
n := new(Callback)
|
||||||
n.low = lowCallback
|
n.low = lowCallback
|
||||||
n.Expression = make(map[string]*PathItem)
|
n.Expression = orderedmap.New[string, *PathItem]()
|
||||||
for i := range lowCallback.Expression.Value {
|
for pair := orderedmap.First(lowCallback.Expression.Value); pair != nil; pair = pair.Next() {
|
||||||
n.Expression[i.Value] = NewPathItem(lowCallback.Expression.Value[i].Value)
|
n.Expression.Set(pair.Key().Value, NewPathItem(pair.Value().Value))
|
||||||
}
|
}
|
||||||
n.Extensions = make(map[string]any)
|
n.Extensions = make(map[string]any)
|
||||||
for k, v := range lowCallback.Extensions {
|
for k, v := range lowCallback.Extensions {
|
||||||
@@ -66,16 +68,16 @@ func (c *Callback) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*cbItem
|
var mapped []*cbItem
|
||||||
|
|
||||||
for k, ex := range c.Expression {
|
for pair := orderedmap.First(c.Expression); pair != nil; pair = pair.Next() {
|
||||||
ln := 999 // default to a high value to weight new content to the bottom.
|
ln := 999 // default to a high value to weight new content to the bottom.
|
||||||
if c.low != nil {
|
if c.low != nil {
|
||||||
for lKey := range c.low.Expression.Value {
|
for lPair := orderedmap.First(c.low.Expression.Value); lPair != nil; lPair = lPair.Next() {
|
||||||
if lKey.Value == k {
|
if lPair.Key().Value == pair.Key() {
|
||||||
ln = lKey.KeyNode.Line
|
ln = lPair.Key().KeyNode.Line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &cbItem{ex, k, ln, nil})
|
mapped = append(mapped, &cbItem{pair.Value(), pair.Key(), ln, nil})
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract extensions
|
// extract extensions
|
||||||
|
|||||||
@@ -4,19 +4,21 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCallback_MarshalYAML(t *testing.T) {
|
func TestCallback_MarshalYAML(t *testing.T) {
|
||||||
|
|
||||||
cb := &Callback{
|
cb := &Callback{
|
||||||
Expression: map[string]*PathItem{
|
Expression: orderedmap.ToOrderedMap(map[string]*PathItem{
|
||||||
"https://pb33f.io": {
|
"https://pb33f.io": {
|
||||||
Get: &Operation{
|
Get: &Operation{
|
||||||
OperationId: "oneTwoThree",
|
OperationId: "oneTwoThree",
|
||||||
@@ -27,7 +29,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
|||||||
OperationId: "openaypeeeye",
|
OperationId: "openaypeeeye",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
Extensions: map[string]any{
|
Extensions: map[string]any{
|
||||||
"x-burgers": "why not?",
|
"x-burgers": "why not?",
|
||||||
},
|
},
|
||||||
@@ -39,7 +41,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
|||||||
assert.Len(t, rend, 152)
|
assert.Len(t, rend, 152)
|
||||||
|
|
||||||
// mutate
|
// mutate
|
||||||
cb.Expression["https://pb33f.io"].Get.OperationId = "blim-blam"
|
cb.Expression.GetOrZero("https://pb33f.io").Get.OperationId = "blim-blam"
|
||||||
cb.Extensions = map[string]interface{}{"x-burgers": "yes please!"}
|
cb.Extensions = map[string]interface{}{"x-burgers": "yes please!"}
|
||||||
|
|
||||||
rend, _ = cb.Render()
|
rend, _ = cb.Render()
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,15 +21,15 @@ import (
|
|||||||
// will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
// will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#components-object
|
// - https://spec.openapis.org/oas/v3.1.0#components-object
|
||||||
type Components struct {
|
type Components struct {
|
||||||
Schemas map[string]*highbase.SchemaProxy `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
Schemas orderedmap.Map[string, *highbase.SchemaProxy] `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||||
Responses map[string]*Response `json:"responses,omitempty" yaml:"responses,omitempty"`
|
Responses orderedmap.Map[string, *Response] `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||||
Parameters map[string]*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
Parameters orderedmap.Map[string, *Parameter] `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||||
Examples map[string]*highbase.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
Examples orderedmap.Map[string, *highbase.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||||
RequestBodies map[string]*RequestBody `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
RequestBodies orderedmap.Map[string, *RequestBody] `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||||
SecuritySchemes map[string]*SecurityScheme `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
SecuritySchemes orderedmap.Map[string, *SecurityScheme] `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||||
Links map[string]*Link `json:"links,omitempty" yaml:"links,omitempty"`
|
Links orderedmap.Map[string, *Link] `json:"links,omitempty" yaml:"links,omitempty"`
|
||||||
Callbacks map[string]*Callback `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
Callbacks orderedmap.Map[string, *Callback] `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Components
|
low *low.Components
|
||||||
}
|
}
|
||||||
@@ -43,15 +43,15 @@ func NewComponents(comp *low.Components) *Components {
|
|||||||
if len(comp.Extensions) > 0 {
|
if len(comp.Extensions) > 0 {
|
||||||
c.Extensions = high.ExtractExtensions(comp.Extensions)
|
c.Extensions = high.ExtractExtensions(comp.Extensions)
|
||||||
}
|
}
|
||||||
cbMap := make(map[string]*Callback)
|
cbMap := orderedmap.New[string, *Callback]()
|
||||||
linkMap := make(map[string]*Link)
|
linkMap := orderedmap.New[string, *Link]()
|
||||||
responseMap := make(map[string]*Response)
|
responseMap := orderedmap.New[string, *Response]()
|
||||||
parameterMap := make(map[string]*Parameter)
|
parameterMap := orderedmap.New[string, *Parameter]()
|
||||||
exampleMap := make(map[string]*highbase.Example)
|
exampleMap := orderedmap.New[string, *highbase.Example]()
|
||||||
requestBodyMap := make(map[string]*RequestBody)
|
requestBodyMap := orderedmap.New[string, *RequestBody]()
|
||||||
headerMap := make(map[string]*Header)
|
headerMap := orderedmap.New[string, *Header]()
|
||||||
securitySchemeMap := make(map[string]*SecurityScheme)
|
securitySchemeMap := orderedmap.New[string, *SecurityScheme]()
|
||||||
schemas := make(map[string]*highbase.SchemaProxy)
|
schemas := orderedmap.New[string, *highbase.SchemaProxy]()
|
||||||
|
|
||||||
// build all components asynchronously.
|
// build all components asynchronously.
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
@@ -114,32 +114,33 @@ type componentResult[T any] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// buildComponent builds component structs from low level structs.
|
// buildComponent builds component structs from low level structs.
|
||||||
func buildComponent[IN any, OUT any](inMap map[lowmodel.KeyReference[string]]lowmodel.ValueReference[IN], outMap map[string]OUT, translateItem func(IN) OUT) {
|
func buildComponent[IN any, OUT any](inMap orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[IN]], outMap orderedmap.Map[string, OUT], translateItem func(IN) OUT) {
|
||||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[IN]) (componentResult[OUT], error) {
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[IN]]) (componentResult[OUT], error) {
|
||||||
return componentResult[OUT]{key: key.Value, res: translateItem(value.Value)}, nil
|
return componentResult[OUT]{key: pair.Key().Value, res: translateItem(pair.Value().Value)}, nil
|
||||||
}
|
}
|
||||||
resultFunc := func(value componentResult[OUT]) error {
|
resultFunc := func(value componentResult[OUT]) error {
|
||||||
outMap[value.key] = value.res
|
outMap.Set(value.key, value.res)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
_ = orderedmap.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildSchema builds a schema from low level structs.
|
// buildSchema builds a schema from low level structs.
|
||||||
func buildSchema(inMap map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*base.SchemaProxy], outMap map[string]*highbase.SchemaProxy) {
|
func buildSchema(inMap orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*base.SchemaProxy]], outMap orderedmap.Map[string, *highbase.SchemaProxy]) {
|
||||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[*base.SchemaProxy]) (componentResult[*highbase.SchemaProxy], error) {
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*base.SchemaProxy]]) (componentResult[*highbase.SchemaProxy], error) {
|
||||||
|
value := pair.Value()
|
||||||
var sch *highbase.SchemaProxy
|
var sch *highbase.SchemaProxy
|
||||||
sch = highbase.NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
sch = highbase.NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||||
Value: value.Value,
|
Value: value.Value,
|
||||||
ValueNode: value.ValueNode,
|
ValueNode: value.ValueNode,
|
||||||
})
|
})
|
||||||
return componentResult[*highbase.SchemaProxy]{res: sch, key: key.Value}, nil
|
return componentResult[*highbase.SchemaProxy]{res: sch, key: pair.Key().Value}, nil
|
||||||
}
|
}
|
||||||
resultFunc := func(value componentResult[*highbase.SchemaProxy]) error {
|
resultFunc := func(value componentResult[*highbase.SchemaProxy]) error {
|
||||||
outMap[value.key] = value.res
|
outMap.Set(value.key, value.res)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
_ = orderedmap.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoLow returns the low-level Components instance used to create the high-level one.
|
// GoLow returns the low-level Components instance used to create the high-level one.
|
||||||
|
|||||||
@@ -4,38 +4,40 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestComponents_MarshalYAML(t *testing.T) {
|
func TestComponents_MarshalYAML(t *testing.T) {
|
||||||
|
|
||||||
comp := &Components{
|
comp := &Components{
|
||||||
Responses: map[string]*Response{
|
Responses: orderedmap.ToOrderedMap(map[string]*Response{
|
||||||
"200": {
|
"200": {
|
||||||
Description: "OK",
|
Description: "OK",
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
Parameters: map[string]*Parameter{
|
Parameters: orderedmap.ToOrderedMap(map[string]*Parameter{
|
||||||
"id": {
|
"id": {
|
||||||
Name: "id",
|
Name: "id",
|
||||||
In: "path",
|
In: "path",
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
RequestBodies: map[string]*RequestBody{
|
RequestBodies: orderedmap.ToOrderedMap(map[string]*RequestBody{
|
||||||
"body": {
|
"body": {
|
||||||
Content: map[string]*MediaType{
|
Content: orderedmap.ToOrderedMap(map[string]*MediaType{
|
||||||
"application/json": {
|
"application/json": {
|
||||||
Example: "why?",
|
Example: "why?",
|
||||||
},
|
},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dat, _ := comp.Render()
|
dat, _ := comp.Render()
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -81,7 +83,7 @@ type Document struct {
|
|||||||
// for example by an out-of-band registration. The key name is a unique string to refer to each webhook,
|
// for example by an out-of-band registration. The key name is a unique string to refer to each webhook,
|
||||||
// while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider
|
// while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider
|
||||||
// and the expected responses. An example is available.
|
// and the expected responses. An example is available.
|
||||||
Webhooks map[string]*PathItem `json:"webhooks,omitempty" yaml:"webhooks,omitempty"`
|
Webhooks orderedmap.Map[string, *PathItem] `json:"webhooks,omitempty" yaml:"webhooks,omitempty"`
|
||||||
|
|
||||||
// Index is a reference to the *index.SpecIndex that was created for the document and used
|
// Index is a reference to the *index.SpecIndex that was created for the document and used
|
||||||
// as a guide when building out the Document. Ideal if further processing is required on the model and
|
// as a guide when building out the Document. Ideal if further processing is required on the model and
|
||||||
@@ -129,9 +131,9 @@ func NewDocument(document *low.Document) *Document {
|
|||||||
d.JsonSchemaDialect = document.JsonSchemaDialect.Value
|
d.JsonSchemaDialect = document.JsonSchemaDialect.Value
|
||||||
}
|
}
|
||||||
if !document.Webhooks.IsEmpty() {
|
if !document.Webhooks.IsEmpty() {
|
||||||
hooks := make(map[string]*PathItem)
|
hooks := orderedmap.New[string, *PathItem]()
|
||||||
for h := range document.Webhooks.Value {
|
for pair := orderedmap.First(document.Webhooks.Value); pair != nil; pair = pair.Next() {
|
||||||
hooks[h.Value] = NewPathItem(document.Webhooks.Value[h].Value)
|
hooks.Set(pair.Key().Value, NewPathItem(pair.Value().Value))
|
||||||
}
|
}
|
||||||
d.Webhooks = hooks
|
d.Webhooks = hooks
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func TestNewDocument_Security(t *testing.T) {
|
|||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Security, 1)
|
assert.Len(t, h.Security, 1)
|
||||||
assert.Len(t, h.Security[0].Requirements, 1)
|
assert.Len(t, h.Security[0].Requirements, 1)
|
||||||
assert.Len(t, h.Security[0].Requirements["OAuthScheme"], 2)
|
assert.Len(t, h.Security[0].Requirements.GetOrZero("OAuthScheme"), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Info(t *testing.T) {
|
func TestNewDocument_Info(t *testing.T) {
|
||||||
@@ -98,14 +98,14 @@ func TestNewDocument_Servers(t *testing.T) {
|
|||||||
assert.Equal(t, "{scheme}://api.pb33f.io", h.Servers[0].URL)
|
assert.Equal(t, "{scheme}://api.pb33f.io", h.Servers[0].URL)
|
||||||
assert.Equal(t, "this is our main API server, for all fun API things.", h.Servers[0].Description)
|
assert.Equal(t, "this is our main API server, for all fun API things.", h.Servers[0].Description)
|
||||||
assert.Len(t, h.Servers[0].Variables, 1)
|
assert.Len(t, h.Servers[0].Variables, 1)
|
||||||
assert.Equal(t, "https", h.Servers[0].Variables["scheme"].Default)
|
assert.Equal(t, "https", h.Servers[0].Variables.GetOrZero("scheme").Default)
|
||||||
assert.Len(t, h.Servers[0].Variables["scheme"].Enum, 2)
|
assert.Len(t, h.Servers[0].Variables.GetOrZero("scheme").Enum, 2)
|
||||||
|
|
||||||
assert.Equal(t, "https://{domain}.{host}.com", h.Servers[1].URL)
|
assert.Equal(t, "https://{domain}.{host}.com", h.Servers[1].URL)
|
||||||
assert.Equal(t, "this is our second API server, for all fun API things.", h.Servers[1].Description)
|
assert.Equal(t, "this is our second API server, for all fun API things.", h.Servers[1].Description)
|
||||||
assert.Len(t, h.Servers[1].Variables, 2)
|
assert.Len(t, h.Servers[1].Variables, 2)
|
||||||
assert.Equal(t, "api", h.Servers[1].Variables["domain"].Default)
|
assert.Equal(t, "api", h.Servers[1].Variables.GetOrZero("domain").Default)
|
||||||
assert.Equal(t, "pb33f.io", h.Servers[1].Variables["host"].Default)
|
assert.Equal(t, "pb33f.io", h.Servers[1].Variables.GetOrZero("host").Default)
|
||||||
|
|
||||||
wentLow := h.GoLow()
|
wentLow := h.GoLow()
|
||||||
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.KeyNode.Line)
|
assert.Equal(t, 45, wentLow.Servers.Value[0].Value.Description.KeyNode.Line)
|
||||||
@@ -117,7 +117,7 @@ func TestNewDocument_Servers(t *testing.T) {
|
|||||||
assert.Equal(t, 45, wentLower.Description.ValueNode.Line)
|
assert.Equal(t, 45, wentLower.Description.ValueNode.Line)
|
||||||
assert.Equal(t, 18, wentLower.Description.ValueNode.Column)
|
assert.Equal(t, 18, wentLower.Description.ValueNode.Column)
|
||||||
|
|
||||||
wentLowest := h.Servers[0].Variables["scheme"].GoLow()
|
wentLowest := h.Servers[0].Variables.GetOrZero("scheme").GoLow()
|
||||||
assert.Equal(t, 50, wentLowest.Description.ValueNode.Line)
|
assert.Equal(t, 50, wentLowest.Description.ValueNode.Line)
|
||||||
assert.Equal(t, 22, wentLowest.Description.ValueNode.Column)
|
assert.Equal(t, 22, wentLowest.Description.ValueNode.Column)
|
||||||
}
|
}
|
||||||
@@ -147,18 +147,18 @@ func TestNewDocument_Tags(t *testing.T) {
|
|||||||
func TestNewDocument_Webhooks(t *testing.T) {
|
func TestNewDocument_Webhooks(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Webhooks, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Webhooks))
|
||||||
assert.Equal(t, "Information about a new burger", h.Webhooks["someHook"].Post.RequestBody.Description)
|
assert.Equal(t, "Information about a new burger", h.Webhooks.GetOrZero("someHook").Post.RequestBody.Description)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Components_Links(t *testing.T) {
|
func TestNewDocument_Components_Links(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Links, 2)
|
assert.Equal(t, 2, orderedmap.Len(h.Components.Links))
|
||||||
assert.Equal(t, "locateBurger", h.Components.Links["LocateBurger"].OperationId)
|
assert.Equal(t, "locateBurger", h.Components.Links.GetOrZero("LocateBurger").OperationId)
|
||||||
assert.Equal(t, "$response.body#/id", h.Components.Links["LocateBurger"].Parameters["burgerId"])
|
assert.Equal(t, "$response.body#/id", h.Components.Links.GetOrZero("LocateBurger").Parameters.GetOrZero("burgerId"))
|
||||||
|
|
||||||
wentLow := h.Components.Links["LocateBurger"].GoLow()
|
wentLow := h.Components.Links.GetOrZero("LocateBurger").GoLow()
|
||||||
assert.Equal(t, 310, wentLow.OperationId.ValueNode.Line)
|
assert.Equal(t, 310, wentLow.OperationId.ValueNode.Line)
|
||||||
assert.Equal(t, 20, wentLow.OperationId.ValueNode.Column)
|
assert.Equal(t, 20, wentLow.OperationId.ValueNode.Column)
|
||||||
}
|
}
|
||||||
@@ -166,29 +166,29 @@ func TestNewDocument_Components_Links(t *testing.T) {
|
|||||||
func TestNewDocument_Components_Callbacks(t *testing.T) {
|
func TestNewDocument_Components_Callbacks(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Callbacks, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Components.Callbacks))
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t,
|
t,
|
||||||
"Callback payload",
|
"Callback payload",
|
||||||
h.Components.Callbacks["BurgerCallback"].Expression["{$request.query.queryUrl}"].Post.RequestBody.Description,
|
h.Components.Callbacks.GetOrZero("BurgerCallback").Expression.GetOrZero("{$request.query.queryUrl}").Post.RequestBody.Description,
|
||||||
)
|
)
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t,
|
t,
|
||||||
298,
|
298,
|
||||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Line,
|
h.Components.Callbacks.GetOrZero("BurgerCallback").GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Line,
|
||||||
)
|
)
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t,
|
t,
|
||||||
9,
|
9,
|
||||||
h.Components.Callbacks["BurgerCallback"].GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Column,
|
h.Components.Callbacks.GetOrZero("BurgerCallback").GoLow().FindExpression("{$request.query.queryUrl}").ValueNode.Column,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert.Equal(t, "please", h.Components.Callbacks["BurgerCallback"].Extensions["x-break-everything"])
|
assert.Equal(t, "please", h.Components.Callbacks.GetOrZero("BurgerCallback").Extensions["x-break-everything"])
|
||||||
|
|
||||||
for k := range h.Components.GoLow().Callbacks.Value {
|
for pair := orderedmap.First(h.Components.GoLow().Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||||
if k.Value == "BurgerCallback" {
|
if pair.Key().Value == "BurgerCallback" {
|
||||||
assert.Equal(t, 295, k.KeyNode.Line)
|
assert.Equal(t, 295, pair.Key().KeyNode.Line)
|
||||||
assert.Equal(t, 5, k.KeyNode.Column)
|
assert.Equal(t, 5, pair.Key().KeyNode.Column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,30 +196,30 @@ func TestNewDocument_Components_Callbacks(t *testing.T) {
|
|||||||
func TestNewDocument_Components_Schemas(t *testing.T) {
|
func TestNewDocument_Components_Schemas(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Schemas, 6)
|
assert.Equal(t, 6, orderedmap.Len(h.Components.Schemas))
|
||||||
|
|
||||||
goLow := h.Components.GoLow()
|
goLow := h.Components.GoLow()
|
||||||
|
|
||||||
a := h.Components.Schemas["Error"]
|
a := h.Components.Schemas.GetOrZero("Error")
|
||||||
abcd := a.Schema().Properties["message"].Schema().Example
|
abcd := a.Schema().Properties.GetOrZero("message").Schema().Example
|
||||||
assert.Equal(t, "No such burger as 'Big-Whopper'", abcd)
|
assert.Equal(t, "No such burger as 'Big-Whopper'", abcd)
|
||||||
assert.Equal(t, 433, goLow.Schemas.KeyNode.Line)
|
assert.Equal(t, 433, goLow.Schemas.KeyNode.Line)
|
||||||
assert.Equal(t, 3, goLow.Schemas.KeyNode.Column)
|
assert.Equal(t, 3, goLow.Schemas.KeyNode.Column)
|
||||||
assert.Equal(t, 436, a.Schema().GoLow().Description.KeyNode.Line)
|
assert.Equal(t, 436, a.Schema().GoLow().Description.KeyNode.Line)
|
||||||
|
|
||||||
b := h.Components.Schemas["Burger"]
|
b := h.Components.Schemas.GetOrZero("Burger")
|
||||||
assert.Len(t, b.Schema().Required, 2)
|
assert.Len(t, b.Schema().Required, 2)
|
||||||
assert.Equal(t, "golden slices of happy fun joy", b.Schema().Properties["fries"].Schema().Description)
|
assert.Equal(t, "golden slices of happy fun joy", b.Schema().Properties.GetOrZero("fries").Schema().Description)
|
||||||
assert.Equal(t, int64(2), b.Schema().Properties["numPatties"].Schema().Example)
|
assert.Equal(t, int64(2), b.Schema().Properties.GetOrZero("numPatties").Schema().Example)
|
||||||
assert.Equal(t, 448, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Line)
|
assert.Equal(t, 448, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Line)
|
||||||
assert.Equal(t, 7, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Column)
|
assert.Equal(t, 7, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Column)
|
||||||
assert.Equal(t, 450, b.Schema().GoLow().FindProperty("name").ValueNode.Line)
|
assert.Equal(t, 450, b.Schema().GoLow().FindProperty("name").ValueNode.Line)
|
||||||
|
|
||||||
f := h.Components.Schemas["Fries"]
|
f := h.Components.Schemas.GetOrZero("Fries")
|
||||||
assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items.A.Schema().Example)
|
assert.Equal(t, "salt", f.Schema().Properties.GetOrZero("seasoning").Schema().Items.A.Schema().Example)
|
||||||
assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 1)
|
assert.Len(t, f.Schema().Properties.GetOrZero("favoriteDrink").Schema().Properties.GetOrZero("drinkType").Schema().Enum, 1)
|
||||||
|
|
||||||
d := h.Components.Schemas["Drink"]
|
d := h.Components.Schemas.GetOrZero("Drink")
|
||||||
assert.Len(t, d.Schema().Required, 2)
|
assert.Len(t, d.Schema().Required, 2)
|
||||||
assert.True(t, d.Schema().AdditionalProperties.(bool))
|
assert.True(t, d.Schema().AdditionalProperties.(bool))
|
||||||
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
||||||
@@ -227,7 +227,7 @@ func TestNewDocument_Components_Schemas(t *testing.T) {
|
|||||||
assert.Equal(t, 516, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
assert.Equal(t, 516, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
||||||
assert.Equal(t, 23, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Column)
|
assert.Equal(t, 23, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Column)
|
||||||
|
|
||||||
pl := h.Components.Schemas["SomePayload"]
|
pl := h.Components.Schemas.GetOrZero("SomePayload")
|
||||||
assert.Equal(t, "is html programming? yes.", pl.Schema().XML.Name)
|
assert.Equal(t, "is html programming? yes.", pl.Schema().XML.Name)
|
||||||
assert.Equal(t, 523, pl.Schema().XML.GoLow().Name.ValueNode.Line)
|
assert.Equal(t, 523, pl.Schema().XML.GoLow().Name.ValueNode.Line)
|
||||||
|
|
||||||
@@ -238,62 +238,62 @@ func TestNewDocument_Components_Schemas(t *testing.T) {
|
|||||||
func TestNewDocument_Components_Headers(t *testing.T) {
|
func TestNewDocument_Components_Headers(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Headers, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Components.Headers))
|
||||||
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers["UseOil"].Description)
|
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers.GetOrZero("UseOil").Description)
|
||||||
assert.Equal(t, 323, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 323, h.Components.Headers.GetOrZero("UseOil").GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 20, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Column)
|
assert.Equal(t, 20, h.Components.Headers.GetOrZero("UseOil").GoLow().Description.ValueNode.Column)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Components_RequestBodies(t *testing.T) {
|
func TestNewDocument_Components_RequestBodies(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.RequestBodies, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Components.RequestBodies))
|
||||||
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies["BurgerRequest"].Description)
|
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies.GetOrZero("BurgerRequest").Description)
|
||||||
assert.Equal(t, 328, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 328, h.Components.RequestBodies.GetOrZero("BurgerRequest").GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 20, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Column)
|
assert.Equal(t, 20, h.Components.RequestBodies.GetOrZero("BurgerRequest").GoLow().Description.ValueNode.Column)
|
||||||
assert.Len(t, h.Components.RequestBodies["BurgerRequest"].Content["application/json"].Examples, 2)
|
assert.Equal(t, 2, orderedmap.Len(h.Components.RequestBodies.GetOrZero("BurgerRequest").Content.GetOrZero("application/json").Examples))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Components_Examples(t *testing.T) {
|
func TestNewDocument_Components_Examples(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Examples, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Components.Examples))
|
||||||
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples["QuarterPounder"].Summary)
|
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples.GetOrZero("QuarterPounder").Summary)
|
||||||
assert.Equal(t, 346, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Line)
|
assert.Equal(t, 346, h.Components.Examples.GetOrZero("QuarterPounder").GoLow().Summary.ValueNode.Line)
|
||||||
assert.Equal(t, 16, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Column)
|
assert.Equal(t, 16, h.Components.Examples.GetOrZero("QuarterPounder").GoLow().Summary.ValueNode.Column)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Components_Responses(t *testing.T) {
|
func TestNewDocument_Components_Responses(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Responses, 1)
|
assert.Equal(t, 1, orderedmap.Len(h.Components.Responses))
|
||||||
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses["DressingResponse"].Description)
|
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses.GetOrZero("DressingResponse").Description)
|
||||||
assert.Equal(t, "array", h.Components.Responses["DressingResponse"].Content["application/json"].Schema.Schema().Type[0])
|
assert.Equal(t, "array", h.Components.Responses.GetOrZero("DressingResponse").Content.GetOrZero("application/json").Schema.Schema().Type[0])
|
||||||
assert.Equal(t, 352, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Line)
|
assert.Equal(t, 352, h.Components.Responses.GetOrZero("DressingResponse").GoLow().Description.KeyNode.Line)
|
||||||
assert.Equal(t, 7, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Column)
|
assert.Equal(t, 7, h.Components.Responses.GetOrZero("DressingResponse").GoLow().Description.KeyNode.Column)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.SecuritySchemes, 3)
|
assert.Equal(t, 3, orderedmap.Len(h.Components.SecuritySchemes))
|
||||||
|
|
||||||
api := h.Components.SecuritySchemes["APIKeyScheme"]
|
api := h.Components.SecuritySchemes.GetOrZero("APIKeyScheme")
|
||||||
assert.Equal(t, "an apiKey security scheme", api.Description)
|
assert.Equal(t, "an apiKey security scheme", api.Description)
|
||||||
assert.Equal(t, 364, api.GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 364, api.GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 20, api.GoLow().Description.ValueNode.Column)
|
assert.Equal(t, 20, api.GoLow().Description.ValueNode.Column)
|
||||||
|
|
||||||
jwt := h.Components.SecuritySchemes["JWTScheme"]
|
jwt := h.Components.SecuritySchemes.GetOrZero("JWTScheme")
|
||||||
assert.Equal(t, "an JWT security scheme", jwt.Description)
|
assert.Equal(t, "an JWT security scheme", jwt.Description)
|
||||||
assert.Equal(t, 369, jwt.GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 369, jwt.GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 20, jwt.GoLow().Description.ValueNode.Column)
|
assert.Equal(t, 20, jwt.GoLow().Description.ValueNode.Column)
|
||||||
|
|
||||||
oAuth := h.Components.SecuritySchemes["OAuthScheme"]
|
oAuth := h.Components.SecuritySchemes.GetOrZero("OAuthScheme")
|
||||||
assert.Equal(t, "an oAuth security scheme", oAuth.Description)
|
assert.Equal(t, "an oAuth security scheme", oAuth.Description)
|
||||||
assert.Equal(t, 375, oAuth.GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 375, oAuth.GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
|
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
|
||||||
assert.Len(t, oAuth.Flows.Implicit.Scopes, 2)
|
assert.Equal(t, 2, orderedmap.Len(oAuth.Flows.Implicit.Scopes))
|
||||||
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes["read:burgers"])
|
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes.GetOrZero("read:burgers"))
|
||||||
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
|
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
|
||||||
|
|
||||||
// check the lowness is low.
|
// check the lowness is low.
|
||||||
@@ -306,26 +306,26 @@ func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
|||||||
func TestNewDocument_Components_Parameters(t *testing.T) {
|
func TestNewDocument_Components_Parameters(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Components.Parameters, 2)
|
assert.Equal(t, 2, orderedmap.Len(h.Components.Parameters))
|
||||||
bh := h.Components.Parameters["BurgerHeader"]
|
bh := h.Components.Parameters.GetOrZero("BurgerHeader")
|
||||||
assert.Equal(t, "burgerHeader", bh.Name)
|
assert.Equal(t, "burgerHeader", bh.Name)
|
||||||
assert.Equal(t, 392, bh.GoLow().Name.KeyNode.Line)
|
assert.Equal(t, 392, bh.GoLow().Name.KeyNode.Line)
|
||||||
assert.Len(t, bh.Schema.Schema().Properties, 2)
|
assert.Equal(t, 2, orderedmap.Len(bh.Schema.Schema().Properties))
|
||||||
assert.Equal(t, "big-mac", bh.Example)
|
assert.Equal(t, "big-mac", bh.Example)
|
||||||
assert.True(t, bh.Required)
|
assert.True(t, bh.Required)
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t,
|
t,
|
||||||
"this is a header",
|
"this is a header",
|
||||||
bh.Content["application/json"].Encoding["burgerTheme"].Headers["someHeader"].Description,
|
bh.Content.GetOrZero("application/json").Encoding.GetOrZero("burgerTheme").Headers.GetOrZero("someHeader").Description,
|
||||||
)
|
)
|
||||||
assert.Len(t, bh.Content["application/json"].Schema.Schema().Properties, 2)
|
assert.Equal(t, 2, orderedmap.Len(bh.Content.GetOrZero("application/json").Schema.Schema().Properties))
|
||||||
assert.Equal(t, 409, bh.Content["application/json"].Encoding["burgerTheme"].GoLow().ContentType.ValueNode.Line)
|
assert.Equal(t, 409, bh.Content.GetOrZero("application/json").Encoding.GetOrZero("burgerTheme").GoLow().ContentType.ValueNode.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewDocument_Paths(t *testing.T) {
|
func TestNewDocument_Paths(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
assert.Len(t, h.Paths.PathItems, 5)
|
assert.Equal(t, 5, orderedmap.Len(h.Paths.PathItems))
|
||||||
|
|
||||||
testBurgerShop(t, h, true)
|
testBurgerShop(t, h, true)
|
||||||
}
|
}
|
||||||
@@ -346,36 +346,36 @@ func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
|||||||
assert.Len(t, burgersOp.Post.Tags, 1)
|
assert.Len(t, burgersOp.Post.Tags, 1)
|
||||||
assert.Equal(t, "A new burger for our menu, yummy yum yum.", burgersOp.Post.Description)
|
assert.Equal(t, "A new burger for our menu, yummy yum yum.", burgersOp.Post.Description)
|
||||||
assert.Equal(t, "Give us the new burger!", burgersOp.Post.RequestBody.Description)
|
assert.Equal(t, "Give us the new burger!", burgersOp.Post.RequestBody.Description)
|
||||||
assert.Len(t, burgersOp.Post.Responses.Codes, 3)
|
assert.Equal(t, 3, orderedmap.Len(burgersOp.Post.Responses.Codes))
|
||||||
if checkLines {
|
if checkLines {
|
||||||
assert.Equal(t, 64, burgersOp.GoLow().Post.KeyNode.Line)
|
assert.Equal(t, 64, burgersOp.GoLow().Post.KeyNode.Line)
|
||||||
assert.Equal(t, 63, h.Paths.GoLow().FindPath("/burgers").ValueNode.Line)
|
assert.Equal(t, 63, h.Paths.GoLow().FindPath("/burgers").ValueNode.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
okResp := burgersOp.Post.Responses.FindResponseByCode(200)
|
okResp := burgersOp.Post.Responses.FindResponseByCode(200)
|
||||||
assert.Len(t, okResp.Headers, 1)
|
assert.Equal(t, 1, orderedmap.Len(okResp.Headers))
|
||||||
assert.Equal(t, "A tasty burger for you to eat.", okResp.Description)
|
assert.Equal(t, "A tasty burger for you to eat.", okResp.Description)
|
||||||
assert.Len(t, okResp.Content["application/json"].Examples, 2)
|
assert.Equal(t, 2, orderedmap.Len(okResp.Content.GetOrZero("application/json").Examples))
|
||||||
assert.Equal(
|
assert.Equal(
|
||||||
t,
|
t,
|
||||||
"a cripsy fish sammich filled with ocean goodness.",
|
"a cripsy fish sammich filled with ocean goodness.",
|
||||||
okResp.Content["application/json"].Examples["filetOFish"].Summary,
|
okResp.Content.GetOrZero("application/json").Examples.GetOrZero("filetOFish").Summary,
|
||||||
)
|
)
|
||||||
assert.Len(t, okResp.Links, 2)
|
assert.Equal(t, 2, orderedmap.Len(okResp.Links))
|
||||||
assert.Equal(t, "locateBurger", okResp.Links["LocateBurger"].OperationId)
|
assert.Equal(t, "locateBurger", okResp.Links.GetOrZero("LocateBurger").OperationId)
|
||||||
assert.Len(t, burgersOp.Post.Security[0].Requirements, 1)
|
assert.Len(t, burgersOp.Post.Security[0].Requirements, 1)
|
||||||
assert.Len(t, burgersOp.Post.Security[0].Requirements["OAuthScheme"], 2)
|
assert.Len(t, burgersOp.Post.Security[0].Requirements.GetOrZero("OAuthScheme"), 2)
|
||||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements["OAuthScheme"][0])
|
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements.GetOrZero("OAuthScheme")[0])
|
||||||
assert.Len(t, burgersOp.Post.Servers, 1)
|
assert.Len(t, burgersOp.Post.Servers, 1)
|
||||||
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
||||||
|
|
||||||
if checkLines {
|
if checkLines {
|
||||||
assert.Equal(t, 69, burgersOp.Post.GoLow().Description.ValueNode.Line)
|
assert.Equal(t, 69, burgersOp.Post.GoLow().Description.ValueNode.Line)
|
||||||
assert.Equal(t, 74, burgersOp.Post.Responses.GoLow().FindResponseByCode("200").ValueNode.Line)
|
assert.Equal(t, 74, burgersOp.Post.Responses.GoLow().FindResponseByCode("200").ValueNode.Line)
|
||||||
assert.Equal(t, 80, okResp.Content["application/json"].GoLow().Schema.KeyNode.Line)
|
assert.Equal(t, 80, okResp.Content.GetOrZero("application/json").GoLow().Schema.KeyNode.Line)
|
||||||
assert.Equal(t, 15, okResp.Content["application/json"].GoLow().Schema.KeyNode.Column)
|
assert.Equal(t, 15, okResp.Content.GetOrZero("application/json").GoLow().Schema.KeyNode.Column)
|
||||||
assert.Equal(t, 77, okResp.GoLow().Description.KeyNode.Line)
|
assert.Equal(t, 77, okResp.GoLow().Description.KeyNode.Line)
|
||||||
assert.Equal(t, 310, okResp.Links["LocateBurger"].GoLow().OperationId.ValueNode.Line)
|
assert.Equal(t, 310, okResp.Links.GetOrZero("LocateBurger").GoLow().OperationId.ValueNode.Line)
|
||||||
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ func TestDocument_MarshalJSON(t *testing.T) {
|
|||||||
newDoc := NewDocument(lowDoc)
|
newDoc := NewDocument(lowDoc)
|
||||||
|
|
||||||
assert.Equal(t, orderedmap.Len(newDoc.Paths.PathItems), orderedmap.Len(highDoc.Paths.PathItems))
|
assert.Equal(t, orderedmap.Len(newDoc.Paths.PathItems), orderedmap.Len(highDoc.Paths.PathItems))
|
||||||
assert.Equal(t, len(newDoc.Components.Schemas), len(highDoc.Components.Schemas))
|
assert.Equal(t, orderedmap.Len(newDoc.Components.Schemas), orderedmap.Len(highDoc.Components.Schemas))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAMLInline(t *testing.T) {
|
func TestDocument_MarshalYAMLInline(t *testing.T) {
|
||||||
@@ -711,8 +711,8 @@ components:
|
|||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
|
|
||||||
// mutate the schema
|
// mutate the schema
|
||||||
g := h.Components.Schemas["BurgerHeader"].Schema()
|
g := h.Components.Schemas.GetOrZero("BurgerHeader").Schema()
|
||||||
ds := g.Properties["burgerTheme"].Schema()
|
ds := g.Properties.GetOrZero("burgerTheme").Schema()
|
||||||
ds.Description = "changed"
|
ds.Description = "changed"
|
||||||
|
|
||||||
// render the document to YAML and it should be identical.
|
// render the document to YAML and it should be identical.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import (
|
|||||||
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
||||||
type Encoding struct {
|
type Encoding struct {
|
||||||
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||||
@@ -55,10 +56,10 @@ func (e *Encoding) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExtractEncoding converts hard to navigate low-level plumbing Encoding definitions, into a high-level simple map
|
// ExtractEncoding converts hard to navigate low-level plumbing Encoding definitions, into a high-level simple map
|
||||||
func ExtractEncoding(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Encoding]) map[string]*Encoding {
|
func ExtractEncoding(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Encoding]]) orderedmap.Map[string, *Encoding] {
|
||||||
extracted := make(map[string]*Encoding)
|
extracted := orderedmap.New[string, *Encoding]()
|
||||||
for k, v := range elements {
|
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||||
extracted[k.Value] = NewEncoding(v.Value)
|
extracted.Set(pair.Key().Value, NewEncoding(pair.Value().Value))
|
||||||
}
|
}
|
||||||
return extracted
|
return extracted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEncoding_MarshalYAML(t *testing.T) {
|
func TestEncoding_MarshalYAML(t *testing.T) {
|
||||||
@@ -14,7 +16,9 @@ func TestEncoding_MarshalYAML(t *testing.T) {
|
|||||||
explode := true
|
explode := true
|
||||||
encoding := &Encoding{
|
encoding := &Encoding{
|
||||||
ContentType: "application/json",
|
ContentType: "application/json",
|
||||||
Headers: map[string]*Header{"x-pizza-time": {Description: "oh yes please"}},
|
Headers: orderedmap.ToOrderedMap(map[string]*Header{
|
||||||
|
"x-pizza-time": {Description: "oh yes please"},
|
||||||
|
}),
|
||||||
Style: "simple",
|
Style: "simple",
|
||||||
Explode: &explode,
|
Explode: &explode,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,8 +25,8 @@ type Header struct {
|
|||||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||||
Schema *highbase.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
Schema *highbase.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||||
Examples map[string]*highbase.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
Examples orderedmap.Map[string, *highbase.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Header
|
low *low.Header
|
||||||
}
|
}
|
||||||
@@ -65,10 +66,10 @@ func (h *Header) GoLowUntyped() any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ExtractHeaders will extract a hard to navigate low-level Header map, into simple high-level one.
|
// ExtractHeaders will extract a hard to navigate low-level Header map, into simple high-level one.
|
||||||
func ExtractHeaders(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Header]) map[string]*Header {
|
func ExtractHeaders(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Header]]) orderedmap.Map[string, *Header] {
|
||||||
extracted := make(map[string]*Header)
|
extracted := orderedmap.New[string, *Header]()
|
||||||
for k, v := range elements {
|
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||||
extracted[k.Value] = NewHeader(v.Value)
|
extracted.Set(pair.Key().Value, NewHeader(pair.Value().Value))
|
||||||
}
|
}
|
||||||
return extracted
|
return extracted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,12 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHeader_MarshalYAML(t *testing.T) {
|
func TestHeader_MarshalYAML(t *testing.T) {
|
||||||
@@ -21,7 +23,9 @@ func TestHeader_MarshalYAML(t *testing.T) {
|
|||||||
Explode: true,
|
Explode: true,
|
||||||
AllowReserved: true,
|
AllowReserved: true,
|
||||||
Example: "example",
|
Example: "example",
|
||||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||||
|
"example": {Value: "example"},
|
||||||
|
}),
|
||||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ import (
|
|||||||
type Link struct {
|
type Link struct {
|
||||||
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
||||||
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||||
Parameters map[string]string `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
Parameters orderedmap.Map[string, string] `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||||
RequestBody string `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
RequestBody string `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||||
@@ -38,9 +39,9 @@ func NewLink(link *low.Link) *Link {
|
|||||||
l.low = link
|
l.low = link
|
||||||
l.OperationRef = link.OperationRef.Value
|
l.OperationRef = link.OperationRef.Value
|
||||||
l.OperationId = link.OperationId.Value
|
l.OperationId = link.OperationId.Value
|
||||||
params := make(map[string]string)
|
params := orderedmap.New[string, string]()
|
||||||
for k, v := range link.Parameters.Value {
|
for pair := orderedmap.First(link.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||||
params[k.Value] = v.Value
|
params.Set(pair.Key().Value, pair.Value().Value)
|
||||||
}
|
}
|
||||||
l.Parameters = params
|
l.Parameters = params
|
||||||
l.RequestBody = link.RequestBody.Value
|
l.RequestBody = link.RequestBody.Value
|
||||||
|
|||||||
@@ -4,18 +4,20 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLink_MarshalYAML(t *testing.T) {
|
func TestLink_MarshalYAML(t *testing.T) {
|
||||||
link := Link{
|
link := Link{
|
||||||
OperationRef: "somewhere",
|
OperationRef: "somewhere",
|
||||||
OperationId: "somewhereOutThere",
|
OperationId: "somewhereOutThere",
|
||||||
Parameters: map[string]string{
|
Parameters: orderedmap.ToOrderedMap(map[string]string{
|
||||||
"over": "theRainbow",
|
"over": "theRainbow",
|
||||||
},
|
}),
|
||||||
RequestBody: "hello?",
|
RequestBody: "hello?",
|
||||||
Description: "are you there?",
|
Description: "are you there?",
|
||||||
Server: &Server{
|
Server: &Server{
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -20,8 +19,8 @@ import (
|
|||||||
type MediaType struct {
|
type MediaType struct {
|
||||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||||
Examples map[string]*base.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
Examples orderedmap.Map[string, *base.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||||
Encoding map[string]*Encoding `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
Encoding orderedmap.Map[string, *Encoding] `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.MediaType
|
low *low.MediaType
|
||||||
}
|
}
|
||||||
@@ -74,29 +73,18 @@ func (m *MediaType) MarshalYAMLInline() (interface{}, error) {
|
|||||||
|
|
||||||
// ExtractContent takes in a complex and hard to navigate low-level content map, and converts it in to a much simpler
|
// ExtractContent takes in a complex and hard to navigate low-level content map, and converts it in to a much simpler
|
||||||
// and easier to navigate high-level one.
|
// and easier to navigate high-level one.
|
||||||
func ExtractContent(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.MediaType]) map[string]*MediaType {
|
func ExtractContent(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.MediaType]]) orderedmap.Map[string, *MediaType] {
|
||||||
// extract everything async
|
extracted := orderedmap.New[string, *MediaType]()
|
||||||
doneChan := make(chan bool)
|
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.MediaType]]) (asyncResult[*MediaType], error) {
|
||||||
|
return asyncResult[*MediaType]{
|
||||||
var extLock sync.RWMutex
|
key: pair.Key().Value,
|
||||||
extractContentItem := func(k lowmodel.KeyReference[string],
|
result: NewMediaType(pair.Value().Value),
|
||||||
v lowmodel.ValueReference[*low.MediaType], c chan bool, e map[string]*MediaType) {
|
}, nil
|
||||||
extLock.Lock()
|
|
||||||
e[k.Value] = NewMediaType(v.Value)
|
|
||||||
extLock.Unlock()
|
|
||||||
c <- true
|
|
||||||
|
|
||||||
}
|
|
||||||
extracted := make(map[string]*MediaType)
|
|
||||||
for k, v := range elements {
|
|
||||||
go extractContentItem(k, v, doneChan, extracted)
|
|
||||||
}
|
|
||||||
n := 0
|
|
||||||
for n < len(elements) {
|
|
||||||
select {
|
|
||||||
case <-doneChan:
|
|
||||||
n++
|
|
||||||
}
|
}
|
||||||
|
resultFunc := func(value asyncResult[*MediaType]) error {
|
||||||
|
extracted.Set(value.key, value.result)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.TranslateMapParallel(elements, translateFunc, resultFunc)
|
||||||
return extracted
|
return extracted
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
|||||||
|
|
||||||
// create a new document and extract a media type object from it.
|
// create a new document and extract a media type object from it.
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content["application/json"]
|
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content.GetOrZero("application/json")
|
||||||
|
|
||||||
// render out the media type
|
// render out the media type
|
||||||
yml, _ := mt.Render()
|
yml, _ := mt.Render()
|
||||||
@@ -118,7 +118,7 @@ func TestMediaType_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
// create a new document and extract a media type object from it.
|
// create a new document and extract a media type object from it.
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content["application/json"]
|
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content.GetOrZero("application/json")
|
||||||
|
|
||||||
// render out the media type
|
// render out the media type
|
||||||
yml, _ := mt.Render()
|
yml, _ := mt.Render()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ type OAuthFlow struct {
|
|||||||
AuthorizationUrl string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
AuthorizationUrl string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||||
TokenUrl string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
TokenUrl string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||||
RefreshUrl string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
RefreshUrl string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||||
Scopes map[string]string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
|
Scopes orderedmap.Map[string, string] `json:"scopes,omitempty" yaml:"scopes,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.OAuthFlow
|
low *low.OAuthFlow
|
||||||
}
|
}
|
||||||
@@ -27,9 +28,9 @@ func NewOAuthFlow(flow *low.OAuthFlow) *OAuthFlow {
|
|||||||
o.TokenUrl = flow.TokenUrl.Value
|
o.TokenUrl = flow.TokenUrl.Value
|
||||||
o.AuthorizationUrl = flow.AuthorizationUrl.Value
|
o.AuthorizationUrl = flow.AuthorizationUrl.Value
|
||||||
o.RefreshUrl = flow.RefreshUrl.Value
|
o.RefreshUrl = flow.RefreshUrl.Value
|
||||||
scopes := make(map[string]string)
|
scopes := orderedmap.New[string, string]()
|
||||||
for k, v := range flow.Scopes.Value {
|
for pair := orderedmap.First(flow.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||||
scopes[k.Value] = v.Value
|
scopes.Set(pair.Key().Value, pair.Value().Value)
|
||||||
}
|
}
|
||||||
o.Scopes = scopes
|
o.Scopes = scopes
|
||||||
o.Extensions = high.ExtractExtensions(flow.Extensions)
|
o.Extensions = high.ExtractExtensions(flow.Extensions)
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOAuthFlow_MarshalYAML(t *testing.T) {
|
func TestOAuthFlow_MarshalYAML(t *testing.T) {
|
||||||
@@ -15,7 +17,10 @@ func TestOAuthFlow_MarshalYAML(t *testing.T) {
|
|||||||
AuthorizationUrl: "https://pb33f.io",
|
AuthorizationUrl: "https://pb33f.io",
|
||||||
TokenUrl: "https://pb33f.io/token",
|
TokenUrl: "https://pb33f.io/token",
|
||||||
RefreshUrl: "https://pb33f.io/refresh",
|
RefreshUrl: "https://pb33f.io/refresh",
|
||||||
Scopes: map[string]string{"chicken": "nuggets", "beefy": "soup"},
|
Scopes: orderedmap.ToOrderedMap(map[string]string{
|
||||||
|
"chicken": "nuggets",
|
||||||
|
"beefy": "soup",
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
rend, _ := oflow.Render()
|
rend, _ := oflow.Render()
|
||||||
|
|||||||
@@ -4,13 +4,14 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewOAuthFlows(t *testing.T) {
|
func TestNewOAuthFlows(t *testing.T) {
|
||||||
@@ -81,7 +82,7 @@ clientCredentials:
|
|||||||
CHIP:CHOP: microwave a sock`
|
CHIP:CHOP: microwave a sock`
|
||||||
|
|
||||||
// now modify it and render it back out, and it should be identical!
|
// now modify it and render it back out, and it should be identical!
|
||||||
r.ClientCredentials.Scopes["CHIP:CHOP"] = "microwave a sock"
|
r.ClientCredentials.Scopes.Set("CHIP:CHOP", "microwave a sock")
|
||||||
rBytes, _ = r.Render()
|
rBytes, _ = r.Render()
|
||||||
assert.Equal(t, modified, strings.TrimSpace(string(rBytes)))
|
assert.Equal(t, modified, strings.TrimSpace(string(rBytes)))
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ type Operation struct {
|
|||||||
Parameters []*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
Parameters []*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||||
RequestBody *RequestBody `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
RequestBody *RequestBody `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||||
Responses *Responses `json:"responses,omitempty" yaml:"responses,omitempty"`
|
Responses *Responses `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||||
Callbacks map[string]*Callback `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
Callbacks orderedmap.Map[string, *Callback] `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||||
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||||
Security []*base.SecurityRequirement `json:"security,omitempty" yaml:"security,omitempty"`
|
Security []*base.SecurityRequirement `json:"security,omitempty" yaml:"security,omitempty"`
|
||||||
Servers []*Server `json:"servers,omitempty" yaml:"servers,omitempty"`
|
Servers []*Server `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||||
@@ -81,9 +82,9 @@ func NewOperation(operation *low.Operation) *Operation {
|
|||||||
o.Servers = servers
|
o.Servers = servers
|
||||||
o.Extensions = high.ExtractExtensions(operation.Extensions)
|
o.Extensions = high.ExtractExtensions(operation.Extensions)
|
||||||
if !operation.Callbacks.IsEmpty() {
|
if !operation.Callbacks.IsEmpty() {
|
||||||
cbs := make(map[string]*Callback)
|
cbs := orderedmap.New[string, *Callback]()
|
||||||
for k, v := range operation.Callbacks.Value {
|
for pair := orderedmap.First(operation.Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||||
cbs[k.Value] = NewCallback(v.Value)
|
cbs.Set(pair.Key().Value, NewCallback(pair.Value().Value))
|
||||||
}
|
}
|
||||||
o.Callbacks = cbs
|
o.Callbacks = cbs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ callbacks:
|
|||||||
assert.Equal(t, "https://pb33f.io", r.ExternalDocs.URL)
|
assert.Equal(t, "https://pb33f.io", r.ExternalDocs.URL)
|
||||||
assert.Equal(t, 1, r.GoLow().ExternalDocs.KeyNode.Line)
|
assert.Equal(t, 1, r.GoLow().ExternalDocs.KeyNode.Line)
|
||||||
assert.Contains(t, r.Callbacks, "testCallback")
|
assert.Contains(t, r.Callbacks, "testCallback")
|
||||||
assert.Contains(t, r.Callbacks["testCallback"].Expression, "{$request.body#/callbackUrl}")
|
assert.Contains(t, r.Callbacks.GetOrZero("testCallback").Expression, "{$request.body#/callbackUrl}")
|
||||||
assert.Equal(t, 3, r.GoLow().Callbacks.KeyNode.Line)
|
assert.Equal(t, 3, r.GoLow().Callbacks.KeyNode.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,6 @@ func Example_createHighLevelOpenAPIDocument() {
|
|||||||
|
|
||||||
// Print out some details
|
// Print out some details
|
||||||
fmt.Printf("Petstore contains %d paths and %d component schemas",
|
fmt.Printf("Petstore contains %d paths and %d component schemas",
|
||||||
orderedmap.Len(doc.Paths.PathItems), len(doc.Components.Schemas))
|
orderedmap.Len(doc.Paths.PathItems), orderedmap.Len(doc.Components.Schemas))
|
||||||
// Output: Petstore contains 13 paths and 8 component schemas
|
// Output: Petstore contains 13 paths and 8 component schemas
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@ type Parameter struct {
|
|||||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||||
Examples map[string]*base.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
Examples orderedmap.Map[string, *base.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Parameter
|
low *low.Parameter
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,7 +24,9 @@ func TestParameter_MarshalYAML(t *testing.T) {
|
|||||||
Explode: &explode,
|
Explode: &explode,
|
||||||
AllowReserved: true,
|
AllowReserved: true,
|
||||||
Example: "example",
|
Example: "example",
|
||||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||||
|
"example": {Value: "example"},
|
||||||
|
}),
|
||||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +60,9 @@ func TestParameter_MarshalYAMLInline(t *testing.T) {
|
|||||||
Explode: &explode,
|
Explode: &explode,
|
||||||
AllowReserved: true,
|
AllowReserved: true,
|
||||||
Example: "example",
|
Example: "example",
|
||||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||||
|
"example": {Value: "example"},
|
||||||
|
}),
|
||||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*pathItem
|
var mapped []*pathItem
|
||||||
|
|
||||||
action := func(pair orderedmap.Pair[string, *PathItem]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
k := pair.Key()
|
k := pair.Key()
|
||||||
pi := pair.Value()
|
pi := pair.Value()
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
@@ -95,9 +95,7 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
|
||||||
|
|
||||||
nb := high.NewNodeBuilder(p, p.low)
|
nb := high.NewNodeBuilder(p, p.low)
|
||||||
extNode := nb.Render()
|
extNode := nb.Render()
|
||||||
@@ -142,7 +140,7 @@ func (p *Paths) MarshalYAMLInline() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*pathItem
|
var mapped []*pathItem
|
||||||
|
|
||||||
action := func(pair orderedmap.Pair[string, *PathItem]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
k := pair.Key()
|
k := pair.Key()
|
||||||
pi := pair.Value()
|
pi := pair.Value()
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
@@ -153,9 +151,7 @@ func (p *Paths) MarshalYAMLInline() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
|
||||||
|
|
||||||
nb := high.NewNodeBuilder(p, p.low)
|
nb := high.NewNodeBuilder(p, p.low)
|
||||||
nb.Resolve = true
|
nb.Resolve = true
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ import (
|
|||||||
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
||||||
type RequestBody struct {
|
type RequestBody struct {
|
||||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||||
Required *bool `json:"required,omitempty" yaml:"required,renderZero,omitempty"`
|
Required *bool `json:"required,omitempty" yaml:"required,renderZero,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.RequestBody
|
low *low.RequestBody
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,9 +17,9 @@ import (
|
|||||||
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
||||||
type Response struct {
|
type Response struct {
|
||||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||||
Links map[string]*Link `json:"links,omitempty" yaml:"links,omitempty"`
|
Links orderedmap.Map[string, *Link] `json:"links,omitempty" yaml:"links,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Response
|
low *low.Response
|
||||||
}
|
}
|
||||||
@@ -36,9 +37,9 @@ func NewResponse(response *low.Response) *Response {
|
|||||||
r.Content = ExtractContent(response.Content.Value)
|
r.Content = ExtractContent(response.Content.Value)
|
||||||
}
|
}
|
||||||
if !response.Links.IsEmpty() {
|
if !response.Links.IsEmpty() {
|
||||||
responseLinks := make(map[string]*Link)
|
responseLinks := orderedmap.New[string, *Link]()
|
||||||
for k, v := range response.Links.Value {
|
for pair := orderedmap.First(response.Links.Value); pair != nil; pair = pair.Next() {
|
||||||
responseLinks[k.Value] = NewLink(v.Value)
|
responseLinks.Set(pair.Key().Value, NewLink(pair.Value().Value))
|
||||||
}
|
}
|
||||||
r.Links = responseLinks
|
r.Links = responseLinks
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -30,7 +30,7 @@ import (
|
|||||||
// be the response for a successful operation call.
|
// be the response for a successful operation call.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#responses-object
|
// - https://spec.openapis.org/oas/v3.1.0#responses-object
|
||||||
type Responses struct {
|
type Responses struct {
|
||||||
Codes map[string]*Response `json:"-" yaml:"-"`
|
Codes orderedmap.Map[string, *Response] `json:"-" yaml:"-"`
|
||||||
Default *Response `json:"default,omitempty" yaml:"default,omitempty"`
|
Default *Response `json:"default,omitempty" yaml:"default,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Responses
|
low *low.Responses
|
||||||
@@ -45,28 +45,31 @@ func NewResponses(responses *low.Responses) *Responses {
|
|||||||
if !responses.Default.IsEmpty() {
|
if !responses.Default.IsEmpty() {
|
||||||
r.Default = NewResponse(responses.Default.Value)
|
r.Default = NewResponse(responses.Default.Value)
|
||||||
}
|
}
|
||||||
codes := make(map[string]*Response)
|
codes := orderedmap.New[string, *Response]()
|
||||||
|
|
||||||
type respRes struct {
|
type respRes struct {
|
||||||
code string
|
code string
|
||||||
resp *Response
|
resp *Response
|
||||||
}
|
}
|
||||||
|
|
||||||
translateFunc := func(key lowbase.KeyReference[string], value lowbase.ValueReference[*low.Response]) (respRes, error) {
|
translateFunc := func(pair orderedmap.Pair[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
||||||
return respRes{code: key.Value, resp: NewResponse(value.Value)}, nil
|
return asyncResult[*Response]{
|
||||||
|
key: pair.Key().Value,
|
||||||
|
result: NewResponse(pair.Value().Value),
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
resultFunc := func(value respRes) error {
|
resultFunc := func(value asyncResult[*Response]) error {
|
||||||
codes[value.code] = value.resp
|
codes.Set(value.key, value.result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = datamodel.TranslateMapParallel[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response], respRes](responses.Codes, translateFunc, resultFunc)
|
_ = orderedmap.TranslateMapParallel[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response], asyncResult[*Response]](responses.Codes, translateFunc, resultFunc)
|
||||||
r.Codes = codes
|
r.Codes = codes
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindResponseByCode is a shortcut for looking up code by an integer vs. a string
|
// FindResponseByCode is a shortcut for looking up code by an integer vs. a string
|
||||||
func (r *Responses) FindResponseByCode(code int) *Response {
|
func (r *Responses) FindResponseByCode(code int) *Response {
|
||||||
return r.Codes[fmt.Sprintf("%d", code)]
|
return r.Codes.GetOrZero(fmt.Sprintf("%d", code))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoLow returns the low-level Response object used to create the high-level one.
|
// GoLow returns the low-level Response object used to create the high-level one.
|
||||||
@@ -101,16 +104,16 @@ func (r *Responses) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*responseItem
|
var mapped []*responseItem
|
||||||
|
|
||||||
for k, re := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
if r.low != nil {
|
if r.low != nil {
|
||||||
for lKey := range r.low.Codes {
|
for lPair := orderedmap.First(r.low.Codes); lPair != nil; lPair = lPair.Next() {
|
||||||
if lKey.Value == k {
|
if lPair.Key().Value == pair.Key() {
|
||||||
ln = lKey.KeyNode.Line
|
ln = lPair.Key().KeyNode.Line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &responseItem{re, k, ln, nil})
|
mapped = append(mapped, &responseItem{pair.Value(), pair.Key(), ln, nil})
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract extensions
|
// extract extensions
|
||||||
@@ -157,16 +160,16 @@ func (r *Responses) MarshalYAMLInline() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*responseItem
|
var mapped []*responseItem
|
||||||
|
|
||||||
for k, re := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
if r.low != nil {
|
if r.low != nil {
|
||||||
for lKey := range r.low.Codes {
|
for lPair := orderedmap.First(r.low.Codes); lPair != nil; lPair = lPair.Next() {
|
||||||
if lKey.Value == k {
|
if lPair.Key().Value == pair.Key() {
|
||||||
ln = lKey.KeyNode.Line
|
ln = lPair.Key().KeyNode.Line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &responseItem{re, k, ln, nil})
|
mapped = append(mapped, &responseItem{pair.Value(), pair.Key(), ln, nil})
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract extensions
|
// extract extensions
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
|
Variables orderedmap.Map[string, *ServerVariable] `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *low.Server
|
low *low.Server
|
||||||
}
|
}
|
||||||
@@ -25,9 +26,9 @@ func NewServer(server *low.Server) *Server {
|
|||||||
s.low = server
|
s.low = server
|
||||||
s.Description = server.Description.Value
|
s.Description = server.Description.Value
|
||||||
s.URL = server.URL.Value
|
s.URL = server.URL.Value
|
||||||
vars := make(map[string]*ServerVariable)
|
vars := orderedmap.New[string, *ServerVariable]()
|
||||||
for k, val := range server.Variables.Value {
|
for pair := orderedmap.First(server.Variables.Value); pair != nil; pair = pair.Next() {
|
||||||
vars[k.Value] = NewServerVariable(val.Value)
|
vars.Set(pair.Key().Value, NewServerVariable(pair.Value().Value))
|
||||||
}
|
}
|
||||||
s.Variables = vars
|
s.Variables = vars
|
||||||
s.Extensions = high.ExtractExtensions(server.Extensions)
|
s.Extensions = high.ExtractExtensions(server.Extensions)
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServer_MarshalYAML(t *testing.T) {
|
func TestServer_MarshalYAML(t *testing.T) {
|
||||||
@@ -23,11 +25,11 @@ description: the b33f`
|
|||||||
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
|
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
|
||||||
|
|
||||||
// mutate
|
// mutate
|
||||||
server.Variables = map[string]*ServerVariable{
|
server.Variables = orderedmap.ToOrderedMap(map[string]*ServerVariable{
|
||||||
"rainbow": {
|
"rainbow": {
|
||||||
Enum: []string{"one", "two", "three"},
|
Enum: []string{"one", "two", "three"},
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
|
|
||||||
desired = `url: https://pb33f.io
|
desired = `url: https://pb33f.io
|
||||||
description: the b33f
|
description: the b33f
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -96,8 +97,8 @@ type Schema struct {
|
|||||||
If low.NodeReference[*SchemaProxy]
|
If low.NodeReference[*SchemaProxy]
|
||||||
Else low.NodeReference[*SchemaProxy]
|
Else low.NodeReference[*SchemaProxy]
|
||||||
Then low.NodeReference[*SchemaProxy]
|
Then low.NodeReference[*SchemaProxy]
|
||||||
DependentSchemas low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]
|
DependentSchemas low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||||
PatternProperties low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]
|
PatternProperties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||||
PropertyNames low.NodeReference[*SchemaProxy]
|
PropertyNames low.NodeReference[*SchemaProxy]
|
||||||
UnevaluatedItems low.NodeReference[*SchemaProxy]
|
UnevaluatedItems low.NodeReference[*SchemaProxy]
|
||||||
UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]
|
UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]
|
||||||
@@ -120,7 +121,7 @@ type Schema struct {
|
|||||||
Required low.NodeReference[[]low.ValueReference[string]]
|
Required low.NodeReference[[]low.ValueReference[string]]
|
||||||
Enum low.NodeReference[[]low.ValueReference[any]]
|
Enum low.NodeReference[[]low.ValueReference[any]]
|
||||||
Not low.NodeReference[*SchemaProxy]
|
Not low.NodeReference[*SchemaProxy]
|
||||||
Properties low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]
|
Properties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||||
AdditionalProperties low.NodeReference[any]
|
AdditionalProperties low.NodeReference[any]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
ContentEncoding low.NodeReference[string]
|
ContentEncoding low.NodeReference[string]
|
||||||
@@ -305,10 +306,10 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
for i := range s.Enum.Value {
|
for i := range s.Enum.Value {
|
||||||
d = append(d, fmt.Sprint(s.Enum.Value[i].Value))
|
d = append(d, fmt.Sprint(s.Enum.Value[i].Value))
|
||||||
}
|
}
|
||||||
propKeys := make([]string, len(s.Properties.Value))
|
propKeys := make([]string, orderedmap.Len(s.Properties.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for i := range s.Properties.Value {
|
for pair := orderedmap.First(s.Properties.Value); pair != nil; pair = pair.Next() {
|
||||||
propKeys[z] = i.Value
|
propKeys[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(propKeys)
|
sort.Strings(propKeys)
|
||||||
@@ -414,10 +415,10 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
d = append(d, fmt.Sprint(s.Anchor.Value))
|
d = append(d, fmt.Sprint(s.Anchor.Value))
|
||||||
}
|
}
|
||||||
|
|
||||||
depSchemasKeys := make([]string, len(s.DependentSchemas.Value))
|
depSchemasKeys := make([]string, orderedmap.Len(s.DependentSchemas.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for i := range s.DependentSchemas.Value {
|
for pair := orderedmap.First(s.DependentSchemas.Value); pair != nil; pair = pair.Next() {
|
||||||
depSchemasKeys[z] = i.Value
|
depSchemasKeys[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(depSchemasKeys)
|
sort.Strings(depSchemasKeys)
|
||||||
@@ -425,10 +426,10 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
d = append(d, low.GenerateHashString(s.FindDependentSchema(depSchemasKeys[k]).Value))
|
d = append(d, low.GenerateHashString(s.FindDependentSchema(depSchemasKeys[k]).Value))
|
||||||
}
|
}
|
||||||
|
|
||||||
patternPropsKeys := make([]string, len(s.PatternProperties.Value))
|
patternPropsKeys := make([]string, orderedmap.Len(s.PatternProperties.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for i := range s.PatternProperties.Value {
|
for pair := orderedmap.First(s.PatternProperties.Value); pair != nil; pair = pair.Next() {
|
||||||
patternPropsKeys[z] = i.Value
|
patternPropsKeys[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(patternPropsKeys)
|
sort.Strings(patternPropsKeys)
|
||||||
@@ -490,19 +491,19 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
// FindProperty will return a ValueReference pointer containing a SchemaProxy pointer
|
// FindProperty will return a ValueReference pointer containing a SchemaProxy pointer
|
||||||
// from a property key name. if found
|
// from a property key name. if found
|
||||||
func (s *Schema) FindProperty(name string) *low.ValueReference[*SchemaProxy] {
|
func (s *Schema) FindProperty(name string) *low.ValueReference[*SchemaProxy] {
|
||||||
return low.FindItemInMap[*SchemaProxy](name, s.Properties.Value)
|
return low.FindItemInOrderedMap[*SchemaProxy](name, s.Properties.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindDependentSchema will return a ValueReference pointer containing a SchemaProxy pointer
|
// FindDependentSchema will return a ValueReference pointer containing a SchemaProxy pointer
|
||||||
// from a dependent schema key name. if found (3.1+ only)
|
// from a dependent schema key name. if found (3.1+ only)
|
||||||
func (s *Schema) FindDependentSchema(name string) *low.ValueReference[*SchemaProxy] {
|
func (s *Schema) FindDependentSchema(name string) *low.ValueReference[*SchemaProxy] {
|
||||||
return low.FindItemInMap[*SchemaProxy](name, s.DependentSchemas.Value)
|
return low.FindItemInOrderedMap[*SchemaProxy](name, s.DependentSchemas.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindPatternProperty will return a ValueReference pointer containing a SchemaProxy pointer
|
// FindPatternProperty will return a ValueReference pointer containing a SchemaProxy pointer
|
||||||
// from a pattern property key name. if found (3.1+ only)
|
// from a pattern property key name. if found (3.1+ only)
|
||||||
func (s *Schema) FindPatternProperty(name string) *low.ValueReference[*SchemaProxy] {
|
func (s *Schema) FindPatternProperty(name string) *low.ValueReference[*SchemaProxy] {
|
||||||
return low.FindItemInMap[*SchemaProxy](name, s.PatternProperties.Value)
|
return low.FindItemInOrderedMap[*SchemaProxy](name, s.PatternProperties.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExtensions returns all extensions for Schema
|
// GetExtensions returns all extensions for Schema
|
||||||
@@ -1067,7 +1068,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]], error) {
|
func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]], error) {
|
||||||
// for property, build in a new thread!
|
// for property, build in a new thread!
|
||||||
bChan := make(chan schemaProxyBuildResult)
|
bChan := make(chan schemaProxyBuildResult)
|
||||||
|
|
||||||
@@ -1088,7 +1089,7 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
|
|
||||||
_, propLabel, propsNode := utils.FindKeyNodeFullTop(label, root.Content)
|
_, propLabel, propsNode := utils.FindKeyNodeFullTop(label, root.Content)
|
||||||
if propsNode != nil {
|
if propsNode != nil {
|
||||||
propertyMap := make(map[low.KeyReference[string]]low.ValueReference[*SchemaProxy])
|
propertyMap := orderedmap.New[low.KeyReference[string], low.ValueReference[*SchemaProxy]]()
|
||||||
var currentProp *yaml.Node
|
var currentProp *yaml.Node
|
||||||
totalProps := 0
|
totalProps := 0
|
||||||
for i, prop := range propsNode.Content {
|
for i, prop := range propsNode.Content {
|
||||||
@@ -1119,10 +1120,10 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
select {
|
select {
|
||||||
case res := <-bChan:
|
case res := <-bChan:
|
||||||
completedProps++
|
completedProps++
|
||||||
propertyMap[res.k] = res.v
|
propertyMap.Set(res.k, res.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]{
|
return &low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]{
|
||||||
Value: propertyMap,
|
Value: propertyMap,
|
||||||
KeyNode: propLabel,
|
KeyNode: propLabel,
|
||||||
ValueNode: propsNode,
|
ValueNode: propsNode,
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package base
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SecurityRequirement is a low-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.
|
// SecurityRequirement is a low-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.
|
||||||
@@ -23,7 +25,7 @@ import (
|
|||||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||||
// - https://swagger.io/specification/#security-requirement-object
|
// - https://swagger.io/specification/#security-requirement-object
|
||||||
type SecurityRequirement struct {
|
type SecurityRequirement struct {
|
||||||
Requirements low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
Requirements low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]]]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +35,7 @@ func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) erro
|
|||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
var labelNode *yaml.Node
|
var labelNode *yaml.Node
|
||||||
valueMap := make(map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]])
|
valueMap := orderedmap.New[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]]()
|
||||||
var arr []low.ValueReference[string]
|
var arr []low.ValueReference[string]
|
||||||
for i := range root.Content {
|
for i := range root.Content {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
@@ -47,15 +49,18 @@ func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) erro
|
|||||||
ValueNode: root.Content[i].Content[j],
|
ValueNode: root.Content[i].Content[j],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
valueMap[low.KeyReference[string]{
|
valueMap.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: labelNode.Value,
|
Value: labelNode.Value,
|
||||||
KeyNode: labelNode,
|
KeyNode: labelNode,
|
||||||
}] = low.ValueReference[[]low.ValueReference[string]]{
|
},
|
||||||
|
low.ValueReference[[]low.ValueReference[string]]{
|
||||||
Value: arr,
|
Value: arr,
|
||||||
ValueNode: root.Content[i],
|
ValueNode: root.Content[i],
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
s.Requirements = low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]]]{
|
||||||
s.Requirements = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]{
|
|
||||||
Value: valueMap,
|
Value: valueMap,
|
||||||
ValueNode: root,
|
ValueNode: root,
|
||||||
}
|
}
|
||||||
@@ -64,9 +69,9 @@ func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) erro
|
|||||||
|
|
||||||
// FindRequirement will attempt to locate a security requirement string from a supplied name.
|
// FindRequirement will attempt to locate a security requirement string from a supplied name.
|
||||||
func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
|
func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
|
||||||
for k := range s.Requirements.Value {
|
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
if k.Value == name {
|
if pair.Key().Value == name {
|
||||||
return s.Requirements.Value[k].Value
|
return pair.Value().Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -74,10 +79,10 @@ func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[
|
|||||||
|
|
||||||
// GetKeys returns a string slice of all the keys used in the requirement.
|
// GetKeys returns a string slice of all the keys used in the requirement.
|
||||||
func (s *SecurityRequirement) GetKeys() []string {
|
func (s *SecurityRequirement) GetKeys() []string {
|
||||||
keys := make([]string, len(s.Requirements.Value))
|
keys := make([]string, orderedmap.Len(s.Requirements.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range s.Requirements.Value {
|
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
}
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
@@ -85,18 +90,17 @@ func (s *SecurityRequirement) GetKeys() []string {
|
|||||||
// Hash will return a consistent SHA256 Hash of the SecurityRequirement object
|
// Hash will return a consistent SHA256 Hash of the SecurityRequirement object
|
||||||
func (s *SecurityRequirement) Hash() [32]byte {
|
func (s *SecurityRequirement) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
values := make(map[string][]string, len(s.Requirements.Value))
|
values := make(map[string][]string, orderedmap.Len(s.Requirements.Value))
|
||||||
var valKeys []string
|
var valKeys []string
|
||||||
for k := range s.Requirements.Value {
|
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
var vals []string
|
var vals []string
|
||||||
for y := range s.Requirements.Value[k].Value {
|
for y := range pair.Value().Value {
|
||||||
vals = append(vals, s.Requirements.Value[k].Value[y].Value)
|
vals = append(vals, pair.Value().Value[y].Value)
|
||||||
// lol, I know. -------^^^^^ <- this is the actual value.
|
|
||||||
}
|
}
|
||||||
sort.Strings(vals)
|
sort.Strings(vals)
|
||||||
valKeys = append(valKeys, k.Value)
|
valKeys = append(valKeys, pair.Key().Value)
|
||||||
if len(vals) > 0 {
|
if len(vals) > 0 {
|
||||||
values[k.Value] = vals
|
values[pair.Key().Value] = vals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(valKeys)
|
sort.Strings(valKeys)
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package low
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FindItemInMap accepts a string key and a collection of KeyReference[string] and ValueReference[T]. Every
|
// FindItemInMap accepts a string key and a collection of KeyReference[string] and ValueReference[T]. Every
|
||||||
@@ -29,6 +31,22 @@ func FindItemInMap[T any](item string, collection map[KeyReference[string]]Value
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindItemInOrderedMap accepts a string key and a collection of KeyReference[string] and ValueReference[T].
|
||||||
|
// Every KeyReference will have its value checked against the string key and if there is a match, it will be
|
||||||
|
// returned.
|
||||||
|
func FindItemInOrderedMap[T any](item string, collection orderedmap.Map[KeyReference[string], ValueReference[T]]) *ValueReference[T] {
|
||||||
|
for pair := orderedmap.First(collection); pair != nil; pair = pair.Next() {
|
||||||
|
n := pair.Key()
|
||||||
|
if n.Value == item {
|
||||||
|
return pair.ValuePtr()
|
||||||
|
}
|
||||||
|
if strings.EqualFold(item, n.Value) {
|
||||||
|
return pair.ValuePtr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to generate a list of all the things an index should be searched for.
|
// helper function to generate a list of all the things an index should be searched for.
|
||||||
func generateIndexCollection(idx *index.SpecIndex) []func() map[string]*index.Reference {
|
func generateIndexCollection(idx *index.SpecIndex) []func() map[string]*index.Reference {
|
||||||
return []func() map[string]*index.Reference{
|
return []func() map[string]*index.Reference{
|
||||||
@@ -366,8 +384,8 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
includeExtensions bool,
|
includeExtensions bool,
|
||||||
) (map[KeyReference[string]]ValueReference[PT], error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
||||||
valueMap := make(map[KeyReference[string]]ValueReference[PT])
|
valueMap := orderedmap.New[KeyReference[string], ValueReference[PT]]()
|
||||||
var circError error
|
var circError error
|
||||||
if utils.IsNodeMap(root) {
|
if utils.IsNodeMap(root) {
|
||||||
var currentKey *yaml.Node
|
var currentKey *yaml.Node
|
||||||
@@ -431,15 +449,18 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
SetReference(n, referenceValue)
|
SetReference(n, referenceValue)
|
||||||
}
|
}
|
||||||
if currentKey != nil {
|
if currentKey != nil {
|
||||||
valueMap[KeyReference[string]{
|
valueMap.Set(
|
||||||
|
KeyReference[string]{
|
||||||
Value: currentKey.Value,
|
Value: currentKey.Value,
|
||||||
KeyNode: currentKey,
|
KeyNode: currentKey,
|
||||||
}] = ValueReference[PT]{
|
},
|
||||||
|
ValueReference[PT]{
|
||||||
Value: n,
|
Value: n,
|
||||||
ValueNode: node,
|
ValueNode: node,
|
||||||
//IsReference: isReference,
|
//IsReference: isReference,
|
||||||
Reference: referenceValue,
|
Reference: referenceValue,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -458,7 +479,7 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
func ExtractMapNoLookup[PT Buildable[N], N any](
|
func ExtractMapNoLookup[PT Buildable[N], N any](
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
) (map[KeyReference[string]]ValueReference[PT], error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
||||||
return ExtractMapNoLookupExtensions[PT, N](root, idx, false)
|
return ExtractMapNoLookupExtensions[PT, N](root, idx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -478,7 +499,7 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
extensions bool,
|
extensions bool,
|
||||||
) (map[KeyReference[string]]ValueReference[PT], *yaml.Node, *yaml.Node, error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
||||||
//var isReference bool
|
//var isReference bool
|
||||||
var referenceValue string
|
var referenceValue string
|
||||||
var labelNode, valueNode *yaml.Node
|
var labelNode, valueNode *yaml.Node
|
||||||
@@ -522,8 +543,9 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
}
|
}
|
||||||
if valueNode != nil {
|
if valueNode != nil {
|
||||||
var currentLabelNode *yaml.Node
|
var currentLabelNode *yaml.Node
|
||||||
valueMap := make(map[KeyReference[string]]ValueReference[PT])
|
valueMap := orderedmap.New[KeyReference[string], ValueReference[PT]]()
|
||||||
|
|
||||||
|
// TODO: Convert to datamodel.TranslatePipeline.
|
||||||
bChan := make(chan mappingResult[PT])
|
bChan := make(chan mappingResult[PT])
|
||||||
eChan := make(chan error)
|
eChan := make(chan error)
|
||||||
|
|
||||||
@@ -598,7 +620,7 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
return valueMap, labelNode, valueNode, err
|
return valueMap, labelNode, valueNode, err
|
||||||
case res := <-bChan:
|
case res := <-bChan:
|
||||||
completedKeys++
|
completedKeys++
|
||||||
valueMap[res.k] = res.v
|
valueMap.Set(res.k, res.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if circError != nil && !idx.AllowCircularReferenceResolving() {
|
if circError != nil && !idx.AllowCircularReferenceResolving() {
|
||||||
@@ -618,7 +640,7 @@ func ExtractMap[PT Buildable[N], N any](
|
|||||||
label string,
|
label string,
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
) (map[KeyReference[string]]ValueReference[PT], *yaml.Node, *yaml.Node, error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
||||||
return ExtractMapExtensions[PT, N](label, root, idx, false)
|
return ExtractMapExtensions[PT, N](label, root, idx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
"github.com/pb33f/libopenapi/resolver"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -994,12 +995,12 @@ one:
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, things, 2)
|
assert.Len(t, things, 2)
|
||||||
|
|
||||||
for k, v := range things {
|
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||||
if k.Value == "x-hey" {
|
if pair.Key().Value == "x-hey" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
assert.Equal(t, "one", k.Value)
|
assert.Equal(t, "one", pair.Key().Value)
|
||||||
assert.Len(t, v.ValueNode.Content, 2)
|
assert.Len(t, pair.Value().ValueNode.Content, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1050,8 +1051,8 @@ one:
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, things, 1)
|
assert.Len(t, things, 1)
|
||||||
|
|
||||||
for k := range things {
|
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||||
assert.Equal(t, "one", k.Value)
|
assert.Equal(t, "one", pair.Key().Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1283,8 +1284,8 @@ one:
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, things, 1)
|
assert.Len(t, things, 1)
|
||||||
|
|
||||||
for k := range things {
|
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||||
assert.Equal(t, 99, things[k].Value.AlmostWork.Value)
|
assert.Equal(t, 99, pair.Value().Value.AlmostWork.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1313,8 +1314,8 @@ func TestExtractMapFlat_DoubleRef(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, things, 1)
|
assert.Len(t, things, 1)
|
||||||
|
|
||||||
for k := range things {
|
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||||
assert.Equal(t, 99, things[k].Value.AlmostWork.Value)
|
assert.Equal(t, 99, pair.Value().Value.AlmostWork.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,15 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ParameterDefinitions is a low-level representation of a Swagger / OpenAPI 2 Parameters Definitions object.
|
// ParameterDefinitions is a low-level representation of a Swagger / OpenAPI 2 Parameters Definitions object.
|
||||||
@@ -20,7 +22,7 @@ import (
|
|||||||
// referenced to the ones defined here. It does not define global operation parameters
|
// referenced to the ones defined here. It does not define global operation parameters
|
||||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||||
type ParameterDefinitions struct {
|
type ParameterDefinitions struct {
|
||||||
Definitions map[low.KeyReference[string]]low.ValueReference[*Parameter]
|
Definitions orderedmap.Map[low.KeyReference[string], low.ValueReference[*Parameter]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResponsesDefinitions is a low-level representation of a Swagger / OpenAPI 2 Responses Definitions object.
|
// ResponsesDefinitions is a low-level representation of a Swagger / OpenAPI 2 Responses Definitions object.
|
||||||
@@ -29,7 +31,7 @@ type ParameterDefinitions struct {
|
|||||||
// referenced to the ones defined here. It does not define global operation responses
|
// referenced to the ones defined here. It does not define global operation responses
|
||||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||||
type ResponsesDefinitions struct {
|
type ResponsesDefinitions struct {
|
||||||
Definitions map[low.KeyReference[string]]low.ValueReference[*Response]
|
Definitions orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// SecurityDefinitions is a low-level representation of a Swagger / OpenAPI 2 Security Definitions object.
|
// SecurityDefinitions is a low-level representation of a Swagger / OpenAPI 2 Security Definitions object.
|
||||||
@@ -38,7 +40,7 @@ type ResponsesDefinitions struct {
|
|||||||
// schemes on the operations and only serves to provide the relevant details for each scheme
|
// schemes on the operations and only serves to provide the relevant details for each scheme
|
||||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||||
type SecurityDefinitions struct {
|
type SecurityDefinitions struct {
|
||||||
Definitions map[low.KeyReference[string]]low.ValueReference[*SecurityScheme]
|
Definitions orderedmap.Map[low.KeyReference[string], low.ValueReference[*SecurityScheme]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Definitions is a low-level representation of a Swagger / OpenAPI 2 Definitions object
|
// Definitions is a low-level representation of a Swagger / OpenAPI 2 Definitions object
|
||||||
@@ -47,33 +49,34 @@ type SecurityDefinitions struct {
|
|||||||
// arrays or models.
|
// arrays or models.
|
||||||
// - https://swagger.io/specification/v2/#definitionsObject
|
// - https://swagger.io/specification/v2/#definitionsObject
|
||||||
type Definitions struct {
|
type Definitions struct {
|
||||||
Schemas map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]
|
Schemas orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSchema will attempt to locate a base.SchemaProxy instance using a name.
|
// FindSchema will attempt to locate a base.SchemaProxy instance using a name.
|
||||||
func (d *Definitions) FindSchema(schema string) *low.ValueReference[*base.SchemaProxy] {
|
func (d *Definitions) FindSchema(schema string) *low.ValueReference[*base.SchemaProxy] {
|
||||||
return low.FindItemInMap[*base.SchemaProxy](schema, d.Schemas)
|
return low.FindItemInOrderedMap[*base.SchemaProxy](schema, d.Schemas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindParameter will attempt to locate a Parameter instance using a name.
|
// FindParameter will attempt to locate a Parameter instance using a name.
|
||||||
func (pd *ParameterDefinitions) FindParameter(parameter string) *low.ValueReference[*Parameter] {
|
func (pd *ParameterDefinitions) FindParameter(parameter string) *low.ValueReference[*Parameter] {
|
||||||
return low.FindItemInMap[*Parameter](parameter, pd.Definitions)
|
return low.FindItemInOrderedMap[*Parameter](parameter, pd.Definitions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindResponse will attempt to locate a Response instance using a name.
|
// FindResponse will attempt to locate a Response instance using a name.
|
||||||
func (r *ResponsesDefinitions) FindResponse(response string) *low.ValueReference[*Response] {
|
func (r *ResponsesDefinitions) FindResponse(response string) *low.ValueReference[*Response] {
|
||||||
return low.FindItemInMap[*Response](response, r.Definitions)
|
return low.FindItemInOrderedMap[*Response](response, r.Definitions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSecurityDefinition will attempt to locate a SecurityScheme using a name.
|
// FindSecurityDefinition will attempt to locate a SecurityScheme using a name.
|
||||||
func (s *SecurityDefinitions) FindSecurityDefinition(securityDef string) *low.ValueReference[*SecurityScheme] {
|
func (s *SecurityDefinitions) FindSecurityDefinition(securityDef string) *low.ValueReference[*SecurityScheme] {
|
||||||
return low.FindItemInMap[*SecurityScheme](securityDef, s.Definitions)
|
return low.FindItemInOrderedMap[*SecurityScheme](securityDef, s.Definitions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all definitions into SchemaProxy instances.
|
// Build will extract all definitions into SchemaProxy instances.
|
||||||
func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
|
// TODO: Refactor with orderedmap.TranslatePipeline.
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*base.SchemaProxy])
|
resultChan := make(chan definitionResult[*base.SchemaProxy])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -99,17 +102,18 @@ func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
completedDefs := 0
|
completedDefs := 0
|
||||||
results := make(map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy])
|
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]()
|
||||||
for completedDefs < totalDefinitions {
|
for completedDefs < totalDefinitions {
|
||||||
select {
|
select {
|
||||||
case err := <-errorChan:
|
case err := <-errorChan:
|
||||||
return err
|
return err
|
||||||
case sch := <-resultChan:
|
case sch := <-resultChan:
|
||||||
completedDefs++
|
completedDefs++
|
||||||
results[low.KeyReference[string]{
|
key := low.KeyReference[string]{
|
||||||
Value: sch.k.Value,
|
Value: sch.k.Value,
|
||||||
KeyNode: sch.k,
|
KeyNode: sch.k,
|
||||||
}] = sch.v
|
}
|
||||||
|
results.Set(key, sch.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d.Schemas = results
|
d.Schemas = results
|
||||||
@@ -119,10 +123,10 @@ func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the Definitions object
|
// Hash will return a consistent SHA256 Hash of the Definitions object
|
||||||
func (d *Definitions) Hash() [32]byte {
|
func (d *Definitions) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
keys := make([]string, len(d.Schemas))
|
keys := make([]string, orderedmap.Len(d.Schemas))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range d.Schemas {
|
for pair := orderedmap.First(d.Schemas); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
@@ -158,17 +162,18 @@ func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
completedDefs := 0
|
completedDefs := 0
|
||||||
results := make(map[low.KeyReference[string]]low.ValueReference[*Parameter])
|
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*Parameter]]()
|
||||||
for completedDefs < totalDefinitions {
|
for completedDefs < totalDefinitions {
|
||||||
select {
|
select {
|
||||||
case err := <-errorChan:
|
case err := <-errorChan:
|
||||||
return err
|
return err
|
||||||
case sch := <-resultChan:
|
case sch := <-resultChan:
|
||||||
completedDefs++
|
completedDefs++
|
||||||
results[low.KeyReference[string]{
|
key := low.KeyReference[string]{
|
||||||
Value: sch.k.Value,
|
Value: sch.k.Value,
|
||||||
KeyNode: sch.k,
|
KeyNode: sch.k,
|
||||||
}] = sch.v
|
}
|
||||||
|
results.Set(key, sch.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pd.Definitions = results
|
pd.Definitions = results
|
||||||
@@ -207,17 +212,18 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
completedDefs := 0
|
completedDefs := 0
|
||||||
results := make(map[low.KeyReference[string]]low.ValueReference[*Response])
|
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*Response]]()
|
||||||
for completedDefs < totalDefinitions {
|
for completedDefs < totalDefinitions {
|
||||||
select {
|
select {
|
||||||
case err := <-errorChan:
|
case err := <-errorChan:
|
||||||
return err
|
return err
|
||||||
case sch := <-resultChan:
|
case sch := <-resultChan:
|
||||||
completedDefs++
|
completedDefs++
|
||||||
results[low.KeyReference[string]{
|
key := low.KeyReference[string]{
|
||||||
Value: sch.k.Value,
|
Value: sch.k.Value,
|
||||||
KeyNode: sch.k,
|
KeyNode: sch.k,
|
||||||
}] = sch.v
|
}
|
||||||
|
results.Set(key, sch.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.Definitions = results
|
r.Definitions = results
|
||||||
@@ -253,17 +259,18 @@ func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
completedDefs := 0
|
completedDefs := 0
|
||||||
results := make(map[low.KeyReference[string]]low.ValueReference[*SecurityScheme])
|
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*SecurityScheme]]()
|
||||||
for completedDefs < totalDefinitions {
|
for completedDefs < totalDefinitions {
|
||||||
select {
|
select {
|
||||||
case err := <-errorChan:
|
case err := <-errorChan:
|
||||||
return err
|
return err
|
||||||
case sch := <-resultChan:
|
case sch := <-resultChan:
|
||||||
completedDefs++
|
completedDefs++
|
||||||
results[low.KeyReference[string]{
|
key := low.KeyReference[string]{
|
||||||
Value: sch.k.Value,
|
Value: sch.k.Value,
|
||||||
KeyNode: sch.k,
|
KeyNode: sch.k,
|
||||||
}] = sch.v
|
}
|
||||||
|
results.Set(key, sch.v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Definitions = results
|
s.Definitions = results
|
||||||
|
|||||||
@@ -6,24 +6,26 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Examples represents a low-level Swagger / OpenAPI 2 Example object.
|
// Examples represents a low-level Swagger / OpenAPI 2 Example object.
|
||||||
// Allows sharing examples for operation responses
|
// Allows sharing examples for operation responses
|
||||||
// - https://swagger.io/specification/v2/#exampleObject
|
// - https://swagger.io/specification/v2/#exampleObject
|
||||||
type Examples struct {
|
type Examples struct {
|
||||||
Values map[low.KeyReference[string]]low.ValueReference[any]
|
Values orderedmap.Map[low.KeyReference[string], low.ValueReference[any]]
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExample attempts to locate an example value, using a key label.
|
// FindExample attempts to locate an example value, using a key label.
|
||||||
func (e *Examples) FindExample(name string) *low.ValueReference[any] {
|
func (e *Examples) FindExample(name string) *low.ValueReference[any] {
|
||||||
return low.FindItemInMap[any](name, e.Values)
|
return low.FindItemInOrderedMap[any](name, e.Values)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
||||||
@@ -32,7 +34,7 @@ func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
|||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
var keyNode, currNode *yaml.Node
|
var keyNode, currNode *yaml.Node
|
||||||
var err error
|
var err error
|
||||||
e.Values = make(map[low.KeyReference[string]]low.ValueReference[any])
|
e.Values = orderedmap.New[low.KeyReference[string], low.ValueReference[any]]()
|
||||||
for i := range root.Content {
|
for i := range root.Content {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
keyNode = root.Content[i]
|
keyNode = root.Content[i]
|
||||||
@@ -48,32 +50,40 @@ func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
|||||||
// lets just default to interface
|
// lets just default to interface
|
||||||
var j interface{}
|
var j interface{}
|
||||||
_ = currNode.Decode(&j)
|
_ = currNode.Decode(&j)
|
||||||
e.Values[low.KeyReference[string]{
|
e.Values.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: keyNode.Value,
|
Value: keyNode.Value,
|
||||||
KeyNode: keyNode,
|
KeyNode: keyNode,
|
||||||
}] = low.ValueReference[any]{
|
},
|
||||||
|
low.ValueReference[any]{
|
||||||
Value: j,
|
Value: j,
|
||||||
ValueNode: currNode,
|
ValueNode: currNode,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.Values[low.KeyReference[string]{
|
e.Values.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: keyNode.Value,
|
Value: keyNode.Value,
|
||||||
KeyNode: keyNode,
|
KeyNode: keyNode,
|
||||||
}] = low.ValueReference[any]{
|
},
|
||||||
|
low.ValueReference[any]{
|
||||||
Value: k,
|
Value: k,
|
||||||
ValueNode: currNode,
|
ValueNode: currNode,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
e.Values[low.KeyReference[string]{
|
e.Values.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: keyNode.Value,
|
Value: keyNode.Value,
|
||||||
KeyNode: keyNode,
|
KeyNode: keyNode,
|
||||||
}] = low.ValueReference[any]{
|
},
|
||||||
|
low.ValueReference[any]{
|
||||||
Value: n,
|
Value: n,
|
||||||
ValueNode: currNode,
|
ValueNode: currNode,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -81,10 +91,10 @@ func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the Examples object
|
// Hash will return a consistent SHA256 Hash of the Examples object
|
||||||
func (e *Examples) Hash() [32]byte {
|
func (e *Examples) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
keys := make([]string, len(e.Values))
|
keys := make([]string, orderedmap.Len(e.Values))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range e.Values {
|
for pair := orderedmap.First(e.Values); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -32,28 +31,24 @@ func (p *Paths) GetExtensions() map[low.KeyReference[string]]low.ValueReference[
|
|||||||
|
|
||||||
// FindPath attempts to locate a PathItem instance, given a path key.
|
// FindPath attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
if pair.Key().Value == path {
|
if pair.Key().Value == path {
|
||||||
result = pair.ValuePtr()
|
result = pair.ValuePtr()
|
||||||
return io.EOF
|
break
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
if pair.Key().Value == path {
|
if pair.Key().Value == path {
|
||||||
key = pair.KeyPtr()
|
key = pair.KeyPtr()
|
||||||
value = pair.ValuePtr()
|
value = pair.ValuePtr()
|
||||||
return io.EOF
|
break
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
return key, value
|
return key, value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,14 +162,12 @@ func (p *Paths) Hash() [32]byte {
|
|||||||
keys := make(map[string]low.ValueReference[*PathItem])
|
keys := make(map[string]low.ValueReference[*PathItem])
|
||||||
z := 0
|
z := 0
|
||||||
|
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
k := pair.Key().Value
|
k := pair.Key().Value
|
||||||
keys[k] = pair.Value()
|
keys[k] = pair.Value()
|
||||||
l[z] = k
|
l[z] = k
|
||||||
z++
|
z++
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
|
|
||||||
sort.Strings(l)
|
sort.Strings(l)
|
||||||
for k := range l {
|
for k := range l {
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Response is a representation of a high-level Swagger / OpenAPI 2 Response object, backed by a low-level one.
|
// Response is a representation of a high-level Swagger / OpenAPI 2 Response object, backed by a low-level one.
|
||||||
@@ -22,7 +24,7 @@ import (
|
|||||||
type Response struct {
|
type Response struct {
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Schema low.NodeReference[*base.SchemaProxy]
|
Schema low.NodeReference[*base.SchemaProxy]
|
||||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||||
Examples low.NodeReference[*Examples]
|
Examples low.NodeReference[*Examples]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
@@ -39,7 +41,7 @@ func (r *Response) GetExtensions() map[low.KeyReference[string]]low.ValueReferen
|
|||||||
|
|
||||||
// FindHeader will attempt to locate a Header value, given a key
|
// FindHeader will attempt to locate a Header value, given a key
|
||||||
func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
||||||
return low.FindItemInMap[*Header](hType, r.Headers.Value)
|
return low.FindItemInOrderedMap[*Header](hType, r.Headers.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract schema, extensions, examples and headers from node
|
// Build will extract schema, extensions, examples and headers from node
|
||||||
@@ -68,7 +70,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if headers != nil {
|
if headers != nil {
|
||||||
r.Headers = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]{
|
r.Headers = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]{
|
||||||
Value: headers,
|
Value: headers,
|
||||||
KeyNode: lN,
|
KeyNode: lN,
|
||||||
ValueNode: kN,
|
ValueNode: kN,
|
||||||
@@ -87,8 +89,8 @@ func (r *Response) Hash() [32]byte {
|
|||||||
f = append(f, low.GenerateHashString(r.Schema.Value))
|
f = append(f, low.GenerateHashString(r.Schema.Value))
|
||||||
}
|
}
|
||||||
if !r.Examples.IsEmpty() {
|
if !r.Examples.IsEmpty() {
|
||||||
for k := range r.Examples.Value.Values {
|
for pair := orderedmap.First(r.Examples.Value.Values); pair != nil; pair = pair.Next() {
|
||||||
f = append(f, low.GenerateHashString(r.Examples.Value.Values[k].Value))
|
f = append(f, low.GenerateHashString(pair.Value().Value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys := make([]string, len(r.Extensions))
|
keys := make([]string, len(r.Extensions))
|
||||||
|
|||||||
@@ -6,17 +6,19 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Responses is a low-level representation of a Swagger / OpenAPI 2 Responses object.
|
// Responses is a low-level representation of a Swagger / OpenAPI 2 Responses object.
|
||||||
type Responses struct {
|
type Responses struct {
|
||||||
Codes map[low.KeyReference[string]]low.ValueReference[*Response]
|
Codes orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]
|
||||||
Default low.NodeReference[*Response]
|
Default low.NodeReference[*Response]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
@@ -55,12 +57,12 @@ func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
||||||
for n, o := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
if strings.ToLower(n.Value) == DefaultLabel {
|
if strings.ToLower(pair.Key().Value) == DefaultLabel {
|
||||||
return &low.NodeReference[*Response]{
|
return &low.NodeReference[*Response]{
|
||||||
ValueNode: o.ValueNode,
|
ValueNode: pair.Value().ValueNode,
|
||||||
KeyNode: n.KeyNode,
|
KeyNode: pair.Key().KeyNode,
|
||||||
Value: o.Value,
|
Value: pair.Value().Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,34 +73,34 @@ func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
|||||||
func (r *Responses) deleteCode(code string) {
|
func (r *Responses) deleteCode(code string) {
|
||||||
var key *low.KeyReference[string]
|
var key *low.KeyReference[string]
|
||||||
if r.Codes != nil {
|
if r.Codes != nil {
|
||||||
for k := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
if k.Value == code {
|
if pair.Key().Value == code {
|
||||||
key = &k
|
key = pair.KeyPtr()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// should never be nil, but, you never know... science and all that!
|
// should never be nil, but, you never know... science and all that!
|
||||||
if key != nil {
|
if key != nil {
|
||||||
delete(r.Codes, *key)
|
r.Codes.Delete(*key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindResponseByCode will attempt to locate a Response instance using an HTTP response code string.
|
// FindResponseByCode will attempt to locate a Response instance using an HTTP response code string.
|
||||||
func (r *Responses) FindResponseByCode(code string) *low.ValueReference[*Response] {
|
func (r *Responses) FindResponseByCode(code string) *low.ValueReference[*Response] {
|
||||||
return low.FindItemInMap[*Response](code, r.Codes)
|
return low.FindItemInOrderedMap[*Response](code, r.Codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash will return a consistent SHA256 Hash of the Examples object
|
// Hash will return a consistent SHA256 Hash of the Examples object
|
||||||
func (r *Responses) Hash() [32]byte {
|
func (r *Responses) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
var keys []string
|
var keys []string
|
||||||
keys = make([]string, len(r.Codes))
|
keys = make([]string, orderedmap.Len(r.Codes))
|
||||||
cmap := make(map[string]*Response, len(keys))
|
cmap := make(map[string]*Response, len(keys))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
cmap[k.Value] = r.Codes[k].Value
|
cmap[pair.Key().Value] = pair.Value().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Scopes is a low-level representation of a Swagger / OpenAPI 2 OAuth2 Scopes object.
|
// Scopes is a low-level representation of a Swagger / OpenAPI 2 OAuth2 Scopes object.
|
||||||
@@ -19,7 +21,7 @@ import (
|
|||||||
// Scopes lists the available scopes for an OAuth2 security scheme.
|
// Scopes lists the available scopes for an OAuth2 security scheme.
|
||||||
// - https://swagger.io/specification/v2/#scopesObject
|
// - https://swagger.io/specification/v2/#scopesObject
|
||||||
type Scopes struct {
|
type Scopes struct {
|
||||||
Values map[low.KeyReference[string]]low.ValueReference[string]
|
Values orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ func (s *Scopes) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
|
|
||||||
// FindScope will attempt to locate a scope string using a key.
|
// FindScope will attempt to locate a scope string using a key.
|
||||||
func (s *Scopes) FindScope(scope string) *low.ValueReference[string] {
|
func (s *Scopes) FindScope(scope string) *low.ValueReference[string] {
|
||||||
return low.FindItemInMap[string](scope, s.Values)
|
return low.FindItemInOrderedMap[string](scope, s.Values)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract scope values and extensions from node.
|
// Build will extract scope values and extensions from node.
|
||||||
@@ -38,20 +40,23 @@ func (s *Scopes) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Extensions = low.ExtractExtensions(root)
|
s.Extensions = low.ExtractExtensions(root)
|
||||||
valueMap := make(map[low.KeyReference[string]]low.ValueReference[string])
|
valueMap := orderedmap.New[low.KeyReference[string], low.ValueReference[string]]()
|
||||||
if utils.IsNodeMap(root) {
|
if utils.IsNodeMap(root) {
|
||||||
for k := range root.Content {
|
for k := range root.Content {
|
||||||
if k%2 == 0 {
|
if k%2 == 0 {
|
||||||
if strings.Contains(root.Content[k].Value, "x-") {
|
if strings.Contains(root.Content[k].Value, "x-") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
valueMap[low.KeyReference[string]{
|
valueMap.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: root.Content[k].Value,
|
Value: root.Content[k].Value,
|
||||||
KeyNode: root.Content[k],
|
KeyNode: root.Content[k],
|
||||||
}] = low.ValueReference[string]{
|
},
|
||||||
|
low.ValueReference[string]{
|
||||||
Value: root.Content[k+1].Value,
|
Value: root.Content[k+1].Value,
|
||||||
ValueNode: root.Content[k+1],
|
ValueNode: root.Content[k+1],
|
||||||
}
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.Values = valueMap
|
s.Values = valueMap
|
||||||
@@ -62,12 +67,12 @@ func (s *Scopes) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the Scopes object
|
// Hash will return a consistent SHA256 Hash of the Scopes object
|
||||||
func (s *Scopes) Hash() [32]byte {
|
func (s *Scopes) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
vals := make(map[string]low.ValueReference[string], len(s.Values))
|
vals := make(map[string]low.ValueReference[string], orderedmap.Len(s.Values))
|
||||||
keys := make([]string, len(s.Values))
|
keys := make([]string, orderedmap.Len(s.Values))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range s.Values {
|
for pair := orderedmap.First(s.Values); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
vals[k.Value] = s.Values[k]
|
vals[pair.Key().Value] = pair.Value()
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -23,7 +25,7 @@ import (
|
|||||||
// that identifies a URL to use for the callback operation.
|
// that identifies a URL to use for the callback operation.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
||||||
type Callback struct {
|
type Callback struct {
|
||||||
Expression low.ValueReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]
|
Expression low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -35,7 +37,7 @@ func (cb *Callback) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
|
|
||||||
// FindExpression will locate a string expression and return a ValueReference containing the located PathItem
|
// FindExpression will locate a string expression and return a ValueReference containing the located PathItem
|
||||||
func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
|
func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
|
||||||
return low.FindItemInMap[*PathItem](exp, cb.Expression.Value)
|
return low.FindItemInOrderedMap[*PathItem](exp, cb.Expression.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions, expressions and PathItem objects for Callback
|
// Build will extract extensions, expressions and PathItem objects for Callback
|
||||||
@@ -47,7 +49,7 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
|
|
||||||
// handle callback
|
// handle callback
|
||||||
var currentCB *yaml.Node
|
var currentCB *yaml.Node
|
||||||
callbacks := make(map[low.KeyReference[string]]low.ValueReference[*PathItem])
|
callbacks := orderedmap.New[low.KeyReference[string], low.ValueReference[*PathItem]]()
|
||||||
|
|
||||||
for i, callbackNode := range root.Content {
|
for i, callbackNode := range root.Content {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
@@ -61,17 +63,20 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
callbacks[low.KeyReference[string]{
|
callbacks.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: currentCB.Value,
|
Value: currentCB.Value,
|
||||||
KeyNode: currentCB,
|
KeyNode: currentCB,
|
||||||
}] = low.ValueReference[*PathItem]{
|
},
|
||||||
|
low.ValueReference[*PathItem]{
|
||||||
Value: callback,
|
Value: callback,
|
||||||
ValueNode: callbackNode,
|
ValueNode: callbackNode,
|
||||||
Reference: rv,
|
Reference: rv,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
if orderedmap.Len(callbacks) > 0 {
|
||||||
if len(callbacks) > 0 {
|
cb.Expression = low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]]{
|
||||||
cb.Expression = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
|
|
||||||
Value: callbacks,
|
Value: callbacks,
|
||||||
ValueNode: root,
|
ValueNode: root,
|
||||||
}
|
}
|
||||||
@@ -83,10 +88,10 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
func (cb *Callback) Hash() [32]byte {
|
func (cb *Callback) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
var keys []string
|
var keys []string
|
||||||
keys = make([]string, len(cb.Expression.Value))
|
keys = make([]string, orderedmap.Len(cb.Expression.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range cb.Expression.Value {
|
for pair := orderedmap.First(cb.Expression.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(cb.Expression.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -24,15 +25,15 @@ import (
|
|||||||
// will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
// will have no effect on the API unless they are explicitly referenced from properties outside the components object.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#components-object
|
// - https://spec.openapis.org/oas/v3.1.0#components-object
|
||||||
type Components struct {
|
type Components struct {
|
||||||
Schemas low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]]
|
Schemas low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]]
|
||||||
Responses low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Response]]
|
Responses low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]]
|
||||||
Parameters low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Parameter]]
|
Parameters low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Parameter]]]
|
||||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||||
RequestBodies low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*RequestBody]]
|
RequestBodies low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*RequestBody]]]
|
||||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||||
SecuritySchemes low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SecurityScheme]]
|
SecuritySchemes low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SecurityScheme]]]
|
||||||
Links low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]]
|
Links low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Link]]]
|
||||||
Callbacks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]]
|
Callbacks low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Callback]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -75,16 +76,16 @@ func (co *Components) Hash() [32]byte {
|
|||||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHashForObjectMap[T any](collection map[low.KeyReference[string]]low.ValueReference[T], hash *[]string) {
|
func generateHashForObjectMap[T any](collection orderedmap.Map[low.KeyReference[string], low.ValueReference[T]], hash *[]string) {
|
||||||
if collection == nil {
|
if collection == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
l := make([]string, len(collection))
|
l := make([]string, orderedmap.Len(collection))
|
||||||
keys := make(map[string]low.ValueReference[T])
|
keys := make(map[string]low.ValueReference[T])
|
||||||
z := 0
|
z := 0
|
||||||
for k := range collection {
|
for pair := orderedmap.First(collection); pair != nil; pair = pair.Next() {
|
||||||
keys[k.Value] = collection[k]
|
keys[pair.Key().Value] = pair.Value()
|
||||||
l[z] = k.Value
|
l[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(l)
|
sort.Strings(l)
|
||||||
@@ -100,43 +101,43 @@ func (co *Components) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
|
|
||||||
// FindSchema attempts to locate a SchemaProxy from 'schemas' with a specific name
|
// FindSchema attempts to locate a SchemaProxy from 'schemas' with a specific name
|
||||||
func (co *Components) FindSchema(schema string) *low.ValueReference[*base.SchemaProxy] {
|
func (co *Components) FindSchema(schema string) *low.ValueReference[*base.SchemaProxy] {
|
||||||
return low.FindItemInMap[*base.SchemaProxy](schema, co.Schemas.Value)
|
return low.FindItemInOrderedMap[*base.SchemaProxy](schema, co.Schemas.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindResponse attempts to locate a Response from 'responses' with a specific name
|
// FindResponse attempts to locate a Response from 'responses' with a specific name
|
||||||
func (co *Components) FindResponse(response string) *low.ValueReference[*Response] {
|
func (co *Components) FindResponse(response string) *low.ValueReference[*Response] {
|
||||||
return low.FindItemInMap[*Response](response, co.Responses.Value)
|
return low.FindItemInOrderedMap[*Response](response, co.Responses.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindParameter attempts to locate a Parameter from 'parameters' with a specific name
|
// FindParameter attempts to locate a Parameter from 'parameters' with a specific name
|
||||||
func (co *Components) FindParameter(response string) *low.ValueReference[*Parameter] {
|
func (co *Components) FindParameter(response string) *low.ValueReference[*Parameter] {
|
||||||
return low.FindItemInMap[*Parameter](response, co.Parameters.Value)
|
return low.FindItemInOrderedMap[*Parameter](response, co.Parameters.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSecurityScheme attempts to locate a SecurityScheme from 'securitySchemes' with a specific name
|
// FindSecurityScheme attempts to locate a SecurityScheme from 'securitySchemes' with a specific name
|
||||||
func (co *Components) FindSecurityScheme(sScheme string) *low.ValueReference[*SecurityScheme] {
|
func (co *Components) FindSecurityScheme(sScheme string) *low.ValueReference[*SecurityScheme] {
|
||||||
return low.FindItemInMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value)
|
return low.FindItemInOrderedMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExample attempts tp
|
// FindExample attempts tp
|
||||||
func (co *Components) FindExample(example string) *low.ValueReference[*base.Example] {
|
func (co *Components) FindExample(example string) *low.ValueReference[*base.Example] {
|
||||||
return low.FindItemInMap[*base.Example](example, co.Examples.Value)
|
return low.FindItemInOrderedMap[*base.Example](example, co.Examples.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Components) FindRequestBody(requestBody string) *low.ValueReference[*RequestBody] {
|
func (co *Components) FindRequestBody(requestBody string) *low.ValueReference[*RequestBody] {
|
||||||
return low.FindItemInMap[*RequestBody](requestBody, co.RequestBodies.Value)
|
return low.FindItemInOrderedMap[*RequestBody](requestBody, co.RequestBodies.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Components) FindHeader(header string) *low.ValueReference[*Header] {
|
func (co *Components) FindHeader(header string) *low.ValueReference[*Header] {
|
||||||
return low.FindItemInMap[*Header](header, co.Headers.Value)
|
return low.FindItemInOrderedMap[*Header](header, co.Headers.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Components) FindLink(link string) *low.ValueReference[*Link] {
|
func (co *Components) FindLink(link string) *low.ValueReference[*Link] {
|
||||||
return low.FindItemInMap[*Link](link, co.Links.Value)
|
return low.FindItemInOrderedMap[*Link](link, co.Links.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (co *Components) FindCallback(callback string) *low.ValueReference[*Callback] {
|
func (co *Components) FindCallback(callback string) *low.ValueReference[*Callback] {
|
||||||
return low.FindItemInMap[*Callback](callback, co.Callbacks.Value)
|
return low.FindItemInOrderedMap[*Callback](callback, co.Callbacks.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build converts root YAML node containing components to low level model.
|
// Build converts root YAML node containing components to low level model.
|
||||||
@@ -222,13 +223,13 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// extractComponentValues converts all the YAML nodes of a component type to
|
// extractComponentValues converts all the YAML nodes of a component type to
|
||||||
// low level model.
|
// low level model.
|
||||||
// Process each node in parallel.
|
// Process each node in parallel.
|
||||||
func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]], error) {
|
func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]], error) {
|
||||||
var emptyResult low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]
|
var emptyResult low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]]
|
||||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
||||||
if nodeValue == nil {
|
if nodeValue == nil {
|
||||||
return emptyResult, nil
|
return emptyResult, nil
|
||||||
}
|
}
|
||||||
componentValues := make(map[low.KeyReference[string]]low.ValueReference[T])
|
componentValues := orderedmap.New[low.KeyReference[string], low.ValueReference[T]]()
|
||||||
if utils.IsNodeArray(nodeValue) {
|
if utils.IsNodeArray(nodeValue) {
|
||||||
return emptyResult, fmt.Errorf("node is array, cannot be used in components: line %d, column %d", nodeValue.Line, nodeValue.Column)
|
return emptyResult, fmt.Errorf("node is array, cannot be used in components: line %d, column %d", nodeValue.Line, nodeValue.Column)
|
||||||
}
|
}
|
||||||
@@ -271,7 +272,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
// Collect output.
|
// Collect output.
|
||||||
go func() {
|
go func() {
|
||||||
for result := range out {
|
for result := range out {
|
||||||
componentValues[result.key] = result.value
|
componentValues.Set(result.key, result.value)
|
||||||
}
|
}
|
||||||
close(done)
|
close(done)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -317,7 +318,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
return emptyResult, err
|
return emptyResult, err
|
||||||
}
|
}
|
||||||
|
|
||||||
results := low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]{
|
results := low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]]{
|
||||||
KeyNode: nodeLabel,
|
KeyNode: nodeLabel,
|
||||||
ValueNode: nodeValue,
|
ValueNode: nodeValue,
|
||||||
Value: componentValues,
|
Value: componentValues,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
"github.com/pb33f/libopenapi/resolver"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
)
|
)
|
||||||
@@ -247,7 +248,7 @@ func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInd
|
|||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
if hooks != nil {
|
if hooks != nil {
|
||||||
doc.Webhooks = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
|
doc.Webhooks = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]]{
|
||||||
Value: hooks,
|
Value: hooks,
|
||||||
KeyNode: hooksL,
|
KeyNode: hooksL,
|
||||||
ValueNode: hooksN,
|
ValueNode: hooksN,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -225,10 +226,10 @@ func TestCreateDocument_Info(t *testing.T) {
|
|||||||
func TestCreateDocument_WebHooks(t *testing.T) {
|
func TestCreateDocument_WebHooks(t *testing.T) {
|
||||||
initTest()
|
initTest()
|
||||||
assert.Len(t, doc.Webhooks.Value, 1)
|
assert.Len(t, doc.Webhooks.Value, 1)
|
||||||
for i := range doc.Webhooks.Value {
|
for pair := orderedmap.First(doc.Webhooks.Value); pair != nil; pair = pair.Next() {
|
||||||
// a nice deep model should be available for us.
|
// a nice deep model should be available for us.
|
||||||
assert.Equal(t, "Information about a new burger",
|
assert.Equal(t, "Information about a new burger",
|
||||||
doc.Webhooks.Value[i].Value.Post.Value.RequestBody.Value.Description.Value)
|
pair.Value().Value.Post.Value.RequestBody.Value.Description.Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Document struct {
|
type Document struct {
|
||||||
@@ -37,7 +38,7 @@ type Document struct {
|
|||||||
// for example by an out-of-band registration. The key name is a unique string to refer to each webhook,
|
// for example by an out-of-band registration. The key name is a unique string to refer to each webhook,
|
||||||
// while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider
|
// while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider
|
||||||
// and the expected responses. An example is available.
|
// and the expected responses. An example is available.
|
||||||
Webhooks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]] // 3.1
|
Webhooks low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]] // 3.1
|
||||||
|
|
||||||
// Servers is a slice of Server instances which provide connectivity information to a target server. If the servers
|
// Servers is a slice of Server instances which provide connectivity information to a target server. If the servers
|
||||||
// property is not provided, or is an empty array, the default value would be a Server Object with an url value of /.
|
// property is not provided, or is an empty array, the default value would be a Server Object with an url value of /.
|
||||||
@@ -87,9 +88,10 @@ type Document struct {
|
|||||||
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
||||||
func (d *Document) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
func (d *Document) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||||
for k := range d.Security.Value {
|
for k := range d.Security.Value {
|
||||||
for i := range d.Security.Value[k].Value.Requirements.Value {
|
requirements := d.Security.Value[k].Value.Requirements
|
||||||
if i.Value == name {
|
for pair := orderedmap.First(requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
return d.Security.Value[k].Value.Requirements.Value[i].Value
|
if pair.Key().Value == name {
|
||||||
|
return pair.Value().Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,20 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encoding represents a low-level OpenAPI 3+ Encoding object
|
// Encoding represents a low-level OpenAPI 3+ Encoding object
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
||||||
type Encoding struct {
|
type Encoding struct {
|
||||||
ContentType low.NodeReference[string]
|
ContentType low.NodeReference[string]
|
||||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||||
Style low.NodeReference[string]
|
Style low.NodeReference[string]
|
||||||
Explode low.NodeReference[bool]
|
Explode low.NodeReference[bool]
|
||||||
AllowReserved low.NodeReference[bool]
|
AllowReserved low.NodeReference[bool]
|
||||||
@@ -26,7 +28,7 @@ type Encoding struct {
|
|||||||
|
|
||||||
// FindHeader attempts to locate a Header with the supplied name
|
// FindHeader attempts to locate a Header with the supplied name
|
||||||
func (en *Encoding) FindHeader(hType string) *low.ValueReference[*Header] {
|
func (en *Encoding) FindHeader(hType string) *low.ValueReference[*Header] {
|
||||||
return low.FindItemInMap[*Header](hType, en.Headers.Value)
|
return low.FindItemInOrderedMap[*Header](hType, en.Headers.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash will return a consistent SHA256 Hash of the Encoding object
|
// Hash will return a consistent SHA256 Hash of the Encoding object
|
||||||
@@ -35,18 +37,19 @@ func (en *Encoding) Hash() [32]byte {
|
|||||||
if en.ContentType.Value != "" {
|
if en.ContentType.Value != "" {
|
||||||
f = append(f, en.ContentType.Value)
|
f = append(f, en.ContentType.Value)
|
||||||
}
|
}
|
||||||
if len(en.Headers.Value) > 0 {
|
if orderedmap.Len(en.Headers.Value) > 0 {
|
||||||
l := make([]string, len(en.Headers.Value))
|
l := make([]string, orderedmap.Len(en.Headers.Value))
|
||||||
keys := make(map[string]low.ValueReference[*Header])
|
keys := make(map[string]low.ValueReference[*Header])
|
||||||
z := 0
|
z := 0
|
||||||
for k := range en.Headers.Value {
|
for pair := orderedmap.First(en.Headers.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[k.Value] = en.Headers.Value[k]
|
keys[pair.Key().Value] = pair.Value()
|
||||||
l[z] = k.Value
|
l[z] = pair.Key().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range en.Headers.Value {
|
// FIXME: Redundant iteration?
|
||||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, en.Headers.Value[k].Value.Hash()))
|
for pair := orderedmap.First(en.Headers.Value); pair != nil; pair = pair.Next() {
|
||||||
|
f = append(f, fmt.Sprintf("%s-%x", pair.Key().Value, pair.Value().Value.Hash()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if en.Style.Value != "" {
|
if en.Style.Value != "" {
|
||||||
@@ -67,7 +70,7 @@ func (en *Encoding) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if headers != nil {
|
if headers != nil {
|
||||||
en.Headers = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]{
|
en.Headers = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]{
|
||||||
Value: headers,
|
Value: headers,
|
||||||
KeyNode: hL,
|
KeyNode: hL,
|
||||||
ValueNode: hN,
|
ValueNode: hN,
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Header represents a low-level OpenAPI 3+ Header object.
|
// Header represents a low-level OpenAPI 3+ Header object.
|
||||||
@@ -27,8 +29,8 @@ type Header struct {
|
|||||||
AllowReserved low.NodeReference[bool]
|
AllowReserved low.NodeReference[bool]
|
||||||
Schema low.NodeReference[*base.SchemaProxy]
|
Schema low.NodeReference[*base.SchemaProxy]
|
||||||
Example low.NodeReference[any]
|
Example low.NodeReference[any]
|
||||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -40,12 +42,12 @@ func (h *Header) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
|
|
||||||
// FindExample will attempt to locate an Example with a specified name
|
// FindExample will attempt to locate an Example with a specified name
|
||||||
func (h *Header) FindExample(eType string) *low.ValueReference[*base.Example] {
|
func (h *Header) FindExample(eType string) *low.ValueReference[*base.Example] {
|
||||||
return low.FindItemInMap[*base.Example](eType, h.Examples.Value)
|
return low.FindItemInOrderedMap[*base.Example](eType, h.Examples.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindContent will attempt to locate a MediaType definition, with a specified name
|
// FindContent will attempt to locate a MediaType definition, with a specified name
|
||||||
func (h *Header) FindContent(ext string) *low.ValueReference[*MediaType] {
|
func (h *Header) FindContent(ext string) *low.ValueReference[*MediaType] {
|
||||||
return low.FindItemInMap[*MediaType](ext, h.Content.Value)
|
return low.FindItemInOrderedMap[*MediaType](ext, h.Content.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExtensions returns all Header extensions and satisfies the low.HasExtensions interface.
|
// GetExtensions returns all Header extensions and satisfies the low.HasExtensions interface.
|
||||||
@@ -73,14 +75,14 @@ func (h *Header) Hash() [32]byte {
|
|||||||
if h.Example.Value != nil {
|
if h.Example.Value != nil {
|
||||||
f = append(f, fmt.Sprint(h.Example.Value))
|
f = append(f, fmt.Sprint(h.Example.Value))
|
||||||
}
|
}
|
||||||
if len(h.Examples.Value) > 0 {
|
if orderedmap.Len(h.Examples.Value) > 0 {
|
||||||
for k := range h.Examples.Value {
|
for pair := orderedmap.First(h.Examples.Value); pair != nil; pair = pair.Next() {
|
||||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Examples.Value[k].Value.Hash()))
|
f = append(f, fmt.Sprintf("%s-%x", pair.Key().Value, pair.Value().Value.Hash()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(h.Content.Value) > 0 {
|
if orderedmap.Len(h.Content.Value) > 0 {
|
||||||
for k := range h.Content.Value {
|
for pair := orderedmap.First(h.Content.Value); pair != nil; pair = pair.Next() {
|
||||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Content.Value[k].Value.Hash()))
|
f = append(f, fmt.Sprintf("%s-%x", pair.Key().Value, pair.Value().Value.Hash()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keys := make([]string, len(h.Extensions))
|
keys := make([]string, len(h.Extensions))
|
||||||
@@ -113,7 +115,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
if exps != nil {
|
if exps != nil {
|
||||||
h.Examples = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]{
|
h.Examples = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]{
|
||||||
Value: exps,
|
Value: exps,
|
||||||
KeyNode: expsL,
|
KeyNode: expsL,
|
||||||
ValueNode: expsN,
|
ValueNode: expsN,
|
||||||
@@ -134,7 +136,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
h.Content = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]{
|
h.Content = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]{
|
||||||
Value: con,
|
Value: con,
|
||||||
KeyNode: cL,
|
KeyNode: cL,
|
||||||
ValueNode: cN,
|
ValueNode: cN,
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Link represents a low-level OpenAPI 3+ Link object.
|
// Link represents a low-level OpenAPI 3+ Link object.
|
||||||
@@ -29,7 +31,7 @@ import (
|
|||||||
type Link struct {
|
type Link struct {
|
||||||
OperationRef low.NodeReference[string]
|
OperationRef low.NodeReference[string]
|
||||||
OperationId low.NodeReference[string]
|
OperationId low.NodeReference[string]
|
||||||
Parameters low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]]
|
Parameters low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
|
||||||
RequestBody low.NodeReference[string]
|
RequestBody low.NodeReference[string]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Server low.NodeReference[*Server]
|
Server low.NodeReference[*Server]
|
||||||
@@ -44,7 +46,7 @@ func (l *Link) GetExtensions() map[low.KeyReference[string]]low.ValueReference[a
|
|||||||
|
|
||||||
// FindParameter will attempt to locate a parameter string value, using a parameter name input.
|
// FindParameter will attempt to locate a parameter string value, using a parameter name input.
|
||||||
func (l *Link) FindParameter(pName string) *low.ValueReference[string] {
|
func (l *Link) FindParameter(pName string) *low.ValueReference[string] {
|
||||||
return low.FindItemInMap[string](pName, l.Parameters.Value)
|
return low.FindItemInOrderedMap[string](pName, l.Parameters.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension will attempt to locate an extension with a specific key
|
// FindExtension will attempt to locate an extension with a specific key
|
||||||
@@ -87,10 +89,10 @@ func (l *Link) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
// todo: needs ordering.
|
// todo: needs ordering.
|
||||||
|
|
||||||
keys := make([]string, len(l.Parameters.Value))
|
keys := make([]string, orderedmap.Len(l.Parameters.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range l.Parameters.Value {
|
for pair := orderedmap.First(l.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = l.Parameters.Value[k].Value
|
keys[z] = pair.Value().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MediaType represents a low-level OpenAPI MediaType object.
|
// MediaType represents a low-level OpenAPI MediaType object.
|
||||||
@@ -22,8 +24,8 @@ import (
|
|||||||
type MediaType struct {
|
type MediaType struct {
|
||||||
Schema low.NodeReference[*base.SchemaProxy]
|
Schema low.NodeReference[*base.SchemaProxy]
|
||||||
Example low.NodeReference[any]
|
Example low.NodeReference[any]
|
||||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||||
Encoding low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Encoding]]
|
Encoding low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Encoding]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -40,16 +42,16 @@ func (mt *MediaType) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
|
|
||||||
// FindPropertyEncoding will attempt to locate an Encoding value with a specific name.
|
// FindPropertyEncoding will attempt to locate an Encoding value with a specific name.
|
||||||
func (mt *MediaType) FindPropertyEncoding(eType string) *low.ValueReference[*Encoding] {
|
func (mt *MediaType) FindPropertyEncoding(eType string) *low.ValueReference[*Encoding] {
|
||||||
return low.FindItemInMap[*Encoding](eType, mt.Encoding.Value)
|
return low.FindItemInOrderedMap[*Encoding](eType, mt.Encoding.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExample will attempt to locate an Example with a specific name.
|
// FindExample will attempt to locate an Example with a specific name.
|
||||||
func (mt *MediaType) FindExample(eType string) *low.ValueReference[*base.Example] {
|
func (mt *MediaType) FindExample(eType string) *low.ValueReference[*base.Example] {
|
||||||
return low.FindItemInMap[*base.Example](eType, mt.Examples.Value)
|
return low.FindItemInOrderedMap[*base.Example](eType, mt.Examples.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllExamples will extract all examples from the MediaType instance.
|
// GetAllExamples will extract all examples from the MediaType instance.
|
||||||
func (mt *MediaType) GetAllExamples() map[low.KeyReference[string]]low.ValueReference[*base.Example] {
|
func (mt *MediaType) GetAllExamples() orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]] {
|
||||||
return mt.Examples.Value
|
return mt.Examples.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
if exps != nil {
|
if exps != nil {
|
||||||
mt.Examples = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]{
|
mt.Examples = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]{
|
||||||
Value: exps,
|
Value: exps,
|
||||||
KeyNode: expsL,
|
KeyNode: expsL,
|
||||||
ValueNode: expsN,
|
ValueNode: expsN,
|
||||||
@@ -110,7 +112,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return encErr
|
return encErr
|
||||||
}
|
}
|
||||||
if encs != nil {
|
if encs != nil {
|
||||||
mt.Encoding = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Encoding]]{
|
mt.Encoding = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Encoding]]]{
|
||||||
Value: encs,
|
Value: encs,
|
||||||
KeyNode: encsL,
|
KeyNode: encsL,
|
||||||
ValueNode: encsN,
|
ValueNode: encsN,
|
||||||
@@ -128,18 +130,18 @@ func (mt *MediaType) Hash() [32]byte {
|
|||||||
if mt.Example.Value != nil {
|
if mt.Example.Value != nil {
|
||||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(mt.Example.Value)))))
|
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(mt.Example.Value)))))
|
||||||
}
|
}
|
||||||
keys := make([]string, len(mt.Examples.Value))
|
keys := make([]string, orderedmap.Len(mt.Examples.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range mt.Examples.Value {
|
for pair := orderedmap.First(mt.Examples.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(mt.Examples.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
keys = make([]string, len(mt.Encoding.Value))
|
keys = make([]string, orderedmap.Len(mt.Encoding.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for k := range mt.Encoding.Value {
|
for pair := orderedmap.First(mt.Encoding.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(mt.Encoding.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthFlows represents a low-level OpenAPI 3+ OAuthFlows object.
|
// OAuthFlows represents a low-level OpenAPI 3+ OAuthFlows object.
|
||||||
@@ -95,7 +97,7 @@ type OAuthFlow struct {
|
|||||||
AuthorizationUrl low.NodeReference[string]
|
AuthorizationUrl low.NodeReference[string]
|
||||||
TokenUrl low.NodeReference[string]
|
TokenUrl low.NodeReference[string]
|
||||||
RefreshUrl low.NodeReference[string]
|
RefreshUrl low.NodeReference[string]
|
||||||
Scopes low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]]
|
Scopes low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -107,7 +109,7 @@ func (o *OAuthFlow) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
|
|
||||||
// FindScope attempts to locate a scope using a specified name.
|
// FindScope attempts to locate a scope using a specified name.
|
||||||
func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] {
|
func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] {
|
||||||
return low.FindItemInMap[string](scope, o.Scopes.Value)
|
return low.FindItemInOrderedMap[string](scope, o.Scopes.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension attempts to locate an extension with a specified key
|
// FindExtension attempts to locate an extension with a specified key
|
||||||
@@ -134,10 +136,10 @@ func (o *OAuthFlow) Hash() [32]byte {
|
|||||||
if !o.RefreshUrl.IsEmpty() {
|
if !o.RefreshUrl.IsEmpty() {
|
||||||
f = append(f, o.RefreshUrl.Value)
|
f = append(f, o.RefreshUrl.Value)
|
||||||
}
|
}
|
||||||
keys := make([]string, len(o.Scopes.Value))
|
keys := make([]string, orderedmap.Len(o.Scopes.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range o.Scopes.Value {
|
for pair := orderedmap.First(o.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, sha256.Sum256([]byte(fmt.Sprint(o.Scopes.Value[k].Value))))
|
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, sha256.Sum256([]byte(fmt.Sprint(pair.Value().Value))))
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Operation is a low-level representation of an OpenAPI 3+ Operation object.
|
// Operation is a low-level representation of an OpenAPI 3+ Operation object.
|
||||||
@@ -29,7 +31,7 @@ type Operation struct {
|
|||||||
Parameters low.NodeReference[[]low.ValueReference[*Parameter]]
|
Parameters low.NodeReference[[]low.ValueReference[*Parameter]]
|
||||||
RequestBody low.NodeReference[*RequestBody]
|
RequestBody low.NodeReference[*RequestBody]
|
||||||
Responses low.NodeReference[*Responses]
|
Responses low.NodeReference[*Responses]
|
||||||
Callbacks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]]
|
Callbacks low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Callback]]]
|
||||||
Deprecated low.NodeReference[bool]
|
Deprecated low.NodeReference[bool]
|
||||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||||
Servers low.NodeReference[[]low.ValueReference[*Server]]
|
Servers low.NodeReference[[]low.ValueReference[*Server]]
|
||||||
@@ -39,15 +41,16 @@ type Operation struct {
|
|||||||
|
|
||||||
// FindCallback will attempt to locate a Callback instance by the supplied name.
|
// FindCallback will attempt to locate a Callback instance by the supplied name.
|
||||||
func (o *Operation) FindCallback(callback string) *low.ValueReference[*Callback] {
|
func (o *Operation) FindCallback(callback string) *low.ValueReference[*Callback] {
|
||||||
return low.FindItemInMap[*Callback](callback, o.Callbacks.Value)
|
return low.FindItemInOrderedMap[*Callback](callback, o.Callbacks.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
||||||
func (o *Operation) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
func (o *Operation) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||||
for k := range o.Security.Value {
|
for k := range o.Security.Value {
|
||||||
for i := range o.Security.Value[k].Value.Requirements.Value {
|
requirements := o.Security.Value[k].Value.Requirements
|
||||||
if i.Value == name {
|
for pair := orderedmap.First(requirements.Value); pair != nil; pair = pair.Next() {
|
||||||
return o.Security.Value[k].Value.Requirements.Value[i].Value
|
if pair.Key().Value == name {
|
||||||
|
return pair.Value().Value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +104,7 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return cbErr
|
return cbErr
|
||||||
}
|
}
|
||||||
if callbacks != nil {
|
if callbacks != nil {
|
||||||
o.Callbacks = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]]{
|
o.Callbacks = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Callback]]]{
|
||||||
Value: callbacks,
|
Value: callbacks,
|
||||||
KeyNode: cbL,
|
KeyNode: cbL,
|
||||||
ValueNode: cbN,
|
ValueNode: cbN,
|
||||||
@@ -202,10 +205,10 @@ func (o *Operation) Hash() [32]byte {
|
|||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
|
|
||||||
keys = make([]string, len(o.Callbacks.Value))
|
keys = make([]string, orderedmap.Len(o.Callbacks.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range o.Callbacks.Value {
|
for pair := orderedmap.First(o.Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(o.Callbacks.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
@@ -278,6 +281,6 @@ func (o *Operation) GetServers() low.NodeReference[any] {
|
|||||||
Value: o.Servers.Value,
|
Value: o.Servers.Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (o *Operation) GetCallbacks() low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]] {
|
func (o *Operation) GetCallbacks() low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Callback]]] {
|
||||||
return o.Callbacks
|
return o.Callbacks
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parameter represents a high-level OpenAPI 3+ Parameter object, that is backed by a low-level one.
|
// Parameter represents a high-level OpenAPI 3+ Parameter object, that is backed by a low-level one.
|
||||||
@@ -31,20 +33,20 @@ type Parameter struct {
|
|||||||
AllowReserved low.NodeReference[bool]
|
AllowReserved low.NodeReference[bool]
|
||||||
Schema low.NodeReference[*base.SchemaProxy]
|
Schema low.NodeReference[*base.SchemaProxy]
|
||||||
Example low.NodeReference[any]
|
Example low.NodeReference[any]
|
||||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindContent will attempt to locate a MediaType instance using the specified name.
|
// FindContent will attempt to locate a MediaType instance using the specified name.
|
||||||
func (p *Parameter) FindContent(cType string) *low.ValueReference[*MediaType] {
|
func (p *Parameter) FindContent(cType string) *low.ValueReference[*MediaType] {
|
||||||
return low.FindItemInMap[*MediaType](cType, p.Content.Value)
|
return low.FindItemInOrderedMap[*MediaType](cType, p.Content.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExample will attempt to locate a base.Example instance using the specified name.
|
// FindExample will attempt to locate a base.Example instance using the specified name.
|
||||||
func (p *Parameter) FindExample(eType string) *low.ValueReference[*base.Example] {
|
func (p *Parameter) FindExample(eType string) *low.ValueReference[*base.Example] {
|
||||||
return low.FindItemInMap[*base.Example](eType, p.Examples.Value)
|
return low.FindItemInOrderedMap[*base.Example](eType, p.Examples.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension attempts to locate an extension using the specified name.
|
// FindExtension attempts to locate an extension using the specified name.
|
||||||
@@ -85,7 +87,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
if exps != nil {
|
if exps != nil {
|
||||||
p.Examples = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]{
|
p.Examples = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]{
|
||||||
Value: exps,
|
Value: exps,
|
||||||
KeyNode: expsL,
|
KeyNode: expsL,
|
||||||
ValueNode: expsN,
|
ValueNode: expsN,
|
||||||
@@ -97,7 +99,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
p.Content = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]{
|
p.Content = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]{
|
||||||
Value: con,
|
Value: con,
|
||||||
KeyNode: cL,
|
KeyNode: cL,
|
||||||
ValueNode: cN,
|
ValueNode: cN,
|
||||||
@@ -133,18 +135,18 @@ func (p *Parameter) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var keys []string
|
var keys []string
|
||||||
keys = make([]string, len(p.Examples.Value))
|
keys = make([]string, orderedmap.Len(p.Examples.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range p.Examples.Value {
|
for pair := orderedmap.First(p.Examples.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(p.Examples.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
keys = make([]string, len(p.Content.Value))
|
keys = make([]string, orderedmap.Len(p.Content.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for k := range p.Content.Value {
|
for pair := orderedmap.First(p.Content.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(p.Content.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -33,28 +32,24 @@ type Paths struct {
|
|||||||
|
|
||||||
// FindPath will attempt to locate a PathItem using the provided path string.
|
// FindPath will attempt to locate a PathItem using the provided path string.
|
||||||
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
if pair.Key().Value == path {
|
if pair.Key().Value == path {
|
||||||
result = pair.ValuePtr()
|
result = pair.ValuePtr()
|
||||||
return io.EOF
|
break
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
if pair.Key().Value == path {
|
if pair.Key().Value == path {
|
||||||
key = pair.KeyPtr()
|
key = pair.KeyPtr()
|
||||||
value = pair.ValuePtr()
|
value = pair.ValuePtr()
|
||||||
return io.EOF
|
break
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
return key, value
|
return key, value
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,14 +193,12 @@ func (p *Paths) Hash() [32]byte {
|
|||||||
keys := make(map[string]low.ValueReference[*PathItem])
|
keys := make(map[string]low.ValueReference[*PathItem])
|
||||||
z := 0
|
z := 0
|
||||||
|
|
||||||
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
for pair := orderedmap.First(p.PathItems); pair != nil; pair = pair.Next() {
|
||||||
k := pair.Key().Value
|
k := pair.Key().Value
|
||||||
keys[k] = pair.Value()
|
keys[k] = pair.Value()
|
||||||
l[z] = k
|
l[z] = k
|
||||||
z++
|
z++
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
|
||||||
|
|
||||||
sort.Strings(l)
|
sort.Strings(l)
|
||||||
for k := range l {
|
for k := range l {
|
||||||
|
|||||||
@@ -6,19 +6,21 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RequestBody represents a low-level OpenAPI 3+ RequestBody object.
|
// RequestBody represents a low-level OpenAPI 3+ RequestBody object.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
||||||
type RequestBody struct {
|
type RequestBody struct {
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||||
Required low.NodeReference[bool]
|
Required low.NodeReference[bool]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
@@ -36,7 +38,7 @@ func (rb *RequestBody) GetExtensions() map[low.KeyReference[string]]low.ValueRef
|
|||||||
|
|
||||||
// FindContent attempts to find content/MediaType defined using a specified name.
|
// FindContent attempts to find content/MediaType defined using a specified name.
|
||||||
func (rb *RequestBody) FindContent(cType string) *low.ValueReference[*MediaType] {
|
func (rb *RequestBody) FindContent(cType string) *low.ValueReference[*MediaType] {
|
||||||
return low.FindItemInMap[*MediaType](cType, rb.Content.Value)
|
return low.FindItemInOrderedMap[*MediaType](cType, rb.Content.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and MediaType objects from the node.
|
// Build will extract extensions and MediaType objects from the node.
|
||||||
@@ -52,7 +54,7 @@ func (rb *RequestBody) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
if con != nil {
|
if con != nil {
|
||||||
rb.Content = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]{
|
rb.Content = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]{
|
||||||
Value: con,
|
Value: con,
|
||||||
KeyNode: cL,
|
KeyNode: cL,
|
||||||
ValueNode: cN,
|
ValueNode: cN,
|
||||||
@@ -70,8 +72,8 @@ func (rb *RequestBody) Hash() [32]byte {
|
|||||||
if !rb.Required.IsEmpty() {
|
if !rb.Required.IsEmpty() {
|
||||||
f = append(f, fmt.Sprint(rb.Required.Value))
|
f = append(f, fmt.Sprint(rb.Required.Value))
|
||||||
}
|
}
|
||||||
for k := range rb.Content.Value {
|
for pair := orderedmap.First(rb.Content.Value); pair != nil; pair = pair.Next() {
|
||||||
f = append(f, low.GenerateHashString(rb.Content.Value[k].Value))
|
f = append(f, low.GenerateHashString(pair.Value().Value))
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := make([]string, len(rb.Extensions))
|
keys := make([]string, len(rb.Extensions))
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Response represents a high-level OpenAPI 3+ Response object that is backed by a low-level one.
|
// Response represents a high-level OpenAPI 3+ Response object that is backed by a low-level one.
|
||||||
@@ -21,10 +23,10 @@ import (
|
|||||||
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
||||||
type Response struct {
|
type Response struct {
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
Links low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]]
|
Links low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Link]]]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,17 +42,17 @@ func (r *Response) GetExtensions() map[low.KeyReference[string]]low.ValueReferen
|
|||||||
|
|
||||||
// FindContent will attempt to locate a MediaType instance using the supplied key.
|
// FindContent will attempt to locate a MediaType instance using the supplied key.
|
||||||
func (r *Response) FindContent(cType string) *low.ValueReference[*MediaType] {
|
func (r *Response) FindContent(cType string) *low.ValueReference[*MediaType] {
|
||||||
return low.FindItemInMap[*MediaType](cType, r.Content.Value)
|
return low.FindItemInOrderedMap[*MediaType](cType, r.Content.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindHeader will attempt to locate a Header instance using the supplied key.
|
// FindHeader will attempt to locate a Header instance using the supplied key.
|
||||||
func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
||||||
return low.FindItemInMap[*Header](hType, r.Headers.Value)
|
return low.FindItemInOrderedMap[*Header](hType, r.Headers.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindLink will attempt to locate a Link instance using the supplied key.
|
// FindLink will attempt to locate a Link instance using the supplied key.
|
||||||
func (r *Response) FindLink(hType string) *low.ValueReference[*Link] {
|
func (r *Response) FindLink(hType string) *low.ValueReference[*Link] {
|
||||||
return low.FindItemInMap[*Link](hType, r.Links.Value)
|
return low.FindItemInOrderedMap[*Link](hType, r.Links.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract headers, extensions, content and links from node.
|
// Build will extract headers, extensions, content and links from node.
|
||||||
@@ -66,7 +68,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if headers != nil {
|
if headers != nil {
|
||||||
r.Headers = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]{
|
r.Headers = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]{
|
||||||
Value: headers,
|
Value: headers,
|
||||||
KeyNode: lN,
|
KeyNode: lN,
|
||||||
ValueNode: kN,
|
ValueNode: kN,
|
||||||
@@ -78,7 +80,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
if con != nil {
|
if con != nil {
|
||||||
r.Content = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]{
|
r.Content = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]{
|
||||||
Value: con,
|
Value: con,
|
||||||
KeyNode: clN,
|
KeyNode: clN,
|
||||||
ValueNode: cN,
|
ValueNode: cN,
|
||||||
@@ -91,7 +93,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return lErr
|
return lErr
|
||||||
}
|
}
|
||||||
if links != nil {
|
if links != nil {
|
||||||
r.Links = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]]{
|
r.Links = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Link]]]{
|
||||||
Value: links,
|
Value: links,
|
||||||
KeyNode: linkLabel,
|
KeyNode: linkLabel,
|
||||||
ValueNode: linkValue,
|
ValueNode: linkValue,
|
||||||
@@ -106,26 +108,26 @@ func (r *Response) Hash() [32]byte {
|
|||||||
if r.Description.Value != "" {
|
if r.Description.Value != "" {
|
||||||
f = append(f, r.Description.Value)
|
f = append(f, r.Description.Value)
|
||||||
}
|
}
|
||||||
keys := make([]string, len(r.Headers.Value))
|
keys := make([]string, orderedmap.Len(r.Headers.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range r.Headers.Value {
|
for pair := orderedmap.First(r.Headers.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Headers.Value[k].Value))
|
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
keys = make([]string, len(r.Content.Value))
|
keys = make([]string, orderedmap.Len(r.Content.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for k := range r.Content.Value {
|
for pair := orderedmap.First(r.Content.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Content.Value[k].Value))
|
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
keys = make([]string, len(r.Links.Value))
|
keys = make([]string, orderedmap.Len(r.Links.Value))
|
||||||
z = 0
|
z = 0
|
||||||
for k := range r.Links.Value {
|
for pair := orderedmap.First(r.Links.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Links.Value[k].Value))
|
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Responses represents a low-level OpenAPI 3+ Responses object.
|
// Responses represents a low-level OpenAPI 3+ Responses object.
|
||||||
@@ -33,7 +35,7 @@ import (
|
|||||||
// the duplication. Perhaps in the future we could use generics here, but for now to keep things
|
// the duplication. Perhaps in the future we could use generics here, but for now to keep things
|
||||||
// simple, they are broken out into individual versions.
|
// simple, they are broken out into individual versions.
|
||||||
type Responses struct {
|
type Responses struct {
|
||||||
Codes map[low.KeyReference[string]]low.ValueReference[*Response]
|
Codes orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]
|
||||||
Default low.NodeReference[*Response]
|
Default low.NodeReference[*Response]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
@@ -75,12 +77,12 @@ func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
||||||
for n, o := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
if strings.ToLower(n.Value) == DefaultLabel {
|
if strings.ToLower(pair.Key().Value) == DefaultLabel {
|
||||||
return &low.NodeReference[*Response]{
|
return &low.NodeReference[*Response]{
|
||||||
ValueNode: o.ValueNode,
|
ValueNode: pair.Value().ValueNode,
|
||||||
KeyNode: n.KeyNode,
|
KeyNode: pair.Key().KeyNode,
|
||||||
Value: o.Value,
|
Value: pair.Value().Value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,35 +92,33 @@ func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
|||||||
// used to remove default from codes extracted by Build()
|
// used to remove default from codes extracted by Build()
|
||||||
func (r *Responses) deleteCode(code string) {
|
func (r *Responses) deleteCode(code string) {
|
||||||
var key *low.KeyReference[string]
|
var key *low.KeyReference[string]
|
||||||
if r.Codes != nil {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
for k := range r.Codes {
|
if pair.Key().Value == code {
|
||||||
if k.Value == code {
|
key = pair.KeyPtr()
|
||||||
key = &k
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// should never be nil, but, you never know... science and all that!
|
// should never be nil, but, you never know... science and all that!
|
||||||
if key != nil {
|
if key != nil {
|
||||||
delete(r.Codes, *key)
|
r.Codes.Delete(*key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindResponseByCode will attempt to locate a Response using an HTTP response code.
|
// FindResponseByCode will attempt to locate a Response using an HTTP response code.
|
||||||
func (r *Responses) FindResponseByCode(code string) *low.ValueReference[*Response] {
|
func (r *Responses) FindResponseByCode(code string) *low.ValueReference[*Response] {
|
||||||
return low.FindItemInMap[*Response](code, r.Codes)
|
return low.FindItemInOrderedMap[*Response](code, r.Codes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash will return a consistent SHA256 Hash of the Examples object
|
// Hash will return a consistent SHA256 Hash of the Examples object
|
||||||
func (r *Responses) Hash() [32]byte {
|
func (r *Responses) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
var keys []string
|
var keys []string
|
||||||
keys = make([]string, len(r.Codes))
|
keys = make([]string, orderedmap.Len(r.Codes))
|
||||||
cMap := make(map[string]*Response, len(keys))
|
cMap := make(map[string]*Response, len(keys))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range r.Codes {
|
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = k.Value
|
keys[z] = pair.Key().Value
|
||||||
cMap[k.Value] = r.Codes[k].Value
|
cMap[pair.Key().Value] = pair.Value().Value
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server represents a low-level OpenAPI 3+ Server object.
|
// Server represents a low-level OpenAPI 3+ Server object.
|
||||||
@@ -18,7 +20,7 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
URL low.NodeReference[string]
|
URL low.NodeReference[string]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Variables low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*ServerVariable]]
|
Variables low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*ServerVariable]]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
@@ -30,7 +32,7 @@ func (s *Server) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
|
|
||||||
// FindVariable attempts to locate a ServerVariable instance using the supplied key.
|
// FindVariable attempts to locate a ServerVariable instance using the supplied key.
|
||||||
func (s *Server) FindVariable(serverVar string) *low.ValueReference[*ServerVariable] {
|
func (s *Server) FindVariable(serverVar string) *low.ValueReference[*ServerVariable] {
|
||||||
return low.FindItemInMap[*ServerVariable](serverVar, s.Variables.Value)
|
return low.FindItemInOrderedMap[*ServerVariable](serverVar, s.Variables.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract server variables from the supplied node.
|
// Build will extract server variables from the supplied node.
|
||||||
@@ -43,7 +45,7 @@ func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if vars == nil {
|
if vars == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
variablesMap := make(map[low.KeyReference[string]]low.ValueReference[*ServerVariable])
|
variablesMap := orderedmap.New[low.KeyReference[string], low.ValueReference[*ServerVariable]]()
|
||||||
if utils.IsNodeMap(vars) {
|
if utils.IsNodeMap(vars) {
|
||||||
var currentNode string
|
var currentNode string
|
||||||
var keyNode *yaml.Node
|
var keyNode *yaml.Node
|
||||||
@@ -56,15 +58,18 @@ func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
variable := ServerVariable{}
|
variable := ServerVariable{}
|
||||||
variable.Reference = new(low.Reference)
|
variable.Reference = new(low.Reference)
|
||||||
_ = low.BuildModel(varNode, &variable)
|
_ = low.BuildModel(varNode, &variable)
|
||||||
variablesMap[low.KeyReference[string]{
|
variablesMap.Set(
|
||||||
|
low.KeyReference[string]{
|
||||||
Value: currentNode,
|
Value: currentNode,
|
||||||
KeyNode: keyNode,
|
KeyNode: keyNode,
|
||||||
}] = low.ValueReference[*ServerVariable]{
|
},
|
||||||
|
low.ValueReference[*ServerVariable]{
|
||||||
ValueNode: varNode,
|
ValueNode: varNode,
|
||||||
Value: &variable,
|
Value: &variable,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
s.Variables = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*ServerVariable]]]{
|
||||||
s.Variables = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*ServerVariable]]{
|
|
||||||
KeyNode: kn,
|
KeyNode: kn,
|
||||||
ValueNode: vars,
|
ValueNode: vars,
|
||||||
Value: variablesMap,
|
Value: variablesMap,
|
||||||
@@ -76,10 +81,10 @@ func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the Server object
|
// Hash will return a consistent SHA256 Hash of the Server object
|
||||||
func (s *Server) Hash() [32]byte {
|
func (s *Server) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
keys := make([]string, len(s.Variables.Value))
|
keys := make([]string, orderedmap.Len(s.Variables.Value))
|
||||||
z := 0
|
z := 0
|
||||||
for k := range s.Variables.Value {
|
for pair := orderedmap.First(s.Variables.Value); pair != nil; pair = pair.Next() {
|
||||||
keys[z] = low.GenerateHashString(s.Variables.Value[k].Value)
|
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func ExampleNewDocument_fromOpenAPI3Document() {
|
|||||||
|
|
||||||
// get a count of the number of paths and schemas.
|
// get a count of the number of paths and schemas.
|
||||||
paths := orderedmap.Len(v3Model.Model.Paths.PathItems)
|
paths := orderedmap.Len(v3Model.Model.Paths.PathItems)
|
||||||
schemas := len(v3Model.Model.Components.Schemas)
|
schemas := orderedmap.Len(v3Model.Model.Components.Schemas)
|
||||||
|
|
||||||
// print the number of paths and schemas in the document
|
// print the number of paths and schemas in the document
|
||||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||||
@@ -156,7 +156,7 @@ func ExampleNewDocument_fromSwaggerDocument() {
|
|||||||
|
|
||||||
// get a count of the number of paths and schemas.
|
// get a count of the number of paths and schemas.
|
||||||
paths := orderedmap.Len(v2Model.Model.Paths.PathItems)
|
paths := orderedmap.Len(v2Model.Model.Paths.PathItems)
|
||||||
schemas := len(v2Model.Model.Definitions.Definitions)
|
schemas := orderedmap.Len(v2Model.Model.Definitions.Definitions)
|
||||||
|
|
||||||
// print the number of paths and schemas in the document
|
// print the number of paths and schemas in the document
|
||||||
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
fmt.Printf("There are %d paths and %d schemas in the document", paths, schemas)
|
||||||
@@ -187,7 +187,7 @@ func ExampleNewDocument_fromUnknownVersion() {
|
|||||||
}
|
}
|
||||||
if len(errors) <= 0 {
|
if len(errors) <= 0 {
|
||||||
paths = orderedmap.Len(v3Model.Model.Paths.PathItems)
|
paths = orderedmap.Len(v3Model.Model.Paths.PathItems)
|
||||||
schemas = len(v3Model.Model.Components.Schemas)
|
schemas = orderedmap.Len(v3Model.Model.Components.Schemas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if document.GetSpecInfo().SpecType == utils.OpenApi2 {
|
if document.GetSpecInfo().SpecType == utils.OpenApi2 {
|
||||||
@@ -197,7 +197,7 @@ func ExampleNewDocument_fromUnknownVersion() {
|
|||||||
}
|
}
|
||||||
if len(errors) <= 0 {
|
if len(errors) <= 0 {
|
||||||
paths = orderedmap.Len(v2Model.Model.Paths.PathItems)
|
paths = orderedmap.Len(v2Model.Model.Paths.PathItems)
|
||||||
schemas = len(v2Model.Model.Definitions.Definitions)
|
schemas = orderedmap.Len(v2Model.Model.Definitions.Definitions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,8 +562,8 @@ components:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get a reference to SchemaOne and ParameterOne
|
// get a reference to SchemaOne and ParameterOne
|
||||||
schemaOne := docModel.Model.Components.Schemas["SchemaOne"].Schema()
|
schemaOne := docModel.Model.Components.Schemas.GetOrZero("SchemaOne").Schema()
|
||||||
parameterOne := docModel.Model.Components.Parameters["ParameterOne"]
|
parameterOne := docModel.Model.Components.Parameters.GetOrZero("ParameterOne")
|
||||||
|
|
||||||
// unpack schemaOne extensions into complex `cakes` type
|
// unpack schemaOne extensions into complex `cakes` type
|
||||||
schemaOneExtensions, schemaUnpackErrors := high.UnpackExtensions[cakes, *low.Schema](schemaOne)
|
schemaOneExtensions, schemaUnpackErrors := high.UnpackExtensions[cakes, *low.Schema](schemaOne)
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
|
||||||
"github.com/pb33f/libopenapi/what-changed/model"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
||||||
@@ -254,17 +249,18 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
|||||||
// mutate the model
|
// mutate the model
|
||||||
h := m.Model
|
h := m.Model
|
||||||
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId = "findACakeInABakery"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId = "findACakeInABakery"
|
||||||
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes["400"].Description = "a nice bucket of mice"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes.GetOrZero("400").Description = "a nice bucket of mice"
|
||||||
h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags =
|
h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags =
|
||||||
append(h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, "gurgle", "giggle")
|
append(h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, "gurgle", "giggle")
|
||||||
|
|
||||||
h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security = append(h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security,
|
h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security = append(h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security,
|
||||||
&base.SecurityRequirement{Requirements: map[string][]string{
|
&base.SecurityRequirement{Requirements: orderedmap.ToOrderedMap(map[string][]string{
|
||||||
"pizza-and-cake": {"read:abook", "write:asong"},
|
"pizza-and-cake": {"read:abook", "write:asong"},
|
||||||
}})
|
})},
|
||||||
|
)
|
||||||
|
|
||||||
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example = "I am a teapot, filled with love."
|
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example = "I am a teapot, filled with love."
|
||||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||||
|
|
||||||
bytes, _, newDocModel, e := doc.RenderAndReload()
|
bytes, _, newDocModel, e := doc.RenderAndReload()
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
@@ -273,17 +269,17 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
|||||||
h = newDocModel.Model
|
h = newDocModel.Model
|
||||||
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId)
|
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId)
|
||||||
assert.Equal(t, "a nice bucket of mice",
|
assert.Equal(t, "a nice bucket of mice",
|
||||||
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes["400"].Description)
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes.GetOrZero("400").Description)
|
||||||
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
|
|
||||||
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
yu := h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security
|
yu := h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security
|
||||||
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements["pizza-and-cake"][0])
|
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements.GetOrZero("pizza-and-cake")[0])
|
||||||
assert.Equal(t, "I am a teapot, filled with love.",
|
assert.Equal(t, "I am a teapot, filled with love.",
|
||||||
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example)
|
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example)
|
||||||
|
|
||||||
assert.Equal(t, "https://pb33f.io",
|
assert.Equal(t, "https://pb33f.io",
|
||||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl)
|
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_Render(t *testing.T) {
|
func TestDocument_Render(t *testing.T) {
|
||||||
@@ -304,18 +300,20 @@ func TestDocument_Render(t *testing.T) {
|
|||||||
|
|
||||||
// mutate the model
|
// mutate the model
|
||||||
h := m.Model
|
h := m.Model
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.OperationId = "findACakeInABakery"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId = "findACakeInABakery"
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description = "a nice bucket of mice"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").
|
||||||
h.Paths.PathItems["/pet/findByTags"].Get.Tags =
|
Get.Responses.Codes.GetOrZero("400").Description = "a nice bucket of mice"
|
||||||
append(h.Paths.PathItems["/pet/findByTags"].Get.Tags, "gurgle", "giggle")
|
h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags =
|
||||||
|
append(h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, "gurgle", "giggle")
|
||||||
|
|
||||||
h.Paths.PathItems["/pet/{petId}"].Delete.Security = append(h.Paths.PathItems["/pet/{petId}"].Delete.Security,
|
h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security = append(h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security,
|
||||||
&base.SecurityRequirement{Requirements: map[string][]string{
|
&base.SecurityRequirement{Requirements: orderedmap.ToOrderedMap(map[string][]string{
|
||||||
"pizza-and-cake": {"read:abook", "write:asong"},
|
"pizza-and-cake": {"read:abook", "write:asong"},
|
||||||
}})
|
})},
|
||||||
|
)
|
||||||
|
|
||||||
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example = "I am a teapot, filled with love."
|
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example = "I am a teapot, filled with love."
|
||||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||||
|
|
||||||
bytes, e := doc.Render()
|
bytes, e := doc.Render()
|
||||||
assert.NoError(t, e)
|
assert.NoError(t, e)
|
||||||
@@ -329,19 +327,19 @@ func TestDocument_Render(t *testing.T) {
|
|||||||
assert.Len(t, docErrs, 0)
|
assert.Len(t, docErrs, 0)
|
||||||
|
|
||||||
h = newDocModel.Model
|
h = newDocModel.Model
|
||||||
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems["/pet/findByStatus"].Get.OperationId)
|
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId)
|
||||||
assert.Equal(t, "a nice bucket of mice",
|
assert.Equal(t, "a nice bucket of mice",
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description)
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes.GetOrZero("400").Description)
|
||||||
assert.Len(t, h.Paths.PathItems["/pet/findByTags"].Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
|
|
||||||
assert.Len(t, h.Paths.PathItems["/pet/findByTags"].Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
yu := h.Paths.PathItems["/pet/{petId}"].Delete.Security
|
yu := h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security
|
||||||
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements["pizza-and-cake"][0])
|
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements.GetOrZero("pizza-and-cake")[0])
|
||||||
assert.Equal(t, "I am a teapot, filled with love.",
|
assert.Equal(t, "I am a teapot, filled with love.",
|
||||||
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example)
|
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example)
|
||||||
|
|
||||||
assert.Equal(t, "https://pb33f.io",
|
assert.Equal(t, "https://pb33f.io",
|
||||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl)
|
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_RenderWithLargeIndention(t *testing.T) {
|
func TestDocument_RenderWithLargeIndention(t *testing.T) {
|
||||||
@@ -354,7 +352,6 @@ func TestDocument_RenderWithLargeIndention(t *testing.T) {
|
|||||||
doc.BuildV3Model()
|
doc.BuildV3Model()
|
||||||
bytes, _ := doc.Render()
|
bytes, _ := doc.Render()
|
||||||
assert.Equal(t, json, string(bytes))
|
assert.Equal(t, json, string(bytes))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_Render_ChangeCheck_Burgershop(t *testing.T) {
|
func TestDocument_Render_ChangeCheck_Burgershop(t *testing.T) {
|
||||||
@@ -566,16 +563,16 @@ func TestSchemaRefIsFollowed(t *testing.T) {
|
|||||||
|
|
||||||
// get a count of the number of paths and schemas.
|
// get a count of the number of paths and schemas.
|
||||||
schemas := v3Model.Model.Components.Schemas
|
schemas := v3Model.Model.Components.Schemas
|
||||||
assert.Equal(t, 4, len(schemas))
|
assert.Equal(t, 4, orderedmap.Len(schemas))
|
||||||
|
|
||||||
fp := schemas["FP"]
|
fp := schemas.GetOrZero("FP")
|
||||||
fbsref := schemas["FBSRef"]
|
fbsref := schemas.GetOrZero("FBSRef")
|
||||||
|
|
||||||
assert.Equal(t, fp.Schema().Pattern, fbsref.Schema().Pattern)
|
assert.Equal(t, fp.Schema().Pattern, fbsref.Schema().Pattern)
|
||||||
assert.Equal(t, fp.Schema().Example, fbsref.Schema().Example)
|
assert.Equal(t, fp.Schema().Example, fbsref.Schema().Example)
|
||||||
|
|
||||||
byte := schemas["Byte"]
|
byte := schemas.GetOrZero("Byte")
|
||||||
uint64 := schemas["UInt64"]
|
uint64 := schemas.GetOrZero("UInt64")
|
||||||
|
|
||||||
assert.Equal(t, uint64.Schema().Format, byte.Schema().Format)
|
assert.Equal(t, uint64.Schema().Format, byte.Schema().Format)
|
||||||
assert.Equal(t, uint64.Schema().Type, byte.Schema().Type)
|
assert.Equal(t, uint64.Schema().Type, byte.Schema().Type)
|
||||||
@@ -674,7 +671,8 @@ components:
|
|||||||
example:
|
example:
|
||||||
"4578152156": Not Started
|
"4578152156": Not Started
|
||||||
"5678904321": On Hold
|
"5678904321": On Hold
|
||||||
type: object`
|
type: object
|
||||||
|
`
|
||||||
|
|
||||||
doc, err := NewDocument([]byte(d))
|
doc, err := NewDocument([]byte(d))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -689,7 +687,7 @@ components:
|
|||||||
// render the document.
|
// render the document.
|
||||||
rend, _ := result.Model.Render()
|
rend, _ := result.Model.Render()
|
||||||
|
|
||||||
assert.Len(t, rend, 644)
|
assert.Equal(t, d, string(rend))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_OperationsAsRefs(t *testing.T) {
|
func TestDocument_OperationsAsRefs(t *testing.T) {
|
||||||
@@ -897,12 +895,11 @@ func TestDocument_Render_PreserveOrder(t *testing.T) {
|
|||||||
require.Equal(t, pathCount, orderedmap.Len(pathItems))
|
require.Equal(t, pathCount, orderedmap.Len(pathItems))
|
||||||
|
|
||||||
var i int
|
var i int
|
||||||
_ = orderedmap.For(model.Model.Paths.PathItems, func(pair orderedmap.Pair[string, *v3high.PathItem]) error {
|
for pair := orderedmap.First(model.Model.Paths.PathItems); pair != nil; pair = pair.Next() {
|
||||||
pathName := fmt.Sprintf("/foobar/%d", i)
|
pathName := fmt.Sprintf("/foobar/%d", i)
|
||||||
assert.Equal(t, pathName, pair.Key())
|
assert.Equal(t, pathName, pair.Key())
|
||||||
i++
|
i++
|
||||||
return nil
|
}
|
||||||
})
|
|
||||||
assert.Equal(t, pathCount, i)
|
assert.Equal(t, pathCount, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,11 @@ func (o *wrapOrderedMap[K, V]) First() Pair[K, V] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsZero is required to support `omitempty` tag for YAML/JSON marshaling.
|
||||||
|
func (o *wrapOrderedMap[K, V]) IsZero() bool {
|
||||||
|
return o.Len() == 0
|
||||||
|
}
|
||||||
|
|
||||||
func (p *wrapPair[K, V]) Next() Pair[K, V] {
|
func (p *wrapPair[K, V]) Next() Pair[K, V] {
|
||||||
next := p.Pair.Next()
|
next := p.Pair.Next()
|
||||||
if next == nil {
|
if next == nil {
|
||||||
@@ -140,23 +145,13 @@ func ToOrderedMap[K comparable, V any](m map[K]V) Map[K, V] {
|
|||||||
return om
|
return om
|
||||||
}
|
}
|
||||||
|
|
||||||
// For iterates a `Map` and calls action() on each map pair.
|
// First returns map's first pair for iteration.
|
||||||
// action() may return `io.EOF` to break iteration.
|
|
||||||
// Safely handles nil pointer.
|
// Safely handles nil pointer.
|
||||||
func For[K comparable, V any](m Map[K, V], action ActionFunc[K, V]) error {
|
func First[K comparable, V any](m Map[K, V]) Pair[K, V] {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
if m == nil {
|
||||||
defer cancel()
|
|
||||||
c := Iterate(ctx, m)
|
|
||||||
for pair := range c {
|
|
||||||
err := action(pair)
|
|
||||||
if err == io.EOF {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
return m.First()
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TranslateMapParallel iterates a `Map` in parallel and calls translate()
|
// TranslateMapParallel iterates a `Map` in parallel and calls translate()
|
||||||
|
|||||||
@@ -159,68 +159,6 @@ func TestMap(t *testing.T) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("For()", func(t *testing.T) {
|
|
||||||
const mapSize = 10
|
|
||||||
|
|
||||||
t.Run("Nil pointer", func(t *testing.T) {
|
|
||||||
var m orderedmap.Map[string, int]
|
|
||||||
err := orderedmap.For(m, func(_ orderedmap.Pair[string, int]) error {
|
|
||||||
return errors.New("Expected no data")
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Empty", func(t *testing.T) {
|
|
||||||
m := orderedmap.New[string, int]()
|
|
||||||
err := orderedmap.For(m, func(_ orderedmap.Pair[string, int]) error {
|
|
||||||
return errors.New("Expected no data")
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Full iteration", func(t *testing.T) {
|
|
||||||
m := orderedmap.New[string, int]()
|
|
||||||
for i := 0; i < mapSize; i++ {
|
|
||||||
m.Set(fmt.Sprintf("key%d", i), i+1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
var i int
|
|
||||||
err := orderedmap.For(m, func(pair orderedmap.Pair[string, int]) error {
|
|
||||||
assert.Equal(t, fmt.Sprintf("key%d", i), pair.Key())
|
|
||||||
assert.Equal(t, fmt.Sprintf("key%d", i), *pair.KeyPtr())
|
|
||||||
assert.Equal(t, i+1000, pair.Value())
|
|
||||||
assert.Equal(t, i+1000, *pair.ValuePtr())
|
|
||||||
i++
|
|
||||||
require.LessOrEqual(t, i, mapSize)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, mapSize, i)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Partial iteration", func(t *testing.T) {
|
|
||||||
m := orderedmap.New[string, int]()
|
|
||||||
for i := 0; i < mapSize; i++ {
|
|
||||||
m.Set(fmt.Sprintf("key%d", i), i+1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
var i int
|
|
||||||
err := orderedmap.For(m, func(pair orderedmap.Pair[string, int]) error {
|
|
||||||
assert.Equal(t, fmt.Sprintf("key%d", i), pair.Key())
|
|
||||||
assert.Equal(t, fmt.Sprintf("key%d", i), *pair.KeyPtr())
|
|
||||||
assert.Equal(t, i+1000, pair.Value())
|
|
||||||
assert.Equal(t, i+1000, *pair.ValuePtr())
|
|
||||||
i++
|
|
||||||
if i >= mapSize/2 {
|
|
||||||
return io.EOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, mapSize/2, i)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TranslateMapParallel()", func(t *testing.T) {
|
t.Run("TranslateMapParallel()", func(t *testing.T) {
|
||||||
const mapSize = 1000
|
const mapSize = 1000
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ package renderer
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExampleMockGenerator_generateBurgerMock_yaml() {
|
func ExampleMockGenerator_generateBurgerMock_yaml() {
|
||||||
@@ -21,7 +22,7 @@ func ExampleMockGenerator_generateBurgerMock_yaml() {
|
|||||||
v3Model, _ := document.BuildV3Model()
|
v3Model, _ := document.BuildV3Model()
|
||||||
|
|
||||||
// create a mock of the Burger model
|
// create a mock of the Burger model
|
||||||
burgerModel := v3Model.Model.Components.Schemas["Burger"]
|
burgerModel := v3Model.Model.Components.Schemas.GetOrZero("Burger")
|
||||||
burger := burgerModel.Schema()
|
burger := burgerModel.Schema()
|
||||||
mock, err := mg.GenerateMock(burger, "")
|
mock, err := mg.GenerateMock(burger, "")
|
||||||
|
|
||||||
@@ -45,7 +46,7 @@ func ExampleMockGenerator_generateFriesMock_json() {
|
|||||||
v3Model, _ := document.BuildV3Model()
|
v3Model, _ := document.BuildV3Model()
|
||||||
|
|
||||||
// create a mock of the Fries model
|
// create a mock of the Fries model
|
||||||
friesModel := v3Model.Model.Components.Schemas["Fries"]
|
friesModel := v3Model.Model.Components.Schemas.GetOrZero("Fries")
|
||||||
fries := friesModel.Schema()
|
fries := friesModel.Schema()
|
||||||
mock, err := mg.GenerateMock(fries, "")
|
mock, err := mg.GenerateMock(fries, "")
|
||||||
|
|
||||||
@@ -68,7 +69,8 @@ func ExampleMockGenerator_generateRequestMock_json() {
|
|||||||
v3Model, _ := document.BuildV3Model()
|
v3Model, _ := document.BuildV3Model()
|
||||||
|
|
||||||
// create a mock of the burger request model, extracted from the operation directly.
|
// create a mock of the burger request model, extracted from the operation directly.
|
||||||
burgerRequestModel := v3Model.Model.Paths.PathItems["/burgers"].Post.RequestBody.Content["application/json"]
|
burgerRequestModel := v3Model.Model.Paths.PathItems.GetOrZero("/burgers").
|
||||||
|
Post.RequestBody.Content.GetOrZero("application/json")
|
||||||
|
|
||||||
// use the 'cakeBurger' example to generate a mock
|
// use the 'cakeBurger' example to generate a mock
|
||||||
mock, err := mg.GenerateMock(burgerRequestModel, "cakeBurger")
|
mock, err := mg.GenerateMock(burgerRequestModel, "cakeBurger")
|
||||||
@@ -92,7 +94,8 @@ func ExampleMockGenerator_generateResponseMock_json() {
|
|||||||
v3Model, _ := document.BuildV3Model()
|
v3Model, _ := document.BuildV3Model()
|
||||||
|
|
||||||
// create a mock of the burger response model, extracted from the operation directly.
|
// create a mock of the burger response model, extracted from the operation directly.
|
||||||
burgerResponseModel := v3Model.Model.Paths.PathItems["/burgers"].Post.Responses.Codes["200"].Content["application/json"]
|
burgerResponseModel := v3Model.Model.Paths.PathItems.GetOrZero("/burgers").
|
||||||
|
Post.Responses.Codes.GetOrZero("200").Content.GetOrZero("application/json")
|
||||||
|
|
||||||
// use the 'filetOFish' example to generate a mock
|
// use the 'filetOFish' example to generate a mock
|
||||||
mock, err := mg.GenerateMock(burgerResponseModel, "filetOFish")
|
mock, err := mg.GenerateMock(burgerResponseModel, "filetOFish")
|
||||||
@@ -116,7 +119,7 @@ func ExampleMockGenerator_generatePolymorphicMock_json() {
|
|||||||
v3Model, _ := document.BuildV3Model()
|
v3Model, _ := document.BuildV3Model()
|
||||||
|
|
||||||
// create a mock of the SomePayload component, which uses polymorphism (incorrectly)
|
// create a mock of the SomePayload component, which uses polymorphism (incorrectly)
|
||||||
payloadModel := v3Model.Model.Components.Schemas["SomePayload"]
|
payloadModel := v3Model.Model.Components.Schemas.GetOrZero("SomePayload")
|
||||||
payload := payloadModel.Schema()
|
payload := payloadModel.Schema()
|
||||||
mock, err := mg.GenerateMock(payload, "")
|
mock, err := mg.GenerateMock(payload, "")
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,16 @@ import (
|
|||||||
cryptoRand "crypto/rand"
|
cryptoRand "crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/lucasjones/reggen"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/lucasjones/reggen"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
const rootType = "rootType"
|
const rootType = "rootType"
|
||||||
@@ -217,16 +219,17 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
if properties != nil {
|
if properties != nil {
|
||||||
// check if this schema has required properties, if so, then only render required props, if not
|
// check if this schema has required properties, if so, then only render required props, if not
|
||||||
// render everything in the schema.
|
// render everything in the schema.
|
||||||
checkProps := make(map[string]*base.SchemaProxy)
|
checkProps := orderedmap.New[string, *base.SchemaProxy]()
|
||||||
if len(schema.Required) > 0 {
|
if len(schema.Required) > 0 {
|
||||||
for _, requiredProp := range schema.Required {
|
for _, requiredProp := range schema.Required {
|
||||||
checkProps[requiredProp] = properties[requiredProp]
|
checkProps.Set(requiredProp, properties.GetOrZero(requiredProp))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
checkProps = properties
|
checkProps = properties
|
||||||
}
|
}
|
||||||
for propName, propValue := range checkProps {
|
for pair := orderedmap.First(checkProps); pair != nil; pair = pair.Next() {
|
||||||
// render property
|
// render property
|
||||||
|
propName, propValue := pair.Key(), pair.Value()
|
||||||
propertySchema := propValue.Schema()
|
propertySchema := propValue.Schema()
|
||||||
wr.DiveIntoSchema(propertySchema, propName, propertyMap, depth+1)
|
wr.DiveIntoSchema(propertySchema, propName, propertyMap, depth+1)
|
||||||
}
|
}
|
||||||
@@ -249,8 +252,9 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
|||||||
dependentSchemas := schema.DependentSchemas
|
dependentSchemas := schema.DependentSchemas
|
||||||
if dependentSchemas != nil {
|
if dependentSchemas != nil {
|
||||||
dependentSchemasMap := make(map[string]any)
|
dependentSchemasMap := make(map[string]any)
|
||||||
for k, dependentSchema := range dependentSchemas {
|
for pair := orderedmap.First(dependentSchemas); pair != nil; pair = pair.Next() {
|
||||||
// only map if the property exists
|
// only map if the property exists
|
||||||
|
k, dependentSchema := pair.Key(), pair.Value()
|
||||||
if propertyMap[k] != nil {
|
if propertyMap[k] != nil {
|
||||||
dependentSchemaCompiled := dependentSchema.Schema()
|
dependentSchemaCompiled := dependentSchema.Schema()
|
||||||
wr.DiveIntoSchema(dependentSchemaCompiled, k, dependentSchemasMap, depth+1)
|
wr.DiveIntoSchema(dependentSchemaCompiled, k, dependentSchemasMap, depth+1)
|
||||||
|
|||||||
@@ -8,17 +8,18 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRenderSchema(t *testing.T) {
|
func TestRenderSchema(t *testing.T) {
|
||||||
@@ -1144,7 +1145,7 @@ properties:
|
|||||||
loopMe = func(parent *highbase.SchemaProxy, level int) {
|
loopMe = func(parent *highbase.SchemaProxy, level int) {
|
||||||
schemaProxy := buildSchema()
|
schemaProxy := buildSchema()
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
parent.Schema().Properties["child"] = schemaProxy
|
parent.Schema().Properties.Set("child", schemaProxy)
|
||||||
}
|
}
|
||||||
if level < 110 {
|
if level < 110 {
|
||||||
loopMe(schemaProxy, level+1)
|
loopMe(schemaProxy, level+1)
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CallbackChanges represents all changes made between two Callback OpenAPI objects.
|
// CallbackChanges represents all changes made between two Callback OpenAPI objects.
|
||||||
@@ -65,14 +66,14 @@ func CompareCallback(l, r *v3.Callback) *CallbackChanges {
|
|||||||
lValues := make(map[string]low.ValueReference[*v3.PathItem])
|
lValues := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
rValues := make(map[string]low.ValueReference[*v3.PathItem])
|
rValues := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
|
|
||||||
for k := range l.Expression.Value {
|
for pair := orderedmap.First(l.Expression.Value); pair != nil; pair = pair.Next() {
|
||||||
lHashes[k.Value] = low.GenerateHashString(l.Expression.Value[k].Value)
|
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
lValues[k.Value] = l.Expression.Value[k]
|
lValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range r.Expression.Value {
|
for pair := orderedmap.First(r.Expression.Value); pair != nil; pair = pair.Next() {
|
||||||
rHashes[k.Value] = low.GenerateHashString(r.Expression.Value[k].Value)
|
rHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
rValues[k.Value] = r.Expression.Value[k]
|
rValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
expChanges := make(map[string]*PathItemChanges)
|
expChanges := make(map[string]*PathItemChanges)
|
||||||
|
|||||||
@@ -5,11 +5,13 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -235,12 +237,12 @@ func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Chan
|
|||||||
|
|
||||||
// CheckMapForChanges checks a left and right low level map for any additions, subtractions or modifications to
|
// CheckMapForChanges checks a left and right low level map for any additions, subtractions or modifications to
|
||||||
// values. The compareFunc argument should reference the correct comparison function for the generic type.
|
// values. The compareFunc argument should reference the correct comparison function for the generic type.
|
||||||
func CheckMapForChanges[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
|
func CheckMapForChanges[T any, R any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
|
||||||
changes *[]*Change, label string, compareFunc func(l, r T) R) map[string]R {
|
changes *[]*Change, label string, compareFunc func(l, r T) R) map[string]R {
|
||||||
return CheckMapForChangesWithComp(expLeft, expRight, changes, label, compareFunc, true)
|
return CheckMapForChangesWithComp(expLeft, expRight, changes, label, compareFunc, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckMapForAdditionRemoval[T any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
|
func CheckMapForAdditionRemoval[T any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
|
||||||
changes *[]*Change, label string) any {
|
changes *[]*Change, label string) any {
|
||||||
// do nothing
|
// do nothing
|
||||||
doNothing := func(l, r T) any {
|
doNothing := func(l, r T) any {
|
||||||
@@ -263,7 +265,7 @@ func CheckMapForAdditionRemoval[T any](expLeft, expRight map[low.KeyReference[st
|
|||||||
// CheckMapForChangesWithComp checks a left and right low level map for any additions, subtractions or modifications to
|
// CheckMapForChangesWithComp checks a left and right low level map for any additions, subtractions or modifications to
|
||||||
// values. The compareFunc argument should reference the correct comparison function for the generic type. The compare
|
// values. The compareFunc argument should reference the correct comparison function for the generic type. The compare
|
||||||
// bit determines if the comparison should be run or not.
|
// bit determines if the comparison should be run or not.
|
||||||
func CheckMapForChangesWithComp[T any, R any](expLeft, expRight map[low.KeyReference[string]]low.ValueReference[T],
|
func CheckMapForChangesWithComp[T any, R any](expLeft, expRight orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
|
||||||
changes *[]*Change, label string, compareFunc func(l, r T) R, compare bool) map[string]R {
|
changes *[]*Change, label string, compareFunc func(l, r T) R, compare bool) map[string]R {
|
||||||
|
|
||||||
// stop concurrent threads screwing up changes.
|
// stop concurrent threads screwing up changes.
|
||||||
@@ -274,14 +276,16 @@ func CheckMapForChangesWithComp[T any, R any](expLeft, expRight map[low.KeyRefer
|
|||||||
lValues := make(map[string]low.ValueReference[T])
|
lValues := make(map[string]low.ValueReference[T])
|
||||||
rValues := make(map[string]low.ValueReference[T])
|
rValues := make(map[string]low.ValueReference[T])
|
||||||
|
|
||||||
for k := range expLeft {
|
for pair := orderedmap.First(expLeft); pair != nil; pair = pair.Next() {
|
||||||
lHashes[k.Value] = low.GenerateHashString(expLeft[k].Value)
|
k := pair.Key()
|
||||||
lValues[k.Value] = expLeft[k]
|
lHashes[k.Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
|
lValues[k.Value] = pair.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range expRight {
|
for pair := orderedmap.First(expRight); pair != nil; pair = pair.Next() {
|
||||||
rHashes[k.Value] = low.GenerateHashString(expRight[k].Value)
|
k := pair.Key()
|
||||||
rValues[k.Value] = expRight[k]
|
rHashes[k.Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
|
rValues[k.Value] = pair.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
expChanges := make(map[string]R)
|
expChanges := make(map[string]R)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ComponentsChanges represents changes made to both OpenAPI and Swagger documents. This model is based on OpenAPI 3
|
// ComponentsChanges represents changes made to both OpenAPI and Swagger documents. This model is based on OpenAPI 3
|
||||||
@@ -55,7 +56,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
|||||||
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.ParameterDefinitions)
|
lDef := l.(*v2.ParameterDefinitions)
|
||||||
rDef := r.(*v2.ParameterDefinitions)
|
rDef := r.(*v2.ParameterDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Parameter]
|
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Parameter]]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
@@ -70,7 +71,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
|||||||
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.ResponsesDefinitions)
|
lDef := l.(*v2.ResponsesDefinitions)
|
||||||
rDef := r.(*v2.ResponsesDefinitions)
|
rDef := r.(*v2.ResponsesDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.Response]
|
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.Response]]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
|||||||
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.Definitions)
|
lDef := l.(*v2.Definitions)
|
||||||
rDef := r.(*v2.Definitions)
|
rDef := r.(*v2.Definitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]
|
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Schemas
|
a = lDef.Schemas
|
||||||
}
|
}
|
||||||
@@ -100,7 +101,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
|||||||
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
|
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
|
||||||
lDef := l.(*v2.SecurityDefinitions)
|
lDef := l.(*v2.SecurityDefinitions)
|
||||||
rDef := r.(*v2.SecurityDefinitions)
|
rDef := r.(*v2.SecurityDefinitions)
|
||||||
var a, b map[low.KeyReference[string]]low.ValueReference[*v2.SecurityScheme]
|
var a, b orderedmap.Map[low.KeyReference[string], low.ValueReference[*v2.SecurityScheme]]
|
||||||
if lDef != nil {
|
if lDef != nil {
|
||||||
a = lDef.Definitions
|
a = lDef.Definitions
|
||||||
}
|
}
|
||||||
@@ -217,7 +218,7 @@ type componentComparison struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run a generic comparison in a thread which in turn splits checks into further threads.
|
// run a generic comparison in a thread which in turn splits checks into further threads.
|
||||||
func runComparison[T any, R any](l, r map[low.KeyReference[string]]low.ValueReference[T],
|
func runComparison[T any, R any](l, r orderedmap.Map[low.KeyReference[string], low.ValueReference[T]],
|
||||||
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
|
changes *[]*Change, label string, compareFunc func(l, r T) R, doneChan chan componentComparison) {
|
||||||
|
|
||||||
// for schemas
|
// for schemas
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExamplesChanges represents changes made between Swagger Examples objects (Not OpenAPI 3).
|
// ExamplesChanges represents changes made between Swagger Examples objects (Not OpenAPI 3).
|
||||||
@@ -37,14 +38,14 @@ func CompareExamplesV2(l, r *v2.Examples) *ExamplesChanges {
|
|||||||
lValues := make(map[string]low.ValueReference[any])
|
lValues := make(map[string]low.ValueReference[any])
|
||||||
rValues := make(map[string]low.ValueReference[any])
|
rValues := make(map[string]low.ValueReference[any])
|
||||||
|
|
||||||
for k := range l.Values {
|
for pair := orderedmap.First(l.Values); pair != nil; pair = pair.Next() {
|
||||||
lHashes[k.Value] = low.GenerateHashString(l.Values[k].Value)
|
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
lValues[k.Value] = l.Values[k]
|
lValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
for k := range r.Values {
|
for pair := orderedmap.First(r.Values); pair != nil; pair = pair.Next() {
|
||||||
rHashes[k.Value] = low.GenerateHashString(r.Values[k].Value)
|
rHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||||
rValues[k.Value] = r.Values[k]
|
rValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package model
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LinkChanges represent changes made between two OpenAPI Link Objects.
|
// LinkChanges represent changes made between two OpenAPI Link Objects.
|
||||||
@@ -127,11 +128,11 @@ func CompareLinks(l, r *v3.Link) *LinkChanges {
|
|||||||
// parameters
|
// parameters
|
||||||
lValues := make(map[string]low.ValueReference[string])
|
lValues := make(map[string]low.ValueReference[string])
|
||||||
rValues := make(map[string]low.ValueReference[string])
|
rValues := make(map[string]low.ValueReference[string])
|
||||||
for i := range l.Parameters.Value {
|
for pair := orderedmap.First(l.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||||
lValues[i.Value] = l.Parameters.Value[i]
|
lValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
for i := range r.Parameters.Value {
|
for pair := orderedmap.First(r.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||||
rValues[i.Value] = r.Parameters.Value[i]
|
rValues[pair.Key().Value] = pair.Value()
|
||||||
}
|
}
|
||||||
for k := range lValues {
|
for k := range lValues {
|
||||||
if _, ok := rValues[k]; !ok {
|
if _, ok := rValues[k]; !ok {
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OAuthFlowsChanges represents changes found between two OpenAPI OAuthFlows objects.
|
// OAuthFlowsChanges represents changes found between two OpenAPI OAuthFlows objects.
|
||||||
@@ -228,26 +229,26 @@ func CompareOAuthFlow(l, r *v3.OAuthFlow) *OAuthFlowChanges {
|
|||||||
|
|
||||||
CheckProperties(props)
|
CheckProperties(props)
|
||||||
|
|
||||||
for v := range l.Scopes.Value {
|
for pair := orderedmap.First(l.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||||
if r != nil && r.FindScope(v.Value) == nil {
|
if r != nil && r.FindScope(pair.Key().Value) == nil {
|
||||||
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
||||||
l.Scopes.Value[v].ValueNode, nil, true,
|
pair.Value().ValueNode, nil, true,
|
||||||
v.Value, nil)
|
pair.Key().Value, nil)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r != nil && r.FindScope(v.Value) != nil {
|
if r != nil && r.FindScope(pair.Key().Value) != nil {
|
||||||
if l.Scopes.Value[v].Value != r.FindScope(v.Value).Value {
|
if pair.Value().Value != r.FindScope(pair.Key().Value).Value {
|
||||||
CreateChange(&changes, Modified, v3.Scopes,
|
CreateChange(&changes, Modified, v3.Scopes,
|
||||||
l.Scopes.Value[v].ValueNode, r.FindScope(v.Value).ValueNode, true,
|
pair.Value().ValueNode, r.FindScope(pair.Key().Value).ValueNode, true,
|
||||||
l.Scopes.Value[v].Value, r.FindScope(v.Value).Value)
|
pair.Value().Value, r.FindScope(pair.Key().Value).Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for v := range r.Scopes.Value {
|
for pair := orderedmap.First(r.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||||
if l != nil && l.FindScope(v.Value) == nil {
|
if l != nil && l.FindScope(pair.Key().Value) == nil {
|
||||||
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
||||||
nil, r.Scopes.Value[v].ValueNode, false,
|
nil, pair.Value().ValueNode, false,
|
||||||
nil, v.Value)
|
nil, pair.Key().Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
oa := new(OAuthFlowChanges)
|
oa := new(OAuthFlowChanges)
|
||||||
|
|||||||
@@ -77,16 +77,12 @@ func ComparePaths(l, r any) *PathsChanges {
|
|||||||
|
|
||||||
lKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
lKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
||||||
rKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
rKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
||||||
laction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2.PathItem]]) error {
|
for pair := orderedmap.First(lPath.PathItems); pair != nil; pair = pair.Next() {
|
||||||
lKeys[pair.Key().Value] = pair.Value()
|
lKeys[pair.Key().Value] = pair.Value()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v2.PathItem]](lPath.PathItems, laction)
|
for pair := orderedmap.First(rPath.PathItems); pair != nil; pair = pair.Next() {
|
||||||
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2.PathItem]]) error {
|
|
||||||
rKeys[pair.Key().Value] = pair.Value()
|
rKeys[pair.Key().Value] = pair.Value()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v2.PathItem]](rPath.PathItems, raction)
|
|
||||||
|
|
||||||
// run every comparison in a thread.
|
// run every comparison in a thread.
|
||||||
var mLock sync.Mutex
|
var mLock sync.Mutex
|
||||||
@@ -152,16 +148,12 @@ func ComparePaths(l, r any) *PathsChanges {
|
|||||||
|
|
||||||
lKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
lKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
rKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
rKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
laction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3.PathItem]]) error {
|
for pair := orderedmap.First(lPath.PathItems); pair != nil; pair = pair.Next() {
|
||||||
lKeys[pair.Key().Value] = pair.Value()
|
lKeys[pair.Key().Value] = pair.Value()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v3.PathItem]](lPath.PathItems, laction)
|
for pair := orderedmap.First(rPath.PathItems); pair != nil; pair = pair.Next() {
|
||||||
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3.PathItem]]) error {
|
|
||||||
rKeys[pair.Key().Value] = pair.Value()
|
rKeys[pair.Key().Value] = pair.Value()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v3.PathItem]](rPath.PathItems, raction)
|
|
||||||
|
|
||||||
// run every comparison in a thread.
|
// run every comparison in a thread.
|
||||||
var mLock sync.Mutex
|
var mLock sync.Mutex
|
||||||
|
|||||||
@@ -5,14 +5,15 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"golang.org/x/exp/slices"
|
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -424,7 +425,7 @@ func checkSchemaXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chan
|
|||||||
|
|
||||||
func checkMappedSchemaOfASchema(
|
func checkMappedSchemaOfASchema(
|
||||||
lSchema,
|
lSchema,
|
||||||
rSchema map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy],
|
rSchema orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]],
|
||||||
changes *[]*Change,
|
changes *[]*Change,
|
||||||
doneChan chan bool,
|
doneChan chan bool,
|
||||||
) (map[string]*SchemaChanges, int) {
|
) (map[string]*SchemaChanges, int) {
|
||||||
@@ -437,15 +438,15 @@ func checkMappedSchemaOfASchema(
|
|||||||
rEntities := make(map[string]*base.SchemaProxy)
|
rEntities := make(map[string]*base.SchemaProxy)
|
||||||
rKeyNodes := make(map[string]*yaml.Node)
|
rKeyNodes := make(map[string]*yaml.Node)
|
||||||
|
|
||||||
for w := range lSchema {
|
for pair := orderedmap.First(lSchema); pair != nil; pair = pair.Next() {
|
||||||
lProps = append(lProps, w.Value)
|
lProps = append(lProps, pair.Key().Value)
|
||||||
lEntities[w.Value] = lSchema[w].Value
|
lEntities[pair.Key().Value] = pair.Value().Value
|
||||||
lKeyNodes[w.Value] = w.KeyNode
|
lKeyNodes[pair.Key().Value] = pair.Key().KeyNode
|
||||||
}
|
}
|
||||||
for w := range rSchema {
|
for pair := orderedmap.First(rSchema); pair != nil; pair = pair.Next() {
|
||||||
rProps = append(rProps, w.Value)
|
rProps = append(rProps, pair.Key().Value)
|
||||||
rEntities[w.Value] = rSchema[w].Value
|
rEntities[pair.Key().Value] = pair.Value().Value
|
||||||
rKeyNodes[w.Value] = w.KeyNode
|
rKeyNodes[pair.Key().Value] = pair.Key().KeyNode
|
||||||
}
|
}
|
||||||
sort.Strings(lProps)
|
sort.Strings(lProps)
|
||||||
sort.Strings(rProps)
|
sort.Strings(rProps)
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ package model
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ScopesChanges represents changes between two Swagger Scopes Objects
|
// ScopesChanges represents changes between two Swagger Scopes Objects
|
||||||
@@ -46,26 +47,26 @@ func CompareScopes(l, r *v2.Scopes) *ScopesChanges {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var changes []*Change
|
var changes []*Change
|
||||||
for v := range l.Values {
|
for pair := orderedmap.First(l.Values); pair != nil; pair = pair.Next() {
|
||||||
if r != nil && r.FindScope(v.Value) == nil {
|
if r != nil && r.FindScope(pair.Key().Value) == nil {
|
||||||
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
||||||
l.Values[v].ValueNode, nil, true,
|
pair.Value().ValueNode, nil, true,
|
||||||
v.Value, nil)
|
pair.Key().Value, nil)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r != nil && r.FindScope(v.Value) != nil {
|
if r != nil && r.FindScope(pair.Key().Value) != nil {
|
||||||
if l.Values[v].Value != r.FindScope(v.Value).Value {
|
if pair.Value().Value != r.FindScope(pair.Key().Value).Value {
|
||||||
CreateChange(&changes, Modified, v3.Scopes,
|
CreateChange(&changes, Modified, v3.Scopes,
|
||||||
l.Values[v].ValueNode, r.FindScope(v.Value).ValueNode, true,
|
pair.Value().ValueNode, r.FindScope(pair.Key().Value).ValueNode, true,
|
||||||
l.Values[v].Value, r.FindScope(v.Value).Value)
|
pair.Value().Value, r.FindScope(pair.Key().Value).Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for v := range r.Values {
|
for pair := orderedmap.First(r.Values); pair != nil; pair = pair.Next() {
|
||||||
if l != nil && l.FindScope(v.Value) == nil {
|
if l != nil && l.FindScope(pair.Key().Value) == nil {
|
||||||
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
||||||
nil, r.Values[v].ValueNode, false,
|
nil, pair.Value().ValueNode, false,
|
||||||
nil, v.Value)
|
nil, pair.Key().Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ package model
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,22 +57,22 @@ func addedSecurityRequirement(vn *yaml.Node, name string, changes *[]*Change) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tricky to do this correctly, this is my solution.
|
// tricky to do this correctly, this is my solution.
|
||||||
func checkSecurityRequirement(lSec, rSec map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]],
|
func checkSecurityRequirement(lSec, rSec orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]],
|
||||||
changes *[]*Change) {
|
changes *[]*Change) {
|
||||||
|
|
||||||
lKeys := make([]string, len(lSec))
|
lKeys := make([]string, orderedmap.Len(lSec))
|
||||||
rKeys := make([]string, len(rSec))
|
rKeys := make([]string, orderedmap.Len(rSec))
|
||||||
lValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
lValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
||||||
rValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
rValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
||||||
var n, z int
|
var n, z int
|
||||||
for i := range lSec {
|
for pair := orderedmap.First(lSec); pair != nil; pair = pair.Next() {
|
||||||
lKeys[n] = i.Value
|
lKeys[n] = pair.Key().Value
|
||||||
lValues[i.Value] = lSec[i]
|
lValues[pair.Key().Value] = pair.Value()
|
||||||
n++
|
n++
|
||||||
}
|
}
|
||||||
for i := range rSec {
|
for pair := orderedmap.First(rSec); pair != nil; pair = pair.Next() {
|
||||||
rKeys[z] = i.Value
|
rKeys[z] = pair.Key().Value
|
||||||
rValues[i.Value] = rSec[i]
|
rValues[pair.Key().Value] = pair.Value()
|
||||||
z++
|
z++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user