mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 20:47:45 +00:00
Refactor Paths to OrderedMap.
This commit is contained in:
@@ -4,15 +4,15 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v2low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Paths represents a high-level Swagger / OpenAPI Paths object, backed by a low-level one.
|
// Paths represents a high-level Swagger / OpenAPI Paths object, backed by a low-level one.
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
PathItems map[string]*PathItem
|
PathItems orderedmap.Map[string, *PathItem]
|
||||||
Extensions map[string]any
|
Extensions map[string]any
|
||||||
low *v2low.Paths
|
low *v2low.Paths
|
||||||
}
|
}
|
||||||
@@ -22,19 +22,19 @@ func NewPaths(paths *v2low.Paths) *Paths {
|
|||||||
p := new(Paths)
|
p := new(Paths)
|
||||||
p.low = paths
|
p.low = paths
|
||||||
p.Extensions = high.ExtractExtensions(paths.Extensions)
|
p.Extensions = high.ExtractExtensions(paths.Extensions)
|
||||||
pathItems := make(map[string]*PathItem)
|
pathItems := orderedmap.New[string, *PathItem]()
|
||||||
|
|
||||||
translateFunc := func(key low.KeyReference[string], value low.ValueReference[*v2low.PathItem]) (asyncResult[*PathItem], error) {
|
translateFunc := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2low.PathItem]]) (asyncResult[*PathItem], error) {
|
||||||
return asyncResult[*PathItem]{
|
return asyncResult[*PathItem]{
|
||||||
key: key.Value,
|
key: pair.Key().Value,
|
||||||
result: NewPathItem(value.Value),
|
result: NewPathItem(pair.Value().Value),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
resultFunc := func(result asyncResult[*PathItem]) error {
|
resultFunc := func(result asyncResult[*PathItem]) error {
|
||||||
pathItems[result.key] = result.result
|
pathItems.Set(result.key, result.result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = datamodel.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v2low.PathItem], asyncResult[*PathItem]](
|
_ = orderedmap.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v2low.PathItem], asyncResult[*PathItem]](
|
||||||
paths.PathItems, translateFunc, resultFunc,
|
paths.PathItems, translateFunc, resultFunc,
|
||||||
)
|
)
|
||||||
p.PathItems = pathItems
|
p.PathItems = pathItems
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ func TestNewSwaggerDocument_Paths(t *testing.T) {
|
|||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
assert.Len(t, highDoc.Paths.PathItems, 15)
|
assert.Len(t, highDoc.Paths.PathItems, 15)
|
||||||
|
|
||||||
upload := highDoc.Paths.PathItems["/pet/{petId}/uploadImage"]
|
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage")
|
||||||
assert.Equal(t, "man", upload.Extensions["x-potato"])
|
assert.Equal(t, "man", upload.Extensions["x-potato"])
|
||||||
assert.Nil(t, upload.Get)
|
assert.Nil(t, upload.Get)
|
||||||
assert.Nil(t, upload.Put)
|
assert.Nil(t, upload.Put)
|
||||||
@@ -262,7 +262,7 @@ func TestNewSwaggerDocument_Responses(t *testing.T) {
|
|||||||
|
|
||||||
initTest()
|
initTest()
|
||||||
highDoc := NewSwaggerDocument(doc)
|
highDoc := NewSwaggerDocument(doc)
|
||||||
upload := highDoc.Paths.PathItems["/pet/{petId}/uploadImage"].Post
|
upload := highDoc.Paths.PathItems.GetOrZero("/pet/{petId}/uploadImage").Post
|
||||||
|
|
||||||
assert.Len(t, upload.Responses.Codes, 1)
|
assert.Len(t, upload.Responses.Codes, 1)
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
||||||
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -330,7 +331,7 @@ func TestNewDocument_Paths(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
||||||
burgersOp := h.Paths.PathItems["/burgers"]
|
burgersOp := h.Paths.PathItems.GetOrZero("/burgers")
|
||||||
|
|
||||||
assert.Len(t, burgersOp.GetOperations(), 1)
|
assert.Len(t, burgersOp.GetOperations(), 1)
|
||||||
assert.Equal(t, "meaty", burgersOp.Extensions["x-burger-meta"])
|
assert.Equal(t, "meaty", burgersOp.Extensions["x-burger-meta"])
|
||||||
@@ -410,7 +411,7 @@ func TestAsanaAsDoc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
assert.Equal(t, 118, len(d.Paths.PathItems))
|
assert.Equal(t, 118, orderedmap.Len(d.Paths.PathItems))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
||||||
@@ -434,7 +435,7 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
|||||||
}
|
}
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
assert.Equal(t, 183, len(d.Paths.PathItems))
|
assert.Equal(t, 183, orderedmap.Len(d.Paths.PathItems))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,7 +449,7 @@ func TestPetstoreAsDoc(t *testing.T) {
|
|||||||
}
|
}
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
assert.Equal(t, 13, len(d.Paths.PathItems))
|
assert.Equal(t, 13, orderedmap.Len(d.Paths.PathItems))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularReferencesDoc(t *testing.T) {
|
func TestCircularReferencesDoc(t *testing.T) {
|
||||||
@@ -532,7 +533,7 @@ func TestDocument_MarshalJSON(t *testing.T) {
|
|||||||
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
newDoc := NewDocument(lowDoc)
|
newDoc := NewDocument(lowDoc)
|
||||||
|
|
||||||
assert.Equal(t, len(newDoc.Paths.PathItems), len(highDoc.Paths.PathItems))
|
assert.Equal(t, orderedmap.Len(newDoc.Paths.PathItems), orderedmap.Len(highDoc.Paths.PathItems))
|
||||||
assert.Equal(t, len(newDoc.Components.Schemas), len(highDoc.Components.Schemas))
|
assert.Equal(t, len(newDoc.Components.Schemas), len(highDoc.Components.Schemas))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
|||||||
|
|
||||||
// create a new document and extract a media type object from it.
|
// create a new document and extract a media type object from it.
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
mt := d.Paths.PathItems["/pet"].Put.RequestBody.Content["application/json"]
|
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content["application/json"]
|
||||||
|
|
||||||
// render out the media type
|
// render out the media type
|
||||||
yml, _ := mt.Render()
|
yml, _ := mt.Render()
|
||||||
@@ -118,7 +118,7 @@ func TestMediaType_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
// create a new document and extract a media type object from it.
|
// create a new document and extract a media type object from it.
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
mt := d.Paths.PathItems["/pet"].Put.RequestBody.Content["application/json"]
|
mt := d.Paths.PathItems.GetOrZero("/pet").Put.RequestBody.Content["application/json"]
|
||||||
|
|
||||||
// render out the media type
|
// render out the media type
|
||||||
yml, _ := mt.Render()
|
yml, _ := mt.Render()
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"io/ioutil"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// An example of how to create a new high-level OpenAPI 3+ document from an OpenAPI specification.
|
// An example of how to create a new high-level OpenAPI 3+ document from an OpenAPI specification.
|
||||||
@@ -36,6 +38,6 @@ func Example_createHighLevelOpenAPIDocument() {
|
|||||||
|
|
||||||
// Print out some details
|
// Print out some details
|
||||||
fmt.Printf("Petstore contains %d paths and %d component schemas",
|
fmt.Printf("Petstore contains %d paths and %d component schemas",
|
||||||
len(doc.Paths.PathItems), len(doc.Components.Schemas))
|
orderedmap.Len(doc.Paths.PathItems), len(doc.Components.Schemas))
|
||||||
// Output: Petstore contains 13 paths and 8 component schemas
|
// Output: Petstore contains 13 paths and 8 component schemas
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,10 +6,10 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -21,8 +21,8 @@ import (
|
|||||||
// constraints.
|
// constraints.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#paths-object
|
// - https://spec.openapis.org/oas/v3.1.0#paths-object
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
PathItems map[string]*PathItem `json:"-" yaml:"-"`
|
PathItems orderedmap.Map[string, *PathItem] `json:"-" yaml:"-"`
|
||||||
Extensions map[string]any `json:"-" yaml:"-"`
|
Extensions map[string]any `json:"-" yaml:"-"`
|
||||||
low *v3low.Paths
|
low *v3low.Paths
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,21 +31,21 @@ func NewPaths(paths *v3low.Paths) *Paths {
|
|||||||
p := new(Paths)
|
p := new(Paths)
|
||||||
p.low = paths
|
p.low = paths
|
||||||
p.Extensions = high.ExtractExtensions(paths.Extensions)
|
p.Extensions = high.ExtractExtensions(paths.Extensions)
|
||||||
items := make(map[string]*PathItem)
|
items := orderedmap.New[string, *PathItem]()
|
||||||
|
|
||||||
type pathItemResult struct {
|
type pathItemResult struct {
|
||||||
key string
|
key string
|
||||||
value *PathItem
|
value *PathItem
|
||||||
}
|
}
|
||||||
|
|
||||||
translateFunc := func(key low.KeyReference[string], value low.ValueReference[*v3low.PathItem]) (pathItemResult, error) {
|
translateFunc := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3low.PathItem]]) (pathItemResult, error) {
|
||||||
return pathItemResult{key: key.Value, value: NewPathItem(value.Value)}, nil
|
return pathItemResult{key: pair.Key().Value, value: NewPathItem(pair.Value().Value)}, nil
|
||||||
}
|
}
|
||||||
resultFunc := func(value pathItemResult) error {
|
resultFunc := func(value pathItemResult) error {
|
||||||
items[value.key] = value.value
|
items.Set(value.key, value.value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = datamodel.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v3low.PathItem], pathItemResult](
|
_ = orderedmap.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v3low.PathItem], pathItemResult](
|
||||||
paths.PathItems, translateFunc, resultFunc,
|
paths.PathItems, translateFunc, resultFunc,
|
||||||
)
|
)
|
||||||
p.PathItems = items
|
p.PathItems = items
|
||||||
@@ -84,7 +84,9 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*pathItem
|
var mapped []*pathItem
|
||||||
|
|
||||||
for k, pi := range p.PathItems {
|
action := func(pair orderedmap.Pair[string, *PathItem]) error {
|
||||||
|
k := pair.Key()
|
||||||
|
pi := pair.Value()
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
if p.low != nil {
|
if p.low != nil {
|
||||||
lpi := p.low.FindPath(k)
|
lpi := p.low.FindPath(k)
|
||||||
@@ -93,7 +95,9 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
||||||
|
|
||||||
nb := high.NewNodeBuilder(p, p.low)
|
nb := high.NewNodeBuilder(p, p.low)
|
||||||
extNode := nb.Render()
|
extNode := nb.Render()
|
||||||
@@ -138,7 +142,9 @@ func (p *Paths) MarshalYAMLInline() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
var mapped []*pathItem
|
var mapped []*pathItem
|
||||||
|
|
||||||
for k, pi := range p.PathItems {
|
action := func(pair orderedmap.Pair[string, *PathItem]) error {
|
||||||
|
k := pair.Key()
|
||||||
|
pi := pair.Value()
|
||||||
ln := 9999 // default to a high value to weight new content to the bottom.
|
ln := 9999 // default to a high value to weight new content to the bottom.
|
||||||
if p.low != nil {
|
if p.low != nil {
|
||||||
lpi := p.low.FindPath(k)
|
lpi := p.low.FindPath(k)
|
||||||
@@ -147,7 +153,9 @@ func (p *Paths) MarshalYAMLInline() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
mapped = append(mapped, &pathItem{pi, k, ln, nil})
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[string, *PathItem](p.PathItems, action)
|
||||||
|
|
||||||
nb := high.NewNodeBuilder(p, p.low)
|
nb := high.NewNodeBuilder(p, p.low)
|
||||||
nb.Resolve = true
|
nb.Resolve = true
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func TestPaths_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
// mutate
|
// mutate
|
||||||
deprecated := true
|
deprecated := true
|
||||||
high.PathItems["/beer"].Get.Deprecated = &deprecated
|
high.PathItems.GetOrZero("/beer").Get.Deprecated = &deprecated
|
||||||
|
|
||||||
yml = `/foo/bar/bizzle:
|
yml = `/foo/bar/bizzle:
|
||||||
get:
|
get:
|
||||||
@@ -100,7 +100,7 @@ func TestPaths_MarshalYAMLInline(t *testing.T) {
|
|||||||
|
|
||||||
// mutate
|
// mutate
|
||||||
deprecated := true
|
deprecated := true
|
||||||
high.PathItems["/beer"].Get.Deprecated = &deprecated
|
high.PathItems.GetOrZero("/beer").Get.Deprecated = &deprecated
|
||||||
|
|
||||||
yml = `/foo/bar/bizzle:
|
yml = `/foo/bar/bizzle:
|
||||||
get:
|
get:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v2
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -13,13 +14,14 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Paths represents a low-level Swagger / OpenAPI Paths object.
|
// Paths represents a low-level Swagger / OpenAPI Paths object.
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
PathItems map[low.KeyReference[string]]low.ValueReference[*PathItem]
|
PathItems orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,23 +31,30 @@ func (p *Paths) GetExtensions() map[low.KeyReference[string]]low.ValueReference[
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FindPath attempts to locate a PathItem instance, given a path key.
|
// FindPath attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] {
|
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
||||||
for k, j := range p.PathItems {
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
if k.Value == path {
|
if pair.Key().Value == path {
|
||||||
return &j
|
result = pair.ValuePtr()
|
||||||
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
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.
|
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPathAndKey(path string) (*low.KeyReference[string], *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
||||||
for k, j := range p.PathItems {
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
if k.Value == path {
|
if pair.Key().Value == path {
|
||||||
return &k, &j
|
key = pair.KeyPtr()
|
||||||
|
value = pair.ValuePtr()
|
||||||
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||||
|
return key, value
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension will attempt to locate an extension value given a name.
|
// FindExtension will attempt to locate an extension value given a name.
|
||||||
@@ -68,7 +77,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
currentNode *yaml.Node
|
currentNode *yaml.Node
|
||||||
pathNode *yaml.Node
|
pathNode *yaml.Node
|
||||||
}
|
}
|
||||||
pathsMap := make(map[low.KeyReference[string]]low.ValueReference[*PathItem])
|
pathsMap := orderedmap.New[low.KeyReference[string], low.ValueReference[*PathItem]]()
|
||||||
in := make(chan buildInput)
|
in := make(chan buildInput)
|
||||||
out := make(chan pathBuildResult)
|
out := make(chan pathBuildResult)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@@ -115,7 +124,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pathsMap[result.key] = result.value
|
pathsMap.Set(result.key, result.value)
|
||||||
}
|
}
|
||||||
close(done)
|
close(done)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -154,14 +163,19 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the PathItem object
|
// Hash will return a consistent SHA256 Hash of the PathItem object
|
||||||
func (p *Paths) Hash() [32]byte {
|
func (p *Paths) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
l := make([]string, len(p.PathItems))
|
l := make([]string, orderedmap.Len(p.PathItems))
|
||||||
keys := make(map[string]low.ValueReference[*PathItem])
|
keys := make(map[string]low.ValueReference[*PathItem])
|
||||||
z := 0
|
z := 0
|
||||||
for k := range p.PathItems {
|
|
||||||
keys[k.Value] = p.PathItems[k]
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
l[z] = k.Value
|
k := pair.Key().Value
|
||||||
|
keys[k] = pair.Value()
|
||||||
|
l[z] = k
|
||||||
z++
|
z++
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||||
|
|
||||||
sort.Strings(l)
|
sort.Strings(l)
|
||||||
for k := range l {
|
for k := range l {
|
||||||
f = append(f, low.GenerateHashString(keys[l[k]].Value))
|
f = append(f, low.GenerateHashString(keys[l[k]].Value))
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -24,29 +26,36 @@ import (
|
|||||||
// constraints.
|
// constraints.
|
||||||
// - https://spec.openapis.org/oas/v3.1.0#paths-object
|
// - https://spec.openapis.org/oas/v3.1.0#paths-object
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
PathItems map[low.KeyReference[string]]low.ValueReference[*PathItem]
|
PathItems orderedmap.Map[low.KeyReference[string], low.ValueReference[*PathItem]]
|
||||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindPath will attempt to locate a PathItem using the provided path string.
|
// FindPath will attempt to locate a PathItem using the provided path string.
|
||||||
func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] {
|
func (p *Paths) FindPath(path string) (result *low.ValueReference[*PathItem]) {
|
||||||
for k, j := range p.PathItems {
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
if k.Value == path {
|
if pair.Key().Value == path {
|
||||||
return &j
|
result = pair.ValuePtr()
|
||||||
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
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.
|
// FindPathAndKey attempts to locate a PathItem instance, given a path key.
|
||||||
func (p *Paths) FindPathAndKey(path string) (*low.KeyReference[string], *low.ValueReference[*PathItem]) {
|
func (p *Paths) FindPathAndKey(path string) (key *low.KeyReference[string], value *low.ValueReference[*PathItem]) {
|
||||||
for k, j := range p.PathItems {
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
if k.Value == path {
|
if pair.Key().Value == path {
|
||||||
return &k, &j
|
key = pair.KeyPtr()
|
||||||
|
value = pair.ValuePtr()
|
||||||
|
return io.EOF
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil, nil
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||||
|
return key, value
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension will attempt to locate an extension using the specified string.
|
// FindExtension will attempt to locate an extension using the specified string.
|
||||||
@@ -75,7 +84,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
currentNode *yaml.Node
|
currentNode *yaml.Node
|
||||||
pathNode *yaml.Node
|
pathNode *yaml.Node
|
||||||
}
|
}
|
||||||
pathsMap := make(map[low.KeyReference[string]]low.ValueReference[*PathItem])
|
pathsMap := orderedmap.New[low.KeyReference[string], low.ValueReference[*PathItem]]()
|
||||||
in := make(chan buildInput)
|
in := make(chan buildInput)
|
||||||
out := make(chan buildResult)
|
out := make(chan buildResult)
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@@ -122,7 +131,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if !ok {
|
if !ok {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
pathsMap[result.key] = result.value
|
pathsMap.Set(result.key, result.value)
|
||||||
}
|
}
|
||||||
close(done)
|
close(done)
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -185,14 +194,19 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// Hash will return a consistent SHA256 Hash of the PathItem object
|
// Hash will return a consistent SHA256 Hash of the PathItem object
|
||||||
func (p *Paths) Hash() [32]byte {
|
func (p *Paths) Hash() [32]byte {
|
||||||
var f []string
|
var f []string
|
||||||
l := make([]string, len(p.PathItems))
|
l := make([]string, orderedmap.Len(p.PathItems))
|
||||||
keys := make(map[string]low.ValueReference[*PathItem])
|
keys := make(map[string]low.ValueReference[*PathItem])
|
||||||
z := 0
|
z := 0
|
||||||
for k := range p.PathItems {
|
|
||||||
keys[k.Value] = p.PathItems[k]
|
action := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*PathItem]]) error {
|
||||||
l[z] = k.Value
|
k := pair.Key().Value
|
||||||
|
keys[k] = pair.Value()
|
||||||
|
l[z] = k
|
||||||
z++
|
z++
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*PathItem]](p.PathItems, action)
|
||||||
|
|
||||||
sort.Strings(l)
|
sort.Strings(l)
|
||||||
for k := range l {
|
for k := range l {
|
||||||
f = append(f, fmt.Sprintf("%s-%s", l[k], low.GenerateHashString(keys[l[k]].Value)))
|
f = append(f, fmt.Sprintf("%s-%s", l[k], low.GenerateHashString(keys[l[k]].Value)))
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ package libopenapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/base"
|
low "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
@@ -47,7 +49,7 @@ func ExampleNewDocument_fromOpenAPI3Document() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get a count of the number of paths and schemas.
|
// get a count of the number of paths and schemas.
|
||||||
paths := len(v3Model.Model.Paths.PathItems)
|
paths := orderedmap.Len(v3Model.Model.Paths.PathItems)
|
||||||
schemas := len(v3Model.Model.Components.Schemas)
|
schemas := len(v3Model.Model.Components.Schemas)
|
||||||
|
|
||||||
// print the number of paths and schemas in the document
|
// print the number of paths and schemas in the document
|
||||||
@@ -153,7 +155,7 @@ func ExampleNewDocument_fromSwaggerDocument() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get a count of the number of paths and schemas.
|
// get a count of the number of paths and schemas.
|
||||||
paths := len(v2Model.Model.Paths.PathItems)
|
paths := orderedmap.Len(v2Model.Model.Paths.PathItems)
|
||||||
schemas := len(v2Model.Model.Definitions.Definitions)
|
schemas := len(v2Model.Model.Definitions.Definitions)
|
||||||
|
|
||||||
// print the number of paths and schemas in the document
|
// print the number of paths and schemas in the document
|
||||||
@@ -184,7 +186,7 @@ func ExampleNewDocument_fromUnknownVersion() {
|
|||||||
errors = errs
|
errors = errs
|
||||||
}
|
}
|
||||||
if len(errors) <= 0 {
|
if len(errors) <= 0 {
|
||||||
paths = len(v3Model.Model.Paths.PathItems)
|
paths = orderedmap.Len(v3Model.Model.Paths.PathItems)
|
||||||
schemas = len(v3Model.Model.Components.Schemas)
|
schemas = len(v3Model.Model.Components.Schemas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,7 +196,7 @@ func ExampleNewDocument_fromUnknownVersion() {
|
|||||||
errors = errs
|
errors = errs
|
||||||
}
|
}
|
||||||
if len(errors) <= 0 {
|
if len(errors) <= 0 {
|
||||||
paths = len(v2Model.Model.Paths.PathItems)
|
paths = orderedmap.Len(v2Model.Model.Paths.PathItems)
|
||||||
schemas = len(v2Model.Model.Definitions.Definitions)
|
schemas = len(v2Model.Model.Definitions.Definitions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -641,10 +643,10 @@ func ExampleNewDocument_modifyAndReRender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// capture original number of paths
|
// capture original number of paths
|
||||||
originalPaths := len(v3Model.Model.Paths.PathItems)
|
originalPaths := orderedmap.Len(v3Model.Model.Paths.PathItems)
|
||||||
|
|
||||||
// add the path to the document
|
// add the path to the document
|
||||||
v3Model.Model.Paths.PathItems["/new/path"] = newPath
|
v3Model.Model.Paths.PathItems.Set("/new/path", newPath)
|
||||||
|
|
||||||
// render the document back to bytes and reload the model.
|
// render the document back to bytes and reload the model.
|
||||||
rawBytes, _, newModel, errs := doc.RenderAndReload()
|
rawBytes, _, newModel, errs := doc.RenderAndReload()
|
||||||
@@ -655,7 +657,7 @@ func ExampleNewDocument_modifyAndReRender() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// capture new number of paths after re-rendering
|
// capture new number of paths after re-rendering
|
||||||
newPaths := len(newModel.Model.Paths.PathItems)
|
newPaths := orderedmap.Len(newModel.Model.Paths.PathItems)
|
||||||
|
|
||||||
// print the number of paths and schemas in the document
|
// print the number of paths and schemas in the document
|
||||||
fmt.Printf("There were %d original paths. There are now %d paths in the document\n", originalPaths, newPaths)
|
fmt.Printf("There were %d original paths. There are now %d paths in the document\n", originalPaths, newPaths)
|
||||||
|
|||||||
@@ -4,13 +4,22 @@ package libopenapi
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high/base"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
"github.com/pb33f/libopenapi/what-changed/model"
|
"github.com/pb33f/libopenapi/what-changed/model"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"os"
|
|
||||||
"strings"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"testing"
|
"github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
|
v3high "github.com/pb33f/libopenapi/datamodel/high/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/what-changed/model"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLoadDocument_Simple_V2(t *testing.T) {
|
func TestLoadDocument_Simple_V2(t *testing.T) {
|
||||||
@@ -244,12 +253,12 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
|||||||
|
|
||||||
// mutate the model
|
// mutate the model
|
||||||
h := m.Model
|
h := m.Model
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.OperationId = "findACakeInABakery"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId = "findACakeInABakery"
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description = "a nice bucket of mice"
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes["400"].Description = "a nice bucket of mice"
|
||||||
h.Paths.PathItems["/pet/findByTags"].Get.Tags =
|
h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags =
|
||||||
append(h.Paths.PathItems["/pet/findByTags"].Get.Tags, "gurgle", "giggle")
|
append(h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, "gurgle", "giggle")
|
||||||
|
|
||||||
h.Paths.PathItems["/pet/{petId}"].Delete.Security = append(h.Paths.PathItems["/pet/{petId}"].Delete.Security,
|
h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security = append(h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security,
|
||||||
&base.SecurityRequirement{Requirements: map[string][]string{
|
&base.SecurityRequirement{Requirements: map[string][]string{
|
||||||
"pizza-and-cake": {"read:abook", "write:asong"},
|
"pizza-and-cake": {"read:abook", "write:asong"},
|
||||||
}})
|
}})
|
||||||
@@ -262,13 +271,13 @@ func TestDocument_RenderAndReload(t *testing.T) {
|
|||||||
assert.NotNil(t, bytes)
|
assert.NotNil(t, bytes)
|
||||||
|
|
||||||
h = newDocModel.Model
|
h = newDocModel.Model
|
||||||
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems["/pet/findByStatus"].Get.OperationId)
|
assert.Equal(t, "findACakeInABakery", h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.OperationId)
|
||||||
assert.Equal(t, "a nice bucket of mice",
|
assert.Equal(t, "a nice bucket of mice",
|
||||||
h.Paths.PathItems["/pet/findByStatus"].Get.Responses.Codes["400"].Description)
|
h.Paths.PathItems.GetOrZero("/pet/findByStatus").Get.Responses.Codes["400"].Description)
|
||||||
assert.Len(t, h.Paths.PathItems["/pet/findByTags"].Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
|
|
||||||
assert.Len(t, h.Paths.PathItems["/pet/findByTags"].Get.Tags, 3)
|
assert.Len(t, h.Paths.PathItems.GetOrZero("/pet/findByTags").Get.Tags, 3)
|
||||||
yu := h.Paths.PathItems["/pet/{petId}"].Delete.Security
|
yu := h.Paths.PathItems.GetOrZero("/pet/{petId}").Delete.Security
|
||||||
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements["pizza-and-cake"][0])
|
assert.Equal(t, "read:abook", yu[len(yu)-1].Requirements["pizza-and-cake"][0])
|
||||||
assert.Equal(t, "I am a teapot, filled with love.",
|
assert.Equal(t, "I am a teapot, filled with love.",
|
||||||
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example)
|
h.Components.Schemas["Order"].Schema().Properties["status"].Schema().Example)
|
||||||
@@ -479,7 +488,7 @@ paths:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract operation.
|
// extract operation.
|
||||||
operation := result.Model.Paths.PathItems["/something"].Get
|
operation := result.Model.Paths.PathItems.GetOrZero("/something").Get
|
||||||
|
|
||||||
// print it out.
|
// print it out.
|
||||||
fmt.Printf("param1: %s, is reference? %t, original reference %s",
|
fmt.Printf("param1: %s, is reference? %t, original reference %s",
|
||||||
@@ -647,7 +656,7 @@ paths:
|
|||||||
// panic(errs)
|
// panic(errs)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// assert.Equal(t, "crs", result.Model.Paths.PathItems["/test"].Get.Parameters[0].Name)
|
// assert.Equal(t, "crs", result.Model.Paths.PathItems.GetOrZero("/test").Get.Parameters[0].Name)
|
||||||
//}
|
//}
|
||||||
|
|
||||||
func TestDocument_ExampleMap(t *testing.T) {
|
func TestDocument_ExampleMap(t *testing.T) {
|
||||||
@@ -858,3 +867,59 @@ components:
|
|||||||
assert.Len(t, m.Index.GetCircularReferences(), 0)
|
assert.Len(t, m.Index.GetCircularReferences(), 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure document ordering is preserved after building and loading.
|
||||||
|
func TestDocument_Render_PreserveOrder(t *testing.T) {
|
||||||
|
t.Run("Paths", func(t *testing.T) {
|
||||||
|
const pathCount = 100
|
||||||
|
doc, err := NewDocument([]byte(`openapi: 3.1.0`))
|
||||||
|
require.NoError(t, err)
|
||||||
|
model, errs := doc.BuildV3Model()
|
||||||
|
require.Empty(t, errs)
|
||||||
|
pathItems := orderedmap.New[string, *v3high.PathItem]()
|
||||||
|
model.Model.Paths = &v3high.Paths{
|
||||||
|
PathItems: pathItems,
|
||||||
|
}
|
||||||
|
for i := 0; i < pathCount; i++ {
|
||||||
|
pathItem := &v3high.PathItem{
|
||||||
|
Get: &v3high.Operation{
|
||||||
|
Parameters: make([]*v3high.Parameter, 0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
pathName := fmt.Sprintf("/foobar/%d", i)
|
||||||
|
pathItems.Set(pathName, pathItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkOrder := func(t *testing.T, doc Document) {
|
||||||
|
model, errs := doc.BuildV3Model()
|
||||||
|
require.Empty(t, errs)
|
||||||
|
pathItems := model.Model.Paths.PathItems
|
||||||
|
require.Equal(t, pathCount, orderedmap.Len(pathItems))
|
||||||
|
|
||||||
|
var i int
|
||||||
|
_ = orderedmap.For(model.Model.Paths.PathItems, func(pair orderedmap.Pair[string, *v3high.PathItem]) error {
|
||||||
|
pathName := fmt.Sprintf("/foobar/%d", i)
|
||||||
|
assert.Equal(t, pathName, pair.Key())
|
||||||
|
i++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
assert.Equal(t, pathCount, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
checkOrder(t, doc)
|
||||||
|
yamlBytes, doc, _, errs := doc.RenderAndReload()
|
||||||
|
require.Empty(t, errs)
|
||||||
|
|
||||||
|
t.Run("Unmarshalled YAML ordering", func(t *testing.T) {
|
||||||
|
// Reload YAML into new Document, verify ordering.
|
||||||
|
doc2, err := NewDocument(yamlBytes)
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkOrder(t, doc2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Reloaded document ordering", func(t *testing.T) {
|
||||||
|
// Verify ordering of reloaded document after call to RenderAndReload().
|
||||||
|
checkOrder(t, doc)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,11 +4,13 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PathsChanges represents changes found between two Swagger or OpenAPI Paths Objects.
|
// PathsChanges represents changes found between two Swagger or OpenAPI Paths Objects.
|
||||||
@@ -75,12 +77,16 @@ func ComparePaths(l, r any) *PathsChanges {
|
|||||||
|
|
||||||
lKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
lKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
||||||
rKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
rKeys := make(map[string]low.ValueReference[*v2.PathItem])
|
||||||
for k := range lPath.PathItems {
|
laction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2.PathItem]]) error {
|
||||||
lKeys[k.Value] = lPath.PathItems[k]
|
lKeys[pair.Key().Value] = pair.Value()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
for k := range rPath.PathItems {
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v2.PathItem]](lPath.PathItems, laction)
|
||||||
rKeys[k.Value] = rPath.PathItems[k]
|
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v2.PathItem]]) error {
|
||||||
|
rKeys[pair.Key().Value] = pair.Value()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v2.PathItem]](rPath.PathItems, raction)
|
||||||
|
|
||||||
// run every comparison in a thread.
|
// run every comparison in a thread.
|
||||||
var mLock sync.Mutex
|
var mLock sync.Mutex
|
||||||
@@ -146,12 +152,16 @@ func ComparePaths(l, r any) *PathsChanges {
|
|||||||
|
|
||||||
lKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
lKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
rKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
rKeys := make(map[string]low.ValueReference[*v3.PathItem])
|
||||||
for k := range lPath.PathItems {
|
laction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3.PathItem]]) error {
|
||||||
lKeys[k.Value] = lPath.PathItems[k]
|
lKeys[pair.Key().Value] = pair.Value()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
for k := range rPath.PathItems {
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v3.PathItem]](lPath.PathItems, laction)
|
||||||
rKeys[k.Value] = rPath.PathItems[k]
|
raction := func(pair orderedmap.Pair[low.KeyReference[string], low.ValueReference[*v3.PathItem]]) error {
|
||||||
|
rKeys[pair.Key().Value] = pair.Value()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
_ = orderedmap.For[low.KeyReference[string], low.ValueReference[*v3.PathItem]](rPath.PathItems, raction)
|
||||||
|
|
||||||
// run every comparison in a thread.
|
// run every comparison in a thread.
|
||||||
var mLock sync.Mutex
|
var mLock sync.Mutex
|
||||||
|
|||||||
Reference in New Issue
Block a user