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"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"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.
|
||||
// no fidelity is lost, everything is still available via GoLow()
|
||||
func ExtractExamples(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Example]) map[string]*Example {
|
||||
extracted := make(map[string]*Example)
|
||||
for k, v := range elements {
|
||||
extracted[k.Value] = NewExample(v.Value)
|
||||
func ExtractExamples(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Example]]) orderedmap.Map[string, *Example] {
|
||||
extracted := orderedmap.New[string, *Example]()
|
||||
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||
extracted.Set(pair.Key().Value, NewExample(pair.Value().Value))
|
||||
}
|
||||
return extracted
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ package base
|
||||
|
||||
import (
|
||||
"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"
|
||||
"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) {
|
||||
@@ -61,14 +63,13 @@ func TestExtractExamples(t *testing.T) {
|
||||
|
||||
_ = lowExample.Build(nil, cNode.Content[0], nil)
|
||||
|
||||
examplesMap := make(map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*lowbase.Example])
|
||||
examplesMap[lowmodel.KeyReference[string]{
|
||||
Value: "green",
|
||||
}] = lowmodel.ValueReference[*lowbase.Example]{
|
||||
Value: &lowExample,
|
||||
}
|
||||
examplesMap := orderedmap.New[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.Example]]()
|
||||
examplesMap.Set(
|
||||
lowmodel.KeyReference[string]{Value: "green"},
|
||||
lowmodel.ValueReference[*lowbase.Example]{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"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -50,16 +51,16 @@ type Schema struct {
|
||||
PrefixItems []*SchemaProxy `json:"prefixItems,omitempty" yaml:"prefixItems,omitempty"`
|
||||
|
||||
// 3.1 Specific properties
|
||||
Contains *SchemaProxy `json:"contains,omitempty" yaml:"contains,omitempty"`
|
||||
MinContains *int64 `json:"minContains,omitempty" yaml:"minContains,omitempty"`
|
||||
MaxContains *int64 `json:"maxContains,omitempty" yaml:"maxContains,omitempty"`
|
||||
If *SchemaProxy `json:"if,omitempty" yaml:"if,omitempty"`
|
||||
Else *SchemaProxy `json:"else,omitempty" yaml:"else,omitempty"`
|
||||
Then *SchemaProxy `json:"then,omitempty" yaml:"then,omitempty"`
|
||||
DependentSchemas map[string]*SchemaProxy `json:"dependentSchemas,omitempty" yaml:"dependentSchemas,omitempty"`
|
||||
PatternProperties map[string]*SchemaProxy `json:"patternProperties,omitempty" yaml:"patternProperties,omitempty"`
|
||||
PropertyNames *SchemaProxy `json:"propertyNames,omitempty" yaml:"propertyNames,omitempty"`
|
||||
UnevaluatedItems *SchemaProxy `json:"unevaluatedItems,omitempty" yaml:"unevaluatedItems,omitempty"`
|
||||
Contains *SchemaProxy `json:"contains,omitempty" yaml:"contains,omitempty"`
|
||||
MinContains *int64 `json:"minContains,omitempty" yaml:"minContains,omitempty"`
|
||||
MaxContains *int64 `json:"maxContains,omitempty" yaml:"maxContains,omitempty"`
|
||||
If *SchemaProxy `json:"if,omitempty" yaml:"if,omitempty"`
|
||||
Else *SchemaProxy `json:"else,omitempty" yaml:"else,omitempty"`
|
||||
Then *SchemaProxy `json:"then,omitempty" yaml:"then,omitempty"`
|
||||
DependentSchemas orderedmap.Map[string, *SchemaProxy] `json:"dependentSchemas,omitempty" yaml:"dependentSchemas,omitempty"`
|
||||
PatternProperties orderedmap.Map[string, *SchemaProxy] `json:"patternProperties,omitempty" yaml:"patternProperties,omitempty"`
|
||||
PropertyNames *SchemaProxy `json:"propertyNames,omitempty" yaml:"propertyNames,omitempty"`
|
||||
UnevaluatedItems *SchemaProxy `json:"unevaluatedItems,omitempty" yaml:"unevaluatedItems,omitempty"`
|
||||
|
||||
// in 3.1 UnevaluatedProperties can be a Schema or a boolean
|
||||
// https://github.com/pb33f/libopenapi/issues/118
|
||||
@@ -72,35 +73,35 @@ type Schema struct {
|
||||
Anchor string `json:"$anchor,omitempty" yaml:"$anchor,omitempty"`
|
||||
|
||||
// Compatible with all versions
|
||||
Not *SchemaProxy `json:"not,omitempty" yaml:"not,omitempty"`
|
||||
Properties map[string]*SchemaProxy `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
||||
Maximum *float64 `json:"maximum,omitempty" yaml:"maximum,omitempty"`
|
||||
Minimum *float64 `json:"minimum,omitempty" yaml:"minimum,omitempty"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
|
||||
MinLength *int64 `json:"minLength,omitempty" yaml:"minLength,omitempty"`
|
||||
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty" yaml:"maxItems,omitempty"`
|
||||
MinItems *int64 `json:"minItems,omitempty" yaml:"minItems,omitempty"`
|
||||
UniqueItems *bool `json:"uniqueItems,omitempty" yaml:"uniqueItems,omitempty"`
|
||||
MaxProperties *int64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
|
||||
MinProperties *int64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Enum []any `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
AdditionalProperties any `json:"additionalProperties,omitempty" yaml:"additionalProperties,renderZero,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Default any `json:"default,omitempty" yaml:"default,renderZero,omitempty"`
|
||||
Const any `json:"const,omitempty" yaml:"const,renderZero,omitempty"`
|
||||
Nullable *bool `json:"nullable,omitempty" yaml:"nullable,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"` // https://github.com/pb33f/libopenapi/issues/30
|
||||
WriteOnly bool `json:"writeOnly,omitempty" yaml:"writeOnly,omitempty"` // https://github.com/pb33f/libopenapi/issues/30
|
||||
XML *XML `json:"xml,omitempty" yaml:"xml,omitempty"`
|
||||
ExternalDocs *ExternalDoc `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Not *SchemaProxy `json:"not,omitempty" yaml:"not,omitempty"`
|
||||
Properties orderedmap.Map[string, *SchemaProxy] `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
||||
Maximum *float64 `json:"maximum,omitempty" yaml:"maximum,omitempty"`
|
||||
Minimum *float64 `json:"minimum,omitempty" yaml:"minimum,omitempty"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
|
||||
MinLength *int64 `json:"minLength,omitempty" yaml:"minLength,omitempty"`
|
||||
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
||||
Format string `json:"format,omitempty" yaml:"format,omitempty"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty" yaml:"maxItems,omitempty"`
|
||||
MinItems *int64 `json:"minItems,omitempty" yaml:"minItems,omitempty"`
|
||||
UniqueItems *bool `json:"uniqueItems,omitempty" yaml:"uniqueItems,omitempty"`
|
||||
MaxProperties *int64 `json:"maxProperties,omitempty" yaml:"maxProperties,omitempty"`
|
||||
MinProperties *int64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Enum []any `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||
AdditionalProperties any `json:"additionalProperties,omitempty" yaml:"additionalProperties,renderZero,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Default any `json:"default,omitempty" yaml:"default,renderZero,omitempty"`
|
||||
Const any `json:"const,omitempty" yaml:"const,renderZero,omitempty"`
|
||||
Nullable *bool `json:"nullable,omitempty" yaml:"nullable,omitempty"`
|
||||
ReadOnly bool `json:"readOnly,omitempty" yaml:"readOnly,omitempty"` // https://github.com/pb33f/libopenapi/issues/30
|
||||
WriteOnly bool `json:"writeOnly,omitempty" yaml:"writeOnly,omitempty"` // https://github.com/pb33f/libopenapi/issues/30
|
||||
XML *XML `json:"xml,omitempty" yaml:"xml,omitempty"`
|
||||
ExternalDocs *ExternalDoc `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *base.Schema
|
||||
|
||||
// Parent Proxy refers back to the low level SchemaProxy that is proxying this schema.
|
||||
@@ -356,14 +357,13 @@ func NewSchema(schema *base.Schema) *Schema {
|
||||
|
||||
// props async
|
||||
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,
|
||||
KeyNode: k.KeyNode,
|
||||
ValueNode: v.ValueNode,
|
||||
},
|
||||
)
|
||||
}))
|
||||
|
||||
switch sw {
|
||||
case 0:
|
||||
@@ -375,18 +375,18 @@ func NewSchema(schema *base.Schema) *Schema {
|
||||
}
|
||||
}
|
||||
|
||||
props := make(map[string]*SchemaProxy)
|
||||
for k, v := range schema.Properties.Value {
|
||||
buildProps(k, v, props, 0)
|
||||
props := orderedmap.New[string, *SchemaProxy]()
|
||||
for pair := orderedmap.First(schema.Properties.Value); pair != nil; pair = pair.Next() {
|
||||
buildProps(pair.Key(), pair.Value(), props, 0)
|
||||
}
|
||||
|
||||
dependents := make(map[string]*SchemaProxy)
|
||||
for k, v := range schema.DependentSchemas.Value {
|
||||
buildProps(k, v, dependents, 1)
|
||||
dependents := orderedmap.New[string, *SchemaProxy]()
|
||||
for pair := orderedmap.First(schema.DependentSchemas.Value); pair != nil; pair = pair.Next() {
|
||||
buildProps(pair.Key(), pair.Value(), dependents, 1)
|
||||
}
|
||||
patternProps := make(map[string]*SchemaProxy)
|
||||
for k, v := range schema.PatternProperties.Value {
|
||||
buildProps(k, v, patternProps, 2)
|
||||
patternProps := orderedmap.New[string, *SchemaProxy]()
|
||||
for pair := orderedmap.First(schema.PatternProperties.Value); pair != nil; pair = pair.Next() {
|
||||
buildProps(pair.Key(), pair.Value(), patternProps, 2)
|
||||
}
|
||||
|
||||
var allOf []*SchemaProxy
|
||||
|
||||
@@ -303,8 +303,8 @@ $anchor: anchor`
|
||||
assert.Equal(t, "string", compiled.If.Schema().Type[0])
|
||||
assert.Equal(t, "integer", compiled.Else.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.DependentSchemas["schemaOne"].Schema().Type[0])
|
||||
assert.Equal(t, "string", compiled.PatternProperties.GetOrZero("patternOne").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, "boolean", compiled.UnevaluatedItems.Schema().Type[0])
|
||||
assert.Equal(t, "integer", compiled.UnevaluatedProperties.A.Schema().Type[0])
|
||||
@@ -416,7 +416,7 @@ anyOf:
|
||||
anyOfB:
|
||||
type: string
|
||||
description: anyOfB description
|
||||
example: 'anyOfBExp'
|
||||
example: 'anyOfBExp'
|
||||
not:
|
||||
type: object
|
||||
description: a not thing
|
||||
@@ -428,7 +428,7 @@ not:
|
||||
notB:
|
||||
type: string
|
||||
description: notB description
|
||||
example: 'notBExp'
|
||||
example: 'notBExp'
|
||||
items:
|
||||
type: object
|
||||
description: an items thing
|
||||
@@ -454,7 +454,7 @@ properties:
|
||||
somethingBProp:
|
||||
exclusiveMinimum: 3
|
||||
exclusiveMaximum: 120
|
||||
type:
|
||||
type:
|
||||
- string
|
||||
- null
|
||||
description: something b subprop
|
||||
@@ -466,9 +466,9 @@ properties:
|
||||
attribute: true
|
||||
wrapped: false
|
||||
x-pizza: love
|
||||
additionalProperties:
|
||||
additionalProperties:
|
||||
why: yes
|
||||
thatIs: true
|
||||
thatIs: true
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: nice
|
||||
@@ -500,9 +500,9 @@ required: [cake, fish]`
|
||||
assert.Nil(t, schemaProxy.GetBuildError())
|
||||
|
||||
assert.True(t, compiled.ExclusiveMaximum.A)
|
||||
assert.Equal(t, float64(123), compiled.Properties["somethingB"].Schema().ExclusiveMinimum.B)
|
||||
assert.Equal(t, float64(334), compiled.Properties["somethingB"].Schema().ExclusiveMaximum.B)
|
||||
assert.Len(t, compiled.Properties["somethingB"].Schema().Properties["somethingBProp"].Schema().Type, 2)
|
||||
assert.Equal(t, float64(123), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMinimum.B)
|
||||
assert.Equal(t, float64(334), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMaximum.B)
|
||||
assert.Len(t, compiled.Properties.GetOrZero("somethingB").Schema().Properties.GetOrZero("somethingBProp").Schema().Type, 2)
|
||||
|
||||
assert.Equal(t, "nice", compiled.AdditionalProperties.(*SchemaProxy).Schema().Description)
|
||||
|
||||
@@ -734,7 +734,7 @@ properties:
|
||||
highSchema := NewSchema(&lowSchema)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -765,7 +765,7 @@ properties:
|
||||
})
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// 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
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
type SecurityRequirement struct {
|
||||
Requirements map[string][]string `json:"-" yaml:"-"`
|
||||
Requirements orderedmap.Map[string, []string] `json:"-" yaml:"-"`
|
||||
low *base.SecurityRequirement
|
||||
}
|
||||
|
||||
@@ -27,14 +29,14 @@ type SecurityRequirement struct {
|
||||
func NewSecurityRequirement(req *base.SecurityRequirement) *SecurityRequirement {
|
||||
r := new(SecurityRequirement)
|
||||
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.
|
||||
for reqK := range req.Requirements.Value {
|
||||
for pair := orderedmap.First(req.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||
var vals []string
|
||||
for valK := range req.Requirements.Value[reqK].Value {
|
||||
vals = append(vals, req.Requirements.Value[reqK].Value[valK].Value)
|
||||
for valK := range pair.Value().Value {
|
||||
vals = append(vals, pair.Value().Value[valK].Value)
|
||||
}
|
||||
values[reqK.Value] = vals
|
||||
values.Set(pair.Key().Value, vals)
|
||||
}
|
||||
r.Requirements = values
|
||||
return r
|
||||
@@ -67,24 +69,23 @@ func (s *SecurityRequirement) MarshalYAML() (interface{}, error) {
|
||||
}
|
||||
|
||||
m := utils.CreateEmptyMapNode()
|
||||
keys := make([]*req, len(s.Requirements))
|
||||
keys := make([]*req, orderedmap.Len(s.Requirements))
|
||||
|
||||
i := 0
|
||||
|
||||
for k := range s.Requirements {
|
||||
keys[i] = &req{key: k, val: s.Requirements[k]}
|
||||
for pair := orderedmap.First(s.Requirements); pair != nil; pair = pair.Next() {
|
||||
keys[i] = &req{key: pair.Key(), val: pair.Value()}
|
||||
i++
|
||||
}
|
||||
i = 0
|
||||
if s.low != nil {
|
||||
for o := range keys {
|
||||
kv := keys[o].key
|
||||
for k := range s.low.Requirements.Value {
|
||||
if k.Value == kv {
|
||||
gh := s.low.Requirements.Value[k]
|
||||
keys[o].line = k.KeyNode.Line
|
||||
keys[o].lowKey = &k
|
||||
keys[o].lowVal = &gh
|
||||
for pair := orderedmap.First(s.low.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == kv {
|
||||
keys[o].line = pair.Key().KeyNode.Line
|
||||
keys[o].lowKey = pair.KeyPtr()
|
||||
keys[o].lowVal = pair.ValuePtr()
|
||||
}
|
||||
i++
|
||||
}
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
package base
|
||||
|
||||
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"
|
||||
"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) {
|
||||
@@ -32,11 +34,11 @@ cake:
|
||||
|
||||
highExt := NewSecurityRequirement(&lowExt)
|
||||
|
||||
assert.Len(t, highExt.Requirements["pizza"], 2)
|
||||
assert.Len(t, highExt.Requirements["cake"], 2)
|
||||
assert.Len(t, highExt.Requirements.GetOrZero("pizza"), 2)
|
||||
assert.Len(t, highExt.Requirements.GetOrZero("cake"), 2)
|
||||
|
||||
wentLow := highExt.GoLow()
|
||||
assert.Len(t, wentLow.Requirements.Value, 2)
|
||||
assert.Equal(t, 2, orderedmap.Len(wentLow.Requirements.Value))
|
||||
assert.NotNil(t, highExt.GoLowUntyped())
|
||||
|
||||
// render the high-level object as YAML
|
||||
|
||||
@@ -5,14 +5,15 @@ package high
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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 {
|
||||
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"
|
||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
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.
|
||||
@@ -16,7 +17,7 @@ import (
|
||||
// arrays or models.
|
||||
// - https://swagger.io/specification/v2/#definitionsObject
|
||||
type Definitions struct {
|
||||
Definitions map[string]*highbase.SchemaProxy
|
||||
Definitions orderedmap.Map[string, *highbase.SchemaProxy]
|
||||
low *low.Definitions
|
||||
}
|
||||
|
||||
@@ -24,12 +25,20 @@ type Definitions struct {
|
||||
func NewDefinitions(definitions *low.Definitions) *Definitions {
|
||||
rd := new(Definitions)
|
||||
rd.low = definitions
|
||||
defs := make(map[string]*highbase.SchemaProxy)
|
||||
for k := range definitions.Schemas {
|
||||
defs[k.Value] = highbase.NewSchemaProxy(&lowmodel.NodeReference[*lowbase.SchemaProxy]{
|
||||
Value: definitions.Schemas[k].Value,
|
||||
})
|
||||
defs := orderedmap.New[string, *highbase.SchemaProxy]()
|
||||
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.SchemaProxy]]) (asyncResult[*highbase.SchemaProxy], error) {
|
||||
return asyncResult[*highbase.SchemaProxy]{
|
||||
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
|
||||
return rd
|
||||
}
|
||||
|
||||
@@ -3,13 +3,16 @@
|
||||
|
||||
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.
|
||||
// Allows sharing examples for operation responses
|
||||
// - https://swagger.io/specification/v2/#exampleObject
|
||||
type Example struct {
|
||||
Values map[string]any
|
||||
Values orderedmap.Map[string, any]
|
||||
low *low.Examples
|
||||
}
|
||||
|
||||
@@ -17,10 +20,10 @@ type Example struct {
|
||||
func NewExample(examples *low.Examples) *Example {
|
||||
e := new(Example)
|
||||
e.low = examples
|
||||
if len(examples.Values) > 0 {
|
||||
values := make(map[string]any)
|
||||
for k := range examples.Values {
|
||||
values[k.Value] = examples.Values[k].Value
|
||||
if orderedmap.Len(examples.Values) > 0 {
|
||||
values := orderedmap.New[string, any]()
|
||||
for pair := orderedmap.First(examples.Values); pair != nil; pair = pair.Next() {
|
||||
values.Set(pair.Key().Value, pair.Value().Value)
|
||||
}
|
||||
e.Values = values
|
||||
}
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
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
|
||||
// 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
|
||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||
type ParameterDefinitions struct {
|
||||
Definitions map[string]*Parameter
|
||||
Definitions orderedmap.Map[string, *Parameter]
|
||||
low *low.ParameterDefinitions
|
||||
}
|
||||
|
||||
@@ -21,26 +25,18 @@ type ParameterDefinitions struct {
|
||||
func NewParametersDefinitions(parametersDefinitions *low.ParameterDefinitions) *ParameterDefinitions {
|
||||
pd := new(ParameterDefinitions)
|
||||
pd.low = parametersDefinitions
|
||||
params := make(map[string]*Parameter)
|
||||
var buildParam = func(name string, param *low.Parameter, rChan chan<- asyncResult[*Parameter]) {
|
||||
rChan <- asyncResult[*Parameter]{
|
||||
key: name,
|
||||
result: NewParameter(param),
|
||||
}
|
||||
params := orderedmap.New[string, *Parameter]()
|
||||
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Parameter]]) (asyncResult[*Parameter], error) {
|
||||
return asyncResult[*Parameter]{
|
||||
key: pair.Key().Value,
|
||||
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
|
||||
return pd
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
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.
|
||||
@@ -15,7 +16,7 @@ import (
|
||||
type Response struct {
|
||||
Description string
|
||||
Schema *base.SchemaProxy
|
||||
Headers map[string]*Header
|
||||
Headers orderedmap.Map[string, *Header]
|
||||
Examples *Example
|
||||
Extensions map[string]any
|
||||
low *low.Response
|
||||
@@ -33,9 +34,9 @@ func NewResponse(response *low.Response) *Response {
|
||||
r.Schema = base.NewSchemaProxy(&response.Schema)
|
||||
}
|
||||
if !response.Headers.IsEmpty() {
|
||||
headers := make(map[string]*Header)
|
||||
for k := range response.Headers.Value {
|
||||
headers[k.Value] = NewHeader(response.Headers.Value[k].Value)
|
||||
headers := orderedmap.New[string, *Header]()
|
||||
for pair := orderedmap.First(response.Headers.Value); pair != nil; pair = pair.Next() {
|
||||
headers.Set(pair.Key().Value, NewHeader(pair.Value().Value))
|
||||
}
|
||||
r.Headers = headers
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ package v2
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
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.
|
||||
type Responses struct {
|
||||
Codes map[string]*Response
|
||||
Codes orderedmap.Map[string, *Response]
|
||||
Default *Response
|
||||
Extensions map[string]any
|
||||
low *low.Responses
|
||||
@@ -22,36 +24,26 @@ func NewResponses(responses *low.Responses) *Responses {
|
||||
r.low = responses
|
||||
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() {
|
||||
r.Default = NewResponse(responses.Default.Value)
|
||||
}
|
||||
|
||||
// run everything async. lots of responses with lots of data are possible.
|
||||
if len(responses.Codes) > 0 {
|
||||
resultChan := make(chan asyncResult[*Response])
|
||||
for k := range responses.Codes {
|
||||
go buildPath(k.Value, responses.Codes[k].Value, resultChan)
|
||||
if orderedmap.Len(responses.Codes) > 0 {
|
||||
resp := 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
|
||||
}
|
||||
resp := make(map[string]*Response)
|
||||
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
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
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.
|
||||
// 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
|
||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||
type ResponsesDefinitions struct {
|
||||
Definitions map[string]*Response
|
||||
Definitions orderedmap.Map[string, *Response]
|
||||
low *low.ResponsesDefinitions
|
||||
}
|
||||
|
||||
@@ -20,28 +24,19 @@ type ResponsesDefinitions struct {
|
||||
func NewResponsesDefinitions(responsesDefinitions *low.ResponsesDefinitions) *ResponsesDefinitions {
|
||||
rd := new(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.
|
||||
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
|
||||
}
|
||||
}
|
||||
_ = orderedmap.TranslateMapParallel(responsesDefinitions.Definitions, translateFunc, resultFunc)
|
||||
rd.Definitions = responses
|
||||
return rd
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package v2
|
||||
|
||||
import (
|
||||
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.
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
// Scopes lists the available scopes for an OAuth2 security scheme.
|
||||
// - https://swagger.io/specification/v2/#scopesObject
|
||||
type Scopes struct {
|
||||
Values map[string]string
|
||||
Values orderedmap.Map[string, string]
|
||||
low *low.Scopes
|
||||
}
|
||||
|
||||
@@ -20,9 +21,9 @@ type Scopes struct {
|
||||
func NewScopes(scopes *low.Scopes) *Scopes {
|
||||
s := new(Scopes)
|
||||
s.low = scopes
|
||||
scopeValues := make(map[string]string)
|
||||
for k := range scopes.Values {
|
||||
scopeValues[k.Value] = scopes.Values[k].Value
|
||||
scopeValues := orderedmap.New[string, string]()
|
||||
for pair := orderedmap.First(scopes.Values); pair != nil; pair = pair.Next() {
|
||||
scopeValues.Set(pair.Key().Value, pair.Value().Value)
|
||||
}
|
||||
s.Values = scopeValues
|
||||
return s
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
|
||||
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
|
||||
// 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
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
type SecurityDefinitions struct {
|
||||
Definitions map[string]*SecurityScheme
|
||||
Definitions orderedmap.Map[string, *SecurityScheme]
|
||||
low *low.SecurityDefinitions
|
||||
}
|
||||
|
||||
@@ -20,10 +24,23 @@ type SecurityDefinitions struct {
|
||||
func NewSecurityDefinitions(definitions *low.SecurityDefinitions) *SecurityDefinitions {
|
||||
sd := new(SecurityDefinitions)
|
||||
sd.low = definitions
|
||||
schemes := make(map[string]*SecurityScheme)
|
||||
for k := range definitions.Definitions {
|
||||
schemes[k.Value] = NewSecurityScheme(definitions.Definitions[k].Value)
|
||||
schemes := orderedmap.New[string, *SecurityScheme]()
|
||||
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.SecurityScheme]]) (asyncResult[*SecurityScheme], error) {
|
||||
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
|
||||
return sd
|
||||
}
|
||||
|
||||
@@ -173,9 +173,3 @@ func NewSwaggerDocument(document *low.Swagger) *Swagger {
|
||||
func (s *Swagger) GoLow() *low.Swagger {
|
||||
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 (
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"io/ioutil"
|
||||
@@ -80,17 +81,17 @@ func TestNewSwaggerDocument_Parameters(t *testing.T) {
|
||||
initTest()
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
params := highDoc.Parameters
|
||||
assert.Len(t, params.Definitions, 1)
|
||||
assert.Equal(t, "query", params.Definitions["simpleParam"].In)
|
||||
assert.Equal(t, "simple", params.Definitions["simpleParam"].Name)
|
||||
assert.Equal(t, "string", params.Definitions["simpleParam"].Type)
|
||||
assert.Equal(t, "nuggets", params.Definitions["simpleParam"].Extensions["x-chicken"])
|
||||
assert.Equal(t, 1, orderedmap.Len(params.Definitions))
|
||||
assert.Equal(t, "query", params.Definitions.GetOrZero("simpleParam").In)
|
||||
assert.Equal(t, "simple", params.Definitions.GetOrZero("simpleParam").Name)
|
||||
assert.Equal(t, "string", params.Definitions.GetOrZero("simpleParam").Type)
|
||||
assert.Equal(t, "nuggets", params.Definitions.GetOrZero("simpleParam").Extensions["x-chicken"])
|
||||
|
||||
wentLow := params.GoLow()
|
||||
assert.Equal(t, 20, wentLow.FindParameter("simpleParam").ValueNode.Line)
|
||||
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, 11, wentLower.Name.ValueNode.Column)
|
||||
|
||||
@@ -100,7 +101,7 @@ func TestNewSwaggerDocument_Security(t *testing.T) {
|
||||
initTest()
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
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()
|
||||
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) {
|
||||
initTest()
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
assert.Len(t, highDoc.SecurityDefinitions.Definitions, 3)
|
||||
assert.Equal(t, "oauth2", highDoc.SecurityDefinitions.Definitions["petstore_auth"].Type)
|
||||
assert.Equal(t, 3, orderedmap.Len(highDoc.SecurityDefinitions.Definitions))
|
||||
assert.Equal(t, "oauth2", highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Type)
|
||||
assert.Equal(t, "https://petstore.swagger.io/oauth/authorize",
|
||||
highDoc.SecurityDefinitions.Definitions["petstore_auth"].AuthorizationUrl)
|
||||
assert.Equal(t, "implicit", highDoc.SecurityDefinitions.Definitions["petstore_auth"].Flow)
|
||||
assert.Len(t, highDoc.SecurityDefinitions.Definitions["petstore_auth"].Scopes.Values, 2)
|
||||
highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").AuthorizationUrl)
|
||||
assert.Equal(t, "implicit", highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Flow)
|
||||
assert.Equal(t, 2, orderedmap.Len(highDoc.SecurityDefinitions.Definitions.GetOrZero("petstore_auth").Scopes.Values))
|
||||
|
||||
goLow := highDoc.SecurityDefinitions.GoLow()
|
||||
|
||||
assert.Equal(t, 661, goLow.FindSecurityDefinition("petstore_auth").ValueNode.Line)
|
||||
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, 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, 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) {
|
||||
initTest()
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
assert.Len(t, highDoc.Responses.Definitions, 2)
|
||||
assert.Equal(t, 2, orderedmap.Len(highDoc.Responses.Definitions))
|
||||
|
||||
defs := highDoc.Responses.Definitions
|
||||
assert.Equal(t, "morning", defs["200"].Extensions["x-coffee"])
|
||||
assert.Equal(t, "OK", defs["200"].Description)
|
||||
assert.Equal(t, "morning", defs.GetOrZero("200").Extensions["x-coffee"])
|
||||
assert.Equal(t, "OK", defs.GetOrZero("200").Description)
|
||||
assert.Equal(t, "a generic API response object",
|
||||
defs["200"].Schema.Schema().Description)
|
||||
assert.Len(t, defs["200"].Examples.Values, 3)
|
||||
defs.GetOrZero("200").Schema.Schema().Description)
|
||||
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.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.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)
|
||||
|
||||
expWentLow := defs["200"].Examples.GoLow()
|
||||
expWentLow := defs.GetOrZero("200").Examples.GoLow()
|
||||
assert.Equal(t, 702, expWentLow.FindExample("application/json").ValueNode.Line)
|
||||
assert.Equal(t, 9, expWentLow.FindExample("application/json").ValueNode.Column)
|
||||
|
||||
wentLow := highDoc.Responses.GoLow()
|
||||
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)
|
||||
x := y.Items
|
||||
|
||||
@@ -192,7 +193,7 @@ func TestNewSwaggerDocument_Definitions(t *testing.T) {
|
||||
initTest()
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
|
||||
assert.Len(t, highDoc.Definitions.Definitions, 6)
|
||||
assert.Equal(t, 6, orderedmap.Len(highDoc.Definitions.Definitions))
|
||||
|
||||
wentLow := highDoc.Definitions.GoLow()
|
||||
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) {
|
||||
initTest()
|
||||
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")
|
||||
assert.Equal(t, "man", upload.Extensions["x-potato"])
|
||||
@@ -264,9 +265,9 @@ func TestNewSwaggerDocument_Responses(t *testing.T) {
|
||||
highDoc := NewSwaggerDocument(doc)
|
||||
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, "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
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// Callback represents a high-level Callback object for OpenAPI 3+.
|
||||
@@ -19,8 +21,8 @@ import (
|
||||
// that identifies a URL to use for the callback operation.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
||||
type Callback struct {
|
||||
Expression map[string]*PathItem `json:"-" yaml:"-"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Expression orderedmap.Map[string, *PathItem] `json:"-" yaml:"-"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Callback
|
||||
}
|
||||
|
||||
@@ -28,9 +30,9 @@ type Callback struct {
|
||||
func NewCallback(lowCallback *low.Callback) *Callback {
|
||||
n := new(Callback)
|
||||
n.low = lowCallback
|
||||
n.Expression = make(map[string]*PathItem)
|
||||
for i := range lowCallback.Expression.Value {
|
||||
n.Expression[i.Value] = NewPathItem(lowCallback.Expression.Value[i].Value)
|
||||
n.Expression = orderedmap.New[string, *PathItem]()
|
||||
for pair := orderedmap.First(lowCallback.Expression.Value); pair != nil; pair = pair.Next() {
|
||||
n.Expression.Set(pair.Key().Value, NewPathItem(pair.Value().Value))
|
||||
}
|
||||
n.Extensions = make(map[string]any)
|
||||
for k, v := range lowCallback.Extensions {
|
||||
@@ -66,16 +68,16 @@ func (c *Callback) MarshalYAML() (interface{}, error) {
|
||||
}
|
||||
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.
|
||||
if c.low != nil {
|
||||
for lKey := range c.low.Expression.Value {
|
||||
if lKey.Value == k {
|
||||
ln = lKey.KeyNode.Line
|
||||
for lPair := orderedmap.First(c.low.Expression.Value); lPair != nil; lPair = lPair.Next() {
|
||||
if lPair.Key().Value == pair.Key() {
|
||||
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
|
||||
|
||||
@@ -4,19 +4,21 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCallback_MarshalYAML(t *testing.T) {
|
||||
|
||||
cb := &Callback{
|
||||
Expression: map[string]*PathItem{
|
||||
Expression: orderedmap.ToOrderedMap(map[string]*PathItem{
|
||||
"https://pb33f.io": {
|
||||
Get: &Operation{
|
||||
OperationId: "oneTwoThree",
|
||||
@@ -27,7 +29,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
||||
OperationId: "openaypeeeye",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
Extensions: map[string]any{
|
||||
"x-burgers": "why not?",
|
||||
},
|
||||
@@ -39,7 +41,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
||||
assert.Len(t, rend, 152)
|
||||
|
||||
// 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!"}
|
||||
|
||||
rend, _ = cb.Render()
|
||||
|
||||
@@ -6,12 +6,12 @@ package v3
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -21,16 +21,16 @@ import (
|
||||
// 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
|
||||
type Components struct {
|
||||
Schemas map[string]*highbase.SchemaProxy `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||
Responses map[string]*Response `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Parameters map[string]*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Examples map[string]*highbase.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
RequestBodies map[string]*RequestBody `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
SecuritySchemes map[string]*SecurityScheme `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||
Links map[string]*Link `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Callbacks map[string]*Callback `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Schemas orderedmap.Map[string, *highbase.SchemaProxy] `json:"schemas,omitempty" yaml:"schemas,omitempty"`
|
||||
Responses orderedmap.Map[string, *Response] `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Parameters orderedmap.Map[string, *Parameter] `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
Examples orderedmap.Map[string, *highbase.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
RequestBodies orderedmap.Map[string, *RequestBody] `json:"requestBodies,omitempty" yaml:"requestBodies,omitempty"`
|
||||
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
SecuritySchemes orderedmap.Map[string, *SecurityScheme] `json:"securitySchemes,omitempty" yaml:"securitySchemes,omitempty"`
|
||||
Links orderedmap.Map[string, *Link] `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Callbacks orderedmap.Map[string, *Callback] `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Components
|
||||
}
|
||||
|
||||
@@ -43,15 +43,15 @@ func NewComponents(comp *low.Components) *Components {
|
||||
if len(comp.Extensions) > 0 {
|
||||
c.Extensions = high.ExtractExtensions(comp.Extensions)
|
||||
}
|
||||
cbMap := make(map[string]*Callback)
|
||||
linkMap := make(map[string]*Link)
|
||||
responseMap := make(map[string]*Response)
|
||||
parameterMap := make(map[string]*Parameter)
|
||||
exampleMap := make(map[string]*highbase.Example)
|
||||
requestBodyMap := make(map[string]*RequestBody)
|
||||
headerMap := make(map[string]*Header)
|
||||
securitySchemeMap := make(map[string]*SecurityScheme)
|
||||
schemas := make(map[string]*highbase.SchemaProxy)
|
||||
cbMap := orderedmap.New[string, *Callback]()
|
||||
linkMap := orderedmap.New[string, *Link]()
|
||||
responseMap := orderedmap.New[string, *Response]()
|
||||
parameterMap := orderedmap.New[string, *Parameter]()
|
||||
exampleMap := orderedmap.New[string, *highbase.Example]()
|
||||
requestBodyMap := orderedmap.New[string, *RequestBody]()
|
||||
headerMap := orderedmap.New[string, *Header]()
|
||||
securitySchemeMap := orderedmap.New[string, *SecurityScheme]()
|
||||
schemas := orderedmap.New[string, *highbase.SchemaProxy]()
|
||||
|
||||
// build all components asynchronously.
|
||||
var wg sync.WaitGroup
|
||||
@@ -114,32 +114,33 @@ type componentResult[T any] struct {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[IN]) (componentResult[OUT], error) {
|
||||
return componentResult[OUT]{key: key.Value, res: translateItem(value.Value)}, nil
|
||||
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(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[IN]]) (componentResult[OUT], error) {
|
||||
return componentResult[OUT]{key: pair.Key().Value, res: translateItem(pair.Value().Value)}, nil
|
||||
}
|
||||
resultFunc := func(value componentResult[OUT]) error {
|
||||
outMap[value.key] = value.res
|
||||
outMap.Set(value.key, value.res)
|
||||
return nil
|
||||
}
|
||||
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||
_ = orderedmap.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||
}
|
||||
|
||||
// buildSchema builds a schema from low level structs.
|
||||
func buildSchema(inMap map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*base.SchemaProxy], outMap map[string]*highbase.SchemaProxy) {
|
||||
translateFunc := func(key lowmodel.KeyReference[string], value lowmodel.ValueReference[*base.SchemaProxy]) (componentResult[*highbase.SchemaProxy], error) {
|
||||
func buildSchema(inMap orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*base.SchemaProxy]], outMap orderedmap.Map[string, *highbase.SchemaProxy]) {
|
||||
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*base.SchemaProxy]]) (componentResult[*highbase.SchemaProxy], error) {
|
||||
value := pair.Value()
|
||||
var sch *highbase.SchemaProxy
|
||||
sch = highbase.NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||
Value: value.Value,
|
||||
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 {
|
||||
outMap[value.key] = value.res
|
||||
outMap.Set(value.key, value.res)
|
||||
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.
|
||||
|
||||
@@ -4,38 +4,40 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestComponents_MarshalYAML(t *testing.T) {
|
||||
|
||||
comp := &Components{
|
||||
Responses: map[string]*Response{
|
||||
Responses: orderedmap.ToOrderedMap(map[string]*Response{
|
||||
"200": {
|
||||
Description: "OK",
|
||||
},
|
||||
},
|
||||
Parameters: map[string]*Parameter{
|
||||
}),
|
||||
Parameters: orderedmap.ToOrderedMap(map[string]*Parameter{
|
||||
"id": {
|
||||
Name: "id",
|
||||
In: "path",
|
||||
},
|
||||
},
|
||||
RequestBodies: map[string]*RequestBody{
|
||||
}),
|
||||
RequestBodies: orderedmap.ToOrderedMap(map[string]*RequestBody{
|
||||
"body": {
|
||||
Content: map[string]*MediaType{
|
||||
Content: orderedmap.ToOrderedMap(map[string]*MediaType{
|
||||
"application/json": {
|
||||
Example: "why?",
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
}
|
||||
|
||||
dat, _ := comp.Render()
|
||||
|
||||
@@ -11,10 +11,12 @@ package v3
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"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,
|
||||
// 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.
|
||||
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
|
||||
// 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
|
||||
}
|
||||
if !document.Webhooks.IsEmpty() {
|
||||
hooks := make(map[string]*PathItem)
|
||||
for h := range document.Webhooks.Value {
|
||||
hooks[h.Value] = NewPathItem(document.Webhooks.Value[h].Value)
|
||||
hooks := orderedmap.New[string, *PathItem]()
|
||||
for pair := orderedmap.First(document.Webhooks.Value); pair != nil; pair = pair.Next() {
|
||||
hooks.Set(pair.Key().Value, NewPathItem(pair.Value().Value))
|
||||
}
|
||||
d.Webhooks = hooks
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestNewDocument_Security(t *testing.T) {
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Security, 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) {
|
||||
@@ -98,14 +98,14 @@ func TestNewDocument_Servers(t *testing.T) {
|
||||
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.Len(t, h.Servers[0].Variables, 1)
|
||||
assert.Equal(t, "https", h.Servers[0].Variables["scheme"].Default)
|
||||
assert.Len(t, h.Servers[0].Variables["scheme"].Enum, 2)
|
||||
assert.Equal(t, "https", h.Servers[0].Variables.GetOrZero("scheme").Default)
|
||||
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, "this is our second API server, for all fun API things.", h.Servers[1].Description)
|
||||
assert.Len(t, h.Servers[1].Variables, 2)
|
||||
assert.Equal(t, "api", h.Servers[1].Variables["domain"].Default)
|
||||
assert.Equal(t, "pb33f.io", h.Servers[1].Variables["host"].Default)
|
||||
assert.Equal(t, "api", h.Servers[1].Variables.GetOrZero("domain").Default)
|
||||
assert.Equal(t, "pb33f.io", h.Servers[1].Variables.GetOrZero("host").Default)
|
||||
|
||||
wentLow := h.GoLow()
|
||||
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, 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, 22, wentLowest.Description.ValueNode.Column)
|
||||
}
|
||||
@@ -147,18 +147,18 @@ func TestNewDocument_Tags(t *testing.T) {
|
||||
func TestNewDocument_Webhooks(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Webhooks, 1)
|
||||
assert.Equal(t, "Information about a new burger", h.Webhooks["someHook"].Post.RequestBody.Description)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Webhooks))
|
||||
assert.Equal(t, "Information about a new burger", h.Webhooks.GetOrZero("someHook").Post.RequestBody.Description)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Links(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Links, 2)
|
||||
assert.Equal(t, "locateBurger", h.Components.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, "$response.body#/id", h.Components.Links["LocateBurger"].Parameters["burgerId"])
|
||||
assert.Equal(t, 2, orderedmap.Len(h.Components.Links))
|
||||
assert.Equal(t, "locateBurger", h.Components.Links.GetOrZero("LocateBurger").OperationId)
|
||||
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, 20, wentLow.OperationId.ValueNode.Column)
|
||||
}
|
||||
@@ -166,29 +166,29 @@ func TestNewDocument_Components_Links(t *testing.T) {
|
||||
func TestNewDocument_Components_Callbacks(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Callbacks, 1)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Components.Callbacks))
|
||||
assert.Equal(
|
||||
t,
|
||||
"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(
|
||||
t,
|
||||
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(
|
||||
t,
|
||||
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 {
|
||||
if k.Value == "BurgerCallback" {
|
||||
assert.Equal(t, 295, k.KeyNode.Line)
|
||||
assert.Equal(t, 5, k.KeyNode.Column)
|
||||
for pair := orderedmap.First(h.Components.GoLow().Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == "BurgerCallback" {
|
||||
assert.Equal(t, 295, pair.Key().KeyNode.Line)
|
||||
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) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Schemas, 6)
|
||||
assert.Equal(t, 6, orderedmap.Len(h.Components.Schemas))
|
||||
|
||||
goLow := h.Components.GoLow()
|
||||
|
||||
a := h.Components.Schemas["Error"]
|
||||
abcd := a.Schema().Properties["message"].Schema().Example
|
||||
a := h.Components.Schemas.GetOrZero("Error")
|
||||
abcd := a.Schema().Properties.GetOrZero("message").Schema().Example
|
||||
assert.Equal(t, "No such burger as 'Big-Whopper'", abcd)
|
||||
assert.Equal(t, 433, goLow.Schemas.KeyNode.Line)
|
||||
assert.Equal(t, 3, goLow.Schemas.KeyNode.Column)
|
||||
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.Equal(t, "golden slices of happy fun joy", b.Schema().Properties["fries"].Schema().Description)
|
||||
assert.Equal(t, int64(2), b.Schema().Properties["numPatties"].Schema().Example)
|
||||
assert.Equal(t, "golden slices of happy fun joy", b.Schema().Properties.GetOrZero("fries").Schema().Description)
|
||||
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, 7, goLow.FindSchema("Burger").Value.Schema().Properties.KeyNode.Column)
|
||||
assert.Equal(t, 450, b.Schema().GoLow().FindProperty("name").ValueNode.Line)
|
||||
|
||||
f := h.Components.Schemas["Fries"]
|
||||
assert.Equal(t, "salt", f.Schema().Properties["seasoning"].Schema().Items.A.Schema().Example)
|
||||
assert.Len(t, f.Schema().Properties["favoriteDrink"].Schema().Properties["drinkType"].Schema().Enum, 1)
|
||||
f := h.Components.Schemas.GetOrZero("Fries")
|
||||
assert.Equal(t, "salt", f.Schema().Properties.GetOrZero("seasoning").Schema().Items.A.Schema().Example)
|
||||
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.True(t, d.Schema().AdditionalProperties.(bool))
|
||||
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, 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, 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) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Headers, 1)
|
||||
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers["UseOil"].Description)
|
||||
assert.Equal(t, 323, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.Headers["UseOil"].GoLow().Description.ValueNode.Column)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Components.Headers))
|
||||
assert.Equal(t, "this is a header example for UseOil", h.Components.Headers.GetOrZero("UseOil").Description)
|
||||
assert.Equal(t, 323, h.Components.Headers.GetOrZero("UseOil").GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.Headers.GetOrZero("UseOil").GoLow().Description.ValueNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_RequestBodies(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.RequestBodies, 1)
|
||||
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies["BurgerRequest"].Description)
|
||||
assert.Equal(t, 328, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.RequestBodies["BurgerRequest"].GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, h.Components.RequestBodies["BurgerRequest"].Content["application/json"].Examples, 2)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Components.RequestBodies))
|
||||
assert.Equal(t, "Give us the new burger!", h.Components.RequestBodies.GetOrZero("BurgerRequest").Description)
|
||||
assert.Equal(t, 328, h.Components.RequestBodies.GetOrZero("BurgerRequest").GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, h.Components.RequestBodies.GetOrZero("BurgerRequest").GoLow().Description.ValueNode.Column)
|
||||
assert.Equal(t, 2, orderedmap.Len(h.Components.RequestBodies.GetOrZero("BurgerRequest").Content.GetOrZero("application/json").Examples))
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Examples(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Examples, 1)
|
||||
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples["QuarterPounder"].Summary)
|
||||
assert.Equal(t, 346, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Line)
|
||||
assert.Equal(t, 16, h.Components.Examples["QuarterPounder"].GoLow().Summary.ValueNode.Column)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Components.Examples))
|
||||
assert.Equal(t, "A juicy two hander sammich", h.Components.Examples.GetOrZero("QuarterPounder").Summary)
|
||||
assert.Equal(t, 346, h.Components.Examples.GetOrZero("QuarterPounder").GoLow().Summary.ValueNode.Line)
|
||||
assert.Equal(t, 16, h.Components.Examples.GetOrZero("QuarterPounder").GoLow().Summary.ValueNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_Responses(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Responses, 1)
|
||||
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses["DressingResponse"].Description)
|
||||
assert.Equal(t, "array", h.Components.Responses["DressingResponse"].Content["application/json"].Schema.Schema().Type[0])
|
||||
assert.Equal(t, 352, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Line)
|
||||
assert.Equal(t, 7, h.Components.Responses["DressingResponse"].GoLow().Description.KeyNode.Column)
|
||||
assert.Equal(t, 1, orderedmap.Len(h.Components.Responses))
|
||||
assert.Equal(t, "all the dressings for a burger.", h.Components.Responses.GetOrZero("DressingResponse").Description)
|
||||
assert.Equal(t, "array", h.Components.Responses.GetOrZero("DressingResponse").Content.GetOrZero("application/json").Schema.Schema().Type[0])
|
||||
assert.Equal(t, 352, h.Components.Responses.GetOrZero("DressingResponse").GoLow().Description.KeyNode.Line)
|
||||
assert.Equal(t, 7, h.Components.Responses.GetOrZero("DressingResponse").GoLow().Description.KeyNode.Column)
|
||||
}
|
||||
|
||||
func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
||||
initTest()
|
||||
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, 364, api.GoLow().Description.ValueNode.Line)
|
||||
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, 369, jwt.GoLow().Description.ValueNode.Line)
|
||||
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, 375, oAuth.GoLow().Description.ValueNode.Line)
|
||||
assert.Equal(t, 20, oAuth.GoLow().Description.ValueNode.Column)
|
||||
assert.Len(t, oAuth.Flows.Implicit.Scopes, 2)
|
||||
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes["read:burgers"])
|
||||
assert.Equal(t, 2, orderedmap.Len(oAuth.Flows.Implicit.Scopes))
|
||||
assert.Equal(t, "read all burgers", oAuth.Flows.Implicit.Scopes.GetOrZero("read:burgers"))
|
||||
assert.Equal(t, "https://pb33f.io/oauth", oAuth.Flows.AuthorizationCode.AuthorizationUrl)
|
||||
|
||||
// check the lowness is low.
|
||||
@@ -306,26 +306,26 @@ func TestNewDocument_Components_SecuritySchemes(t *testing.T) {
|
||||
func TestNewDocument_Components_Parameters(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Components.Parameters, 2)
|
||||
bh := h.Components.Parameters["BurgerHeader"]
|
||||
assert.Equal(t, 2, orderedmap.Len(h.Components.Parameters))
|
||||
bh := h.Components.Parameters.GetOrZero("BurgerHeader")
|
||||
assert.Equal(t, "burgerHeader", bh.Name)
|
||||
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.True(t, bh.Required)
|
||||
assert.Equal(
|
||||
t,
|
||||
"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, 409, bh.Content["application/json"].Encoding["burgerTheme"].GoLow().ContentType.ValueNode.Line)
|
||||
assert.Equal(t, 2, orderedmap.Len(bh.Content.GetOrZero("application/json").Schema.Schema().Properties))
|
||||
assert.Equal(t, 409, bh.Content.GetOrZero("application/json").Encoding.GetOrZero("burgerTheme").GoLow().ContentType.ValueNode.Line)
|
||||
}
|
||||
|
||||
func TestNewDocument_Paths(t *testing.T) {
|
||||
initTest()
|
||||
h := NewDocument(lowDoc)
|
||||
assert.Len(t, h.Paths.PathItems, 5)
|
||||
assert.Equal(t, 5, orderedmap.Len(h.Paths.PathItems))
|
||||
|
||||
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.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.Len(t, burgersOp.Post.Responses.Codes, 3)
|
||||
assert.Equal(t, 3, orderedmap.Len(burgersOp.Post.Responses.Codes))
|
||||
if checkLines {
|
||||
assert.Equal(t, 64, burgersOp.GoLow().Post.KeyNode.Line)
|
||||
assert.Equal(t, 63, h.Paths.GoLow().FindPath("/burgers").ValueNode.Line)
|
||||
}
|
||||
|
||||
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.Len(t, okResp.Content["application/json"].Examples, 2)
|
||||
assert.Equal(t, 2, orderedmap.Len(okResp.Content.GetOrZero("application/json").Examples))
|
||||
assert.Equal(
|
||||
t,
|
||||
"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, "locateBurger", okResp.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, 2, orderedmap.Len(okResp.Links))
|
||||
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["OAuthScheme"], 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements["OAuthScheme"][0])
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements.GetOrZero("OAuthScheme"), 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements.GetOrZero("OAuthScheme")[0])
|
||||
assert.Len(t, burgersOp.Post.Servers, 1)
|
||||
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
||||
|
||||
if checkLines {
|
||||
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, 80, okResp.Content["application/json"].GoLow().Schema.KeyNode.Line)
|
||||
assert.Equal(t, 15, okResp.Content["application/json"].GoLow().Schema.KeyNode.Column)
|
||||
assert.Equal(t, 80, okResp.Content.GetOrZero("application/json").GoLow().Schema.KeyNode.Line)
|
||||
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, 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)
|
||||
}
|
||||
|
||||
@@ -534,7 +534,7 @@ func TestDocument_MarshalJSON(t *testing.T) {
|
||||
newDoc := NewDocument(lowDoc)
|
||||
|
||||
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) {
|
||||
@@ -711,8 +711,8 @@ components:
|
||||
h := NewDocument(lowDoc)
|
||||
|
||||
// mutate the schema
|
||||
g := h.Components.Schemas["BurgerHeader"].Schema()
|
||||
ds := g.Properties["burgerTheme"].Schema()
|
||||
g := h.Components.Schemas.GetOrZero("BurgerHeader").Schema()
|
||||
ds := g.Properties.GetOrZero("burgerTheme").Schema()
|
||||
ds.Description = "changed"
|
||||
|
||||
// render the document to YAML and it should be identical.
|
||||
|
||||
@@ -7,17 +7,18 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Encoding represents an OpenAPI 3+ Encoding object
|
||||
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
||||
type Encoding struct {
|
||||
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
ContentType string `json:"contentType,omitempty" yaml:"contentType,omitempty"`
|
||||
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
low *low.Encoding
|
||||
}
|
||||
|
||||
@@ -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
|
||||
func ExtractEncoding(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Encoding]) map[string]*Encoding {
|
||||
extracted := make(map[string]*Encoding)
|
||||
for k, v := range elements {
|
||||
extracted[k.Value] = NewEncoding(v.Value)
|
||||
func ExtractEncoding(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Encoding]]) orderedmap.Map[string, *Encoding] {
|
||||
extracted := orderedmap.New[string, *Encoding]()
|
||||
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||
extracted.Set(pair.Key().Value, NewEncoding(pair.Value().Value))
|
||||
}
|
||||
return extracted
|
||||
}
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEncoding_MarshalYAML(t *testing.T) {
|
||||
@@ -14,9 +16,11 @@ func TestEncoding_MarshalYAML(t *testing.T) {
|
||||
explode := true
|
||||
encoding := &Encoding{
|
||||
ContentType: "application/json",
|
||||
Headers: map[string]*Header{"x-pizza-time": {Description: "oh yes please"}},
|
||||
Style: "simple",
|
||||
Explode: &explode,
|
||||
Headers: orderedmap.ToOrderedMap(map[string]*Header{
|
||||
"x-pizza-time": {Description: "oh yes please"},
|
||||
}),
|
||||
Style: "simple",
|
||||
Explode: &explode,
|
||||
}
|
||||
|
||||
rend, _ := encoding.Render()
|
||||
|
||||
@@ -9,24 +9,25 @@ import (
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Header represents a high-level OpenAPI 3+ Header object that is backed by a low-level one.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#header-object
|
||||
type Header struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
Schema *highbase.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*highbase.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
Schema *highbase.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples orderedmap.Map[string, *highbase.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
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.
|
||||
func ExtractHeaders(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.Header]) map[string]*Header {
|
||||
extracted := make(map[string]*Header)
|
||||
for k, v := range elements {
|
||||
extracted[k.Value] = NewHeader(v.Value)
|
||||
func ExtractHeaders(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.Header]]) orderedmap.Map[string, *Header] {
|
||||
extracted := orderedmap.New[string, *Header]()
|
||||
for pair := orderedmap.First(elements); pair != nil; pair = pair.Next() {
|
||||
extracted.Set(pair.Key().Value, NewHeader(pair.Value().Value))
|
||||
}
|
||||
return extracted
|
||||
}
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHeader_MarshalYAML(t *testing.T) {
|
||||
@@ -21,8 +23,10 @@ func TestHeader_MarshalYAML(t *testing.T) {
|
||||
Explode: true,
|
||||
AllowReserved: true,
|
||||
Example: "example",
|
||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||
"example": {Value: "example"},
|
||||
}),
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
}
|
||||
|
||||
rend, _ := header.Render()
|
||||
|
||||
@@ -6,6 +6,7 @@ package v3
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -22,13 +23,13 @@ import (
|
||||
// in an operation and using them as parameters while invoking the linked operation.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#link-object
|
||||
type Link struct {
|
||||
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
||||
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Parameters map[string]string `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
RequestBody string `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
OperationRef string `json:"operationRef,omitempty" yaml:"operationRef,omitempty"`
|
||||
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Parameters orderedmap.Map[string, string] `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
RequestBody string `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Server *Server `json:"server,omitempty" yaml:"server,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Link
|
||||
}
|
||||
|
||||
@@ -38,9 +39,9 @@ func NewLink(link *low.Link) *Link {
|
||||
l.low = link
|
||||
l.OperationRef = link.OperationRef.Value
|
||||
l.OperationId = link.OperationId.Value
|
||||
params := make(map[string]string)
|
||||
for k, v := range link.Parameters.Value {
|
||||
params[k.Value] = v.Value
|
||||
params := orderedmap.New[string, string]()
|
||||
for pair := orderedmap.First(link.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||
params.Set(pair.Key().Value, pair.Value().Value)
|
||||
}
|
||||
l.Parameters = params
|
||||
l.RequestBody = link.RequestBody.Value
|
||||
|
||||
@@ -4,18 +4,20 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestLink_MarshalYAML(t *testing.T) {
|
||||
link := Link{
|
||||
OperationRef: "somewhere",
|
||||
OperationId: "somewhereOutThere",
|
||||
Parameters: map[string]string{
|
||||
Parameters: orderedmap.ToOrderedMap(map[string]string{
|
||||
"over": "theRainbow",
|
||||
},
|
||||
}),
|
||||
RequestBody: "hello?",
|
||||
Description: "are you there?",
|
||||
Server: &Server{
|
||||
|
||||
@@ -4,12 +4,11 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -18,11 +17,11 @@ import (
|
||||
// Each Media Type Object provides schema and examples for the media type identified by its key.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#media-type-object
|
||||
type MediaType struct {
|
||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*base.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Encoding map[string]*Encoding `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples orderedmap.Map[string, *base.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Encoding orderedmap.Map[string, *Encoding] `json:"encoding,omitempty" yaml:"encoding,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
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
|
||||
// and easier to navigate high-level one.
|
||||
func ExtractContent(elements map[lowmodel.KeyReference[string]]lowmodel.ValueReference[*low.MediaType]) map[string]*MediaType {
|
||||
// extract everything async
|
||||
doneChan := make(chan bool)
|
||||
|
||||
var extLock sync.RWMutex
|
||||
extractContentItem := func(k lowmodel.KeyReference[string],
|
||||
v lowmodel.ValueReference[*low.MediaType], c chan bool, e map[string]*MediaType) {
|
||||
extLock.Lock()
|
||||
e[k.Value] = NewMediaType(v.Value)
|
||||
extLock.Unlock()
|
||||
c <- true
|
||||
|
||||
func ExtractContent(elements orderedmap.Map[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.MediaType]]) orderedmap.Map[string, *MediaType] {
|
||||
extracted := orderedmap.New[string, *MediaType]()
|
||||
translateFunc := func(pair orderedmap.Pair[lowmodel.KeyReference[string], lowmodel.ValueReference[*low.MediaType]]) (asyncResult[*MediaType], error) {
|
||||
return asyncResult[*MediaType]{
|
||||
key: pair.Key().Value,
|
||||
result: NewMediaType(pair.Value().Value),
|
||||
}, nil
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
||||
|
||||
// create a new document and extract a media type object from it.
|
||||
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
|
||||
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.
|
||||
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
|
||||
yml, _ := mt.Render()
|
||||
|
||||
@@ -6,17 +6,18 @@ package v3
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// OAuthFlow represents a high-level OpenAPI 3+ OAuthFlow object that is backed by a low-level one.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#oauth-flow-object
|
||||
type OAuthFlow struct {
|
||||
AuthorizationUrl string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenUrl string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshUrl string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
Scopes map[string]string `json:"scopes,omitempty" yaml:"scopes,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
AuthorizationUrl string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"`
|
||||
TokenUrl string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"`
|
||||
RefreshUrl string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
|
||||
Scopes orderedmap.Map[string, string] `json:"scopes,omitempty" yaml:"scopes,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.OAuthFlow
|
||||
}
|
||||
|
||||
@@ -27,9 +28,9 @@ func NewOAuthFlow(flow *low.OAuthFlow) *OAuthFlow {
|
||||
o.TokenUrl = flow.TokenUrl.Value
|
||||
o.AuthorizationUrl = flow.AuthorizationUrl.Value
|
||||
o.RefreshUrl = flow.RefreshUrl.Value
|
||||
scopes := make(map[string]string)
|
||||
for k, v := range flow.Scopes.Value {
|
||||
scopes[k.Value] = v.Value
|
||||
scopes := orderedmap.New[string, string]()
|
||||
for pair := orderedmap.First(flow.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||
scopes.Set(pair.Key().Value, pair.Value().Value)
|
||||
}
|
||||
o.Scopes = scopes
|
||||
o.Extensions = high.ExtractExtensions(flow.Extensions)
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestOAuthFlow_MarshalYAML(t *testing.T) {
|
||||
@@ -15,7 +17,10 @@ func TestOAuthFlow_MarshalYAML(t *testing.T) {
|
||||
AuthorizationUrl: "https://pb33f.io",
|
||||
TokenUrl: "https://pb33f.io/token",
|
||||
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()
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewOAuthFlows(t *testing.T) {
|
||||
@@ -81,7 +82,7 @@ clientCredentials:
|
||||
CHIP:CHOP: microwave a sock`
|
||||
|
||||
// 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()
|
||||
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/base"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -16,19 +17,19 @@ import (
|
||||
// happens here. The entire being for existence of this library and the specification, is this Operation.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#operation-object
|
||||
type Operation struct {
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *base.ExternalDoc `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Parameters []*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
RequestBody *RequestBody `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
Responses *Responses `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Callbacks map[string]*Callback `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Security []*base.SecurityRequirement `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Servers []*Server `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Tags []string `json:"tags,omitempty" yaml:"tags,omitempty"`
|
||||
Summary string `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
ExternalDocs *base.ExternalDoc `json:"externalDocs,omitempty" yaml:"externalDocs,omitempty"`
|
||||
OperationId string `json:"operationId,omitempty" yaml:"operationId,omitempty"`
|
||||
Parameters []*Parameter `json:"parameters,omitempty" yaml:"parameters,omitempty"`
|
||||
RequestBody *RequestBody `json:"requestBody,omitempty" yaml:"requestBody,omitempty"`
|
||||
Responses *Responses `json:"responses,omitempty" yaml:"responses,omitempty"`
|
||||
Callbacks orderedmap.Map[string, *Callback] `json:"callbacks,omitempty" yaml:"callbacks,omitempty"`
|
||||
Deprecated *bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
Security []*base.SecurityRequirement `json:"security,omitempty" yaml:"security,omitempty"`
|
||||
Servers []*Server `json:"servers,omitempty" yaml:"servers,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Operation
|
||||
}
|
||||
|
||||
@@ -81,9 +82,9 @@ func NewOperation(operation *low.Operation) *Operation {
|
||||
o.Servers = servers
|
||||
o.Extensions = high.ExtractExtensions(operation.Extensions)
|
||||
if !operation.Callbacks.IsEmpty() {
|
||||
cbs := make(map[string]*Callback)
|
||||
for k, v := range operation.Callbacks.Value {
|
||||
cbs[k.Value] = NewCallback(v.Value)
|
||||
cbs := orderedmap.New[string, *Callback]()
|
||||
for pair := orderedmap.First(operation.Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||
cbs.Set(pair.Key().Value, NewCallback(pair.Value().Value))
|
||||
}
|
||||
o.Callbacks = cbs
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ callbacks:
|
||||
assert.Equal(t, "https://pb33f.io", r.ExternalDocs.URL)
|
||||
assert.Equal(t, 1, r.GoLow().ExternalDocs.KeyNode.Line)
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,6 @@ func Example_createHighLevelOpenAPIDocument() {
|
||||
|
||||
// Print out some details
|
||||
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
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -15,20 +16,20 @@ import (
|
||||
// A unique parameter is defined by a combination of a name and location.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#parameter-object
|
||||
type Parameter struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples map[string]*base.Example `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
In string `json:"in,omitempty" yaml:"in,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Required bool `json:"required,omitempty" yaml:"required,omitempty"`
|
||||
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
|
||||
AllowEmptyValue bool `json:"allowEmptyValue,omitempty" yaml:"allowEmptyValue,omitempty"`
|
||||
Style string `json:"style,omitempty" yaml:"style,omitempty"`
|
||||
Explode *bool `json:"explode,omitempty" yaml:"explode,omitempty"`
|
||||
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
|
||||
Schema *base.SchemaProxy `json:"schema,omitempty" yaml:"schema,omitempty"`
|
||||
Example any `json:"example,omitempty" yaml:"example,omitempty"`
|
||||
Examples orderedmap.Map[string, *base.Example] `json:"examples,omitempty" yaml:"examples,omitempty"`
|
||||
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Parameter
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -23,8 +24,10 @@ func TestParameter_MarshalYAML(t *testing.T) {
|
||||
Explode: &explode,
|
||||
AllowReserved: true,
|
||||
Example: "example",
|
||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||
"example": {Value: "example"},
|
||||
}),
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
}
|
||||
|
||||
rend, _ := param.Render()
|
||||
@@ -57,8 +60,10 @@ func TestParameter_MarshalYAMLInline(t *testing.T) {
|
||||
Explode: &explode,
|
||||
AllowReserved: true,
|
||||
Example: "example",
|
||||
Examples: map[string]*base.Example{"example": {Value: "example"}},
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
Examples: orderedmap.ToOrderedMap(map[string]*base.Example{
|
||||
"example": {Value: "example"},
|
||||
}),
|
||||
Extensions: map[string]interface{}{"x-burgers": "why not?"},
|
||||
}
|
||||
|
||||
rend, _ := param.RenderInline()
|
||||
|
||||
@@ -84,7 +84,7 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
||||
}
|
||||
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()
|
||||
pi := pair.Value()
|
||||
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})
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
||||
|
||||
nb := high.NewNodeBuilder(p, p.low)
|
||||
extNode := nb.Render()
|
||||
@@ -142,7 +140,7 @@ func (p *Paths) MarshalYAMLInline() (interface{}, error) {
|
||||
}
|
||||
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()
|
||||
pi := pair.Value()
|
||||
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})
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
||||
|
||||
nb := high.NewNodeBuilder(p, p.low)
|
||||
nb.Resolve = true
|
||||
|
||||
@@ -6,16 +6,17 @@ package v3
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// RequestBody represents a high-level OpenAPI 3+ RequestBody object, backed by a low-level one.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
||||
type RequestBody struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Required *bool `json:"required,omitempty" yaml:"required,renderZero,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Required *bool `json:"required,omitempty" yaml:"required,renderZero,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.RequestBody
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package v3
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -15,11 +16,11 @@ import (
|
||||
// operations based on the response.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
||||
type Response struct {
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Headers map[string]*Header `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Content map[string]*MediaType `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Links map[string]*Link `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Headers orderedmap.Map[string, *Header] `json:"headers,omitempty" yaml:"headers,omitempty"`
|
||||
Content orderedmap.Map[string, *MediaType] `json:"content,omitempty" yaml:"content,omitempty"`
|
||||
Links orderedmap.Map[string, *Link] `json:"links,omitempty" yaml:"links,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Response
|
||||
}
|
||||
|
||||
@@ -36,9 +37,9 @@ func NewResponse(response *low.Response) *Response {
|
||||
r.Content = ExtractContent(response.Content.Value)
|
||||
}
|
||||
if !response.Links.IsEmpty() {
|
||||
responseLinks := make(map[string]*Link)
|
||||
for k, v := range response.Links.Value {
|
||||
responseLinks[k.Value] = NewLink(v.Value)
|
||||
responseLinks := orderedmap.New[string, *Link]()
|
||||
for pair := orderedmap.First(response.Links.Value); pair != nil; pair = pair.Next() {
|
||||
responseLinks.Set(pair.Key().Value, NewLink(pair.Value().Value))
|
||||
}
|
||||
r.Links = responseLinks
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
lowbase "github.com/pb33f/libopenapi/datamodel/low"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -30,9 +30,9 @@ import (
|
||||
// be the response for a successful operation call.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#responses-object
|
||||
type Responses struct {
|
||||
Codes map[string]*Response `json:"-" yaml:"-"`
|
||||
Default *Response `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
Codes orderedmap.Map[string, *Response] `json:"-" yaml:"-"`
|
||||
Default *Response `json:"default,omitempty" yaml:"default,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Responses
|
||||
}
|
||||
|
||||
@@ -45,28 +45,31 @@ func NewResponses(responses *low.Responses) *Responses {
|
||||
if !responses.Default.IsEmpty() {
|
||||
r.Default = NewResponse(responses.Default.Value)
|
||||
}
|
||||
codes := make(map[string]*Response)
|
||||
codes := orderedmap.New[string, *Response]()
|
||||
|
||||
type respRes struct {
|
||||
code string
|
||||
resp *Response
|
||||
}
|
||||
|
||||
translateFunc := func(key lowbase.KeyReference[string], value lowbase.ValueReference[*low.Response]) (respRes, error) {
|
||||
return respRes{code: key.Value, resp: NewResponse(value.Value)}, nil
|
||||
translateFunc := func(pair orderedmap.Pair[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
||||
return asyncResult[*Response]{
|
||||
key: pair.Key().Value,
|
||||
result: NewResponse(pair.Value().Value),
|
||||
}, nil
|
||||
}
|
||||
resultFunc := func(value respRes) error {
|
||||
codes[value.code] = value.resp
|
||||
resultFunc := func(value asyncResult[*Response]) error {
|
||||
codes.Set(value.key, value.result)
|
||||
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
|
||||
return r
|
||||
}
|
||||
|
||||
// FindResponseByCode is a shortcut for looking up code by an integer vs. a string
|
||||
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.
|
||||
@@ -101,16 +104,16 @@ func (r *Responses) MarshalYAML() (interface{}, error) {
|
||||
}
|
||||
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.
|
||||
if r.low != nil {
|
||||
for lKey := range r.low.Codes {
|
||||
if lKey.Value == k {
|
||||
ln = lKey.KeyNode.Line
|
||||
for lPair := orderedmap.First(r.low.Codes); lPair != nil; lPair = lPair.Next() {
|
||||
if lPair.Key().Value == pair.Key() {
|
||||
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
|
||||
@@ -157,16 +160,16 @@ func (r *Responses) MarshalYAMLInline() (interface{}, error) {
|
||||
}
|
||||
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.
|
||||
if r.low != nil {
|
||||
for lKey := range r.low.Codes {
|
||||
if lKey.Value == k {
|
||||
ln = lKey.KeyNode.Line
|
||||
for lPair := orderedmap.First(r.low.Codes); lPair != nil; lPair = lPair.Next() {
|
||||
if lPair.Key().Value == pair.Key() {
|
||||
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
|
||||
|
||||
@@ -6,16 +6,17 @@ package v3
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/high"
|
||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Server represents a high-level OpenAPI 3+ Server object, that is backed by a low level one.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#server-object
|
||||
type Server struct {
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||
Variables orderedmap.Map[string, *ServerVariable] `json:"variables,omitempty" yaml:"variables,omitempty"`
|
||||
Extensions map[string]any `json:"-" yaml:"-"`
|
||||
low *low.Server
|
||||
}
|
||||
|
||||
@@ -25,9 +26,9 @@ func NewServer(server *low.Server) *Server {
|
||||
s.low = server
|
||||
s.Description = server.Description.Value
|
||||
s.URL = server.URL.Value
|
||||
vars := make(map[string]*ServerVariable)
|
||||
for k, val := range server.Variables.Value {
|
||||
vars[k.Value] = NewServerVariable(val.Value)
|
||||
vars := orderedmap.New[string, *ServerVariable]()
|
||||
for pair := orderedmap.First(server.Variables.Value); pair != nil; pair = pair.Next() {
|
||||
vars.Set(pair.Key().Value, NewServerVariable(pair.Value().Value))
|
||||
}
|
||||
s.Variables = vars
|
||||
s.Extensions = high.ExtractExtensions(server.Extensions)
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestServer_MarshalYAML(t *testing.T) {
|
||||
@@ -23,11 +25,11 @@ description: the b33f`
|
||||
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
|
||||
|
||||
// mutate
|
||||
server.Variables = map[string]*ServerVariable{
|
||||
server.Variables = orderedmap.ToOrderedMap(map[string]*ServerVariable{
|
||||
"rainbow": {
|
||||
Enum: []string{"one", "two", "three"},
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
desired = `url: https://pb33f.io
|
||||
description: the b33f
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"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"
|
||||
)
|
||||
@@ -96,8 +97,8 @@ type Schema struct {
|
||||
If low.NodeReference[*SchemaProxy]
|
||||
Else low.NodeReference[*SchemaProxy]
|
||||
Then low.NodeReference[*SchemaProxy]
|
||||
DependentSchemas low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]
|
||||
PatternProperties low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]]
|
||||
DependentSchemas low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||
PatternProperties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||
PropertyNames low.NodeReference[*SchemaProxy]
|
||||
UnevaluatedItems low.NodeReference[*SchemaProxy]
|
||||
UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]
|
||||
@@ -120,7 +121,7 @@ type Schema struct {
|
||||
Required low.NodeReference[[]low.ValueReference[string]]
|
||||
Enum low.NodeReference[[]low.ValueReference[any]]
|
||||
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]
|
||||
Description low.NodeReference[string]
|
||||
ContentEncoding low.NodeReference[string]
|
||||
@@ -305,10 +306,10 @@ func (s *Schema) Hash() [32]byte {
|
||||
for i := range s.Enum.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
|
||||
for i := range s.Properties.Value {
|
||||
propKeys[z] = i.Value
|
||||
for pair := orderedmap.First(s.Properties.Value); pair != nil; pair = pair.Next() {
|
||||
propKeys[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(propKeys)
|
||||
@@ -414,10 +415,10 @@ func (s *Schema) Hash() [32]byte {
|
||||
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
|
||||
for i := range s.DependentSchemas.Value {
|
||||
depSchemasKeys[z] = i.Value
|
||||
for pair := orderedmap.First(s.DependentSchemas.Value); pair != nil; pair = pair.Next() {
|
||||
depSchemasKeys[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(depSchemasKeys)
|
||||
@@ -425,10 +426,10 @@ func (s *Schema) Hash() [32]byte {
|
||||
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
|
||||
for i := range s.PatternProperties.Value {
|
||||
patternPropsKeys[z] = i.Value
|
||||
for pair := orderedmap.First(s.PatternProperties.Value); pair != nil; pair = pair.Next() {
|
||||
patternPropsKeys[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(patternPropsKeys)
|
||||
@@ -490,19 +491,19 @@ func (s *Schema) Hash() [32]byte {
|
||||
// FindProperty will return a ValueReference pointer containing a SchemaProxy pointer
|
||||
// from a property key name. if found
|
||||
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
|
||||
// from a dependent schema key name. if found (3.1+ only)
|
||||
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
|
||||
// from a pattern property key name. if found (3.1+ only)
|
||||
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
|
||||
@@ -1067,7 +1068,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
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!
|
||||
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)
|
||||
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
|
||||
totalProps := 0
|
||||
for i, prop := range propsNode.Content {
|
||||
@@ -1119,10 +1120,10 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
||||
select {
|
||||
case res := <-bChan:
|
||||
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,
|
||||
KeyNode: propLabel,
|
||||
ValueNode: propsNode,
|
||||
|
||||
@@ -6,12 +6,14 @@ package base
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -23,7 +25,7 @@ import (
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
// - https://swagger.io/specification/#security-requirement-object
|
||||
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
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) erro
|
||||
utils.CheckForMergeNodes(root)
|
||||
s.Reference = new(low.Reference)
|
||||
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]
|
||||
for i := range root.Content {
|
||||
if i%2 == 0 {
|
||||
@@ -47,15 +49,18 @@ func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) erro
|
||||
ValueNode: root.Content[i].Content[j],
|
||||
})
|
||||
}
|
||||
valueMap[low.KeyReference[string]{
|
||||
Value: labelNode.Value,
|
||||
KeyNode: labelNode,
|
||||
}] = low.ValueReference[[]low.ValueReference[string]]{
|
||||
Value: arr,
|
||||
ValueNode: root.Content[i],
|
||||
}
|
||||
valueMap.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: labelNode.Value,
|
||||
KeyNode: labelNode,
|
||||
},
|
||||
low.ValueReference[[]low.ValueReference[string]]{
|
||||
Value: arr,
|
||||
ValueNode: root.Content[i],
|
||||
},
|
||||
)
|
||||
}
|
||||
s.Requirements = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]{
|
||||
s.Requirements = low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]]]{
|
||||
Value: valueMap,
|
||||
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.
|
||||
func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range s.Requirements.Value {
|
||||
if k.Value == name {
|
||||
return s.Requirements.Value[k].Value
|
||||
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == name {
|
||||
return pair.Value().Value
|
||||
}
|
||||
}
|
||||
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.
|
||||
func (s *SecurityRequirement) GetKeys() []string {
|
||||
keys := make([]string, len(s.Requirements.Value))
|
||||
keys := make([]string, orderedmap.Len(s.Requirements.Value))
|
||||
z := 0
|
||||
for k := range s.Requirements.Value {
|
||||
keys[z] = k.Value
|
||||
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
}
|
||||
return keys
|
||||
}
|
||||
@@ -85,18 +90,17 @@ func (s *SecurityRequirement) GetKeys() []string {
|
||||
// Hash will return a consistent SHA256 Hash of the SecurityRequirement object
|
||||
func (s *SecurityRequirement) Hash() [32]byte {
|
||||
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
|
||||
for k := range s.Requirements.Value {
|
||||
for pair := orderedmap.First(s.Requirements.Value); pair != nil; pair = pair.Next() {
|
||||
var vals []string
|
||||
for y := range s.Requirements.Value[k].Value {
|
||||
vals = append(vals, s.Requirements.Value[k].Value[y].Value)
|
||||
// lol, I know. -------^^^^^ <- this is the actual value.
|
||||
for y := range pair.Value().Value {
|
||||
vals = append(vals, pair.Value().Value[y].Value)
|
||||
}
|
||||
sort.Strings(vals)
|
||||
valKeys = append(valKeys, k.Value)
|
||||
valKeys = append(valKeys, pair.Key().Value)
|
||||
if len(vals) > 0 {
|
||||
values[k.Value] = vals
|
||||
values[pair.Key().Value] = vals
|
||||
}
|
||||
}
|
||||
sort.Strings(valKeys)
|
||||
|
||||
@@ -6,13 +6,15 @@ package low
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"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
|
||||
@@ -29,6 +31,22 @@ func FindItemInMap[T any](item string, collection map[KeyReference[string]]Value
|
||||
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.
|
||||
func generateIndexCollection(idx *index.SpecIndex) []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,
|
||||
idx *index.SpecIndex,
|
||||
includeExtensions bool,
|
||||
) (map[KeyReference[string]]ValueReference[PT], error) {
|
||||
valueMap := make(map[KeyReference[string]]ValueReference[PT])
|
||||
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
||||
valueMap := orderedmap.New[KeyReference[string], ValueReference[PT]]()
|
||||
var circError error
|
||||
if utils.IsNodeMap(root) {
|
||||
var currentKey *yaml.Node
|
||||
@@ -431,15 +449,18 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
||||
SetReference(n, referenceValue)
|
||||
}
|
||||
if currentKey != nil {
|
||||
valueMap[KeyReference[string]{
|
||||
Value: currentKey.Value,
|
||||
KeyNode: currentKey,
|
||||
}] = ValueReference[PT]{
|
||||
Value: n,
|
||||
ValueNode: node,
|
||||
//IsReference: isReference,
|
||||
Reference: referenceValue,
|
||||
}
|
||||
valueMap.Set(
|
||||
KeyReference[string]{
|
||||
Value: currentKey.Value,
|
||||
KeyNode: currentKey,
|
||||
},
|
||||
ValueReference[PT]{
|
||||
Value: n,
|
||||
ValueNode: node,
|
||||
//IsReference: isReference,
|
||||
Reference: referenceValue,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,7 +479,7 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
||||
func ExtractMapNoLookup[PT Buildable[N], N any](
|
||||
root *yaml.Node,
|
||||
idx *index.SpecIndex,
|
||||
) (map[KeyReference[string]]ValueReference[PT], error) {
|
||||
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
||||
return ExtractMapNoLookupExtensions[PT, N](root, idx, false)
|
||||
}
|
||||
|
||||
@@ -478,7 +499,7 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
||||
root *yaml.Node,
|
||||
idx *index.SpecIndex,
|
||||
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 referenceValue string
|
||||
var labelNode, valueNode *yaml.Node
|
||||
@@ -522,8 +543,9 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
||||
}
|
||||
if valueNode != nil {
|
||||
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])
|
||||
eChan := make(chan error)
|
||||
|
||||
@@ -598,7 +620,7 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
||||
return valueMap, labelNode, valueNode, err
|
||||
case res := <-bChan:
|
||||
completedKeys++
|
||||
valueMap[res.k] = res.v
|
||||
valueMap.Set(res.k, res.v)
|
||||
}
|
||||
}
|
||||
if circError != nil && !idx.AllowCircularReferenceResolving() {
|
||||
@@ -618,7 +640,7 @@ func ExtractMap[PT Buildable[N], N any](
|
||||
label string,
|
||||
root *yaml.Node,
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -795,7 +796,7 @@ func TestExtractArray_Ref_Nested(t *testing.T) {
|
||||
errs := resolve.CheckForCircularReferences()
|
||||
assert.Len(t, errs, 1)
|
||||
|
||||
yml = `limes:
|
||||
yml = `limes:
|
||||
$ref: '#/components/schemas/let-us-eat-cake'`
|
||||
|
||||
var cNode yaml.Node
|
||||
@@ -824,7 +825,7 @@ func TestExtractArray_Ref_Nested_Circular(t *testing.T) {
|
||||
errs := resolve.CheckForCircularReferences()
|
||||
assert.Len(t, errs, 1)
|
||||
|
||||
yml = `limes:
|
||||
yml = `limes:
|
||||
- $ref: '#/components/schemas/things'`
|
||||
|
||||
var cNode yaml.Node
|
||||
@@ -851,7 +852,7 @@ func TestExtractArray_Ref_Nested_BadRef(t *testing.T) {
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndexWithConfig(&idxNode, index.CreateClosedAPIIndexConfig())
|
||||
|
||||
yml = `limes:
|
||||
yml = `limes:
|
||||
- $ref: '#/components/schemas/thangs'`
|
||||
|
||||
var cNode yaml.Node
|
||||
@@ -880,7 +881,7 @@ func TestExtractArray_Ref_Nested_CircularFlat(t *testing.T) {
|
||||
errs := resolve.CheckForCircularReferences()
|
||||
assert.Len(t, errs, 1)
|
||||
|
||||
yml = `limes:
|
||||
yml = `limes:
|
||||
$ref: '#/components/schemas/things'`
|
||||
|
||||
var cNode yaml.Node
|
||||
@@ -902,7 +903,7 @@ func TestExtractArray_BadBuild(t *testing.T) {
|
||||
assert.NoError(t, mErr)
|
||||
idx := index.NewSpecIndexWithConfig(&idxNode, index.CreateClosedAPIIndexConfig())
|
||||
|
||||
yml = `limes:
|
||||
yml = `limes:
|
||||
- dontWork: 1`
|
||||
|
||||
var cNode yaml.Node
|
||||
@@ -994,12 +995,12 @@ one:
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, things, 2)
|
||||
|
||||
for k, v := range things {
|
||||
if k.Value == "x-hey" {
|
||||
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == "x-hey" {
|
||||
continue
|
||||
}
|
||||
assert.Equal(t, "one", k.Value)
|
||||
assert.Len(t, v.ValueNode.Content, 2)
|
||||
assert.Equal(t, "one", pair.Key().Value)
|
||||
assert.Len(t, pair.Value().ValueNode.Content, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1050,8 +1051,8 @@ one:
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, things, 1)
|
||||
|
||||
for k := range things {
|
||||
assert.Equal(t, "one", k.Value)
|
||||
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||
assert.Equal(t, "one", pair.Key().Value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1283,8 +1284,8 @@ one:
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, things, 1)
|
||||
|
||||
for k := range things {
|
||||
assert.Equal(t, 99, things[k].Value.AlmostWork.Value)
|
||||
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||
assert.Equal(t, 99, pair.Value().Value.AlmostWork.Value)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1313,8 +1314,8 @@ func TestExtractMapFlat_DoubleRef(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, things, 1)
|
||||
|
||||
for k := range things {
|
||||
assert.Equal(t, 99, things[k].Value.AlmostWork.Value)
|
||||
for pair := orderedmap.First(things); pair != nil; pair = pair.Next() {
|
||||
assert.Equal(t, 99, pair.Value().Value.AlmostWork.Value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,15 @@ package v2
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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
|
||||
// - https://swagger.io/specification/v2/#parametersDefinitionsObject
|
||||
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.
|
||||
@@ -29,7 +31,7 @@ type ParameterDefinitions struct {
|
||||
// referenced to the ones defined here. It does not define global operation responses
|
||||
// - https://swagger.io/specification/v2/#responsesDefinitionsObject
|
||||
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.
|
||||
@@ -38,7 +40,7 @@ type ResponsesDefinitions struct {
|
||||
// schemes on the operations and only serves to provide the relevant details for each scheme
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
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
|
||||
@@ -47,33 +49,34 @@ type SecurityDefinitions struct {
|
||||
// arrays or models.
|
||||
// - https://swagger.io/specification/v2/#definitionsObject
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
root = utils.NodeAlias(root)
|
||||
utils.CheckForMergeNodes(root)
|
||||
// TODO: Refactor with orderedmap.TranslatePipeline.
|
||||
errorChan := make(chan error)
|
||||
resultChan := make(chan definitionResult[*base.SchemaProxy])
|
||||
var defLabel *yaml.Node
|
||||
@@ -99,17 +102,18 @@ func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
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 {
|
||||
select {
|
||||
case err := <-errorChan:
|
||||
return err
|
||||
case sch := <-resultChan:
|
||||
completedDefs++
|
||||
results[low.KeyReference[string]{
|
||||
key := low.KeyReference[string]{
|
||||
Value: sch.k.Value,
|
||||
KeyNode: sch.k,
|
||||
}] = sch.v
|
||||
}
|
||||
results.Set(key, sch.v)
|
||||
}
|
||||
}
|
||||
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
|
||||
func (d *Definitions) Hash() [32]byte {
|
||||
var f []string
|
||||
keys := make([]string, len(d.Schemas))
|
||||
keys := make([]string, orderedmap.Len(d.Schemas))
|
||||
z := 0
|
||||
for k := range d.Schemas {
|
||||
keys[z] = k.Value
|
||||
for pair := orderedmap.First(d.Schemas); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
@@ -158,17 +162,18 @@ func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex)
|
||||
}
|
||||
|
||||
completedDefs := 0
|
||||
results := make(map[low.KeyReference[string]]low.ValueReference[*Parameter])
|
||||
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*Parameter]]()
|
||||
for completedDefs < totalDefinitions {
|
||||
select {
|
||||
case err := <-errorChan:
|
||||
return err
|
||||
case sch := <-resultChan:
|
||||
completedDefs++
|
||||
results[low.KeyReference[string]{
|
||||
key := low.KeyReference[string]{
|
||||
Value: sch.k.Value,
|
||||
KeyNode: sch.k,
|
||||
}] = sch.v
|
||||
}
|
||||
results.Set(key, sch.v)
|
||||
}
|
||||
}
|
||||
pd.Definitions = results
|
||||
@@ -207,17 +212,18 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
||||
}
|
||||
|
||||
completedDefs := 0
|
||||
results := make(map[low.KeyReference[string]]low.ValueReference[*Response])
|
||||
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*Response]]()
|
||||
for completedDefs < totalDefinitions {
|
||||
select {
|
||||
case err := <-errorChan:
|
||||
return err
|
||||
case sch := <-resultChan:
|
||||
completedDefs++
|
||||
results[low.KeyReference[string]{
|
||||
key := low.KeyReference[string]{
|
||||
Value: sch.k.Value,
|
||||
KeyNode: sch.k,
|
||||
}] = sch.v
|
||||
}
|
||||
results.Set(key, sch.v)
|
||||
}
|
||||
}
|
||||
r.Definitions = results
|
||||
@@ -253,17 +259,18 @@ func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) er
|
||||
}
|
||||
|
||||
completedDefs := 0
|
||||
results := make(map[low.KeyReference[string]]low.ValueReference[*SecurityScheme])
|
||||
results := orderedmap.New[low.KeyReference[string], low.ValueReference[*SecurityScheme]]()
|
||||
for completedDefs < totalDefinitions {
|
||||
select {
|
||||
case err := <-errorChan:
|
||||
return err
|
||||
case sch := <-resultChan:
|
||||
completedDefs++
|
||||
results[low.KeyReference[string]{
|
||||
key := low.KeyReference[string]{
|
||||
Value: sch.k.Value,
|
||||
KeyNode: sch.k,
|
||||
}] = sch.v
|
||||
}
|
||||
results.Set(key, sch.v)
|
||||
}
|
||||
}
|
||||
s.Definitions = results
|
||||
|
||||
@@ -6,24 +6,26 @@ package v2
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
// Allows sharing examples for operation responses
|
||||
// - https://swagger.io/specification/v2/#exampleObject
|
||||
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.
|
||||
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.
|
||||
@@ -32,7 +34,7 @@ func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
||||
utils.CheckForMergeNodes(root)
|
||||
var keyNode, currNode *yaml.Node
|
||||
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 {
|
||||
if i%2 == 0 {
|
||||
keyNode = root.Content[i]
|
||||
@@ -48,32 +50,40 @@ func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
||||
// lets just default to interface
|
||||
var j interface{}
|
||||
_ = currNode.Decode(&j)
|
||||
e.Values[low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
}] = low.ValueReference[any]{
|
||||
Value: j,
|
||||
ValueNode: currNode,
|
||||
}
|
||||
e.Values.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
},
|
||||
low.ValueReference[any]{
|
||||
Value: j,
|
||||
ValueNode: currNode,
|
||||
},
|
||||
)
|
||||
continue
|
||||
}
|
||||
e.Values[low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
}] = low.ValueReference[any]{
|
||||
Value: k,
|
||||
ValueNode: currNode,
|
||||
}
|
||||
e.Values.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
},
|
||||
low.ValueReference[any]{
|
||||
Value: k,
|
||||
ValueNode: currNode,
|
||||
},
|
||||
)
|
||||
continue
|
||||
}
|
||||
e.Values[low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
}] = low.ValueReference[any]{
|
||||
Value: n,
|
||||
ValueNode: currNode,
|
||||
}
|
||||
|
||||
e.Values.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: keyNode.Value,
|
||||
KeyNode: keyNode,
|
||||
},
|
||||
low.ValueReference[any]{
|
||||
Value: n,
|
||||
ValueNode: currNode,
|
||||
},
|
||||
)
|
||||
}
|
||||
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
|
||||
func (e *Examples) Hash() [32]byte {
|
||||
var f []string
|
||||
keys := make([]string, len(e.Values))
|
||||
keys := make([]string, orderedmap.Len(e.Values))
|
||||
z := 0
|
||||
for k := range e.Values {
|
||||
keys[z] = k.Value
|
||||
for pair := orderedmap.First(e.Values); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,7 +6,6 @@ package v2
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"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.
|
||||
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 {
|
||||
result = pair.ValuePtr()
|
||||
return io.EOF
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
return result
|
||||
}
|
||||
|
||||
// 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]) {
|
||||
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 {
|
||||
key = pair.KeyPtr()
|
||||
value = pair.ValuePtr()
|
||||
return io.EOF
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
return key, value
|
||||
}
|
||||
|
||||
@@ -167,14 +162,12 @@ func (p *Paths) Hash() [32]byte {
|
||||
keys := make(map[string]low.ValueReference[*PathItem])
|
||||
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
|
||||
keys[k] = pair.Value()
|
||||
l[z] = k
|
||||
z++
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
|
||||
sort.Strings(l)
|
||||
for k := range l {
|
||||
|
||||
@@ -6,13 +6,15 @@ package v2
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"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.
|
||||
@@ -22,7 +24,7 @@ import (
|
||||
type Response struct {
|
||||
Description low.NodeReference[string]
|
||||
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]
|
||||
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
|
||||
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
|
||||
@@ -68,7 +70,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return err
|
||||
}
|
||||
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,
|
||||
KeyNode: lN,
|
||||
ValueNode: kN,
|
||||
@@ -87,8 +89,8 @@ func (r *Response) Hash() [32]byte {
|
||||
f = append(f, low.GenerateHashString(r.Schema.Value))
|
||||
}
|
||||
if !r.Examples.IsEmpty() {
|
||||
for k := range r.Examples.Value.Values {
|
||||
f = append(f, low.GenerateHashString(r.Examples.Value.Values[k].Value))
|
||||
for pair := orderedmap.First(r.Examples.Value.Values); pair != nil; pair = pair.Next() {
|
||||
f = append(f, low.GenerateHashString(pair.Value().Value))
|
||||
}
|
||||
}
|
||||
keys := make([]string, len(r.Extensions))
|
||||
|
||||
@@ -6,17 +6,19 @@ package v2
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
type Responses struct {
|
||||
Codes map[low.KeyReference[string]]low.ValueReference[*Response]
|
||||
Codes orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]
|
||||
Default low.NodeReference[*Response]
|
||||
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] {
|
||||
for n, o := range r.Codes {
|
||||
if strings.ToLower(n.Value) == DefaultLabel {
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
if strings.ToLower(pair.Key().Value) == DefaultLabel {
|
||||
return &low.NodeReference[*Response]{
|
||||
ValueNode: o.ValueNode,
|
||||
KeyNode: n.KeyNode,
|
||||
Value: o.Value,
|
||||
ValueNode: pair.Value().ValueNode,
|
||||
KeyNode: pair.Key().KeyNode,
|
||||
Value: pair.Value().Value,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,34 +73,34 @@ func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
||||
func (r *Responses) deleteCode(code string) {
|
||||
var key *low.KeyReference[string]
|
||||
if r.Codes != nil {
|
||||
for k := range r.Codes {
|
||||
if k.Value == code {
|
||||
key = &k
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == code {
|
||||
key = pair.KeyPtr()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
// should never be nil, but, you never know... science and all that!
|
||||
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.
|
||||
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
|
||||
func (r *Responses) Hash() [32]byte {
|
||||
var f []string
|
||||
var keys []string
|
||||
keys = make([]string, len(r.Codes))
|
||||
keys = make([]string, orderedmap.Len(r.Codes))
|
||||
cmap := make(map[string]*Response, len(keys))
|
||||
z := 0
|
||||
for k := range r.Codes {
|
||||
keys[z] = k.Value
|
||||
cmap[k.Value] = r.Codes[k].Value
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
cmap[pair.Key().Value] = pair.Value().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,12 +6,14 @@ package v2
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -19,7 +21,7 @@ import (
|
||||
// Scopes lists the available scopes for an OAuth2 security scheme.
|
||||
// - https://swagger.io/specification/v2/#scopesObject
|
||||
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]
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
@@ -38,20 +40,23 @@ func (s *Scopes) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
root = utils.NodeAlias(root)
|
||||
utils.CheckForMergeNodes(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) {
|
||||
for k := range root.Content {
|
||||
if k%2 == 0 {
|
||||
if strings.Contains(root.Content[k].Value, "x-") {
|
||||
continue
|
||||
}
|
||||
valueMap[low.KeyReference[string]{
|
||||
Value: root.Content[k].Value,
|
||||
KeyNode: root.Content[k],
|
||||
}] = low.ValueReference[string]{
|
||||
Value: root.Content[k+1].Value,
|
||||
ValueNode: root.Content[k+1],
|
||||
}
|
||||
valueMap.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: root.Content[k].Value,
|
||||
KeyNode: root.Content[k],
|
||||
},
|
||||
low.ValueReference[string]{
|
||||
Value: root.Content[k+1].Value,
|
||||
ValueNode: root.Content[k+1],
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
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
|
||||
func (s *Scopes) Hash() [32]byte {
|
||||
var f []string
|
||||
vals := make(map[string]low.ValueReference[string], len(s.Values))
|
||||
keys := make([]string, len(s.Values))
|
||||
vals := make(map[string]low.ValueReference[string], orderedmap.Len(s.Values))
|
||||
keys := make([]string, orderedmap.Len(s.Values))
|
||||
z := 0
|
||||
for k := range s.Values {
|
||||
keys[z] = k.Value
|
||||
vals[k.Value] = s.Values[k]
|
||||
for pair := orderedmap.First(s.Values); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
vals[pair.Key().Value] = pair.Value()
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,10 +6,12 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -23,7 +25,7 @@ import (
|
||||
// that identifies a URL to use for the callback operation.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#callback-object
|
||||
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]
|
||||
*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
|
||||
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
|
||||
@@ -47,7 +49,7 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
|
||||
// handle callback
|
||||
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 {
|
||||
if i%2 == 0 {
|
||||
@@ -61,17 +63,20 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
callbacks[low.KeyReference[string]{
|
||||
Value: currentCB.Value,
|
||||
KeyNode: currentCB,
|
||||
}] = low.ValueReference[*PathItem]{
|
||||
Value: callback,
|
||||
ValueNode: callbackNode,
|
||||
Reference: rv,
|
||||
}
|
||||
callbacks.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: currentCB.Value,
|
||||
KeyNode: currentCB,
|
||||
},
|
||||
low.ValueReference[*PathItem]{
|
||||
Value: callback,
|
||||
ValueNode: callbackNode,
|
||||
Reference: rv,
|
||||
},
|
||||
)
|
||||
}
|
||||
if len(callbacks) > 0 {
|
||||
cb.Expression = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]{
|
||||
if orderedmap.Len(callbacks) > 0 {
|
||||
cb.Expression = low.ValueReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]]{
|
||||
Value: callbacks,
|
||||
ValueNode: root,
|
||||
}
|
||||
@@ -83,10 +88,10 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
func (cb *Callback) Hash() [32]byte {
|
||||
var f []string
|
||||
var keys []string
|
||||
keys = make([]string, len(cb.Expression.Value))
|
||||
keys = make([]string, orderedmap.Len(cb.Expression.Value))
|
||||
z := 0
|
||||
for k := range cb.Expression.Value {
|
||||
keys[z] = low.GenerateHashString(cb.Expression.Value[k].Value)
|
||||
for pair := orderedmap.First(cb.Expression.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"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.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#components-object
|
||||
type Components struct {
|
||||
Schemas low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]]
|
||||
Responses low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Response]]
|
||||
Parameters low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Parameter]]
|
||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
||||
RequestBodies low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*RequestBody]]
|
||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
||||
SecuritySchemes low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SecurityScheme]]
|
||||
Links low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]]
|
||||
Callbacks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]]
|
||||
Schemas low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]]]
|
||||
Responses low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]]
|
||||
Parameters low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Parameter]]]
|
||||
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||
RequestBodies low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*RequestBody]]]
|
||||
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||
SecuritySchemes low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SecurityScheme]]]
|
||||
Links low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Link]]]
|
||||
Callbacks low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Callback]]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*low.Reference
|
||||
}
|
||||
@@ -75,16 +76,16 @@ func (co *Components) Hash() [32]byte {
|
||||
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 {
|
||||
return
|
||||
}
|
||||
l := make([]string, len(collection))
|
||||
l := make([]string, orderedmap.Len(collection))
|
||||
keys := make(map[string]low.ValueReference[T])
|
||||
z := 0
|
||||
for k := range collection {
|
||||
keys[k.Value] = collection[k]
|
||||
l[z] = k.Value
|
||||
for pair := orderedmap.First(collection); pair != nil; pair = pair.Next() {
|
||||
keys[pair.Key().Value] = pair.Value()
|
||||
l[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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] {
|
||||
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] {
|
||||
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] {
|
||||
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] {
|
||||
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.
|
||||
@@ -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
|
||||
// low level model.
|
||||
// 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) {
|
||||
var emptyResult low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]
|
||||
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[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]]
|
||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
||||
if nodeValue == 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) {
|
||||
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.
|
||||
go func() {
|
||||
for result := range out {
|
||||
componentValues[result.key] = result.value
|
||||
componentValues.Set(result.key, result.value)
|
||||
}
|
||||
close(done)
|
||||
wg.Done()
|
||||
@@ -317,7 +318,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
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,
|
||||
ValueNode: nodeValue,
|
||||
Value: componentValues,
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
)
|
||||
@@ -247,7 +248,7 @@ func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInd
|
||||
return eErr
|
||||
}
|
||||
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,
|
||||
KeyNode: hooksL,
|
||||
ValueNode: hooksN,
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@@ -225,10 +226,10 @@ func TestCreateDocument_Info(t *testing.T) {
|
||||
func TestCreateDocument_WebHooks(t *testing.T) {
|
||||
initTest()
|
||||
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.
|
||||
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/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
)
|
||||
|
||||
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,
|
||||
// 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.
|
||||
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
|
||||
// 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.
|
||||
func (d *Document) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range d.Security.Value {
|
||||
for i := range d.Security.Value[k].Value.Requirements.Value {
|
||||
if i.Value == name {
|
||||
return d.Security.Value[k].Value.Requirements.Value[i].Value
|
||||
requirements := d.Security.Value[k].Value.Requirements
|
||||
for pair := orderedmap.First(requirements.Value); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == name {
|
||||
return pair.Value().Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,18 +6,20 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Encoding represents a low-level OpenAPI 3+ Encoding object
|
||||
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
|
||||
type Encoding struct {
|
||||
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]
|
||||
Explode low.NodeReference[bool]
|
||||
AllowReserved low.NodeReference[bool]
|
||||
@@ -26,7 +28,7 @@ type Encoding struct {
|
||||
|
||||
// FindHeader attempts to locate a Header with the supplied name
|
||||
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
|
||||
@@ -35,18 +37,19 @@ func (en *Encoding) Hash() [32]byte {
|
||||
if en.ContentType.Value != "" {
|
||||
f = append(f, en.ContentType.Value)
|
||||
}
|
||||
if len(en.Headers.Value) > 0 {
|
||||
l := make([]string, len(en.Headers.Value))
|
||||
if orderedmap.Len(en.Headers.Value) > 0 {
|
||||
l := make([]string, orderedmap.Len(en.Headers.Value))
|
||||
keys := make(map[string]low.ValueReference[*Header])
|
||||
z := 0
|
||||
for k := range en.Headers.Value {
|
||||
keys[k.Value] = en.Headers.Value[k]
|
||||
l[z] = k.Value
|
||||
for pair := orderedmap.First(en.Headers.Value); pair != nil; pair = pair.Next() {
|
||||
keys[pair.Key().Value] = pair.Value()
|
||||
l[z] = pair.Key().Value
|
||||
z++
|
||||
}
|
||||
|
||||
for k := range en.Headers.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, en.Headers.Value[k].Value.Hash()))
|
||||
// FIXME: Redundant iteration?
|
||||
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 != "" {
|
||||
@@ -67,7 +70,7 @@ func (en *Encoding) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return err
|
||||
}
|
||||
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,
|
||||
KeyNode: hL,
|
||||
ValueNode: hN,
|
||||
|
||||
@@ -6,13 +6,15 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Header represents a low-level OpenAPI 3+ Header object.
|
||||
@@ -27,8 +29,8 @@ type Header struct {
|
||||
AllowReserved low.NodeReference[bool]
|
||||
Schema low.NodeReference[*base.SchemaProxy]
|
||||
Example low.NodeReference[any]
|
||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
||||
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*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
|
||||
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
|
||||
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.
|
||||
@@ -73,14 +75,14 @@ func (h *Header) Hash() [32]byte {
|
||||
if h.Example.Value != nil {
|
||||
f = append(f, fmt.Sprint(h.Example.Value))
|
||||
}
|
||||
if len(h.Examples.Value) > 0 {
|
||||
for k := range h.Examples.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Examples.Value[k].Value.Hash()))
|
||||
if orderedmap.Len(h.Examples.Value) > 0 {
|
||||
for pair := orderedmap.First(h.Examples.Value); pair != nil; pair = pair.Next() {
|
||||
f = append(f, fmt.Sprintf("%s-%x", pair.Key().Value, pair.Value().Value.Hash()))
|
||||
}
|
||||
}
|
||||
if len(h.Content.Value) > 0 {
|
||||
for k := range h.Content.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Content.Value[k].Value.Hash()))
|
||||
if orderedmap.Len(h.Content.Value) > 0 {
|
||||
for pair := orderedmap.First(h.Content.Value); pair != nil; pair = pair.Next() {
|
||||
f = append(f, fmt.Sprintf("%s-%x", pair.Key().Value, pair.Value().Value.Hash()))
|
||||
}
|
||||
}
|
||||
keys := make([]string, len(h.Extensions))
|
||||
@@ -113,7 +115,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return eErr
|
||||
}
|
||||
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,
|
||||
KeyNode: expsL,
|
||||
ValueNode: expsN,
|
||||
@@ -134,7 +136,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if cErr != nil {
|
||||
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,
|
||||
KeyNode: cL,
|
||||
ValueNode: cN,
|
||||
|
||||
@@ -6,12 +6,14 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -29,7 +31,7 @@ import (
|
||||
type Link struct {
|
||||
OperationRef 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]
|
||||
Description low.NodeReference[string]
|
||||
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.
|
||||
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
|
||||
@@ -87,10 +89,10 @@ func (l *Link) Hash() [32]byte {
|
||||
}
|
||||
// todo: needs ordering.
|
||||
|
||||
keys := make([]string, len(l.Parameters.Value))
|
||||
keys := make([]string, orderedmap.Len(l.Parameters.Value))
|
||||
z := 0
|
||||
for k := range l.Parameters.Value {
|
||||
keys[z] = l.Parameters.Value[k].Value
|
||||
for pair := orderedmap.First(l.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Value().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,13 +6,15 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MediaType represents a low-level OpenAPI MediaType object.
|
||||
@@ -22,8 +24,8 @@ import (
|
||||
type MediaType struct {
|
||||
Schema low.NodeReference[*base.SchemaProxy]
|
||||
Example low.NodeReference[any]
|
||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
||||
Encoding low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Encoding]]
|
||||
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||
Encoding low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Encoding]]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*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.
|
||||
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.
|
||||
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.
|
||||
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
|
||||
}
|
||||
|
||||
@@ -97,7 +99,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return eErr
|
||||
}
|
||||
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,
|
||||
KeyNode: expsL,
|
||||
ValueNode: expsN,
|
||||
@@ -110,7 +112,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return encErr
|
||||
}
|
||||
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,
|
||||
KeyNode: encsL,
|
||||
ValueNode: encsN,
|
||||
@@ -128,18 +130,18 @@ func (mt *MediaType) Hash() [32]byte {
|
||||
if mt.Example.Value != nil {
|
||||
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
|
||||
for k := range mt.Examples.Value {
|
||||
keys[z] = low.GenerateHashString(mt.Examples.Value[k].Value)
|
||||
for pair := orderedmap.First(mt.Examples.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
keys = make([]string, len(mt.Encoding.Value))
|
||||
keys = make([]string, orderedmap.Len(mt.Encoding.Value))
|
||||
z = 0
|
||||
for k := range mt.Encoding.Value {
|
||||
keys[z] = low.GenerateHashString(mt.Encoding.Value[k].Value)
|
||||
for pair := orderedmap.First(mt.Encoding.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
|
||||
@@ -6,12 +6,14 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -95,7 +97,7 @@ type OAuthFlow struct {
|
||||
AuthorizationUrl low.NodeReference[string]
|
||||
TokenUrl 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]
|
||||
*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.
|
||||
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
|
||||
@@ -134,10 +136,10 @@ func (o *OAuthFlow) Hash() [32]byte {
|
||||
if !o.RefreshUrl.IsEmpty() {
|
||||
f = append(f, o.RefreshUrl.Value)
|
||||
}
|
||||
keys := make([]string, len(o.Scopes.Value))
|
||||
keys := make([]string, orderedmap.Len(o.Scopes.Value))
|
||||
z := 0
|
||||
for k := range o.Scopes.Value {
|
||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, sha256.Sum256([]byte(fmt.Sprint(o.Scopes.Value[k].Value))))
|
||||
for pair := orderedmap.First(o.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, sha256.Sum256([]byte(fmt.Sprint(pair.Value().Value))))
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,13 +6,15 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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]]
|
||||
RequestBody low.NodeReference[*RequestBody]
|
||||
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]
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
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.
|
||||
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.
|
||||
func (o *Operation) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range o.Security.Value {
|
||||
for i := range o.Security.Value[k].Value.Requirements.Value {
|
||||
if i.Value == name {
|
||||
return o.Security.Value[k].Value.Requirements.Value[i].Value
|
||||
requirements := o.Security.Value[k].Value.Requirements
|
||||
for pair := orderedmap.First(requirements.Value); pair != nil; pair = pair.Next() {
|
||||
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
|
||||
}
|
||||
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,
|
||||
KeyNode: cbL,
|
||||
ValueNode: cbN,
|
||||
@@ -202,10 +205,10 @@ func (o *Operation) Hash() [32]byte {
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
|
||||
keys = make([]string, len(o.Callbacks.Value))
|
||||
keys = make([]string, orderedmap.Len(o.Callbacks.Value))
|
||||
z := 0
|
||||
for k := range o.Callbacks.Value {
|
||||
keys[z] = low.GenerateHashString(o.Callbacks.Value[k].Value)
|
||||
for pair := orderedmap.First(o.Callbacks.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
@@ -278,6 +281,6 @@ func (o *Operation) GetServers() low.NodeReference[any] {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -6,13 +6,15 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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]
|
||||
Schema low.NodeReference[*base.SchemaProxy]
|
||||
Example low.NodeReference[any]
|
||||
Examples low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.Example]]
|
||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
||||
Examples low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.Example]]]
|
||||
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*low.Reference
|
||||
}
|
||||
|
||||
// FindContent will attempt to locate a MediaType instance using the specified name.
|
||||
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.
|
||||
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.
|
||||
@@ -85,7 +87,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return eErr
|
||||
}
|
||||
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,
|
||||
KeyNode: expsL,
|
||||
ValueNode: expsN,
|
||||
@@ -97,7 +99,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if cErr != nil {
|
||||
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,
|
||||
KeyNode: cL,
|
||||
ValueNode: cN,
|
||||
@@ -133,18 +135,18 @@ func (p *Parameter) Hash() [32]byte {
|
||||
}
|
||||
|
||||
var keys []string
|
||||
keys = make([]string, len(p.Examples.Value))
|
||||
keys = make([]string, orderedmap.Len(p.Examples.Value))
|
||||
z := 0
|
||||
for k := range p.Examples.Value {
|
||||
keys[z] = low.GenerateHashString(p.Examples.Value[k].Value)
|
||||
for pair := orderedmap.First(p.Examples.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
keys = make([]string, len(p.Content.Value))
|
||||
keys = make([]string, orderedmap.Len(p.Content.Value))
|
||||
z = 0
|
||||
for k := range p.Content.Value {
|
||||
keys[z] = low.GenerateHashString(p.Content.Value[k].Value)
|
||||
for pair := orderedmap.First(p.Content.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,7 +6,6 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -33,28 +32,24 @@ type Paths struct {
|
||||
|
||||
// FindPath will attempt to locate a PathItem using the provided path string.
|
||||
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 {
|
||||
result = pair.ValuePtr()
|
||||
return io.EOF
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
return result
|
||||
}
|
||||
|
||||
// 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]) {
|
||||
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 {
|
||||
key = pair.KeyPtr()
|
||||
value = pair.ValuePtr()
|
||||
return io.EOF
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
return key, value
|
||||
}
|
||||
|
||||
@@ -198,14 +193,12 @@ func (p *Paths) Hash() [32]byte {
|
||||
keys := make(map[string]low.ValueReference[*PathItem])
|
||||
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
|
||||
keys[k] = pair.Value()
|
||||
l[z] = k
|
||||
z++
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||
|
||||
sort.Strings(l)
|
||||
for k := range l {
|
||||
|
||||
@@ -6,19 +6,21 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
|
||||
type RequestBody struct {
|
||||
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]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*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.
|
||||
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.
|
||||
@@ -52,7 +54,7 @@ func (rb *RequestBody) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return cErr
|
||||
}
|
||||
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,
|
||||
KeyNode: cL,
|
||||
ValueNode: cN,
|
||||
@@ -70,8 +72,8 @@ func (rb *RequestBody) Hash() [32]byte {
|
||||
if !rb.Required.IsEmpty() {
|
||||
f = append(f, fmt.Sprint(rb.Required.Value))
|
||||
}
|
||||
for k := range rb.Content.Value {
|
||||
f = append(f, low.GenerateHashString(rb.Content.Value[k].Value))
|
||||
for pair := orderedmap.First(rb.Content.Value); pair != nil; pair = pair.Next() {
|
||||
f = append(f, low.GenerateHashString(pair.Value().Value))
|
||||
}
|
||||
|
||||
keys := make([]string, len(rb.Extensions))
|
||||
|
||||
@@ -6,12 +6,14 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -21,10 +23,10 @@ import (
|
||||
// - https://spec.openapis.org/oas/v3.1.0#response-object
|
||||
type Response struct {
|
||||
Description low.NodeReference[string]
|
||||
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
|
||||
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
|
||||
Headers low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*Header]]]
|
||||
Content low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*MediaType]]]
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
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.
|
||||
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.
|
||||
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.
|
||||
@@ -66,7 +68,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return err
|
||||
}
|
||||
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,
|
||||
KeyNode: lN,
|
||||
ValueNode: kN,
|
||||
@@ -78,7 +80,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return cErr
|
||||
}
|
||||
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,
|
||||
KeyNode: clN,
|
||||
ValueNode: cN,
|
||||
@@ -91,7 +93,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return lErr
|
||||
}
|
||||
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,
|
||||
KeyNode: linkLabel,
|
||||
ValueNode: linkValue,
|
||||
@@ -106,26 +108,26 @@ func (r *Response) Hash() [32]byte {
|
||||
if 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
|
||||
for k := range r.Headers.Value {
|
||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Headers.Value[k].Value))
|
||||
for pair := orderedmap.First(r.Headers.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
keys = make([]string, len(r.Content.Value))
|
||||
keys = make([]string, orderedmap.Len(r.Content.Value))
|
||||
z = 0
|
||||
for k := range r.Content.Value {
|
||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Content.Value[k].Value))
|
||||
for pair := orderedmap.First(r.Content.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
f = append(f, keys...)
|
||||
keys = make([]string, len(r.Links.Value))
|
||||
keys = make([]string, orderedmap.Len(r.Links.Value))
|
||||
z = 0
|
||||
for k := range r.Links.Value {
|
||||
keys[z] = fmt.Sprintf("%s-%s", k.Value, low.GenerateHashString(r.Links.Value[k].Value))
|
||||
for pair := orderedmap.First(r.Links.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = fmt.Sprintf("%s-%s", pair.Key().Value, low.GenerateHashString(pair.Value().Value))
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -6,12 +6,14 @@ package v3
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -33,7 +35,7 @@ import (
|
||||
// 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.
|
||||
type Responses struct {
|
||||
Codes map[low.KeyReference[string]]low.ValueReference[*Response]
|
||||
Codes orderedmap.Map[low.KeyReference[string], low.ValueReference[*Response]]
|
||||
Default low.NodeReference[*Response]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
*low.Reference
|
||||
@@ -75,12 +77,12 @@ func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
||||
for n, o := range r.Codes {
|
||||
if strings.ToLower(n.Value) == DefaultLabel {
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
if strings.ToLower(pair.Key().Value) == DefaultLabel {
|
||||
return &low.NodeReference[*Response]{
|
||||
ValueNode: o.ValueNode,
|
||||
KeyNode: n.KeyNode,
|
||||
Value: o.Value,
|
||||
ValueNode: pair.Value().ValueNode,
|
||||
KeyNode: pair.Key().KeyNode,
|
||||
Value: pair.Value().Value,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,35 +92,33 @@ func (r *Responses) getDefault() *low.NodeReference[*Response] {
|
||||
// used to remove default from codes extracted by Build()
|
||||
func (r *Responses) deleteCode(code string) {
|
||||
var key *low.KeyReference[string]
|
||||
if r.Codes != nil {
|
||||
for k := range r.Codes {
|
||||
if k.Value == code {
|
||||
key = &k
|
||||
break
|
||||
}
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
if pair.Key().Value == code {
|
||||
key = pair.KeyPtr()
|
||||
break
|
||||
}
|
||||
}
|
||||
// should never be nil, but, you never know... science and all that!
|
||||
if key != nil {
|
||||
delete(r.Codes, *key)
|
||||
r.Codes.Delete(*key)
|
||||
}
|
||||
}
|
||||
|
||||
// FindResponseByCode will attempt to locate a Response using an HTTP response code.
|
||||
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
|
||||
func (r *Responses) Hash() [32]byte {
|
||||
var f []string
|
||||
var keys []string
|
||||
keys = make([]string, len(r.Codes))
|
||||
keys = make([]string, orderedmap.Len(r.Codes))
|
||||
cMap := make(map[string]*Response, len(keys))
|
||||
z := 0
|
||||
for k := range r.Codes {
|
||||
keys[z] = k.Value
|
||||
cMap[k.Value] = r.Codes[k].Value
|
||||
for pair := orderedmap.First(r.Codes); pair != nil; pair = pair.Next() {
|
||||
keys[z] = pair.Key().Value
|
||||
cMap[pair.Key().Value] = pair.Value().Value
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -5,12 +5,14 @@ package v3
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"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.
|
||||
@@ -18,7 +20,7 @@ import (
|
||||
type Server struct {
|
||||
URL 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]
|
||||
*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.
|
||||
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.
|
||||
@@ -43,7 +45,7 @@ func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if vars == 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) {
|
||||
var currentNode string
|
||||
var keyNode *yaml.Node
|
||||
@@ -56,15 +58,18 @@ func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
variable := ServerVariable{}
|
||||
variable.Reference = new(low.Reference)
|
||||
_ = low.BuildModel(varNode, &variable)
|
||||
variablesMap[low.KeyReference[string]{
|
||||
Value: currentNode,
|
||||
KeyNode: keyNode,
|
||||
}] = low.ValueReference[*ServerVariable]{
|
||||
ValueNode: varNode,
|
||||
Value: &variable,
|
||||
}
|
||||
variablesMap.Set(
|
||||
low.KeyReference[string]{
|
||||
Value: currentNode,
|
||||
KeyNode: keyNode,
|
||||
},
|
||||
low.ValueReference[*ServerVariable]{
|
||||
ValueNode: varNode,
|
||||
Value: &variable,
|
||||
},
|
||||
)
|
||||
}
|
||||
s.Variables = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*ServerVariable]]{
|
||||
s.Variables = low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*ServerVariable]]]{
|
||||
KeyNode: kn,
|
||||
ValueNode: vars,
|
||||
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
|
||||
func (s *Server) Hash() [32]byte {
|
||||
var f []string
|
||||
keys := make([]string, len(s.Variables.Value))
|
||||
keys := make([]string, orderedmap.Len(s.Variables.Value))
|
||||
z := 0
|
||||
for k := range s.Variables.Value {
|
||||
keys[z] = low.GenerateHashString(s.Variables.Value[k].Value)
|
||||
for pair := orderedmap.First(s.Variables.Value); pair != nil; pair = pair.Next() {
|
||||
keys[z] = low.GenerateHashString(pair.Value().Value)
|
||||
z++
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
@@ -50,7 +50,7 @@ func ExampleNewDocument_fromOpenAPI3Document() {
|
||||
|
||||
// get a count of the number of paths and schemas.
|
||||
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
|
||||
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.
|
||||
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
|
||||
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 {
|
||||
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 {
|
||||
@@ -197,7 +197,7 @@ func ExampleNewDocument_fromUnknownVersion() {
|
||||
}
|
||||
if len(errors) <= 0 {
|
||||
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
|
||||
schemaOne := docModel.Model.Components.Schemas["SchemaOne"].Schema()
|
||||
parameterOne := docModel.Model.Components.Parameters["ParameterOne"]
|
||||
schemaOne := docModel.Model.Components.Schemas.GetOrZero("SchemaOne").Schema()
|
||||
parameterOne := docModel.Model.Components.Parameters.GetOrZero("ParameterOne")
|
||||
|
||||
// unpack schemaOne extensions into complex `cakes` type
|
||||
schemaOneExtensions, schemaUnpackErrors := high.UnpackExtensions[cakes, *low.Schema](schemaOne)
|
||||
|
||||
@@ -8,11 +8,6 @@ import (
|
||||
"strings"
|
||||
"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/high/base"
|
||||
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
||||
@@ -254,17 +249,18 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
||||
// mutate the model
|
||||
h := m.Model
|
||||
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 =
|
||||
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,
|
||||
&base.SecurityRequirement{Requirements: map[string][]string{
|
||||
&base.SecurityRequirement{Requirements: orderedmap.ToOrderedMap(map[string][]string{
|
||||
"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.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example = "I am a teapot, filled with love."
|
||||
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||
|
||||
bytes, _, newDocModel, e := doc.RenderAndReload()
|
||||
assert.Nil(t, e)
|
||||
@@ -273,17 +269,17 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
||||
h = newDocModel.Model
|
||||
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId)
|
||||
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)
|
||||
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.",
|
||||
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",
|
||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl)
|
||||
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl)
|
||||
}
|
||||
|
||||
func TestDocument_Render(t *testing.T) {
|
||||
@@ -304,18 +300,20 @@ func TestDocument_Render(t *testing.T) {
|
||||
|
||||
// mutate the model
|
||||
h := m.Model
|
||||
h.Paths.PathItems["/pet/findByStatus"].Get.OperationId = "findACakeInABakery"
|
||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description = "a nice bucket of mice"
|
||||
h.Paths.PathItems["/pet/findByTags"].Get.Tags =
|
||||
append(h.Paths.PathItems["/pet/findByTags"].Get.Tags, "gurgle", "giggle")
|
||||
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId = "findACakeInABakery"
|
||||
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 =
|
||||
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,
|
||||
&base.SecurityRequirement{Requirements: map[string][]string{
|
||||
h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security = append(h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security,
|
||||
&base.SecurityRequirement{Requirements: orderedmap.ToOrderedMap(map[string][]string{
|
||||
"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.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||
h.Components.Schemas.GetOrZero("Order").Schema().Properties.GetOrZero("status").Schema().Example = "I am a teapot, filled with love."
|
||||
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl = "https://pb33f.io"
|
||||
|
||||
bytes, e := doc.Render()
|
||||
assert.NoError(t, e)
|
||||
@@ -329,19 +327,19 @@ func TestDocument_Render(t *testing.T) {
|
||||
assert.Len(t, docErrs, 0)
|
||||
|
||||
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",
|
||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description)
|
||||
assert.Len(t, h.Paths.PathItems["/pet/findByTags"].Get.Tags, 3)
|
||||
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["/pet/findByTags"].Get.Tags, 3)
|
||||
yu := h.Paths.PathItems["/pet/{petId}"].Delete.Security
|
||||
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements["pizza-and-cake"][0])
|
||||
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||
yu := h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security
|
||||
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.",
|
||||
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",
|
||||
h.Components.SecuritySchemes["petstore_auth"].Flows.Implicit.AuthorizationUrl)
|
||||
h.Components.SecuritySchemes.GetOrZero("petstore_auth").Flows.Implicit.AuthorizationUrl)
|
||||
}
|
||||
|
||||
func TestDocument_RenderWithLargeIndention(t *testing.T) {
|
||||
@@ -354,7 +352,6 @@ func TestDocument_RenderWithLargeIndention(t *testing.T) {
|
||||
doc.BuildV3Model()
|
||||
bytes, _ := doc.Render()
|
||||
assert.Equal(t, json, string(bytes))
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
schemas := v3Model.Model.Components.Schemas
|
||||
assert.Equal(t, 4, len(schemas))
|
||||
assert.Equal(t, 4, orderedmap.Len(schemas))
|
||||
|
||||
fp := schemas["FP"]
|
||||
fbsref := schemas["FBSRef"]
|
||||
fp := schemas.GetOrZero("FP")
|
||||
fbsref := schemas.GetOrZero("FBSRef")
|
||||
|
||||
assert.Equal(t, fp.Schema().Pattern, fbsref.Schema().Pattern)
|
||||
assert.Equal(t, fp.Schema().Example, fbsref.Schema().Example)
|
||||
|
||||
byte := schemas["Byte"]
|
||||
uint64 := schemas["UInt64"]
|
||||
byte := schemas.GetOrZero("Byte")
|
||||
uint64 := schemas.GetOrZero("UInt64")
|
||||
|
||||
assert.Equal(t, uint64.Schema().Format, byte.Schema().Format)
|
||||
assert.Equal(t, uint64.Schema().Type, byte.Schema().Type)
|
||||
@@ -674,7 +671,8 @@ components:
|
||||
example:
|
||||
"4578152156": Not Started
|
||||
"5678904321": On Hold
|
||||
type: object`
|
||||
type: object
|
||||
`
|
||||
|
||||
doc, err := NewDocument([]byte(d))
|
||||
if err != nil {
|
||||
@@ -689,7 +687,7 @@ components:
|
||||
// render the document.
|
||||
rend, _ := result.Model.Render()
|
||||
|
||||
assert.Len(t, rend, 644)
|
||||
assert.Equal(t, d, string(rend))
|
||||
}
|
||||
|
||||
func TestDocument_OperationsAsRefs(t *testing.T) {
|
||||
@@ -897,12 +895,11 @@ func TestDocument_Render_PreserveOrder(t *testing.T) {
|
||||
require.Equal(t, pathCount, orderedmap.Len(pathItems))
|
||||
|
||||
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)
|
||||
assert.Equal(t, pathName, pair.Key())
|
||||
i++
|
||||
return nil
|
||||
})
|
||||
}
|
||||
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] {
|
||||
next := p.Pair.Next()
|
||||
if next == nil {
|
||||
@@ -140,23 +145,13 @@ func ToOrderedMap[K comparable, V any](m map[K]V) Map[K, V] {
|
||||
return om
|
||||
}
|
||||
|
||||
// For iterates a `Map` and calls action() on each map pair.
|
||||
// action() may return `io.EOF` to break iteration.
|
||||
// First returns map's first pair for iteration.
|
||||
// Safely handles nil pointer.
|
||||
func For[K comparable, V any](m Map[K, V], action ActionFunc[K, V]) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
c := Iterate(ctx, m)
|
||||
for pair := range c {
|
||||
err := action(pair)
|
||||
if err == io.EOF {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func First[K comparable, V any](m Map[K, V]) Pair[K, V] {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
return m.First()
|
||||
}
|
||||
|
||||
// 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) {
|
||||
const mapSize = 1000
|
||||
|
||||
|
||||
@@ -5,8 +5,9 @@ package renderer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi"
|
||||
"os"
|
||||
|
||||
"github.com/pb33f/libopenapi"
|
||||
)
|
||||
|
||||
func ExampleMockGenerator_generateBurgerMock_yaml() {
|
||||
@@ -21,7 +22,7 @@ func ExampleMockGenerator_generateBurgerMock_yaml() {
|
||||
v3Model, _ := document.BuildV3Model()
|
||||
|
||||
// create a mock of the Burger model
|
||||
burgerModel := v3Model.Model.Components.Schemas["Burger"]
|
||||
burgerModel := v3Model.Model.Components.Schemas.GetOrZero("Burger")
|
||||
burger := burgerModel.Schema()
|
||||
mock, err := mg.GenerateMock(burger, "")
|
||||
|
||||
@@ -45,7 +46,7 @@ func ExampleMockGenerator_generateFriesMock_json() {
|
||||
v3Model, _ := document.BuildV3Model()
|
||||
|
||||
// create a mock of the Fries model
|
||||
friesModel := v3Model.Model.Components.Schemas["Fries"]
|
||||
friesModel := v3Model.Model.Components.Schemas.GetOrZero("Fries")
|
||||
fries := friesModel.Schema()
|
||||
mock, err := mg.GenerateMock(fries, "")
|
||||
|
||||
@@ -68,7 +69,8 @@ func ExampleMockGenerator_generateRequestMock_json() {
|
||||
v3Model, _ := document.BuildV3Model()
|
||||
|
||||
// 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
|
||||
mock, err := mg.GenerateMock(burgerRequestModel, "cakeBurger")
|
||||
@@ -92,7 +94,8 @@ func ExampleMockGenerator_generateResponseMock_json() {
|
||||
v3Model, _ := document.BuildV3Model()
|
||||
|
||||
// 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
|
||||
mock, err := mg.GenerateMock(burgerResponseModel, "filetOFish")
|
||||
@@ -116,7 +119,7 @@ func ExampleMockGenerator_generatePolymorphicMock_json() {
|
||||
v3Model, _ := document.BuildV3Model()
|
||||
|
||||
// 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()
|
||||
mock, err := mg.GenerateMock(payload, "")
|
||||
|
||||
|
||||
@@ -7,14 +7,16 @@ import (
|
||||
cryptoRand "crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/lucasjones/reggen"
|
||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||
"golang.org/x/exp/slices"
|
||||
"io"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"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"
|
||||
@@ -217,16 +219,17 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
||||
if properties != nil {
|
||||
// check if this schema has required properties, if so, then only render required props, if not
|
||||
// render everything in the schema.
|
||||
checkProps := make(map[string]*base.SchemaProxy)
|
||||
checkProps := orderedmap.New[string, *base.SchemaProxy]()
|
||||
if len(schema.Required) > 0 {
|
||||
for _, requiredProp := range schema.Required {
|
||||
checkProps[requiredProp] = properties[requiredProp]
|
||||
checkProps.Set(requiredProp, properties.GetOrZero(requiredProp))
|
||||
}
|
||||
} else {
|
||||
checkProps = properties
|
||||
}
|
||||
for propName, propValue := range checkProps {
|
||||
for pair := orderedmap.First(checkProps); pair != nil; pair = pair.Next() {
|
||||
// render property
|
||||
propName, propValue := pair.Key(), pair.Value()
|
||||
propertySchema := propValue.Schema()
|
||||
wr.DiveIntoSchema(propertySchema, propName, propertyMap, depth+1)
|
||||
}
|
||||
@@ -249,8 +252,9 @@ func (wr *SchemaRenderer) DiveIntoSchema(schema *base.Schema, key string, struct
|
||||
dependentSchemas := schema.DependentSchemas
|
||||
if dependentSchemas != nil {
|
||||
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
|
||||
k, dependentSchema := pair.Key(), pair.Value()
|
||||
if propertyMap[k] != nil {
|
||||
dependentSchemaCompiled := dependentSchema.Schema()
|
||||
wr.DiveIntoSchema(dependentSchemaCompiled, k, dependentSchemasMap, depth+1)
|
||||
|
||||
@@ -8,17 +8,18 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"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"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"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) {
|
||||
@@ -1144,7 +1145,7 @@ properties:
|
||||
loopMe = func(parent *highbase.SchemaProxy, level int) {
|
||||
schemaProxy := buildSchema()
|
||||
if parent != nil {
|
||||
parent.Schema().Properties["child"] = schemaProxy
|
||||
parent.Schema().Properties.Set("child", schemaProxy)
|
||||
}
|
||||
if level < 110 {
|
||||
loopMe(schemaProxy, level+1)
|
||||
|
||||
@@ -5,7 +5,8 @@ package model
|
||||
|
||||
import (
|
||||
"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.
|
||||
@@ -65,14 +66,14 @@ func CompareCallback(l, r *v3.Callback) *CallbackChanges {
|
||||
lValues := make(map[string]low.ValueReference[*v3.PathItem])
|
||||
rValues := make(map[string]low.ValueReference[*v3.PathItem])
|
||||
|
||||
for k := range l.Expression.Value {
|
||||
lHashes[k.Value] = low.GenerateHashString(l.Expression.Value[k].Value)
|
||||
lValues[k.Value] = l.Expression.Value[k]
|
||||
for pair := orderedmap.First(l.Expression.Value); pair != nil; pair = pair.Next() {
|
||||
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||
lValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
|
||||
for k := range r.Expression.Value {
|
||||
rHashes[k.Value] = low.GenerateHashString(r.Expression.Value[k].Value)
|
||||
rValues[k.Value] = r.Expression.Value[k]
|
||||
for pair := orderedmap.First(r.Expression.Value); pair != nil; pair = pair.Next() {
|
||||
rHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||
rValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
|
||||
expChanges := make(map[string]*PathItemChanges)
|
||||
|
||||
@@ -5,11 +5,13 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"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
|
||||
// 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 {
|
||||
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 {
|
||||
// do nothing
|
||||
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
|
||||
// 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.
|
||||
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 {
|
||||
|
||||
// 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])
|
||||
rValues := make(map[string]low.ValueReference[T])
|
||||
|
||||
for k := range expLeft {
|
||||
lHashes[k.Value] = low.GenerateHashString(expLeft[k].Value)
|
||||
lValues[k.Value] = expLeft[k]
|
||||
for pair := orderedmap.First(expLeft); pair != nil; pair = pair.Next() {
|
||||
k := pair.Key()
|
||||
lHashes[k.Value] = low.GenerateHashString(pair.Value().Value)
|
||||
lValues[k.Value] = pair.Value()
|
||||
}
|
||||
|
||||
for k := range expRight {
|
||||
rHashes[k.Value] = low.GenerateHashString(expRight[k].Value)
|
||||
rValues[k.Value] = expRight[k]
|
||||
for pair := orderedmap.First(expRight); pair != nil; pair = pair.Next() {
|
||||
k := pair.Key()
|
||||
rHashes[k.Value] = low.GenerateHashString(pair.Value().Value)
|
||||
rValues[k.Value] = pair.Value()
|
||||
}
|
||||
|
||||
expChanges := make(map[string]R)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
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
|
||||
@@ -55,7 +56,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
||||
reflect.TypeOf(&v2.ParameterDefinitions{}) == reflect.TypeOf(r) {
|
||||
lDef := l.(*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 {
|
||||
a = lDef.Definitions
|
||||
}
|
||||
@@ -70,7 +71,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
||||
reflect.TypeOf(&v2.ResponsesDefinitions{}) == reflect.TypeOf(r) {
|
||||
lDef := l.(*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 {
|
||||
a = lDef.Definitions
|
||||
}
|
||||
@@ -85,7 +86,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
||||
reflect.TypeOf(&v2.Definitions{}) == reflect.TypeOf(r) {
|
||||
lDef := l.(*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 {
|
||||
a = lDef.Schemas
|
||||
}
|
||||
@@ -100,7 +101,7 @@ func CompareComponents(l, r any) *ComponentsChanges {
|
||||
reflect.TypeOf(&v2.SecurityDefinitions{}) == reflect.TypeOf(r) {
|
||||
lDef := l.(*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 {
|
||||
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.
|
||||
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) {
|
||||
|
||||
// for schemas
|
||||
|
||||
@@ -6,6 +6,7 @@ package model
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
)
|
||||
|
||||
// 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])
|
||||
rValues := make(map[string]low.ValueReference[any])
|
||||
|
||||
for k := range l.Values {
|
||||
lHashes[k.Value] = low.GenerateHashString(l.Values[k].Value)
|
||||
lValues[k.Value] = l.Values[k]
|
||||
for pair := orderedmap.First(l.Values); pair != nil; pair = pair.Next() {
|
||||
lHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||
lValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
|
||||
for k := range r.Values {
|
||||
rHashes[k.Value] = low.GenerateHashString(r.Values[k].Value)
|
||||
rValues[k.Value] = r.Values[k]
|
||||
for pair := orderedmap.First(r.Values); pair != nil; pair = pair.Next() {
|
||||
rHashes[pair.Key().Value] = low.GenerateHashString(pair.Value().Value)
|
||||
rValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
var changes []*Change
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ package model
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
)
|
||||
|
||||
// LinkChanges represent changes made between two OpenAPI Link Objects.
|
||||
@@ -127,11 +128,11 @@ func CompareLinks(l, r *v3.Link) *LinkChanges {
|
||||
// parameters
|
||||
lValues := make(map[string]low.ValueReference[string])
|
||||
rValues := make(map[string]low.ValueReference[string])
|
||||
for i := range l.Parameters.Value {
|
||||
lValues[i.Value] = l.Parameters.Value[i]
|
||||
for pair := orderedmap.First(l.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||
lValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
for i := range r.Parameters.Value {
|
||||
rValues[i.Value] = r.Parameters.Value[i]
|
||||
for pair := orderedmap.First(r.Parameters.Value); pair != nil; pair = pair.Next() {
|
||||
rValues[pair.Key().Value] = pair.Value()
|
||||
}
|
||||
for k := range lValues {
|
||||
if _, ok := rValues[k]; !ok {
|
||||
|
||||
@@ -5,7 +5,8 @@ package model
|
||||
|
||||
import (
|
||||
"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.
|
||||
@@ -228,26 +229,26 @@ func CompareOAuthFlow(l, r *v3.OAuthFlow) *OAuthFlowChanges {
|
||||
|
||||
CheckProperties(props)
|
||||
|
||||
for v := range l.Scopes.Value {
|
||||
if r != nil && r.FindScope(v.Value) == nil {
|
||||
for pair := orderedmap.First(l.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||
if r != nil && r.FindScope(pair.Key().Value) == nil {
|
||||
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
||||
l.Scopes.Value[v].ValueNode, nil, true,
|
||||
v.Value, nil)
|
||||
pair.Value().ValueNode, nil, true,
|
||||
pair.Key().Value, nil)
|
||||
continue
|
||||
}
|
||||
if r != nil && r.FindScope(v.Value) != nil {
|
||||
if l.Scopes.Value[v].Value != r.FindScope(v.Value).Value {
|
||||
if r != nil && r.FindScope(pair.Key().Value) != nil {
|
||||
if pair.Value().Value != r.FindScope(pair.Key().Value).Value {
|
||||
CreateChange(&changes, Modified, v3.Scopes,
|
||||
l.Scopes.Value[v].ValueNode, r.FindScope(v.Value).ValueNode, true,
|
||||
l.Scopes.Value[v].Value, r.FindScope(v.Value).Value)
|
||||
pair.Value().ValueNode, r.FindScope(pair.Key().Value).ValueNode, true,
|
||||
pair.Value().Value, r.FindScope(pair.Key().Value).Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
for v := range r.Scopes.Value {
|
||||
if l != nil && l.FindScope(v.Value) == nil {
|
||||
for pair := orderedmap.First(r.Scopes.Value); pair != nil; pair = pair.Next() {
|
||||
if l != nil && l.FindScope(pair.Key().Value) == nil {
|
||||
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
||||
nil, r.Scopes.Value[v].ValueNode, false,
|
||||
nil, v.Value)
|
||||
nil, pair.Value().ValueNode, false,
|
||||
nil, pair.Key().Value)
|
||||
}
|
||||
}
|
||||
oa := new(OAuthFlowChanges)
|
||||
|
||||
@@ -77,16 +77,12 @@ func ComparePaths(l, r any) *PathsChanges {
|
||||
|
||||
lKeys := 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()
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v2.PathItem]](lPath.PathItems, laction)
|
||||
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2.PathItem]]) error {
|
||||
for pair := orderedmap.First(rPath.PathItems); pair != nil; pair = pair.Next() {
|
||||
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.
|
||||
var mLock sync.Mutex
|
||||
@@ -152,16 +148,12 @@ func ComparePaths(l, r any) *PathsChanges {
|
||||
|
||||
lKeys := 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()
|
||||
return nil
|
||||
}
|
||||
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v3.PathItem]](lPath.PathItems, laction)
|
||||
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3.PathItem]]) error {
|
||||
for pair := orderedmap.First(rPath.PathItems); pair != nil; pair = pair.Next() {
|
||||
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.
|
||||
var mLock sync.Mutex
|
||||
|
||||
@@ -5,14 +5,15 @@ package model
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/exp/slices"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"golang.org/x/exp/slices"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -424,7 +425,7 @@ func checkSchemaXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chan
|
||||
|
||||
func checkMappedSchemaOfASchema(
|
||||
lSchema,
|
||||
rSchema map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy],
|
||||
rSchema orderedmap.Map[low.KeyReference[string], low.ValueReference[*base.SchemaProxy]],
|
||||
changes *[]*Change,
|
||||
doneChan chan bool,
|
||||
) (map[string]*SchemaChanges, int) {
|
||||
@@ -437,15 +438,15 @@ func checkMappedSchemaOfASchema(
|
||||
rEntities := make(map[string]*base.SchemaProxy)
|
||||
rKeyNodes := make(map[string]*yaml.Node)
|
||||
|
||||
for w := range lSchema {
|
||||
lProps = append(lProps, w.Value)
|
||||
lEntities[w.Value] = lSchema[w].Value
|
||||
lKeyNodes[w.Value] = w.KeyNode
|
||||
for pair := orderedmap.First(lSchema); pair != nil; pair = pair.Next() {
|
||||
lProps = append(lProps, pair.Key().Value)
|
||||
lEntities[pair.Key().Value] = pair.Value().Value
|
||||
lKeyNodes[pair.Key().Value] = pair.Key().KeyNode
|
||||
}
|
||||
for w := range rSchema {
|
||||
rProps = append(rProps, w.Value)
|
||||
rEntities[w.Value] = rSchema[w].Value
|
||||
rKeyNodes[w.Value] = w.KeyNode
|
||||
for pair := orderedmap.First(rSchema); pair != nil; pair = pair.Next() {
|
||||
rProps = append(rProps, pair.Key().Value)
|
||||
rEntities[pair.Key().Value] = pair.Value().Value
|
||||
rKeyNodes[pair.Key().Value] = pair.Key().KeyNode
|
||||
}
|
||||
sort.Strings(lProps)
|
||||
sort.Strings(rProps)
|
||||
|
||||
@@ -5,8 +5,9 @@ package model
|
||||
|
||||
import (
|
||||
"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"
|
||||
"github.com/pb33f/libopenapi/orderedmap"
|
||||
)
|
||||
|
||||
// ScopesChanges represents changes between two Swagger Scopes Objects
|
||||
@@ -46,26 +47,26 @@ func CompareScopes(l, r *v2.Scopes) *ScopesChanges {
|
||||
return nil
|
||||
}
|
||||
var changes []*Change
|
||||
for v := range l.Values {
|
||||
if r != nil && r.FindScope(v.Value) == nil {
|
||||
for pair := orderedmap.First(l.Values); pair != nil; pair = pair.Next() {
|
||||
if r != nil && r.FindScope(pair.Key().Value) == nil {
|
||||
CreateChange(&changes, ObjectRemoved, v3.Scopes,
|
||||
l.Values[v].ValueNode, nil, true,
|
||||
v.Value, nil)
|
||||
pair.Value().ValueNode, nil, true,
|
||||
pair.Key().Value, nil)
|
||||
continue
|
||||
}
|
||||
if r != nil && r.FindScope(v.Value) != nil {
|
||||
if l.Values[v].Value != r.FindScope(v.Value).Value {
|
||||
if r != nil && r.FindScope(pair.Key().Value) != nil {
|
||||
if pair.Value().Value != r.FindScope(pair.Key().Value).Value {
|
||||
CreateChange(&changes, Modified, v3.Scopes,
|
||||
l.Values[v].ValueNode, r.FindScope(v.Value).ValueNode, true,
|
||||
l.Values[v].Value, r.FindScope(v.Value).Value)
|
||||
pair.Value().ValueNode, r.FindScope(pair.Key().Value).ValueNode, true,
|
||||
pair.Value().Value, r.FindScope(pair.Key().Value).Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
for v := range r.Values {
|
||||
if l != nil && l.FindScope(v.Value) == nil {
|
||||
for pair := orderedmap.First(r.Values); pair != nil; pair = pair.Next() {
|
||||
if l != nil && l.FindScope(pair.Key().Value) == nil {
|
||||
CreateChange(&changes, ObjectAdded, v3.Scopes,
|
||||
nil, r.Values[v].ValueNode, false,
|
||||
nil, v.Value)
|
||||
nil, pair.Value().ValueNode, false,
|
||||
nil, pair.Key().Value)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,8 @@ package model
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -56,22 +57,22 @@ func addedSecurityRequirement(vn *yaml.Node, name string, changes *[]*Change) {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
lKeys := make([]string, len(lSec))
|
||||
rKeys := make([]string, len(rSec))
|
||||
lKeys := make([]string, orderedmap.Len(lSec))
|
||||
rKeys := make([]string, orderedmap.Len(rSec))
|
||||
lValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
||||
rValues := make(map[string]low.ValueReference[[]low.ValueReference[string]])
|
||||
var n, z int
|
||||
for i := range lSec {
|
||||
lKeys[n] = i.Value
|
||||
lValues[i.Value] = lSec[i]
|
||||
for pair := orderedmap.First(lSec); pair != nil; pair = pair.Next() {
|
||||
lKeys[n] = pair.Key().Value
|
||||
lValues[pair.Key().Value] = pair.Value()
|
||||
n++
|
||||
}
|
||||
for i := range rSec {
|
||||
rKeys[z] = i.Value
|
||||
rValues[i.Value] = rSec[i]
|
||||
for pair := orderedmap.First(rSec); pair != nil; pair = pair.Next() {
|
||||
rKeys[z] = pair.Key().Value
|
||||
rValues[pair.Key().Value] = pair.Value()
|
||||
z++
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user