mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 12:37:49 +00:00
Working in generics now to reduce code.
generics are a little funky still. sigh.
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Callback struct {
|
type Callback struct {
|
||||||
Node *yaml.Node
|
Node *yaml.Node
|
||||||
Expression map[string]Path
|
Expression map[string]PathItem
|
||||||
Extensions map[string]low.ObjectReference
|
Extensions map[string]low.ObjectReference
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EncodingLabel = "encoding"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Encoding struct {
|
type Encoding struct {
|
||||||
Node *yaml.Node
|
ContentType low.NodeReference[string]
|
||||||
ContentType low.NodeReference[string]
|
Headers map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*Header]
|
||||||
Headers map[string]Parameter
|
Style low.NodeReference[string]
|
||||||
Style low.NodeReference[string]
|
Explode low.NodeReference[bool]
|
||||||
Explode low.NodeReference[bool]
|
AllowReserved low.NodeReference[bool]
|
||||||
AllowReserved low.NodeReference[bool]
|
}
|
||||||
|
|
||||||
|
func (en Encoding) Build(root *yaml.Node) error {
|
||||||
|
|
||||||
|
headers, err := ExtractMap[*Header](HeadersLabel, root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if headers != nil {
|
||||||
|
en.Headers = headers
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,29 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ExamplesLabel = "examples"
|
||||||
|
ExampleLabel = "example"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Example struct {
|
type Example struct {
|
||||||
Node *yaml.Node
|
Summary low.NodeReference[string]
|
||||||
Summary low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Description low.NodeReference[string]
|
Value low.NodeReference[any]
|
||||||
Value low.ObjectReference
|
ExternalValue low.NodeReference[string]
|
||||||
ExternalValue low.NodeReference[string]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
Extensions map[string]low.ObjectReference
|
}
|
||||||
|
|
||||||
|
func (ex Example) Build(root *yaml.Node) error {
|
||||||
|
// extract extensions
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ex.Extensions = extensionMap
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,21 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExternalDoc struct {
|
type ExternalDoc struct {
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
URL low.NodeReference[string]
|
URL low.NodeReference[string]
|
||||||
Extensions map[string]low.ObjectReference
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ex *ExternalDoc) Build(root *yaml.Node) error {
|
||||||
|
// extract extensions
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ex.Extensions = extensionMap
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
123
datamodel/low/3.0/extraction_functions.go
Normal file
123
datamodel/low/3.0/extraction_functions.go
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExtractSchema(root *yaml.Node) (*low.NodeReference[*Schema], error) {
|
||||||
|
_, schLabel, schNode := utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
||||||
|
if schNode != nil {
|
||||||
|
var schema Schema
|
||||||
|
err := BuildModel(schNode, &schema)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = schema.Build(schNode, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &low.NodeReference[*Schema]{Value: &schema, KeyNode: schLabel, ValueNode: schNode}, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var mapLock sync.Mutex
|
||||||
|
|
||||||
|
func ExtractMap[PT low.Buildable[N], N any](label string, root *yaml.Node) (map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[PT], error) {
|
||||||
|
_, labelNode, valueNode := utils.FindKeyNodeFull(label, root.Content)
|
||||||
|
if valueNode != nil {
|
||||||
|
var currentLabelNode *yaml.Node
|
||||||
|
valueMap := make(map[low.KeyReference[string]]low.ValueReference[PT])
|
||||||
|
for i, en := range valueNode.Content {
|
||||||
|
if i%2 == 0 {
|
||||||
|
currentLabelNode = en
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var n PT = new(N)
|
||||||
|
err := BuildModel(valueNode, n)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
berr := n.Build(valueNode)
|
||||||
|
if berr != nil {
|
||||||
|
return nil, berr
|
||||||
|
}
|
||||||
|
valueMap[low.KeyReference[string]{
|
||||||
|
Value: currentLabelNode.Value,
|
||||||
|
KeyNode: currentLabelNode,
|
||||||
|
}] = low.ValueReference[PT]{
|
||||||
|
Value: n,
|
||||||
|
ValueNode: en,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resMap := make(map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[PT])
|
||||||
|
resMap[low.KeyReference[string]{
|
||||||
|
Value: labelNode.Value,
|
||||||
|
KeyNode: labelNode,
|
||||||
|
}] = valueMap
|
||||||
|
return resMap, nil
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExtractExtensions(root *yaml.Node) (map[low.KeyReference[string]]low.ValueReference[any], error) {
|
||||||
|
extensions := utils.FindExtensionNodes(root.Content)
|
||||||
|
extensionMap := make(map[low.KeyReference[string]]low.ValueReference[any])
|
||||||
|
for _, ext := range extensions {
|
||||||
|
if utils.IsNodeMap(ext.Value) {
|
||||||
|
var v interface{}
|
||||||
|
err := ext.Value.Decode(&v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: v, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
if utils.IsNodeStringValue(ext.Value) {
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: ext.Value.Value, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
if utils.IsNodeFloatValue(ext.Value) {
|
||||||
|
fv, _ := strconv.ParseFloat(ext.Value.Value, 64)
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: fv, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
if utils.IsNodeIntValue(ext.Value) {
|
||||||
|
iv, _ := strconv.ParseInt(ext.Value.Value, 10, 64)
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: iv, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
if utils.IsNodeBoolValue(ext.Value) {
|
||||||
|
bv, _ := strconv.ParseBool(ext.Value.Value)
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: bv, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
if utils.IsNodeArray(ext.Value) {
|
||||||
|
var v []interface{}
|
||||||
|
err := ext.Value.Decode(&v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
extensionMap[low.KeyReference[string]{
|
||||||
|
Value: ext.Key.Value,
|
||||||
|
KeyNode: ext.Key,
|
||||||
|
}] = low.ValueReference[any]{Value: v, ValueNode: ext.Value}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extensionMap, nil
|
||||||
|
}
|
||||||
61
datamodel/low/3.0/header.go
Normal file
61
datamodel/low/3.0/header.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HeadersLabel = "headers"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Header struct {
|
||||||
|
Description low.NodeReference[string]
|
||||||
|
Required low.NodeReference[bool]
|
||||||
|
Deprecated low.NodeReference[bool]
|
||||||
|
AllowEmptyValue low.NodeReference[bool]
|
||||||
|
Style low.NodeReference[string]
|
||||||
|
Explode low.NodeReference[bool]
|
||||||
|
AllowReserved low.NodeReference[bool]
|
||||||
|
Schema low.NodeReference[*Schema]
|
||||||
|
Example low.NodeReference[any]
|
||||||
|
Examples map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*Example]
|
||||||
|
Content map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*MediaType]
|
||||||
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Header) Build(root *yaml.Node) error {
|
||||||
|
// extract extensions
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h.Extensions = extensionMap
|
||||||
|
|
||||||
|
// handle examples if set.
|
||||||
|
exps, eErr := ExtractMap[*Example](ExamplesLabel, root)
|
||||||
|
if eErr != nil {
|
||||||
|
return eErr
|
||||||
|
}
|
||||||
|
if exps != nil {
|
||||||
|
h.Examples = exps
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle schema
|
||||||
|
sch, sErr := ExtractSchema(root)
|
||||||
|
if sErr != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if sch != nil {
|
||||||
|
h.Schema = *sch
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle content, if set.
|
||||||
|
con, cErr := ExtractMap[*MediaType](ContentLabel, root)
|
||||||
|
if cErr != nil {
|
||||||
|
return cErr
|
||||||
|
}
|
||||||
|
h.Content = con
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,14 +1,59 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MediaType struct {
|
type MediaType struct {
|
||||||
Node *yaml.Node
|
Schema low.NodeReference[*Schema]
|
||||||
Schema Schema
|
Example low.NodeReference[any]
|
||||||
Example low.ObjectReference
|
Examples map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*Example]
|
||||||
Examples map[string]Example
|
Encoding map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*Encoding]
|
||||||
Encoding map[string]Encoding
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mt *MediaType) Build(root *yaml.Node) error {
|
||||||
|
|
||||||
|
// extract extensions
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
mt.Extensions = extensionMap
|
||||||
|
|
||||||
|
// handle example if set.
|
||||||
|
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||||
|
if expNode != nil {
|
||||||
|
mt.Example = low.NodeReference[any]{Value: expNode.Value, KeyNode: expLabel, ValueNode: expNode}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle schema
|
||||||
|
sch, sErr := ExtractSchema(root)
|
||||||
|
if sErr != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if sch != nil {
|
||||||
|
mt.Schema = *sch
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle examples if set.
|
||||||
|
exps, eErr := ExtractMap[*Example](ExamplesLabel, root)
|
||||||
|
if eErr != nil {
|
||||||
|
return eErr
|
||||||
|
}
|
||||||
|
if exps != nil {
|
||||||
|
mt.Examples = exps
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle encoding
|
||||||
|
encs, encErr := ExtractMap[*Encoding](EncodingLabel, root)
|
||||||
|
if encErr != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if encs != nil {
|
||||||
|
mt.Encoding = encs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -377,60 +377,3 @@ func BuildModelAsync(n *yaml.Node, model interface{}, lwg *sync.WaitGroup, error
|
|||||||
}
|
}
|
||||||
lwg.Done()
|
lwg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExtractExtensions(root *yaml.Node) (map[low.NodeReference[string]]low.NodeReference[any], error) {
|
|
||||||
extensions := utils.FindExtensionNodes(root.Content)
|
|
||||||
extensionMap := make(map[low.NodeReference[string]]low.NodeReference[any])
|
|
||||||
for _, ext := range extensions {
|
|
||||||
if utils.IsNodeMap(ext.Value) {
|
|
||||||
var v interface{}
|
|
||||||
err := ext.Value.Decode(&v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: v, KeyNode: ext.Key}
|
|
||||||
}
|
|
||||||
if utils.IsNodeStringValue(ext.Value) {
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: ext.Value.Value, ValueNode: ext.Value}
|
|
||||||
}
|
|
||||||
if utils.IsNodeFloatValue(ext.Value) {
|
|
||||||
fv, _ := strconv.ParseFloat(ext.Value.Value, 64)
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: fv, ValueNode: ext.Value}
|
|
||||||
}
|
|
||||||
if utils.IsNodeIntValue(ext.Value) {
|
|
||||||
iv, _ := strconv.ParseInt(ext.Value.Value, 10, 64)
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: iv, ValueNode: ext.Value}
|
|
||||||
}
|
|
||||||
if utils.IsNodeBoolValue(ext.Value) {
|
|
||||||
bv, _ := strconv.ParseBool(ext.Value.Value)
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: bv, ValueNode: ext.Value}
|
|
||||||
}
|
|
||||||
if utils.IsNodeArray(ext.Value) {
|
|
||||||
var v []interface{}
|
|
||||||
err := ext.Value.Decode(&v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
extensionMap[low.NodeReference[string]{
|
|
||||||
Value: ext.Key.Value,
|
|
||||||
KeyNode: ext.Key,
|
|
||||||
}] = low.NodeReference[any]{Value: v, ValueNode: ext.Value}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return extensionMap, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -15,19 +14,19 @@ type Operation struct {
|
|||||||
Tags []low.NodeReference[string]
|
Tags []low.NodeReference[string]
|
||||||
Summary low.NodeReference[string]
|
Summary low.NodeReference[string]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
ExternalDocs *low.NodeReference[*ExternalDoc]
|
ExternalDocs low.NodeReference[*ExternalDoc]
|
||||||
OperationId low.NodeReference[string]
|
OperationId low.NodeReference[string]
|
||||||
Parameters []low.NodeReference[*Parameter]
|
Parameters []low.NodeReference[*Parameter]
|
||||||
RequestBody *low.NodeReference[*RequestBody]
|
RequestBody low.NodeReference[*RequestBody]
|
||||||
Responses *low.NodeReference[*Responses]
|
Responses low.NodeReference[*Responses]
|
||||||
Callbacks map[low.NodeReference[string]]low.NodeReference[*Callback]
|
Callbacks map[low.KeyReference[string]]low.ValueReference[*Callback]
|
||||||
Deprecated *low.NodeReference[bool]
|
Deprecated low.NodeReference[bool]
|
||||||
Security []low.NodeReference[*SecurityRequirement]
|
Security []low.NodeReference[*SecurityRequirement]
|
||||||
Servers []low.NodeReference[*Server]
|
Servers []low.NodeReference[*Server]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *Operation) Build(root *yaml.Node) error {
|
||||||
|
|
||||||
extensionMap, err := ExtractExtensions(root)
|
extensionMap, err := ExtractExtensions(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -43,7 +42,7 @@ func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.ExternalDocs = &low.NodeReference[*ExternalDoc]{
|
o.ExternalDocs = low.NodeReference[*ExternalDoc]{
|
||||||
Value: &externalDoc,
|
Value: &externalDoc,
|
||||||
KeyNode: ln,
|
KeyNode: ln,
|
||||||
ValueNode: exDocs,
|
ValueNode: exDocs,
|
||||||
@@ -61,7 +60,7 @@ func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = param.Build(pN, idx)
|
err = param.Build(pN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SchemaLabel = "schema"
|
SchemaLabel = "schema"
|
||||||
|
ContentLabel = "content"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Parameter struct {
|
type Parameter struct {
|
||||||
@@ -23,11 +23,23 @@ type Parameter struct {
|
|||||||
AllowReserved low.NodeReference[bool]
|
AllowReserved low.NodeReference[bool]
|
||||||
Schema low.NodeReference[*Schema]
|
Schema low.NodeReference[*Schema]
|
||||||
Example low.NodeReference[any]
|
Example low.NodeReference[any]
|
||||||
Examples map[low.NodeReference[string]]low.NodeReference[*Example]
|
Examples map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*Example]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Content map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[*MediaType]
|
||||||
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Parameter) GetContent(cType string) *low.ValueReference[*MediaType] {
|
||||||
|
for _, c := range p.Content {
|
||||||
|
for n, o := range c {
|
||||||
|
if n.Value == cType {
|
||||||
|
return &o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Parameter) Build(root *yaml.Node) error {
|
||||||
|
|
||||||
// extract extensions
|
// extract extensions
|
||||||
extensionMap, err := ExtractExtensions(root)
|
extensionMap, err := ExtractExtensions(root)
|
||||||
@@ -36,27 +48,24 @@ func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
p.Extensions = extensionMap
|
p.Extensions = extensionMap
|
||||||
|
|
||||||
// handle schema
|
// handle example if set.
|
||||||
_, schLabel, schNode := utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||||
if schNode != nil {
|
if expNode != nil {
|
||||||
// deal with schema flat props
|
p.Example = low.NodeReference[any]{Value: expNode.Value, KeyNode: expLabel, ValueNode: expNode}
|
||||||
var schema Schema
|
|
||||||
err = BuildModel(schNode, &schema)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// now comes the part where things may get hairy, schemas are recursive.
|
|
||||||
// which means we could be here forever if our resolver has some unknown bug in it.
|
|
||||||
// in order to prevent this from happening, we will add a counter that tracks the depth
|
|
||||||
// and will hard stop once we reach 50 levels. That's too deep for any data structure IMHO.
|
|
||||||
err = schema.Build(schNode, idx, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
p.Schema = low.NodeReference[*Schema]{Value: &schema, KeyNode: schLabel, ValueNode: schNode}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle schema
|
||||||
|
sch, sErr := ExtractSchema(root)
|
||||||
|
if sErr != nil {
|
||||||
|
return sErr
|
||||||
|
}
|
||||||
|
p.Schema = *sch
|
||||||
|
|
||||||
|
// handle content, if set.
|
||||||
|
con, cErr := ExtractMap[*MediaType](ContentLabel, root)
|
||||||
|
if cErr != nil {
|
||||||
|
return cErr
|
||||||
|
}
|
||||||
|
p.Content = con
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -21,19 +20,20 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Paths struct {
|
type Paths struct {
|
||||||
Paths map[low.NodeReference[string]]low.NodeReference[*Path]
|
PathItems map[low.KeyReference[string]]low.ValueReference[*PathItem]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Paths) GetPathMap() map[string]*Path {
|
func (p *Paths) GetPath(path string) *low.ValueReference[*PathItem] {
|
||||||
pMap := make(map[string]*Path)
|
for k, p := range p.PathItems {
|
||||||
for i, pv := range p.Paths {
|
if k.Value == path {
|
||||||
pMap[i.Value] = pv.Value
|
return &p
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return pMap
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Paths) Build(root *yaml.Node) error {
|
||||||
|
|
||||||
// extract extensions
|
// extract extensions
|
||||||
extensionMap, err := ExtractExtensions(root)
|
extensionMap, err := ExtractExtensions(root)
|
||||||
@@ -44,7 +44,7 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
skip := false
|
skip := false
|
||||||
var currentNode *yaml.Node
|
var currentNode *yaml.Node
|
||||||
|
|
||||||
pathsMap := make(map[low.NodeReference[string]]low.NodeReference[*Path])
|
pathsMap := make(map[low.KeyReference[string]]low.ValueReference[*PathItem])
|
||||||
|
|
||||||
for i, pathNode := range root.Content {
|
for i, pathNode := range root.Content {
|
||||||
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
|
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
|
||||||
@@ -59,32 +59,32 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
currentNode = pathNode
|
currentNode = pathNode
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var path = Path{}
|
var path = PathItem{}
|
||||||
err = BuildModel(pathNode, &path)
|
err = BuildModel(pathNode, &path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
}
|
}
|
||||||
err = path.Build(pathNode, idx)
|
err = path.Build(pathNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// add bulk here
|
// add bulk here
|
||||||
pathsMap[low.NodeReference[string]{
|
pathsMap[low.KeyReference[string]{
|
||||||
Value: currentNode.Value,
|
Value: currentNode.Value,
|
||||||
KeyNode: currentNode,
|
KeyNode: currentNode,
|
||||||
}] = low.NodeReference[*Path]{
|
}] = low.ValueReference[*PathItem]{
|
||||||
Value: &path,
|
Value: &path,
|
||||||
ValueNode: pathNode,
|
ValueNode: pathNode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Paths = pathsMap
|
p.PathItems = pathsMap
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Path struct {
|
type PathItem struct {
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Summary low.NodeReference[string]
|
Summary low.NodeReference[string]
|
||||||
Get *low.NodeReference[*Operation]
|
Get *low.NodeReference[*Operation]
|
||||||
@@ -97,10 +97,10 @@ type Path struct {
|
|||||||
Trace *low.NodeReference[*Operation]
|
Trace *low.NodeReference[*Operation]
|
||||||
Servers []*low.NodeReference[*Server]
|
Servers []*low.NodeReference[*Server]
|
||||||
Parameters []*low.NodeReference[*Parameter]
|
Parameters []*low.NodeReference[*Parameter]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Path) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *PathItem) Build(root *yaml.Node) error {
|
||||||
extensionMap, err := ExtractExtensions(root)
|
extensionMap, err := ExtractExtensions(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -171,7 +171,7 @@ func (p *Path) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
|
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
|
||||||
|
|
||||||
// build out the operation.
|
// build out the operation.
|
||||||
er := op.Value.Build(op.ValueNode, idx)
|
er := op.Value.Build(op.ValueNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errCh <- er
|
errCh <- er
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -12,7 +11,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
PropertiesLabel = "properties"
|
PropertiesLabel = "properties"
|
||||||
AdditionalPropertiesLabel = "additionalProperties"
|
AdditionalPropertiesLabel = "additionalProperties"
|
||||||
ExampleLabel = "example"
|
XMLLabel = "xml"
|
||||||
ItemsLabel = "items"
|
ItemsLabel = "items"
|
||||||
AllOfLabel = "allOf"
|
AllOfLabel = "allOf"
|
||||||
AnyOfLabel = "anyOf"
|
AnyOfLabel = "anyOf"
|
||||||
@@ -44,7 +43,7 @@ type Schema struct {
|
|||||||
AnyOf []low.NodeReference[*Schema]
|
AnyOf []low.NodeReference[*Schema]
|
||||||
Not []low.NodeReference[*Schema]
|
Not []low.NodeReference[*Schema]
|
||||||
Items []low.NodeReference[*Schema]
|
Items []low.NodeReference[*Schema]
|
||||||
Properties map[low.NodeReference[string]]*low.NodeReference[*Schema]
|
Properties map[low.KeyReference[string]]*low.ValueReference[*Schema]
|
||||||
AdditionalProperties low.NodeReference[any]
|
AdditionalProperties low.NodeReference[any]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
Default low.NodeReference[any]
|
Default low.NodeReference[any]
|
||||||
@@ -52,14 +51,14 @@ type Schema struct {
|
|||||||
Discriminator low.NodeReference[*Discriminator]
|
Discriminator low.NodeReference[*Discriminator]
|
||||||
ReadOnly low.NodeReference[bool]
|
ReadOnly low.NodeReference[bool]
|
||||||
WriteOnly low.NodeReference[bool]
|
WriteOnly low.NodeReference[bool]
|
||||||
XML *low.NodeReference[*XML]
|
XML low.NodeReference[*XML]
|
||||||
ExternalDocs *low.NodeReference[*ExternalDoc]
|
ExternalDocs low.NodeReference[*ExternalDoc]
|
||||||
Example low.NodeReference[any]
|
Example low.NodeReference[any]
|
||||||
Deprecated low.NodeReference[bool]
|
Deprecated low.NodeReference[bool]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Schema) FindProperty(name string) *low.NodeReference[*Schema] {
|
func (s *Schema) FindProperty(name string) *low.ValueReference[*Schema] {
|
||||||
for k, v := range s.Properties {
|
for k, v := range s.Properties {
|
||||||
if k.Value == name {
|
if k.Value == name {
|
||||||
return v
|
return v
|
||||||
@@ -68,17 +67,16 @@ func (s *Schema) FindProperty(name string) *low.NodeReference[*Schema] {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
func (s *Schema) Build(root *yaml.Node, level int) error {
|
||||||
level++
|
level++
|
||||||
if level > 50 {
|
if level > 50 {
|
||||||
return nil // we're done, son! too fricken deep.
|
return nil // we're done, son! too fricken deep.
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionMap, err := ExtractExtensions(root)
|
err := s.extractExtensions(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Extensions = extensionMap
|
|
||||||
|
|
||||||
// handle example if set.
|
// handle example if set.
|
||||||
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||||
@@ -90,7 +88,10 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
|||||||
if addPNode != nil {
|
if addPNode != nil {
|
||||||
if utils.IsNodeMap(addPNode) {
|
if utils.IsNodeMap(addPNode) {
|
||||||
var props map[string]interface{}
|
var props map[string]interface{}
|
||||||
addPNode.Decode(&props)
|
err = addPNode.Decode(&props)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
s.AdditionalProperties = low.NodeReference[any]{Value: props, KeyNode: addPLabel, ValueNode: addPNode}
|
s.AdditionalProperties = low.NodeReference[any]{Value: props, KeyNode: addPLabel, ValueNode: addPNode}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +112,43 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
|||||||
s.Discriminator = low.NodeReference[*Discriminator]{Value: &discriminator, KeyNode: discLabel, ValueNode: discNode}
|
s.Discriminator = low.NodeReference[*Discriminator]{Value: &discriminator, KeyNode: discLabel, ValueNode: discNode}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle externalDocs if set.
|
||||||
|
_, extDocLabel, extDocNode := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
|
||||||
|
if extDocNode != nil {
|
||||||
|
var exDoc ExternalDoc
|
||||||
|
err = BuildModel(extDocNode, &exDoc)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = exDoc.Build(extDocNode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle xml if set.
|
||||||
|
_, xmlLabel, xmlNode := utils.FindKeyNodeFull(XMLLabel, root.Content)
|
||||||
|
if xmlNode != nil {
|
||||||
|
var xml XML
|
||||||
|
err = BuildModel(xmlNode, &xml)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// extract extensions if set.
|
||||||
|
err = xml.Build(xmlNode)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.XML = low.NodeReference[*XML]{Value: &xml, KeyNode: xmlLabel, ValueNode: xmlNode}
|
||||||
|
}
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
_, propLabel, propsNode := utils.FindKeyNodeFull(PropertiesLabel, root.Content)
|
_, propLabel, propsNode := utils.FindKeyNodeFull(PropertiesLabel, root.Content)
|
||||||
if propsNode != nil {
|
if propsNode != nil {
|
||||||
propertyMap := make(map[low.NodeReference[string]]*low.NodeReference[*Schema])
|
propertyMap := make(map[low.KeyReference[string]]*low.ValueReference[*Schema])
|
||||||
var currentProp *yaml.Node
|
var currentProp *yaml.Node
|
||||||
|
var wg sync.WaitGroup
|
||||||
for i, prop := range propsNode.Content {
|
for i, prop := range propsNode.Content {
|
||||||
if i%2 == 0 {
|
if i%2 == 0 {
|
||||||
currentProp = prop
|
currentProp = prop
|
||||||
@@ -127,17 +160,15 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = property.Build(prop, idx, level)
|
err = property.Build(prop, level)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
propertyMap[low.NodeReference[string]{
|
propertyMap[low.KeyReference[string]{
|
||||||
Value: currentProp.Value,
|
Value: currentProp.Value,
|
||||||
KeyNode: propLabel,
|
KeyNode: propLabel,
|
||||||
ValueNode: propsNode,
|
}] = &low.ValueReference[*Schema]{
|
||||||
}] = &low.NodeReference[*Schema]{
|
|
||||||
Value: &property,
|
Value: &property,
|
||||||
KeyNode: currentProp,
|
|
||||||
ValueNode: prop,
|
ValueNode: prop,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,16 +176,15 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
|||||||
|
|
||||||
// extract all sub-schemas
|
// extract all sub-schemas
|
||||||
var errors []error
|
var errors []error
|
||||||
var wg sync.WaitGroup
|
|
||||||
|
|
||||||
var allOf, anyOf, oneOf, not, items []low.NodeReference[*Schema]
|
var allOf, anyOf, oneOf, not, items []low.NodeReference[*Schema]
|
||||||
|
|
||||||
// make this async at some point to speed things up.
|
// make this async at some point to speed things up.
|
||||||
buildSchema(&allOf, AllOfLabel, idx, root, level, &errors, &wg)
|
buildSchema(&allOf, AllOfLabel, root, level, &errors, &wg)
|
||||||
buildSchema(&anyOf, AnyOfLabel, idx, root, level, &errors, &wg)
|
buildSchema(&anyOf, AnyOfLabel, root, level, &errors, &wg)
|
||||||
buildSchema(&oneOf, OneOfLabel, idx, root, level, &errors, &wg)
|
buildSchema(&oneOf, OneOfLabel, root, level, &errors, &wg)
|
||||||
buildSchema(¬, NotLabel, idx, root, level, &errors, &wg)
|
buildSchema(¬, NotLabel, root, level, &errors, &wg)
|
||||||
buildSchema(&items, ItemsLabel, idx, root, level, &errors, &wg)
|
buildSchema(&items, ItemsLabel, root, level, &errors, &wg)
|
||||||
//wg.Wait()
|
//wg.Wait()
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
@@ -182,7 +212,16 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, idx *index.SpecIndex, rootNode *yaml.Node, level int, errors *[]error, wg *sync.WaitGroup) {
|
func (s *Schema) extractExtensions(root *yaml.Node) error {
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Extensions = extensionMap
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNode *yaml.Node, level int, errors *[]error, wg *sync.WaitGroup) {
|
||||||
_, labelNode, valueNode := utils.FindKeyNodeFull(attribute, rootNode.Content)
|
_, labelNode, valueNode := utils.FindKeyNodeFull(attribute, rootNode.Content)
|
||||||
//wg.Add(1)
|
//wg.Add(1)
|
||||||
if valueNode != nil {
|
if valueNode != nil {
|
||||||
@@ -194,7 +233,7 @@ func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, idx *i
|
|||||||
*errors = append(*errors, err)
|
*errors = append(*errors, err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = schema.Build(vn, idx, level)
|
err = schema.Build(vn, level)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
*errors = append(*errors, err)
|
*errors = append(*errors, err)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -83,15 +83,25 @@ properties:
|
|||||||
somethingB:
|
somethingB:
|
||||||
type: object
|
type: object
|
||||||
description: an object
|
description: an object
|
||||||
|
externalDocs:
|
||||||
|
description: the best docs
|
||||||
|
url: https://pb33f.io
|
||||||
properties:
|
properties:
|
||||||
somethingBProp:
|
somethingBProp:
|
||||||
type: string
|
type: string
|
||||||
description: something b subprop
|
description: something b subprop
|
||||||
example: picnics are nice.
|
example: picnics are nice.
|
||||||
|
xml:
|
||||||
|
name: an xml thing
|
||||||
|
namespace: an xml namespace
|
||||||
|
prefix: a prefix
|
||||||
|
attribute: true
|
||||||
|
wrapped: false
|
||||||
|
x-pizza: love
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
why: yes
|
why: yes
|
||||||
thatIs: true
|
thatIs: true
|
||||||
additionalProperties: true`
|
additionalProperties: true `
|
||||||
|
|
||||||
var rootNode yaml.Node
|
var rootNode yaml.Node
|
||||||
mErr := yaml.Unmarshal([]byte(testSpec), &rootNode)
|
mErr := yaml.Unmarshal([]byte(testSpec), &rootNode)
|
||||||
@@ -101,13 +111,26 @@ additionalProperties: true`
|
|||||||
mbErr := BuildModel(&rootNode, &sch)
|
mbErr := BuildModel(&rootNode, &sch)
|
||||||
assert.NoError(t, mbErr)
|
assert.NoError(t, mbErr)
|
||||||
|
|
||||||
schErr := sch.Build(rootNode.Content[0], nil, 0)
|
schErr := sch.Build(rootNode.Content[0], 0)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
assert.Equal(t, "something object", sch.Description.Value)
|
assert.Equal(t, "something object", sch.Description.Value)
|
||||||
assert.True(t, sch.AdditionalProperties.Value.(bool))
|
assert.True(t, sch.AdditionalProperties.Value.(bool))
|
||||||
|
|
||||||
assert.Len(t, sch.Properties, 2)
|
assert.Len(t, sch.Properties, 2)
|
||||||
v := sch.FindProperty("somethingB")
|
v := sch.FindProperty("somethingB")
|
||||||
|
|
||||||
|
assert.Equal(t, "https://pb33f.io", v.Value.ExternalDocs.Value.URL.Value)
|
||||||
|
assert.Equal(t, "the best docs", v.Value.ExternalDocs.Value.Description.Value)
|
||||||
|
|
||||||
|
j := v.Value.FindProperty("somethingBProp")
|
||||||
|
assert.NotNil(t, j.Value)
|
||||||
|
assert.NotNil(t, j.Value.XML.Value)
|
||||||
|
assert.Equal(t, "an xml thing", j.Value.XML.Value.Name.Value)
|
||||||
|
assert.Equal(t, "an xml namespace", j.Value.XML.Value.Namespace.Value)
|
||||||
|
assert.Equal(t, "a prefix", j.Value.XML.Value.Prefix.Value)
|
||||||
|
assert.Equal(t, true, j.Value.XML.Value.Attribute.Value)
|
||||||
|
assert.Len(t, j.Value.XML.Value.Extensions, 1)
|
||||||
|
|
||||||
assert.NotNil(t, v.Value.AdditionalProperties.Value)
|
assert.NotNil(t, v.Value.AdditionalProperties.Value)
|
||||||
|
|
||||||
var addProps map[string]interface{}
|
var addProps map[string]interface{}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ type Tag struct {
|
|||||||
Name low.NodeReference[string]
|
Name low.NodeReference[string]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
ExternalDocs low.NodeReference[*ExternalDoc]
|
ExternalDocs low.NodeReference[*ExternalDoc]
|
||||||
Extensions map[low.NodeReference[string]]low.NodeReference[any]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *Tag) Build(root *yaml.Node) error {
|
func (t *Tag) Build(root *yaml.Node) error {
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type XML struct {
|
type XML struct {
|
||||||
Node *yaml.Node
|
Name low.NodeReference[string]
|
||||||
Name low.NodeReference[string]
|
Namespace low.NodeReference[string]
|
||||||
Namespace low.NodeReference[string]
|
Prefix low.NodeReference[string]
|
||||||
Prefix low.NodeReference[string]
|
Attribute low.NodeReference[bool]
|
||||||
Attribute low.NodeReference[string]
|
Wrapped low.NodeReference[bool]
|
||||||
Wrapped low.NodeReference[bool]
|
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||||
Extensions map[string]low.ObjectReference
|
}
|
||||||
|
|
||||||
|
func (x *XML) Build(root *yaml.Node) error {
|
||||||
|
extensionMap, err := ExtractExtensions(root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
x.Extensions = extensionMap
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ type HasNode interface {
|
|||||||
GetNode() *yaml.Node
|
GetNode() *yaml.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type Buildable interface {
|
type Buildable[T any] interface {
|
||||||
Build(node *yaml.Node) error
|
Build(node *yaml.Node) error
|
||||||
|
*T
|
||||||
}
|
}
|
||||||
|
|
||||||
type NodeReference[T any] struct {
|
type NodeReference[T any] struct {
|
||||||
@@ -16,6 +17,16 @@ type NodeReference[T any] struct {
|
|||||||
KeyNode *yaml.Node
|
KeyNode *yaml.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type KeyReference[T any] struct {
|
||||||
|
Value T
|
||||||
|
KeyNode *yaml.Node
|
||||||
|
}
|
||||||
|
|
||||||
|
type ValueReference[T any] struct {
|
||||||
|
Value T
|
||||||
|
ValueNode *yaml.Node
|
||||||
|
}
|
||||||
|
|
||||||
type ObjectReference struct {
|
type ObjectReference struct {
|
||||||
Value interface{}
|
Value interface{}
|
||||||
ValueNode *yaml.Node
|
ValueNode *yaml.Node
|
||||||
@@ -25,3 +36,11 @@ type ObjectReference struct {
|
|||||||
func (n NodeReference[T]) IsEmpty() bool {
|
func (n NodeReference[T]) IsEmpty() bool {
|
||||||
return n.KeyNode == nil && n.ValueNode == nil
|
return n.KeyNode == nil && n.ValueNode == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n NodeReference[T]) IsMapKeyNode() bool {
|
||||||
|
return n.KeyNode != nil && n.ValueNode == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n NodeReference[T]) IsMapValueNode() bool {
|
||||||
|
return n.KeyNode == nil && n.ValueNode != nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
|||||||
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||||
|
|
||||||
// build an index
|
// build an index
|
||||||
idx := index.NewSpecIndex(info.RootNode)
|
rsolvr := resolver.NewResolver(index.NewSpecIndex(info.RootNode))
|
||||||
rsolvr := resolver.NewResolver(idx)
|
|
||||||
|
|
||||||
// todo handle errors
|
// todo handle errors
|
||||||
rsolvr.Resolve()
|
rsolvr.Resolve()
|
||||||
@@ -24,18 +23,18 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
var errors []error
|
var errors []error
|
||||||
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document,
|
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document,
|
||||||
runFunc func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error,
|
runFunc func(i *datamodel.SpecInfo, d *v3.Document) error,
|
||||||
ers *[]error,
|
ers *[]error,
|
||||||
wg *sync.WaitGroup) {
|
wg *sync.WaitGroup) {
|
||||||
|
|
||||||
if er := runFunc(info, doc, idx); er != nil {
|
if er := runFunc(info, doc); er != nil {
|
||||||
*ers = append(*ers, er)
|
*ers = append(*ers, er)
|
||||||
}
|
}
|
||||||
|
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error{
|
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document) error{
|
||||||
extractInfo,
|
extractInfo,
|
||||||
extractServers,
|
extractServers,
|
||||||
extractTags,
|
extractTags,
|
||||||
@@ -54,7 +53,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
|||||||
return &doc, nil
|
return &doc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.InfoLabel, info.RootNode.Content)
|
_, ln, vn := utils.FindKeyNodeFull(v3.InfoLabel, info.RootNode.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := v3.Info{}
|
ir := v3.Info{}
|
||||||
@@ -69,7 +68,7 @@ func extractInfo(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecInde
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractServers(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.ServersLabel, info.RootNode.Content)
|
_, ln, vn := utils.FindKeyNodeFull(v3.ServersLabel, info.RootNode.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -95,7 +94,7 @@ func extractServers(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTags(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
|
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -121,11 +120,11 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecInde
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(v3.PathsLabel, info.RootNode.Content)
|
_, ln, vn := utils.FindKeyNodeFull(v3.PathsLabel, info.RootNode.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := v3.Paths{}
|
ir := v3.Paths{}
|
||||||
err := ir.Build(vn, idx)
|
err := ir.Build(vn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,109 +1,126 @@
|
|||||||
package openapi
|
package openapi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
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 *v3.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)
|
||||||
doc, _ = CreateDocument(info)
|
doc, _ = CreateDocument(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument(t *testing.T) {
|
func TestCreateDocument(t *testing.T) {
|
||||||
assert.Equal(t, "3.0.1", doc.Version.Value)
|
assert.Equal(t, "3.0.1", doc.Version.Value)
|
||||||
assert.Equal(t, "Burger Shop", doc.Info.Value.Title.Value)
|
assert.Equal(t, "Burger Shop", doc.Info.Value.Title.Value)
|
||||||
assert.NotEmpty(t, doc.Info.Value.Title.Value)
|
assert.NotEmpty(t, doc.Info.Value.Title.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Info(t *testing.T) {
|
func TestCreateDocument_Info(t *testing.T) {
|
||||||
assert.Equal(t, "https://pb33f.io", doc.Info.Value.TermsOfService.Value)
|
assert.Equal(t, "https://pb33f.io", doc.Info.Value.TermsOfService.Value)
|
||||||
assert.Equal(t, "pb33f", doc.Info.Value.Contact.Value.Name.Value)
|
assert.Equal(t, "pb33f", doc.Info.Value.Contact.Value.Name.Value)
|
||||||
assert.Equal(t, "buckaroo@pb33f.io", doc.Info.Value.Contact.Value.Email.Value)
|
assert.Equal(t, "buckaroo@pb33f.io", doc.Info.Value.Contact.Value.Email.Value)
|
||||||
assert.Equal(t, "https://pb33f.io", doc.Info.Value.Contact.Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io", doc.Info.Value.Contact.Value.URL.Value)
|
||||||
assert.Equal(t, "pb33f", doc.Info.Value.License.Value.Name.Value)
|
assert.Equal(t, "pb33f", doc.Info.Value.License.Value.Name.Value)
|
||||||
assert.Equal(t, "https://pb33f.io/made-up", doc.Info.Value.License.Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io/made-up", doc.Info.Value.License.Value.URL.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Servers(t *testing.T) {
|
func TestCreateDocument_Servers(t *testing.T) {
|
||||||
assert.Len(t, doc.Servers, 2)
|
assert.Len(t, doc.Servers, 2)
|
||||||
server1 := doc.Servers[0]
|
server1 := doc.Servers[0]
|
||||||
server2 := doc.Servers[1]
|
server2 := doc.Servers[1]
|
||||||
|
|
||||||
// server 1
|
// server 1
|
||||||
assert.Equal(t, "{scheme}://api.pb33f.io", server1.Value.URL.Value)
|
assert.Equal(t, "{scheme}://api.pb33f.io", server1.Value.URL.Value)
|
||||||
assert.NotEmpty(t, server1.Value.Description.Value)
|
assert.NotEmpty(t, server1.Value.Description.Value)
|
||||||
assert.Len(t, server1.Value.Variables.Value, 1)
|
assert.Len(t, server1.Value.Variables.Value, 1)
|
||||||
assert.Len(t, server1.Value.Variables.Value["scheme"].Value.Enum, 2)
|
assert.Len(t, server1.Value.Variables.Value["scheme"].Value.Enum, 2)
|
||||||
assert.Equal(t, server1.Value.Variables.Value["scheme"].Value.Default.Value, "https")
|
assert.Equal(t, server1.Value.Variables.Value["scheme"].Value.Default.Value, "https")
|
||||||
assert.NotEmpty(t, server1.Value.Variables.Value["scheme"].Value.Description.Value)
|
assert.NotEmpty(t, server1.Value.Variables.Value["scheme"].Value.Description.Value)
|
||||||
|
|
||||||
// server 2
|
// server 2
|
||||||
assert.Equal(t, "https://{domain}.{host}.com", server2.Value.URL.Value)
|
assert.Equal(t, "https://{domain}.{host}.com", server2.Value.URL.Value)
|
||||||
assert.NotEmpty(t, server2.Value.Description.Value)
|
assert.NotEmpty(t, server2.Value.Description.Value)
|
||||||
assert.Len(t, server2.Value.Variables.Value, 2)
|
assert.Len(t, server2.Value.Variables.Value, 2)
|
||||||
assert.Equal(t, server2.Value.Variables.Value["domain"].Value.Default.Value, "api")
|
assert.Equal(t, server2.Value.Variables.Value["domain"].Value.Default.Value, "api")
|
||||||
assert.NotEmpty(t, server2.Value.Variables.Value["domain"].Value.Description.Value)
|
assert.NotEmpty(t, server2.Value.Variables.Value["domain"].Value.Description.Value)
|
||||||
assert.NotEmpty(t, server2.Value.Variables.Value["host"].Value.Description.Value)
|
assert.NotEmpty(t, server2.Value.Variables.Value["host"].Value.Description.Value)
|
||||||
assert.Equal(t, server2.Value.Variables.Value["host"].Value.Default.Value, "pb33f.io")
|
assert.Equal(t, server2.Value.Variables.Value["host"].Value.Default.Value, "pb33f.io")
|
||||||
assert.Equal(t, "1.2", doc.Info.Value.Version.Value)
|
assert.Equal(t, "1.2", doc.Info.Value.Version.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Tags(t *testing.T) {
|
func TestCreateDocument_Tags(t *testing.T) {
|
||||||
assert.Len(t, doc.Tags, 2)
|
assert.Len(t, doc.Tags, 2)
|
||||||
|
|
||||||
// tag1
|
// tag1
|
||||||
assert.Equal(t, "Burgers", doc.Tags[0].Value.Name.Value)
|
assert.Equal(t, "Burgers", doc.Tags[0].Value.Name.Value)
|
||||||
assert.NotEmpty(t, doc.Tags[0].Value.Description.Value)
|
assert.NotEmpty(t, doc.Tags[0].Value.Description.Value)
|
||||||
assert.NotNil(t, doc.Tags[0].Value.ExternalDocs.Value)
|
assert.NotNil(t, doc.Tags[0].Value.ExternalDocs.Value)
|
||||||
assert.Equal(t, "https://pb33f.io", doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io", doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.NotEmpty(t, doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
|
assert.NotEmpty(t, doc.Tags[0].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.Len(t, doc.Tags[0].Value.Extensions, 7)
|
assert.Len(t, doc.Tags[0].Value.Extensions, 7)
|
||||||
|
|
||||||
for key, extension := range doc.Tags[0].Value.Extensions {
|
for key, extension := range doc.Tags[0].Value.Extensions {
|
||||||
switch key.Value {
|
switch key.Value {
|
||||||
case "x-internal-ting":
|
case "x-internal-ting":
|
||||||
assert.Equal(t, "somethingSpecial", extension.Value)
|
assert.Equal(t, "somethingSpecial", extension.Value)
|
||||||
case "x-internal-tong":
|
case "x-internal-tong":
|
||||||
assert.Equal(t, int64(1), extension.Value)
|
assert.Equal(t, int64(1), extension.Value)
|
||||||
case "x-internal-tang":
|
case "x-internal-tang":
|
||||||
assert.Equal(t, 1.2, extension.Value)
|
assert.Equal(t, 1.2, extension.Value)
|
||||||
case "x-internal-tung":
|
case "x-internal-tung":
|
||||||
assert.Equal(t, true, extension.Value)
|
assert.Equal(t, true, extension.Value)
|
||||||
case "x-internal-arr":
|
case "x-internal-arr":
|
||||||
assert.Len(t, extension.Value, 2)
|
assert.Len(t, extension.Value, 2)
|
||||||
assert.Equal(t, "one", extension.Value.([]interface{})[0].(string))
|
assert.Equal(t, "one", extension.Value.([]interface{})[0].(string))
|
||||||
case "x-internal-arrmap":
|
case "x-internal-arrmap":
|
||||||
assert.Len(t, extension.Value, 2)
|
assert.Len(t, extension.Value, 2)
|
||||||
assert.Equal(t, "now", extension.Value.([]interface{})[0].(map[string]interface{})["what"])
|
assert.Equal(t, "now", extension.Value.([]interface{})[0].(map[string]interface{})["what"])
|
||||||
case "x-something-else":
|
case "x-something-else":
|
||||||
// crazy times in the upside down. this API should be avoided for the higher up use cases.
|
// crazy times in the upside down. this API should be avoided for the higher up use cases.
|
||||||
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
|
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
|
||||||
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
|
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// tag2
|
/// tag2
|
||||||
assert.Equal(t, "Dressing", doc.Tags[1].Value.Name.Value)
|
assert.Equal(t, "Dressing", doc.Tags[1].Value.Name.Value)
|
||||||
assert.NotEmpty(t, doc.Tags[1].Value.Description.Value)
|
assert.NotEmpty(t, doc.Tags[1].Value.Description.Value)
|
||||||
assert.NotNil(t, doc.Tags[1].Value.ExternalDocs.Value)
|
assert.NotNil(t, doc.Tags[1].Value.ExternalDocs.Value)
|
||||||
assert.Equal(t, "https://pb33f.io", doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io", doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.NotEmpty(t, doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
|
assert.NotEmpty(t, doc.Tags[1].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.Len(t, doc.Tags[1].Value.Extensions, 0)
|
assert.Len(t, doc.Tags[1].Value.Extensions, 0)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateDocument_Paths(t *testing.T) {
|
||||||
|
assert.Len(t, doc.Paths.Value.PathItems, 6)
|
||||||
|
burgerId := doc.Paths.Value.GetPath("/burgers/{burgerId}")
|
||||||
|
assert.NotNil(t, burgerId)
|
||||||
|
assert.Len(t, burgerId.Value.Get.Value.Parameters, 2)
|
||||||
|
param := burgerId.Value.Get.Value.Parameters[1]
|
||||||
|
assert.Equal(t, "burgerHeader", param.Value.Name.Value)
|
||||||
|
prop := param.Value.Schema.Value.FindProperty("burgerTheme")
|
||||||
|
assert.Equal(t, "something about a theme?", prop.Value.Description.Value)
|
||||||
|
assert.Equal(t, "big-mac", param.Value.Example.Value)
|
||||||
|
|
||||||
|
// check content
|
||||||
|
pContent := param.Value.GetContent("application/json")
|
||||||
|
assert.Equal(t, "somethingNice", pContent.Value.Example.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -321,6 +321,27 @@ components:
|
|||||||
example: big-mac
|
example: big-mac
|
||||||
description: the name of the burger. use this to order your food
|
description: the name of the burger. use this to order your food
|
||||||
required: true
|
required: true
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
example: somethingNice
|
||||||
|
encoding:
|
||||||
|
burgerTheme:
|
||||||
|
contentType: text/plain
|
||||||
|
headers:
|
||||||
|
someHeader:
|
||||||
|
description: this is a header
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
required: [burgerTheme, burgerTime]
|
||||||
|
properties:
|
||||||
|
burgerTheme:
|
||||||
|
type: string
|
||||||
|
description: something about a theme?
|
||||||
|
burgerTime:
|
||||||
|
type: number
|
||||||
|
description: number of burgers ordered this year.
|
||||||
BurgerId:
|
BurgerId:
|
||||||
in: path
|
in: path
|
||||||
name: burgerId
|
name: burgerId
|
||||||
|
|||||||
Reference in New Issue
Block a user