mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 20:47:45 +00:00
Working through the model builder
Shaping out the design as I go, what makes sence, what feels right, what do we need, how do we want to use it and how to we want to search it etc.
This commit is contained in:
@@ -2,11 +2,9 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Contact struct {
|
||||
Node *yaml.Node
|
||||
Name low.NodeReference[string]
|
||||
URL low.NodeReference[string]
|
||||
Email low.NodeReference[string]
|
||||
|
||||
@@ -1,48 +1,17 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type Document struct {
|
||||
Version string
|
||||
Info Info
|
||||
Servers []Server
|
||||
Paths Paths
|
||||
Components Components
|
||||
Security []SecurityRequirement
|
||||
Tags []Tag
|
||||
ExternalDocs ExternalDoc
|
||||
Version low.NodeReference[string]
|
||||
Info low.NodeReference[*Info]
|
||||
Servers []low.NodeReference[*Server]
|
||||
Paths *Paths
|
||||
Components *Components
|
||||
Security []*SecurityRequirement
|
||||
Tags []*Tag
|
||||
ExternalDocs *ExternalDoc
|
||||
Extensions map[string]low.ObjectReference
|
||||
}
|
||||
|
||||
func (d Document) Build(node *yaml.Node) {
|
||||
|
||||
doc := Document{
|
||||
Version: "",
|
||||
Info: Info{},
|
||||
Servers: nil,
|
||||
Paths: Paths{},
|
||||
Components: Components{},
|
||||
Security: nil,
|
||||
Tags: nil,
|
||||
ExternalDocs: ExternalDoc{},
|
||||
Extensions: nil,
|
||||
}
|
||||
|
||||
var j interface{}
|
||||
j = doc
|
||||
t := reflect.TypeOf(j)
|
||||
v := reflect.ValueOf(j)
|
||||
k := t.Kind()
|
||||
fmt.Println("Type ", t)
|
||||
fmt.Println("Value ", v)
|
||||
fmt.Println("Kind ", k)
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
fmt.Printf("Field:%d type:%T value:%v\n", i, v.Field(i), v.Field(i))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,36 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Info struct {
|
||||
Node *yaml.Node
|
||||
Title low.NodeReference[string]
|
||||
Description low.NodeReference[string]
|
||||
TermsOfService low.NodeReference[string]
|
||||
Contact Contact
|
||||
License License
|
||||
Contact low.NodeReference[*Contact]
|
||||
License low.NodeReference[*License]
|
||||
Version low.NodeReference[string]
|
||||
}
|
||||
|
||||
func (i *Info) Build(root *yaml.Node) error {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
var errs []error
|
||||
|
||||
contact := Contact{}
|
||||
_, kln, cn := utils.FindKeyNodeFull("contact", root.Content)
|
||||
go datamodel.BuildModelAsync(cn, &contact, &wg, &errs)
|
||||
|
||||
license := License{}
|
||||
_, kln, ln := utils.FindKeyNodeFull("license", root.Content)
|
||||
go datamodel.BuildModelAsync(ln, &license, &wg, &errs)
|
||||
wg.Wait()
|
||||
i.Contact = low.NodeReference[*Contact]{Value: &contact, ValueNode: cn, KeyNode: kln}
|
||||
i.License = low.NodeReference[*License]{Value: &license, ValueNode: ln, KeyNode: kln}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type License struct {
|
||||
Node *yaml.Node
|
||||
Name low.NodeReference[string]
|
||||
URL low.NodeReference[string]
|
||||
}
|
||||
|
||||
@@ -1,9 +1,49 @@
|
||||
package v3
|
||||
|
||||
import "github.com/pb33f/libopenapi/datamodel/low"
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
URL low.NodeReference[string]
|
||||
Description low.NodeReference[string]
|
||||
Variables map[string]ServerVariable
|
||||
Variables low.NodeReference[*map[string]low.NodeReference[*ServerVariable]]
|
||||
}
|
||||
|
||||
func (s *Server) Build(root *yaml.Node) error {
|
||||
kn, vars := utils.FindKeyNode("variables", root.Content)
|
||||
if vars == nil {
|
||||
return nil
|
||||
}
|
||||
variablesMap := make(map[string]low.NodeReference[*ServerVariable])
|
||||
if utils.IsNodeMap(vars) {
|
||||
var currentNode string
|
||||
var keyNode *yaml.Node
|
||||
for i, varNode := range vars.Content {
|
||||
if i%2 == 0 {
|
||||
currentNode = varNode.Value
|
||||
keyNode = varNode
|
||||
continue
|
||||
}
|
||||
variable := ServerVariable{}
|
||||
err := datamodel.BuildModel(varNode, &variable)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
variablesMap[currentNode] = low.NodeReference[*ServerVariable]{
|
||||
ValueNode: varNode,
|
||||
KeyNode: keyNode,
|
||||
Value: &variable,
|
||||
}
|
||||
}
|
||||
s.Variables = low.NodeReference[*map[string]low.NodeReference[*ServerVariable]]{
|
||||
KeyNode: kn,
|
||||
ValueNode: vars,
|
||||
Value: &variablesMap,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type ServerVariable struct {
|
||||
Node *yaml.Node
|
||||
Enum []low.NodeReference[string]
|
||||
Default low.NodeReference[string]
|
||||
Description low.NodeReference[string]
|
||||
|
||||
@@ -7,15 +7,17 @@ type HasNode interface {
|
||||
}
|
||||
|
||||
type Buildable interface {
|
||||
Build(node *yaml.Node)
|
||||
Build(node *yaml.Node) error
|
||||
}
|
||||
|
||||
type NodeReference[T comparable] struct {
|
||||
type NodeReference[T any] struct {
|
||||
Value T
|
||||
Node *yaml.Node
|
||||
ValueNode *yaml.Node
|
||||
KeyNode *yaml.Node
|
||||
}
|
||||
|
||||
type ObjectReference struct {
|
||||
Value map[string]interface{}
|
||||
Node *yaml.Node
|
||||
ValueNode *yaml.Node
|
||||
KeyNode *yaml.Node
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package utils
|
||||
package datamodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func BuildModel(node *yaml.Node, model interface{}) error {
|
||||
@@ -19,12 +21,12 @@ func BuildModel(node *yaml.Node, model interface{}) error {
|
||||
fName := v.Type().Field(i).Name
|
||||
|
||||
// we need to find a matching field in the YAML, the cases may be off, so take no chances.
|
||||
cases := []Case{PascalCase, CamelCase, ScreamingSnakeCase,
|
||||
SnakeCase, KebabCase, RegularCase}
|
||||
cases := []utils.Case{utils.PascalCase, utils.CamelCase, utils.ScreamingSnakeCase,
|
||||
utils.SnakeCase, utils.KebabCase, utils.RegularCase}
|
||||
|
||||
var vn, kn *yaml.Node
|
||||
for _, tryCase := range cases {
|
||||
kn, vn = FindKeyNode(ConvertCase(fName, tryCase), node.Content)
|
||||
kn, vn = utils.FindKeyNode(utils.ConvertCase(fName, tryCase), node.Content)
|
||||
if vn != nil {
|
||||
break
|
||||
}
|
||||
@@ -38,7 +40,7 @@ func BuildModel(node *yaml.Node, model interface{}) error {
|
||||
field := v.FieldByName(fName)
|
||||
kind := field.Kind()
|
||||
switch kind {
|
||||
case reflect.Struct, reflect.Slice, reflect.Map:
|
||||
case reflect.Struct, reflect.Slice, reflect.Map, reflect.Pointer:
|
||||
err := SetField(field, vn, kn)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -57,7 +59,7 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
|
||||
case reflect.TypeOf(map[string]low.ObjectReference{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeMap(valueNode) {
|
||||
if utils.IsNodeMap(valueNode) {
|
||||
if field.CanSet() {
|
||||
items := make(map[string]low.ObjectReference)
|
||||
var currentLabel string
|
||||
@@ -73,7 +75,8 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
}
|
||||
items[currentLabel] = low.ObjectReference{
|
||||
Value: decoded,
|
||||
Node: sliceItem,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
}
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
@@ -84,7 +87,7 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
|
||||
case reflect.TypeOf(map[string]low.NodeReference[string]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeMap(valueNode) {
|
||||
if utils.IsNodeMap(valueNode) {
|
||||
if field.CanSet() {
|
||||
items := make(map[string]low.NodeReference[string])
|
||||
var currentLabel string
|
||||
@@ -95,7 +98,8 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
}
|
||||
items[currentLabel] = low.NodeReference[string]{
|
||||
Value: sliceItem.Value,
|
||||
Node: sliceItem,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
}
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
@@ -110,9 +114,9 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if IsNodeMap(valueNode) {
|
||||
if utils.IsNodeMap(valueNode) {
|
||||
if field.CanSet() {
|
||||
or := low.ObjectReference{Value: decoded, Node: valueNode}
|
||||
or := low.ObjectReference{Value: decoded, ValueNode: valueNode}
|
||||
field.Set(reflect.ValueOf(or))
|
||||
}
|
||||
}
|
||||
@@ -120,7 +124,7 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.ObjectReference{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.ObjectReference
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
@@ -131,7 +135,8 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
}
|
||||
items = append(items, low.ObjectReference{
|
||||
Value: decoded,
|
||||
Node: sliceItem,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
@@ -141,9 +146,13 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[string]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeStringValue(valueNode) {
|
||||
if utils.IsNodeStringValue(valueNode) {
|
||||
if field.CanSet() {
|
||||
nr := low.NodeReference[string]{Value: valueNode.Value, Node: valueNode}
|
||||
nr := low.NodeReference[string]{
|
||||
Value: valueNode.Value,
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -151,10 +160,14 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[bool]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeBoolValue(valueNode) {
|
||||
if utils.IsNodeBoolValue(valueNode) {
|
||||
if field.CanSet() {
|
||||
bv, _ := strconv.ParseBool(valueNode.Value)
|
||||
nr := low.NodeReference[bool]{Value: bv, Node: valueNode}
|
||||
nr := low.NodeReference[bool]{
|
||||
Value: bv,
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -162,10 +175,14 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[int]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeIntValue(valueNode) {
|
||||
if utils.IsNodeIntValue(valueNode) {
|
||||
if field.CanSet() {
|
||||
fv, _ := strconv.Atoi(valueNode.Value)
|
||||
nr := low.NodeReference[int]{Value: fv, Node: valueNode}
|
||||
nr := low.NodeReference[int]{
|
||||
Value: fv,
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -173,10 +190,14 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[int64]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeIntValue(valueNode) || IsNodeFloatValue(valueNode) { //
|
||||
if utils.IsNodeIntValue(valueNode) || utils.IsNodeFloatValue(valueNode) { //
|
||||
if field.CanSet() {
|
||||
fv, _ := strconv.ParseInt(valueNode.Value, 10, 64)
|
||||
nr := low.NodeReference[int64]{Value: fv, Node: valueNode}
|
||||
nr := low.NodeReference[int64]{
|
||||
Value: fv,
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -184,10 +205,14 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[float32]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeFloatValue(valueNode) {
|
||||
if utils.IsNodeFloatValue(valueNode) {
|
||||
if field.CanSet() {
|
||||
fv, _ := strconv.ParseFloat(valueNode.Value, 32)
|
||||
nr := low.NodeReference[float32]{Value: float32(fv), Node: valueNode}
|
||||
nr := low.NodeReference[float32]{
|
||||
Value: float32(fv),
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -195,10 +220,14 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf(low.NodeReference[float64]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeFloatValue(valueNode) {
|
||||
if utils.IsNodeFloatValue(valueNode) {
|
||||
if field.CanSet() {
|
||||
fv, _ := strconv.ParseFloat(valueNode.Value, 64)
|
||||
nr := low.NodeReference[float64]{Value: fv, Node: valueNode}
|
||||
nr := low.NodeReference[float64]{
|
||||
Value: fv,
|
||||
ValueNode: valueNode,
|
||||
KeyNode: keyNode,
|
||||
}
|
||||
field.Set(reflect.ValueOf(nr))
|
||||
}
|
||||
}
|
||||
@@ -206,11 +235,15 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[string]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[string]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
items = append(items, low.NodeReference[string]{Value: sliceItem.Value, Node: sliceItem})
|
||||
items = append(items, low.NodeReference[string]{
|
||||
Value: sliceItem.Value,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -219,12 +252,16 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[float32]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[float32]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
fv, _ := strconv.ParseFloat(sliceItem.Value, 32)
|
||||
items = append(items, low.NodeReference[float32]{Value: float32(fv), Node: sliceItem})
|
||||
items = append(items, low.NodeReference[float32]{
|
||||
Value: float32(fv),
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -233,12 +270,12 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[float64]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[float64]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
fv, _ := strconv.ParseFloat(sliceItem.Value, 64)
|
||||
items = append(items, low.NodeReference[float64]{Value: fv, Node: sliceItem})
|
||||
items = append(items, low.NodeReference[float64]{Value: fv, ValueNode: sliceItem})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -247,12 +284,16 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[int]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[int]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
iv, _ := strconv.Atoi(sliceItem.Value)
|
||||
items = append(items, low.NodeReference[int]{Value: iv, Node: sliceItem})
|
||||
items = append(items, low.NodeReference[int]{
|
||||
Value: iv,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -261,12 +302,16 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[int64]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[int64]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
iv, _ := strconv.ParseInt(sliceItem.Value, 10, 64)
|
||||
items = append(items, low.NodeReference[int64]{Value: iv, Node: sliceItem})
|
||||
items = append(items, low.NodeReference[int64]{
|
||||
Value: iv,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -275,12 +320,16 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
break
|
||||
case reflect.TypeOf([]low.NodeReference[bool]{}):
|
||||
if valueNode != nil {
|
||||
if IsNodeArray(valueNode) {
|
||||
if utils.IsNodeArray(valueNode) {
|
||||
if field.CanSet() {
|
||||
var items []low.NodeReference[bool]
|
||||
for _, sliceItem := range valueNode.Content {
|
||||
bv, _ := strconv.ParseBool(sliceItem.Value)
|
||||
items = append(items, low.NodeReference[bool]{Value: bv, Node: sliceItem})
|
||||
items = append(items, low.NodeReference[bool]{
|
||||
Value: bv,
|
||||
ValueNode: sliceItem,
|
||||
KeyNode: valueNode,
|
||||
})
|
||||
}
|
||||
field.Set(reflect.ValueOf(items))
|
||||
}
|
||||
@@ -288,8 +337,18 @@ func SetField(field reflect.Value, valueNode *yaml.Node, keyNode *yaml.Node) err
|
||||
}
|
||||
break
|
||||
default:
|
||||
m := field.Type()
|
||||
return fmt.Errorf("unknown type, cannot parse: %v", m)
|
||||
// we want to ignore everything else.
|
||||
break
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func BuildModelAsync(n *yaml.Node, model interface{}, lwg *sync.WaitGroup, errors *[]error) {
|
||||
if n != nil {
|
||||
err := BuildModel(n, model)
|
||||
if err != nil {
|
||||
*errors = append(*errors, err)
|
||||
}
|
||||
}
|
||||
lwg.Done()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package utils
|
||||
package datamodel
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
@@ -106,7 +106,7 @@ there:
|
||||
hd := hotdog{}
|
||||
cErr := BuildModel(&rootNode, &hd)
|
||||
assert.Equal(t, 200, hd.Fat.Value)
|
||||
assert.Equal(t, 3, hd.Fat.Node.Line)
|
||||
assert.Equal(t, 3, hd.Fat.ValueNode.Line)
|
||||
assert.Equal(t, true, hd.Grilled.Value)
|
||||
assert.Equal(t, "yummy", hd.Name.Value)
|
||||
assert.Equal(t, float32(200.45), hd.Ketchup.Value)
|
||||
@@ -119,7 +119,7 @@ there:
|
||||
assert.Len(t, hd.MaxTempAlt, 5)
|
||||
assert.Equal(t, int64(7392837462032342), hd.MaxTempHigh.Value)
|
||||
assert.Equal(t, 2, hd.Temps[1].Value)
|
||||
assert.Equal(t, 26, hd.Temps[1].Node.Line)
|
||||
assert.Equal(t, 26, hd.Temps[1].ValueNode.Line)
|
||||
assert.Len(t, hd.UnknownElements.Value, 2)
|
||||
assert.Len(t, hd.LotsOfUnknowns, 3)
|
||||
assert.Len(t, hd.Where, 2)
|
||||
@@ -129,24 +129,6 @@ there:
|
||||
assert.NoError(t, cErr)
|
||||
}
|
||||
|
||||
func TestBuildModel_UnsupportedType(t *testing.T) {
|
||||
|
||||
type notSupported struct {
|
||||
cake low.NodeReference[uintptr]
|
||||
}
|
||||
ns := notSupported{}
|
||||
yml := `cake: -99999`
|
||||
|
||||
var rootNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &rootNode)
|
||||
assert.NoError(t, mErr)
|
||||
|
||||
cErr := BuildModel(&rootNode, &ns)
|
||||
assert.Error(t, cErr)
|
||||
assert.Nil(t, ns.cake)
|
||||
|
||||
}
|
||||
|
||||
func TestBuildModel_UseCopyNotRef(t *testing.T) {
|
||||
|
||||
yml := `cake: -99999`
|
||||
@@ -2,7 +2,9 @@ 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/utils"
|
||||
)
|
||||
|
||||
func CreateDocument(spec []byte) (*v3.Document, error) {
|
||||
@@ -13,7 +15,64 @@ func CreateDocument(spec []byte) (*v3.Document, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
doc := &v3.Document{}
|
||||
doc.Build(info.RootNode.Content[0])
|
||||
return doc, nil
|
||||
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||
|
||||
// build an index
|
||||
//idx := index.NewSpecIndex(info.RootNode)
|
||||
datamodel.BuildModel(info.RootNode.Content[0], &doc)
|
||||
|
||||
// extract info
|
||||
extractErr := extractInfo(info, &doc)
|
||||
if extractErr != nil {
|
||||
return nil, extractErr
|
||||
}
|
||||
|
||||
// extract servers
|
||||
extractErr = extractServers(info, &doc)
|
||||
if extractErr != nil {
|
||||
return nil, extractErr
|
||||
}
|
||||
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull("info", info.RootNode.Content)
|
||||
if vn != nil {
|
||||
ir := v3.Info{}
|
||||
err := datamodel.BuildModel(vn, &ir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ir.Build(vn)
|
||||
nr := low.NodeReference[*v3.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Info = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull("servers", info.RootNode.Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
var servers []low.NodeReference[*v3.Server]
|
||||
for _, srvN := range vn.Content {
|
||||
if utils.IsNodeMap(srvN) {
|
||||
srvr := v3.Server{}
|
||||
err := datamodel.BuildModel(srvN, &srvr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srvr.Build(srvN)
|
||||
servers = append(servers, low.NodeReference[*v3.Server]{
|
||||
Value: &srvr,
|
||||
ValueNode: srvN,
|
||||
KeyNode: ln,
|
||||
})
|
||||
}
|
||||
}
|
||||
doc.Servers = servers
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ func TestCreateDocument_NoData(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateDocument(t *testing.T) {
|
||||
data, aErr := ioutil.ReadFile("../test_specs/petstorev3.json")
|
||||
data, aErr := ioutil.ReadFile("../test_specs/burgershop.openapi.yaml")
|
||||
assert.NoError(t, aErr)
|
||||
|
||||
doc, err := CreateDocument(data)
|
||||
|
||||
@@ -6,8 +6,11 @@ info:
|
||||
termsOfService: https://quobix.com
|
||||
contact:
|
||||
name: quobix
|
||||
email: test@quobix.com
|
||||
url: https://quobix.com
|
||||
license:
|
||||
name: Quobix
|
||||
url: https://quobix.com/made-up
|
||||
version: "1.2"
|
||||
tags:
|
||||
- name: "Burgers"
|
||||
@@ -21,7 +24,22 @@ tags:
|
||||
description: "Find out more information about our products)"
|
||||
url: "https://quobix.com/"
|
||||
servers:
|
||||
- url: https://quobix.com/api
|
||||
- url: "{scheme}://api.quobix.com"
|
||||
description: "this is our main API server, for all fun API things."
|
||||
variables:
|
||||
scheme:
|
||||
enum: [https]
|
||||
default: https
|
||||
description: this is a server variable for the scheme
|
||||
- url: "https://{domain}.{host}.com"
|
||||
description: "this is our second API server, for all fun API things."
|
||||
variables:
|
||||
domain:
|
||||
default: "api"
|
||||
description: the default API domain is 'api'
|
||||
host:
|
||||
default: "quobix.com"
|
||||
description: the default host for this API is 'quobix.com'
|
||||
paths:
|
||||
/burgers:
|
||||
post:
|
||||
|
||||
@@ -239,6 +239,29 @@ func FindKeyNode(key string, nodes []*yaml.Node) (keyNode *yaml.Node, valueNode
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func FindKeyNodeFull(key string, nodes []*yaml.Node) (keyNode *yaml.Node, labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||
for i, v := range nodes {
|
||||
if i%2 == 0 && key == v.Value {
|
||||
return v, nodes[i], nodes[i+1] // next node is what we need.
|
||||
}
|
||||
for x, j := range v.Content {
|
||||
if key == j.Value {
|
||||
if IsNodeMap(v) {
|
||||
if x+1 == len(v.Content) {
|
||||
return v, v.Content[x], v.Content[x]
|
||||
}
|
||||
return v, v.Content[x], v.Content[x+1] // next node is what we need.
|
||||
|
||||
}
|
||||
if IsNodeArray(v) {
|
||||
return v, v.Content[x], v.Content[x]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
var ObjectLabel = "object"
|
||||
var IntegerLabel = "integer"
|
||||
var NumberLabel = "number"
|
||||
|
||||
Reference in New Issue
Block a user