2.0 model at 90% coverage

Error handling still required, but a nice jump.
This commit is contained in:
Dave Shanley
2022-09-05 12:22:04 -04:00
parent 1814ac58eb
commit eb7e60c412
13 changed files with 438 additions and 310 deletions

View File

@@ -36,6 +36,13 @@ func (t *Tag) GoLow() *low.Tag {
return t.low
}
func (t *Tag) SetName(value string) {
t.GoLow().Name.ValueNode.Value = value
}
func (t *Tag) SetDescription(value string) {
t.GoLow().Description.ValueNode.Value = value
}
//func (t *Tag) MarshalYAML() (interface{}, error) {
// m := make(map[string]interface{})
// for i := range t.Extensions {

View File

@@ -6,10 +6,13 @@ package v2
import (
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
)
const (
ExamplesLabel = "examples"
)
type Examples struct {
Values map[low.KeyReference[string]]low.ValueReference[any]
}
@@ -17,36 +20,27 @@ type Examples struct {
func (e *Examples) Build(root *yaml.Node, _ *index.SpecIndex) error {
var keyNode, currNode *yaml.Node
var err error
e.Values = make(map[low.KeyReference[string]]low.ValueReference[any])
for i := range root.Content {
if i%2 == 0 {
keyNode = root.Content[i]
continue
}
currNode = root.Content[i]
if utils.IsNodeMap(currNode) {
var n map[string]interface{}
err = currNode.Decode(&n)
var n map[string]interface{}
err = currNode.Decode(&n)
if err != nil {
var k []interface{}
err = currNode.Decode(&k)
if err != nil {
var k []interface{}
err = currNode.Decode(&k)
if err != nil {
// 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,
}
continue
}
// 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: k,
Value: j,
ValueNode: currNode,
}
continue
@@ -55,10 +49,19 @@ func (e *Examples) Build(root *yaml.Node, _ *index.SpecIndex) error {
Value: keyNode.Value,
KeyNode: keyNode,
}] = low.ValueReference[any]{
Value: n,
Value: k,
ValueNode: currNode,
}
continue
}
e.Values[low.KeyReference[string]{
Value: keyNode.Value,
KeyNode: keyNode,
}] = low.ValueReference[any]{
Value: n,
ValueNode: currNode,
}
}
return nil
}

View File

@@ -68,7 +68,7 @@ func (i *Items) Build(root *yaml.Node, idx *index.SpecIndex) error {
}
return nil
}
i.Default.Value = low.NodeReference[any]{
i.Default = low.NodeReference[any]{
Value: n,
KeyNode: ln,
ValueNode: vn,

View File

@@ -4,189 +4,168 @@
package v2
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
"strings"
"sync"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"gopkg.in/yaml.v3"
"strings"
"sync"
)
type PathItem struct {
Ref low.NodeReference[string]
Get low.NodeReference[*Operation]
Put low.NodeReference[*Operation]
Post low.NodeReference[*Operation]
Delete low.NodeReference[*Operation]
Options low.NodeReference[*Operation]
Head low.NodeReference[*Operation]
Patch low.NodeReference[*Operation]
Parameters low.NodeReference[[]low.ValueReference[*Parameter]]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
Ref low.NodeReference[string]
Get low.NodeReference[*Operation]
Put low.NodeReference[*Operation]
Post low.NodeReference[*Operation]
Delete low.NodeReference[*Operation]
Options low.NodeReference[*Operation]
Head low.NodeReference[*Operation]
Patch low.NodeReference[*Operation]
Parameters low.NodeReference[[]low.ValueReference[*Parameter]]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
func (p *PathItem) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, p.Extensions)
return low.FindItemInMap[any](ext, p.Extensions)
}
func (p *PathItem) Build(root *yaml.Node, idx *index.SpecIndex) error {
p.Extensions = low.ExtractExtensions(root)
skip := false
var currentNode *yaml.Node
p.Extensions = low.ExtractExtensions(root)
skip := false
var currentNode *yaml.Node
var wg sync.WaitGroup
var errors []error
var wg sync.WaitGroup
var errors []error
var ops []low.NodeReference[*Operation]
var ops []low.NodeReference[*Operation]
// extract parameters
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
if pErr != nil {
return pErr
}
if params != nil {
p.Parameters = low.NodeReference[[]low.ValueReference[*Parameter]]{
Value: params,
KeyNode: ln,
ValueNode: vn,
}
}
// extract parameters
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
if pErr != nil {
return pErr
}
if params != nil {
p.Parameters = low.NodeReference[[]low.ValueReference[*Parameter]]{
Value: params,
KeyNode: ln,
ValueNode: vn,
}
}
for i, pathNode := range root.Content {
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
skip = true
continue
}
if strings.HasPrefix(strings.ToLower(pathNode.Value), "parameters") {
skip = true
continue
}
// because (for some reason) the spec for swagger docs allows for a '$ref' property for path items.
// this is kinda nuts, because '$ref' is a reserved keyword for JSON references, which is ALSO used
// in swagger. Why this choice was made, I do not know.
if strings.Contains(strings.ToLower(pathNode.Value), "$ref") {
rn := root.Content[i+1]
p.Ref = low.NodeReference[string]{
Value: rn.Value,
ValueNode: rn,
KeyNode: pathNode,
}
skip = true
continue
}
if skip {
skip = false
continue
}
if i%2 == 0 {
currentNode = pathNode
continue
}
for i, pathNode := range root.Content {
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
skip = true
continue
}
// because (for some reason) the spec for swagger docs allows for a '$ref' property for path items.
// this is kinda nuts, because '$ref' is a reserved keyword for JSON references, which is ALSO used
// in swagger. Why this choice was made, I do not know.
if strings.Contains(strings.ToLower(pathNode.Value), "$ref") {
rn := root.Content[i+1]
p.Ref = low.NodeReference[string]{
Value: rn.Value,
ValueNode: rn,
KeyNode: pathNode,
}
skip = true
continue
}
if skip {
skip = false
continue
}
if i%2 == 0 {
currentNode = pathNode
continue
}
// the only thing we now care about is handling operations, filter out anything that's not a verb.
switch currentNode.Value {
case GetLabel:
break
case PostLabel:
break
case PutLabel:
break
case PatchLabel:
break
case DeleteLabel:
break
case HeadLabel:
break
case OptionsLabel:
break
default:
continue // ignore everything else.
}
// the only thing we now care about is handling operations, filter out anything that's not a verb.
switch currentNode.Value {
case GetLabel:
break
case PostLabel:
break
case PutLabel:
break
case PatchLabel:
break
case DeleteLabel:
break
case HeadLabel:
break
case OptionsLabel:
break
default:
continue // ignore everything else.
}
var op Operation
var op Operation
wg.Add(1)
wg.Add(1)
if ok, _, _ := utils.IsNodeRefValue(pathNode); ok {
r, err := low.LocateRefNode(pathNode, idx)
if r != nil {
pathNode = r
if err != nil {
if !idx.AllowCircularReferenceResolving() {
return fmt.Errorf("build schema failed: %s", err.Error())
}
}
} else {
return fmt.Errorf("path item build failed: cannot find reference: %s at line %d, col %d",
pathNode.Content[1].Value, pathNode.Content[1].Line, pathNode.Content[1].Column)
}
}
go low.BuildModelAsync(pathNode, &op, &wg, &errors)
go low.BuildModelAsync(pathNode, &op, &wg, &errors)
opRef := low.NodeReference[*Operation]{
Value: &op,
KeyNode: currentNode,
ValueNode: pathNode,
}
opRef := low.NodeReference[*Operation]{
Value: &op,
KeyNode: currentNode,
ValueNode: pathNode,
}
ops = append(ops, opRef)
ops = append(ops, opRef)
switch currentNode.Value {
case GetLabel:
p.Get = opRef
case PostLabel:
p.Post = opRef
case PutLabel:
p.Put = opRef
case PatchLabel:
p.Patch = opRef
case DeleteLabel:
p.Delete = opRef
case HeadLabel:
p.Head = opRef
case OptionsLabel:
p.Options = opRef
}
}
switch currentNode.Value {
case GetLabel:
p.Get = opRef
case PostLabel:
p.Post = opRef
case PutLabel:
p.Put = opRef
case PatchLabel:
p.Patch = opRef
case DeleteLabel:
p.Delete = opRef
case HeadLabel:
p.Head = opRef
case OptionsLabel:
p.Options = opRef
}
}
//all operations have been superficially built,
//now we need to build out the operation, we will do this asynchronously for speed.
opBuildChan := make(chan bool)
opErrorChan := make(chan error)
//all operations have been superficially built,
//now we need to build out the operation, we will do this asynchronously for speed.
opBuildChan := make(chan bool)
opErrorChan := make(chan error)
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
er := op.Value.Build(op.ValueNode, idx)
if er != nil {
errCh <- er
}
ch <- true
}
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
er := op.Value.Build(op.ValueNode, idx)
if er != nil {
errCh <- er
}
ch <- true
}
if len(ops) <= 0 {
return nil // nothing to do.
}
if len(ops) <= 0 {
return nil // nothing to do.
}
for _, op := range ops {
go buildOpFunc(op, opBuildChan, opErrorChan)
}
for _, op := range ops {
go buildOpFunc(op, opBuildChan, opErrorChan)
}
n := 0
total := len(ops)
for n < total {
select {
case buildError := <-opErrorChan:
return buildError
case <-opBuildChan:
n++
}
}
n := 0
total := len(ops)
for n < total {
select {
case buildError := <-opErrorChan:
return buildError
case <-opBuildChan:
n++
}
}
// make sure we don't exit before the path is finished building.
if len(ops) > 0 {
wg.Wait()
}
// make sure we don't exit before the path is finished building.
if len(ops) > 0 {
wg.Wait()
}
return nil
return nil
}

View File

@@ -4,10 +4,8 @@
package v2
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel/low"
"github.com/pb33f/libopenapi/index"
"github.com/pb33f/libopenapi/utils"
"gopkg.in/yaml.v3"
"strings"
)
@@ -21,7 +19,6 @@ const (
DeleteLabel = "delete"
OptionsLabel = "options"
HeadLabel = "head"
TraceLabel = "trace"
)
type Paths struct {
@@ -58,23 +55,6 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
bChan := make(chan pathBuildResult)
eChan := make(chan error)
var buildPathItem = func(cNode, pNode *yaml.Node, b chan<- pathBuildResult, e chan<- error) {
if ok, _, _ := utils.IsNodeRefValue(pNode); ok {
r, err := low.LocateRefNode(pNode, idx)
if r != nil {
pNode = r
if err != nil {
if !idx.AllowCircularReferenceResolving() {
e <- fmt.Errorf("path item build failed: %s", err.Error())
return
}
}
} else {
e <- fmt.Errorf("path item build failed: cannot find reference: %s at line %d, col %d",
pNode.Content[1].Value, pNode.Content[1].Line, pNode.Content[1].Column)
return
}
}
path := new(PathItem)
_ = low.BuildModel(pNode, path)
err := path.Build(pNode, idx)

View File

@@ -40,6 +40,13 @@ func (r *Response) Build(root *yaml.Node, idx *index.SpecIndex) error {
r.Schema = *s
}
// extract examples
examples, expErr := low.ExtractObject[*Examples](ExamplesLabel, root, idx)
if expErr != nil {
return expErr
}
r.Examples = examples
//extract headers
headers, lN, kN, err := low.ExtractMapFlat[*Header](HeadersLabel, root, idx)
if err != nil {

View File

@@ -90,6 +90,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
case <-doneChan:
completedExtractions++
case e := <-errChan:
completedExtractions++
errors = append(errors, e)
}
}

View File

@@ -4,90 +4,153 @@
package v2
import (
"github.com/pb33f/libopenapi/datamodel"
"github.com/stretchr/testify/assert"
"io/ioutil"
"testing"
"fmt"
"github.com/pb33f/libopenapi/datamodel"
"github.com/stretchr/testify/assert"
"io/ioutil"
"testing"
)
var doc *Swagger
func initTest() {
if doc != nil {
return
}
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
var err []error
doc, err = CreateDocument(info)
wait := true
for wait {
select {
case <-info.JsonParsingChannel:
wait = false
}
}
if err != nil {
panic("broken something")
}
if doc != nil {
return
}
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
var err []error
doc, err = CreateDocument(info)
wait := true
for wait {
select {
case <-info.JsonParsingChannel:
wait = false
}
}
if err != nil {
fmt.Print(err)
panic(err)
}
}
func BenchmarkCreateDocument(b *testing.B) {
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
for i := 0; i < b.N; i++ {
doc, _ = CreateDocument(info)
}
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
info, _ := datamodel.ExtractSpecInfo(data)
for i := 0; i < b.N; i++ {
doc, _ = CreateDocument(info)
}
}
func TestCreateDocument(t *testing.T) {
initTest()
assert.Equal(t, "2.0", doc.SpecInfo.Version)
assert.Equal(t, "1.0.6", doc.Info.Value.Version.Value)
assert.Equal(t, "petstore.swagger.io", doc.Host.Value)
assert.Equal(t, "/v2", doc.BasePath.Value)
assert.Len(t, doc.Parameters.Value.Definitions, 1)
assert.Len(t, doc.Tags.Value, 3)
assert.Len(t, doc.Schemes.Value, 2)
assert.Len(t, doc.Definitions.Value.Schemas, 6)
assert.Len(t, doc.SecurityDefinitions.Value.Definitions, 2)
assert.Len(t, doc.Paths.Value.PathItems, 14)
assert.Len(t, doc.Responses.Value.Definitions, 2)
assert.Equal(t, "http://swagger.io", doc.ExternalDocs.Value.URL.Value)
assert.Equal(t, true, doc.FindExtension("x-pet").Value)
assert.Equal(t, true, doc.FindExtension("X-Pet").Value)
initTest()
assert.Equal(t, "2.0", doc.SpecInfo.Version)
assert.Equal(t, "1.0.6", doc.Info.Value.Version.Value)
assert.Equal(t, "petstore.swagger.io", doc.Host.Value)
assert.Equal(t, "/v2", doc.BasePath.Value)
assert.Len(t, doc.Parameters.Value.Definitions, 1)
assert.Len(t, doc.Tags.Value, 3)
assert.Len(t, doc.Schemes.Value, 2)
assert.Len(t, doc.Definitions.Value.Schemas, 6)
assert.Len(t, doc.SecurityDefinitions.Value.Definitions, 2)
assert.Len(t, doc.Paths.Value.PathItems, 15)
assert.Len(t, doc.Responses.Value.Definitions, 2)
assert.Equal(t, "http://swagger.io", doc.ExternalDocs.Value.URL.Value)
assert.Equal(t, true, doc.FindExtension("x-pet").Value)
assert.Equal(t, true, doc.FindExtension("X-Pet").Value)
}
func TestCreateDocument_Info(t *testing.T) {
initTest()
assert.Equal(t, "Swagger Petstore", doc.Info.Value.Title.Value)
assert.Equal(t, "apiteam@swagger.io", doc.Info.Value.Contact.Value.Email.Value)
assert.Equal(t, "Apache 2.0", doc.Info.Value.License.Value.Name.Value)
initTest()
assert.Equal(t, "Swagger Petstore", doc.Info.Value.Title.Value)
assert.Equal(t, "apiteam@swagger.io", doc.Info.Value.Contact.Value.Email.Value)
assert.Equal(t, "Apache 2.0", doc.Info.Value.License.Value.Name.Value)
}
func TestCreateDocument_Parameters(t *testing.T) {
initTest()
simpleParam := doc.Parameters.Value.FindParameter("simpleParam")
assert.NotNil(t, simpleParam)
assert.Equal(t, "simple", simpleParam.Value.Name.Value)
initTest()
simpleParam := doc.Parameters.Value.FindParameter("simpleParam")
assert.NotNil(t, simpleParam)
assert.Equal(t, "simple", simpleParam.Value.Name.Value)
assert.Equal(t, "nuggets", simpleParam.Value.FindExtension("x-chicken").Value)
}
func TestCreateDocument_Tags(t *testing.T) {
initTest()
assert.Equal(t, "pet", doc.Tags.Value[0].Value.Name.Value)
assert.Equal(t, "http://swagger.io", doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
assert.Equal(t, "store", doc.Tags.Value[1].Value.Name.Value)
assert.Equal(t, "user", doc.Tags.Value[2].Value.Name.Value)
assert.Equal(t, "http://swagger.io", doc.Tags.Value[2].Value.ExternalDocs.Value.URL.Value)
initTest()
assert.Equal(t, "pet", doc.Tags.Value[0].Value.Name.Value)
assert.Equal(t, "http://swagger.io", doc.Tags.Value[0].Value.ExternalDocs.Value.URL.Value)
assert.Equal(t, "store", doc.Tags.Value[1].Value.Name.Value)
assert.Equal(t, "user", doc.Tags.Value[2].Value.Name.Value)
assert.Equal(t, "http://swagger.io", doc.Tags.Value[2].Value.ExternalDocs.Value.URL.Value)
}
func TestCreateDocument_SecurityDefinitions(t *testing.T) {
initTest()
apiKey := doc.SecurityDefinitions.Value.FindSecurityDefinition("api_key")
assert.Equal(t, "apiKey", apiKey.Value.Type.Value)
petStoreAuth := doc.SecurityDefinitions.Value.FindSecurityDefinition("petstore_auth")
assert.Equal(t, "oauth2", petStoreAuth.Value.Type.Value)
assert.Equal(t, "implicit", petStoreAuth.Value.Flow.Value)
assert.Len(t, petStoreAuth.Value.Scopes.Value.Values, 2)
assert.Equal(t, "read your pets", petStoreAuth.Value.Scopes.Value.FindScope("read:pets").Value)
initTest()
apiKey := doc.SecurityDefinitions.Value.FindSecurityDefinition("api_key")
assert.Equal(t, "apiKey", apiKey.Value.Type.Value)
petStoreAuth := doc.SecurityDefinitions.Value.FindSecurityDefinition("petstore_auth")
assert.Equal(t, "oauth2", petStoreAuth.Value.Type.Value)
assert.Equal(t, "implicit", petStoreAuth.Value.Flow.Value)
assert.Len(t, petStoreAuth.Value.Scopes.Value.Values, 2)
assert.Equal(t, "read your pets", petStoreAuth.Value.Scopes.Value.FindScope("read:pets").Value)
}
func TestCreateDocument_Definitions(t *testing.T) {
initTest()
apiResp := doc.Definitions.Value.FindSchema("ApiResponse").Value.Schema()
assert.NotNil(t, apiResp)
assert.Len(t, apiResp.Properties.Value, 3)
assert.Equal(t, "integer", apiResp.FindProperty("code").Value.Schema().Type.Value)
pet := doc.Definitions.Value.FindSchema("Pet").Value.Schema()
assert.NotNil(t, pet)
assert.Len(t, pet.Required.Value, 2)
// perform a deep inline lookup on a schema to ensure chains work
assert.Equal(t, "Category", pet.FindProperty("category").Value.Schema().XML.Value.Name.Value)
// check enums
assert.Len(t, pet.FindProperty("status").Value.Schema().Enum.Value, 3)
}
func TestCreateDocument_ResponseDefinitions(t *testing.T) {
initTest()
apiResp := doc.Responses.Value.FindResponse("200")
assert.NotNil(t, apiResp)
assert.Equal(t, "OK", apiResp.Value.Description.Value)
assert.Equal(t, "morning", apiResp.Value.FindExtension("x-coffee").Value)
header := apiResp.Value.FindHeader("noHeader")
assert.NotNil(t, header)
assert.True(t, header.Value.FindExtension("x-empty").Value.(bool))
header = apiResp.Value.FindHeader("myHeader")
if k, ok := header.Value.Items.Value.Default.Value.(map[string]interface{}); ok {
assert.Equal(t, "here", k["something"])
} else {
panic("should not fail.")
}
if k, ok := header.Value.Items.Value.Items.Value.Default.Value.([]interface{}); ok {
assert.Len(t, k, 2)
assert.Equal(t, "two", k[1])
} else {
panic("should not fail.")
}
header = apiResp.Value.FindHeader("yourHeader")
assert.Equal(t, "somethingSimple", header.Value.Items.Value.Default.Value)
}
func TestCreateDocument_Paths(t *testing.T) {
initTest()
uploadImage := doc.Paths.Value.FindPath("/pet/{petId}/uploadImage").Value
assert.NotNil(t, uploadImage)
assert.Nil(t, doc.Paths.Value.FindPath("/nothing-nowhere-nohow"))
assert.Equal(t, "man", uploadImage.FindExtension("x-potato").Value)
assert.Equal(t, "fresh", doc.Paths.Value.FindExtension("x-minty").Value)
assert.Equal(t, "successful operation",
uploadImage.Post.Value.Responses.Value.FindResponseByCode("200").Value.Description.Value)
}

View File

@@ -21,3 +21,18 @@ type Document struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
Index *index.SpecIndex
}
//
//func (d *Document) AddTag() *base.Tag {
// t := base.NewTag()
// //d.Tags.KeyNode
// t.Name.Value = "nice new tag"
//
// dat, _ := yaml.Marshal(t)
// var inject yaml.Node
// _ = yaml.Unmarshal(dat, &inject)
//
// d.Tags.ValueNode.Content = append(d.Tags.ValueNode.Content, inject.Content[0])
//
// return t
//}

View File

@@ -12,6 +12,8 @@ import (
const (
TagsLabel = "tags"
ExternalDocsLabel = "externalDocs"
NameLabel = "name"
DescriptionLabel = "description"
)
type Tag struct {
@@ -33,3 +35,24 @@ func (t *Tag) Build(root *yaml.Node, idx *index.SpecIndex) error {
t.ExternalDocs = extDocs
return err
}
//func (t *Tag) MarshalYAML() (interface{}, error) {
// m := make(map[string]interface{})
// for i := range t.Extensions {
// m[i.Value] = t.Extensions[i].Value
// }
// if t.Name.Value != "" {
// m[NameLabel] = t.Name.Value
// }
// if t.Description.Value != "" {
// m[DescriptionLabel] = t.Description.Value
// }
// if t.ExternalDocs.Value != nil {
// m[ExternalDocsLabel] = t.ExternalDocs.Value
// }
// return m, nil
//}
//
//func NewTag() *Tag {
// return new(Tag)
//}

View File

@@ -1,18 +1,18 @@
package main
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel"
high "github.com/pb33f/libopenapi/datamodel/high/3.0"
low "github.com/pb33f/libopenapi/datamodel/low/3.0"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"fmt"
"github.com/pb33f/libopenapi/datamodel"
high "github.com/pb33f/libopenapi/datamodel/high/3.0"
low "github.com/pb33f/libopenapi/datamodel/low/3.0"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
)
func main() {
testData := `openapi: 3.0.1
testData := `openapi: 3.0.1
info:
title: this is a title
description: this is a description
@@ -24,28 +24,28 @@ tags:
description: coffee
x-code: hack`
data := []byte(testData)
_ = ioutil.WriteFile("sample.yaml", data, 0664)
data := []byte(testData)
_ = ioutil.WriteFile("sample.yaml", data, 0664)
info, _ := datamodel.ExtractSpecInfo(data)
lowDoc, err := low.CreateDocument(info)
if len(err) > 0 {
for e := range err {
fmt.Printf("%e\n", err[e])
}
return
}
highDoc := high.NewDocument(lowDoc)
fmt.Println(highDoc.Info.Title)
info, _ := datamodel.ExtractSpecInfo(data)
lowDoc, err := low.CreateDocument(info)
if len(err) > 0 {
for e := range err {
fmt.Printf("%e\n", err[e])
}
return
}
highDoc := high.NewDocument(lowDoc)
highDoc.Info.GoLow().Title.ValueNode.Value = "let's hack this shizzle"
highDoc.Info.GoLow().Title.ValueNode.Value = "let's hack this"
highDoc.Tags[0].SetName("We are a new name now")
highDoc.Tags[0].SetDescription("and a new description")
modified, _ := yaml.Marshal(info.RootNode)
fmt.Println(string(modified))
//newTag := lowDoc.AddTag()
//fmt.Println(newTag)
modified, _ := yaml.Marshal(info.RootNode)
fmt.Println(string(modified))
d, _ := yaml.Marshal(highDoc.Tags[0])
fmt.Println(d)
os.Remove("sample.yaml")
os.Remove("sample.yaml")
}

View File

@@ -1,11 +0,0 @@
openapi: 3.0.1
info:
title: this is a title
description: this is a description
tags:
- name: Tag A
description: cake
x-hack: true
- name: Tag B
description: coffee
x-code: hack

View File

@@ -20,6 +20,7 @@ parameters:
in: query
name: simple
type: string
x-chicken: nuggets
tags:
- name: pet
description: Everything about your Pets
@@ -37,7 +38,9 @@ schemes:
- https
- http
paths:
x-minty: fresh
"/pet/{petId}/uploadImage":
x-potato: man
post:
tags:
- pet
@@ -67,15 +70,6 @@ paths:
type: file
responses:
'200':
headers:
myHeader:
type: array
description: myHeader
items:
type: string
collectionFormat: csv
default: [ one, two, three ]
enum: [99,100,101]
description: successful operation
schema:
"$ref": "#/definitions/ApiResponse"
@@ -574,6 +568,28 @@ paths:
default:
description: successful operation
"/user":
borked:
summary: not allowed
options:
summary: hola!
responses:
default:
description: hello there
delete:
summary: sup!
responses:
default:
description: hello there
head:
summary: yo!
responses:
default:
description: hello there
patch:
summary: hi!
responses:
default:
description: hello there
post:
tags:
- user
@@ -595,6 +611,8 @@ paths:
responses:
default:
description: successful operation
"/ref":
$ref: "#/externalPaths/test"
securityDefinitions:
api_key:
type: apiKey
@@ -609,7 +627,46 @@ securityDefinitions:
write:pets: modify pets in your account
responses:
"200":
x-coffee: morning
description: OK
headers:
noHeader:
type: string
x-empty: true
items:
type: string
yourHeader:
type: string
default: yourHeader
items:
default: somethingSimple
ourHeader:
type: string
default:
funny: bunny
myHeader:
type: array
description: myHeader
items:
type: string
default:
something: here
items:
default:
- one
- two
collectionFormat: csv
default: [ one, two, three ]
enum: [ 99,100,101 ]
examples:
"application/json":
one: two
three: four
"text/xml":
- one
- two
- three
"text/plain": something else.
schema:
$ref: '#/definitions/ApiResponse'
"500":
@@ -739,3 +796,7 @@ definitions:
externalDocs:
description: Find out more about Swagger
url: http://swagger.io
externalPaths:
# this is illegal
test:
- summary: this is illegal.