mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-10 12:37:48 +00:00
High level model build is currently fast as lightning.
little refactoring to keep things all clean and in place.
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
package datamodel
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/3.0"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExternalDoc_Build(t *testing.T) {
|
|
||||||
|
|
||||||
yml := `url: https://pb33f.io
|
|
||||||
description: the ranch
|
|
||||||
x-b33f: princess`
|
|
||||||
|
|
||||||
var idxNode yaml.Node
|
|
||||||
mErr := yaml.Unmarshal([]byte(yml), &idxNode)
|
|
||||||
assert.NoError(t, mErr)
|
|
||||||
idx := index.NewSpecIndex(&idxNode)
|
|
||||||
|
|
||||||
var n v3.ExternalDoc
|
|
||||||
err := low.BuildModel(&idxNode, &n)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, "https://pb33f.io", n.URL.Value)
|
|
||||||
assert.Equal(t, "the ranch", n.Description.Value)
|
|
||||||
ext := n.FindExtension("x-b33f")
|
|
||||||
assert.NotNil(t, ext)
|
|
||||||
assert.Equal(t, "princess", ext.Value)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -6,11 +6,25 @@ package v3
|
|||||||
import low "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
import low "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
||||||
|
|
||||||
type Callback struct {
|
type Callback struct {
|
||||||
Expression map[string]*PathItem
|
Expression map[string]*PathItem
|
||||||
Extensions map[string]any
|
Extensions map[string]any
|
||||||
low *low.Callback
|
low *low.Callback
|
||||||
|
}
|
||||||
|
|
||||||
|
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.Extensions = make(map[string]any)
|
||||||
|
for k, v := range lowCallback.Extensions {
|
||||||
|
n.Extensions[k.Value] = v
|
||||||
|
}
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Callback) GoLow() *low.Callback {
|
func (c *Callback) GoLow() *low.Callback {
|
||||||
return c.low
|
return c.low
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,15 @@ type Contact struct {
|
|||||||
low *low.Contact
|
low *low.Contact
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewContact(contact *low.Contact) *Contact {
|
||||||
|
c := new(Contact)
|
||||||
|
c.low = contact
|
||||||
|
c.URL = contact.URL.Value
|
||||||
|
c.Name = contact.Name.Value
|
||||||
|
c.Email = contact.Email.Value
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Contact) GoLow() *low.Contact {
|
func (c *Contact) GoLow() *low.Contact {
|
||||||
return c.low
|
return c.low
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ type Document struct {
|
|||||||
low *low.Document
|
low *low.Document
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDocument(document *low.Document) *Document {
|
||||||
|
d := new(Document)
|
||||||
|
d.low = document
|
||||||
|
d.Info = NewInfo(document.Info.Value)
|
||||||
|
d.Version = document.Version.Value
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Document) GoLow() *low.Document {
|
func (d *Document) GoLow() *low.Document {
|
||||||
return d.low
|
return d.low
|
||||||
}
|
}
|
||||||
|
|||||||
43
datamodel/high/3.0/document_test.go
Normal file
43
datamodel/high/3.0/document_test.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var doc *lowv3.Document
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
data, _ := ioutil.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
var err []error
|
||||||
|
doc, err = lowv3.CreateDocument(info)
|
||||||
|
if err != nil {
|
||||||
|
panic("broken something")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkNewDocument(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = NewDocument(doc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewDocument_Info(t *testing.T) {
|
||||||
|
highDoc := NewDocument(doc)
|
||||||
|
assert.Equal(t, "3.0.1", highDoc.Version)
|
||||||
|
assert.Equal(t, "Burger Shop", highDoc.Info.Title)
|
||||||
|
assert.Equal(t, "https://pb33f.io", highDoc.Info.TermsOfService)
|
||||||
|
assert.Equal(t, "pb33f", highDoc.Info.Contact.Name)
|
||||||
|
assert.Equal(t, "buckaroo@pb33f.io", highDoc.Info.Contact.Email)
|
||||||
|
assert.Equal(t, "https://pb33f.io", highDoc.Info.Contact.URL)
|
||||||
|
assert.Equal(t, "pb33f", highDoc.Info.License.Name)
|
||||||
|
assert.Equal(t, "https://pb33f.io/made-up", highDoc.Info.License.URL)
|
||||||
|
assert.Equal(t, "1.2", highDoc.Info.Version)
|
||||||
|
}
|
||||||
@@ -15,6 +15,18 @@ type Info struct {
|
|||||||
low *low.Info
|
low *low.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewInfo(info *low.Info) *Info {
|
||||||
|
i := new(Info)
|
||||||
|
i.low = info
|
||||||
|
i.Title = info.Title.Value
|
||||||
|
i.Description = info.Description.Value
|
||||||
|
i.TermsOfService = info.TermsOfService.Value
|
||||||
|
i.Contact = NewContact(info.Contact.Value)
|
||||||
|
i.License = NewLicense(info.License.Value)
|
||||||
|
i.Version = info.Version.Value
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Info) GoLow() *low.Info {
|
func (i *Info) GoLow() *low.Info {
|
||||||
return i.low
|
return i.low
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,14 @@ type License struct {
|
|||||||
low *low.License
|
low *low.License
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewLicense(license *low.License) *License {
|
||||||
|
l := new(License)
|
||||||
|
l.low = license
|
||||||
|
l.URL = license.URL.Value
|
||||||
|
l.Name = license.Name.Value
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func (l *License) GoLow() *low.License {
|
func (l *License) GoLow() *low.License {
|
||||||
return l.low
|
return l.low
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,13 @@ type PathItem struct {
|
|||||||
low *low.PathItem
|
low *low.PathItem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewPathItem(lowPathItem *low.PathItem) *PathItem {
|
||||||
|
pi := new(PathItem)
|
||||||
|
pi.Description = lowPathItem.Description.Value
|
||||||
|
pi.Summary = lowPathItem.Summary.Value
|
||||||
|
return pi
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PathItem) GoLow() *low.PathItem {
|
func (p *PathItem) GoLow() *low.PathItem {
|
||||||
return p.low
|
return p.low
|
||||||
}
|
}
|
||||||
|
|||||||
171
datamodel/low/3.0/create_document.go
Normal file
171
datamodel/low/3.0/create_document.go
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
package v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateDocument(info *datamodel.SpecInfo) (*Document, []error) {
|
||||||
|
|
||||||
|
doc := Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||||
|
|
||||||
|
// build an index
|
||||||
|
idx := index.NewSpecIndex(info.RootNode)
|
||||||
|
doc.Index = idx
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
var runExtraction = func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||||
|
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||||
|
ers *[]error,
|
||||||
|
wg *sync.WaitGroup) {
|
||||||
|
|
||||||
|
if er := runFunc(info, doc, idx); er != nil {
|
||||||
|
*ers = append(*ers, er)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
||||||
|
extractInfo,
|
||||||
|
extractServers,
|
||||||
|
extractTags,
|
||||||
|
extractPaths,
|
||||||
|
extractComponents,
|
||||||
|
extractSecurity,
|
||||||
|
extractExternalDocs,
|
||||||
|
}
|
||||||
|
wg.Add(len(extractionFuncs))
|
||||||
|
for _, f := range extractionFuncs {
|
||||||
|
go runExtraction(info, &doc, idx, f, &errors, &wg)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
return &doc, errors
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
_, ln, vn := utils.FindKeyNodeFull(InfoLabel, info.RootNode.Content)
|
||||||
|
if vn != nil {
|
||||||
|
ir := Info{}
|
||||||
|
err := low.BuildModel(vn, &ir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ir.Build(vn, idx)
|
||||||
|
nr := low.NodeReference[*Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||||
|
doc.Info = nr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
sec, sErr := low.ExtractObject[*SecurityRequirement](SecurityLabel, info.RootNode, idx)
|
||||||
|
if sErr != nil {
|
||||||
|
return sErr
|
||||||
|
}
|
||||||
|
doc.Security = sec
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
extDocs, dErr := low.ExtractObject[*ExternalDoc](ExternalDocsLabel, info.RootNode, idx)
|
||||||
|
if dErr != nil {
|
||||||
|
return dErr
|
||||||
|
}
|
||||||
|
doc.ExternalDocs = extDocs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
_, ln, vn := utils.FindKeyNodeFull(ComponentsLabel, info.RootNode.Content)
|
||||||
|
if vn != nil {
|
||||||
|
ir := Components{}
|
||||||
|
err := low.BuildModel(vn, &ir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ir.Build(vn, idx)
|
||||||
|
nr := low.NodeReference[*Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||||
|
doc.Components = nr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content)
|
||||||
|
if vn != nil {
|
||||||
|
if utils.IsNodeArray(vn) {
|
||||||
|
var servers []low.ValueReference[*Server]
|
||||||
|
for _, srvN := range vn.Content {
|
||||||
|
if utils.IsNodeMap(srvN) {
|
||||||
|
srvr := Server{}
|
||||||
|
err := low.BuildModel(srvN, &srvr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
srvr.Build(srvN, idx)
|
||||||
|
servers = append(servers, low.ValueReference[*Server]{
|
||||||
|
Value: &srvr,
|
||||||
|
ValueNode: srvN,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc.Servers = low.NodeReference[[]low.ValueReference[*Server]]{
|
||||||
|
Value: servers,
|
||||||
|
KeyNode: ln,
|
||||||
|
ValueNode: vn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
_, ln, vn := utils.FindKeyNodeFull(TagsLabel, info.RootNode.Content)
|
||||||
|
if vn != nil {
|
||||||
|
if utils.IsNodeArray(vn) {
|
||||||
|
var tags []low.ValueReference[*Tag]
|
||||||
|
for _, tagN := range vn.Content {
|
||||||
|
if utils.IsNodeMap(tagN) {
|
||||||
|
tag := Tag{}
|
||||||
|
err := low.BuildModel(tagN, &tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tag.Build(tagN, idx)
|
||||||
|
tags = append(tags, low.ValueReference[*Tag]{
|
||||||
|
Value: &tag,
|
||||||
|
ValueNode: tagN,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc.Tags = low.NodeReference[[]low.ValueReference[*Tag]]{
|
||||||
|
Value: tags,
|
||||||
|
KeyNode: ln,
|
||||||
|
ValueNode: vn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
|
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content)
|
||||||
|
if vn != nil {
|
||||||
|
ir := Paths{}
|
||||||
|
err := ir.Build(vn, idx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nr := low.NodeReference[*Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||||
|
doc.Paths = nr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,17 +1,16 @@
|
|||||||
package openapi
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var doc *v3.Document
|
var doc *Document
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
|
data, _ := ioutil.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err []error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocument(info)
|
||||||
@@ -21,7 +20,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCreateDocument(b *testing.B) {
|
func BenchmarkCreateDocument(b *testing.B) {
|
||||||
data, _ := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
|
data, _ := ioutil.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
doc, _ = CreateDocument(info)
|
doc, _ = CreateDocument(info)
|
||||||
@@ -29,7 +28,7 @@ func BenchmarkCreateDocument(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
||||||
data, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
|
data, _ := ioutil.ReadFile("../../../test_specs/stripe.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := CreateDocument(info)
|
_, err := CreateDocument(info)
|
||||||
@@ -40,7 +39,7 @@ func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCreateDocument_Petstore(b *testing.B) {
|
func BenchmarkCreateDocument_Petstore(b *testing.B) {
|
||||||
data, _ := ioutil.ReadFile("../test_specs/petstorev3.json")
|
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := CreateDocument(info)
|
_, err := CreateDocument(info)
|
||||||
@@ -136,7 +135,7 @@ func TestCreateDocument_Tags(t *testing.T) {
|
|||||||
|
|
||||||
func TestCreateDocument_Paths(t *testing.T) {
|
func TestCreateDocument_Paths(t *testing.T) {
|
||||||
doc := doc
|
doc := doc
|
||||||
assert.Len(t, doc.Paths.Value.PathItems, 6)
|
assert.Len(t, doc.Paths.Value.PathItems, 5)
|
||||||
burgerId := doc.Paths.Value.FindPath("/burgers/{burgerId}")
|
burgerId := doc.Paths.Value.FindPath("/burgers/{burgerId}")
|
||||||
assert.NotNil(t, burgerId)
|
assert.NotNil(t, burgerId)
|
||||||
assert.Len(t, burgerId.Value.Get.Value.Parameters.Value, 2)
|
assert.Len(t, burgerId.Value.Get.Value.Parameters.Value, 2)
|
||||||
@@ -411,7 +410,7 @@ func TestCreateDocument_CheckAdditionalProperties_Schema(t *testing.T) {
|
|||||||
components := doc.Components.Value
|
components := doc.Components.Value
|
||||||
d := components.FindSchema("Dressing")
|
d := components.FindSchema("Dressing")
|
||||||
assert.NotNil(t, d.Value.AdditionalProperties.Value)
|
assert.NotNil(t, d.Value.AdditionalProperties.Value)
|
||||||
if n, ok := d.Value.AdditionalProperties.Value.(*v3.Schema); ok {
|
if n, ok := d.Value.AdditionalProperties.Value.(*Schema); ok {
|
||||||
assert.Equal(t, "something in here.", n.Description.Value)
|
assert.Equal(t, "something in here.", n.Description.Value)
|
||||||
} else {
|
} else {
|
||||||
assert.Fail(t, "should be a schema")
|
assert.Fail(t, "should be a schema")
|
||||||
@@ -28,3 +28,28 @@ func TestExternalDoc_FindExtension(t *testing.T) {
|
|||||||
assert.Equal(t, "cake", n.FindExtension("x-fish").Value)
|
assert.Equal(t, "cake", n.FindExtension("x-fish").Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExternalDoc_Build(t *testing.T) {
|
||||||
|
|
||||||
|
yml := `url: https://pb33f.io
|
||||||
|
description: the ranch
|
||||||
|
x-b33f: princess`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
idx := index.NewSpecIndex(&idxNode)
|
||||||
|
|
||||||
|
var n ExternalDoc
|
||||||
|
err := low.BuildModel(&idxNode, &n)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = n.Build(idxNode.Content[0], idx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "https://pb33f.io", n.URL.Value)
|
||||||
|
assert.Equal(t, "the ranch", n.Description.Value)
|
||||||
|
ext := n.FindExtension("x-b33f")
|
||||||
|
assert.NotNil(t, ext)
|
||||||
|
assert.Equal(t, "princess", ext.Value)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ func TestSpecIndex_PetstoreV3(t *testing.T) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var mappedRefs = 16
|
var mappedRefs = 15
|
||||||
|
|
||||||
func TestSpecIndex_BurgerShop(t *testing.T) {
|
func TestSpecIndex_BurgerShop(t *testing.T) {
|
||||||
|
|
||||||
@@ -177,12 +177,12 @@ func TestSpecIndex_BurgerShop(t *testing.T) {
|
|||||||
assert.Equal(t, mappedRefs, len(index.GetMappedReferences()))
|
assert.Equal(t, mappedRefs, len(index.GetMappedReferences()))
|
||||||
assert.Equal(t, mappedRefs, len(index.GetMappedReferencesSequenced()))
|
assert.Equal(t, mappedRefs, len(index.GetMappedReferencesSequenced()))
|
||||||
|
|
||||||
assert.Equal(t, 7, index.pathCount)
|
assert.Equal(t, 6, index.pathCount)
|
||||||
assert.Equal(t, 7, index.GetPathCount())
|
assert.Equal(t, 6, index.GetPathCount())
|
||||||
|
|
||||||
assert.Equal(t, 6, len(index.GetAllSchemas()))
|
assert.Equal(t, 6, len(index.GetAllSchemas()))
|
||||||
|
|
||||||
assert.Equal(t, 30, len(index.GetAllSequencedReferences()))
|
assert.Equal(t, 29, len(index.GetAllSequencedReferences()))
|
||||||
assert.NotNil(t, index.GetSchemasNode())
|
assert.NotNil(t, index.GetSchemasNode())
|
||||||
assert.NotNil(t, index.GetParametersNode())
|
assert.NotNil(t, index.GetParametersNode())
|
||||||
|
|
||||||
|
|||||||
@@ -1,172 +0,0 @@
|
|||||||
package openapi
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, []error) {
|
|
||||||
|
|
||||||
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
|
||||||
|
|
||||||
// build an index
|
|
||||||
idx := index.NewSpecIndex(info.RootNode)
|
|
||||||
doc.Index = idx
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
var errors []error
|
|
||||||
|
|
||||||
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex,
|
|
||||||
runFunc func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error,
|
|
||||||
ers *[]error,
|
|
||||||
wg *sync.WaitGroup) {
|
|
||||||
|
|
||||||
if er := runFunc(info, doc, idx); er != nil {
|
|
||||||
*ers = append(*ers, er)
|
|
||||||
}
|
|
||||||
|
|
||||||
wg.Done()
|
|
||||||
}
|
|
||||||
|
|
||||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error{
|
|
||||||
extractInfo,
|
|
||||||
extractServers,
|
|
||||||
extractTags,
|
|
||||||
extractPaths,
|
|
||||||
extractComponents,
|
|
||||||
extractSecurity,
|
|
||||||
extractExternalDocs,
|
|
||||||
}
|
|
||||||
wg.Add(len(extractionFuncs))
|
|
||||||
for _, f := range extractionFuncs {
|
|
||||||
go runExtraction(info, &doc, idx, f, &errors, &wg)
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
return &doc, errors
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.InfoLabel, info.RootNode.Content)
|
|
||||||
if vn != nil {
|
|
||||||
ir := v3.Info{}
|
|
||||||
err := low.BuildModel(vn, &ir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ir.Build(vn, idx)
|
|
||||||
nr := low.NodeReference[*v3.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
|
||||||
doc.Info = nr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractSecurity(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
sec, sErr := low.ExtractObject[*v3.SecurityRequirement](v3.SecurityLabel, info.RootNode, idx)
|
|
||||||
if sErr != nil {
|
|
||||||
return sErr
|
|
||||||
}
|
|
||||||
doc.Security = sec
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
extDocs, dErr := low.ExtractObject[*v3.ExternalDoc](v3.ExternalDocsLabel, info.RootNode, idx)
|
|
||||||
if dErr != nil {
|
|
||||||
return dErr
|
|
||||||
}
|
|
||||||
doc.ExternalDocs = extDocs
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractComponents(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.ComponentsLabel, info.RootNode.Content)
|
|
||||||
if vn != nil {
|
|
||||||
ir := v3.Components{}
|
|
||||||
err := low.BuildModel(vn, &ir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = ir.Build(vn, idx)
|
|
||||||
nr := low.NodeReference[*v3.Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
|
||||||
doc.Components = nr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractServers(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.ServersLabel, info.RootNode.Content)
|
|
||||||
if vn != nil {
|
|
||||||
if utils.IsNodeArray(vn) {
|
|
||||||
var servers []low.ValueReference[*v3.Server]
|
|
||||||
for _, srvN := range vn.Content {
|
|
||||||
if utils.IsNodeMap(srvN) {
|
|
||||||
srvr := v3.Server{}
|
|
||||||
err := low.BuildModel(srvN, &srvr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
srvr.Build(srvN, idx)
|
|
||||||
servers = append(servers, low.ValueReference[*v3.Server]{
|
|
||||||
Value: &srvr,
|
|
||||||
ValueNode: srvN,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doc.Servers = low.NodeReference[[]low.ValueReference[*v3.Server]]{
|
|
||||||
Value: servers,
|
|
||||||
KeyNode: ln,
|
|
||||||
ValueNode: vn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractTags(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
|
|
||||||
if vn != nil {
|
|
||||||
if utils.IsNodeArray(vn) {
|
|
||||||
var tags []low.ValueReference[*v3.Tag]
|
|
||||||
for _, tagN := range vn.Content {
|
|
||||||
if utils.IsNodeMap(tagN) {
|
|
||||||
tag := v3.Tag{}
|
|
||||||
err := low.BuildModel(tagN, &tag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tag.Build(tagN, idx)
|
|
||||||
tags = append(tags, low.ValueReference[*v3.Tag]{
|
|
||||||
Value: &tag,
|
|
||||||
ValueNode: tagN,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doc.Tags = low.NodeReference[[]low.ValueReference[*v3.Tag]]{
|
|
||||||
Value: tags,
|
|
||||||
KeyNode: ln,
|
|
||||||
ValueNode: vn,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.PathsLabel, info.RootNode.Content)
|
|
||||||
if vn != nil {
|
|
||||||
ir := v3.Paths{}
|
|
||||||
err := ir.Build(vn, idx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
nr := low.NodeReference[*v3.Paths]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
|
||||||
doc.Paths = nr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -59,8 +59,6 @@ servers:
|
|||||||
description: the default host for this API is 'pb33f.io'
|
description: the default host for this API is 'pb33f.io'
|
||||||
paths:
|
paths:
|
||||||
x-milky-milk: milky
|
x-milky-milk: milky
|
||||||
/refingtons:
|
|
||||||
$ref: '../test_specs/petstorev3.json#/paths~1pet~1findByStatus'
|
|
||||||
/burgers:
|
/burgers:
|
||||||
x-burger-meta: meaty
|
x-burger-meta: meaty
|
||||||
post:
|
post:
|
||||||
|
|||||||
Reference in New Issue
Block a user