mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 12:37:48 +00:00
We-worked model to remove resolver.
lookups are performed inline now. keeps things simpler, however it has a performance knock, so it's time to refine async building were possible.
This commit is contained in:
@@ -2,6 +2,8 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -14,22 +16,28 @@ func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
|
||||
return FindItemInMap[*PathItem](exp, cb.Expression.Value)
|
||||
}
|
||||
|
||||
func (cb *Callback) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cb.Extensions = extensionMap
|
||||
func (cb *Callback) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
cb.Extensions = ExtractExtensions(root)
|
||||
|
||||
// handle callback
|
||||
var currentCB *yaml.Node
|
||||
callbacks := make(map[low.KeyReference[string]]low.ValueReference[*PathItem])
|
||||
|
||||
if ok, _, _ := utils.IsNodeRefValue(root); ok {
|
||||
r := LocateRefNode(root, idx)
|
||||
if r != nil {
|
||||
root = r
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for i, callbackNode := range root.Content {
|
||||
if i%2 == 0 {
|
||||
currentCB = callbackNode
|
||||
continue
|
||||
}
|
||||
callback, eErr := ExtractObjectRaw[*PathItem](callbackNode)
|
||||
callback, eErr := ExtractObjectRaw[*PathItem](callbackNode, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
|
||||
36
datamodel/low/3.0/callback_test.go
Normal file
36
datamodel/low/3.0/callback_test.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCallback_Build_Success(t *testing.T) {
|
||||
|
||||
yml := `'{$request.query.queryUrl}':
|
||||
post:
|
||||
requestBody:
|
||||
description: Callback payload
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: callback successfully processed`
|
||||
|
||||
var rootNode yaml.Node
|
||||
mErr := yaml.Unmarshal([]byte(yml), &rootNode)
|
||||
assert.NoError(t, mErr)
|
||||
|
||||
var n Callback
|
||||
err := BuildModel(rootNode.Content[0], &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = n.Build(rootNode.Content[0], nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Len(t, n.Expression.Value, 1)
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -56,12 +57,8 @@ func (co *Components) FindCallback(callback string) *low.ValueReference[*Callbac
|
||||
return FindItemInMap[*Callback](callback, co.Callbacks.Value)
|
||||
}
|
||||
|
||||
func (co *Components) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
co.Extensions = extensionMap
|
||||
func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
co.Extensions = ExtractExtensions(root)
|
||||
|
||||
// build out components asynchronously for speed. There could be some significant weight here.
|
||||
skipChan := make(chan bool)
|
||||
@@ -76,15 +73,15 @@ func (co *Components) Build(root *yaml.Node) error {
|
||||
linkChan := make(chan low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]])
|
||||
callbackChan := make(chan low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]])
|
||||
|
||||
go extractComponentValues[*Schema](SchemasLabel, root, skipChan, errorChan, schemaChan)
|
||||
go extractComponentValues[*Parameter](ParametersLabel, root, skipChan, errorChan, paramChan)
|
||||
go extractComponentValues[*Response](ResponsesLabel, root, skipChan, errorChan, responsesChan)
|
||||
go extractComponentValues[*Example](ExamplesLabel, root, skipChan, errorChan, examplesChan)
|
||||
go extractComponentValues[*RequestBody](RequestBodiesLabel, root, skipChan, errorChan, requestBodiesChan)
|
||||
go extractComponentValues[*Header](HeadersLabel, root, skipChan, errorChan, headersChan)
|
||||
go extractComponentValues[*SecurityScheme](SecuritySchemesLabel, root, skipChan, errorChan, securitySchemesChan)
|
||||
go extractComponentValues[*Link](LinksLabel, root, skipChan, errorChan, linkChan)
|
||||
go extractComponentValues[*Callback](CallbacksLabel, root, skipChan, errorChan, callbackChan)
|
||||
go extractComponentValues[*Schema](SchemasLabel, root, skipChan, errorChan, schemaChan, idx)
|
||||
go extractComponentValues[*Parameter](ParametersLabel, root, skipChan, errorChan, paramChan, idx)
|
||||
go extractComponentValues[*Response](ResponsesLabel, root, skipChan, errorChan, responsesChan, idx)
|
||||
go extractComponentValues[*Example](ExamplesLabel, root, skipChan, errorChan, examplesChan, idx)
|
||||
go extractComponentValues[*RequestBody](RequestBodiesLabel, root, skipChan, errorChan, requestBodiesChan, idx)
|
||||
go extractComponentValues[*Header](HeadersLabel, root, skipChan, errorChan, headersChan, idx)
|
||||
go extractComponentValues[*SecurityScheme](SecuritySchemesLabel, root, skipChan, errorChan, securitySchemesChan, idx)
|
||||
go extractComponentValues[*Link](LinksLabel, root, skipChan, errorChan, linkChan, idx)
|
||||
go extractComponentValues[*Callback](CallbacksLabel, root, skipChan, errorChan, callbackChan, idx)
|
||||
|
||||
n := 0
|
||||
total := 9
|
||||
@@ -159,7 +156,7 @@ allDone:
|
||||
}
|
||||
|
||||
func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.Node,
|
||||
skip chan bool, errorChan chan<- error, resultChan chan<- low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]) {
|
||||
skip chan bool, errorChan chan<- error, resultChan chan<- low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]], idx *index.SpecIndex) {
|
||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFull(label, root.Content)
|
||||
if nodeValue == nil {
|
||||
skip <- true
|
||||
@@ -177,7 +174,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
if err != nil {
|
||||
errorChan <- err
|
||||
}
|
||||
err = n.Build(v)
|
||||
err = n.Build(v, idx)
|
||||
if err != nil {
|
||||
errorChan <- err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -21,9 +22,9 @@ func (en *Encoding) FindHeader(hType string) *low.ValueReference[*Header] {
|
||||
return FindItemInMap[*Header](hType, en.Headers.Value)
|
||||
}
|
||||
|
||||
func (en *Encoding) Build(root *yaml.Node) error {
|
||||
func (en *Encoding) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
|
||||
headers, hL, hN, err := ExtractMapFlat[*Header](HeadersLabel, root)
|
||||
headers, hL, hN, err := ExtractMapFlat[*Header](HeadersLabel, root, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -20,19 +21,14 @@ type Example struct {
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
func (ex *Example) Build(root *yaml.Node) error {
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ex.Extensions = extensionMap
|
||||
func (ex *Example) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
ex.Extensions = ExtractExtensions(root)
|
||||
|
||||
// extract value
|
||||
_, ln, vn := utils.FindKeyNodeFull(ValueLabel, root.Content)
|
||||
if vn != nil {
|
||||
var n map[string]interface{}
|
||||
err = vn.Decode(&n)
|
||||
err := vn.Decode(&n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -11,12 +12,7 @@ type ExternalDoc struct {
|
||||
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
|
||||
func (ex *ExternalDoc) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
ex.Extensions = ExtractExtensions(root)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strconv"
|
||||
@@ -9,6 +10,13 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
var KnownSchemas map[string]low.NodeReference[*Schema]
|
||||
|
||||
func init() {
|
||||
KnownSchemas = make(map[string]low.NodeReference[*Schema])
|
||||
|
||||
}
|
||||
|
||||
func FindItemInMap[T any](item string, collection map[low.KeyReference[string]]low.ValueReference[T]) *low.ValueReference[T] {
|
||||
for n, o := range collection {
|
||||
if n.Value == item {
|
||||
@@ -18,15 +26,34 @@ func FindItemInMap[T any](item string, collection map[low.KeyReference[string]]l
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtractSchema(root *yaml.Node) (*low.NodeReference[*Schema], error) {
|
||||
_, schLabel, schNode := utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
||||
func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*Schema], error) {
|
||||
var schLabel, schNode *yaml.Node
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
schNode = ref
|
||||
schLabel = rl
|
||||
}
|
||||
} else {
|
||||
_, schLabel, schNode = utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
||||
if schNode != nil {
|
||||
if h, _, _ := utils.IsNodeRefValue(schNode); h {
|
||||
ref := LocateRefNode(schNode, idx)
|
||||
if ref != nil {
|
||||
schNode = ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if schNode != nil {
|
||||
var schema Schema
|
||||
err := BuildModel(schNode, &schema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = schema.Build(schNode)
|
||||
err = schema.Build(schNode, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -37,21 +64,49 @@ func ExtractSchema(root *yaml.Node) (*low.NodeReference[*Schema], error) {
|
||||
|
||||
var mapLock sync.Mutex
|
||||
|
||||
func ExtractObjectRaw[T low.Buildable[N], N any](root *yaml.Node) (T, error) {
|
||||
func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) *yaml.Node {
|
||||
if rf, _, rv := utils.IsNodeRefValue(root); rf {
|
||||
found := idx.GetMappedReferences()
|
||||
if found != nil && found[rv] != nil {
|
||||
return found[rv].Node
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtractObjectRaw[T low.Buildable[N], N any](root *yaml.Node, idx *index.SpecIndex) (T, error) {
|
||||
var n T = new(N)
|
||||
err := BuildModel(root, n)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
err = n.Build(root)
|
||||
err = n.Build(root, idx)
|
||||
if err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func ExtractObject[T low.Buildable[N], N any](label string, root *yaml.Node) (low.NodeReference[T], error) {
|
||||
_, ln, vn := utils.FindKeyNodeFull(label, root.Content)
|
||||
func ExtractObject[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[T], error) {
|
||||
var ln, vn *yaml.Node
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
ln = rl
|
||||
}
|
||||
} else {
|
||||
_, ln, vn = utils.FindKeyNodeFull(label, root.Content)
|
||||
if vn != nil {
|
||||
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
||||
ref := LocateRefNode(vn, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var n T = new(N)
|
||||
err := BuildModel(vn, n)
|
||||
if err != nil {
|
||||
@@ -60,7 +115,7 @@ func ExtractObject[T low.Buildable[N], N any](label string, root *yaml.Node) (lo
|
||||
if ln == nil {
|
||||
return low.NodeReference[T]{}, nil
|
||||
}
|
||||
err = n.Build(vn)
|
||||
err = n.Build(vn, idx)
|
||||
if err != nil {
|
||||
return low.NodeReference[T]{}, err
|
||||
}
|
||||
@@ -71,17 +126,41 @@ func ExtractObject[T low.Buildable[N], N any](label string, root *yaml.Node) (lo
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ExtractArray[T low.Buildable[N], N any](label string, root *yaml.Node) ([]low.ValueReference[T], *yaml.Node, *yaml.Node, error) {
|
||||
_, ln, vn := utils.FindKeyNodeFull(label, root.Content)
|
||||
func ExtractArray[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) ([]low.ValueReference[T], *yaml.Node, *yaml.Node, error) {
|
||||
var ln, vn *yaml.Node
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
ln = rl
|
||||
}
|
||||
} else {
|
||||
_, ln, vn = utils.FindKeyNodeFull(label, root.Content)
|
||||
if vn != nil {
|
||||
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
||||
ref := LocateRefNode(vn, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var items []low.ValueReference[T]
|
||||
if vn != nil && ln != nil {
|
||||
for _, node := range vn.Content {
|
||||
if rf, _, _ := utils.IsNodeRefValue(node); rf {
|
||||
ref := LocateRefNode(node, idx)
|
||||
if ref != nil {
|
||||
node = ref
|
||||
}
|
||||
}
|
||||
var n T = new(N)
|
||||
err := BuildModel(node, n)
|
||||
if err != nil {
|
||||
return []low.ValueReference[T]{}, ln, vn, err
|
||||
}
|
||||
berr := n.Build(node)
|
||||
berr := n.Build(node, idx)
|
||||
if berr != nil {
|
||||
return nil, ln, vn, berr
|
||||
}
|
||||
@@ -94,7 +173,7 @@ func ExtractArray[T low.Buildable[N], N any](label string, root *yaml.Node) ([]l
|
||||
return items, ln, vn, nil
|
||||
}
|
||||
|
||||
func ExtractMapFlatNoLookup[PT low.Buildable[N], N any](root *yaml.Node) (map[low.KeyReference[string]]low.ValueReference[PT], error) {
|
||||
func ExtractMapFlatNoLookup[PT low.Buildable[N], N any](root *yaml.Node, idx *index.SpecIndex) (map[low.KeyReference[string]]low.ValueReference[PT], error) {
|
||||
valueMap := make(map[low.KeyReference[string]]low.ValueReference[PT])
|
||||
if utils.IsNodeMap(root) {
|
||||
var currentKey *yaml.Node
|
||||
@@ -108,7 +187,7 @@ func ExtractMapFlatNoLookup[PT low.Buildable[N], N any](root *yaml.Node) (map[lo
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
berr := n.Build(node)
|
||||
berr := n.Build(node, idx)
|
||||
if berr != nil {
|
||||
return nil, berr
|
||||
}
|
||||
@@ -124,8 +203,26 @@ func ExtractMapFlatNoLookup[PT low.Buildable[N], N any](root *yaml.Node) (map[lo
|
||||
return valueMap, nil
|
||||
}
|
||||
|
||||
func ExtractMapFlat[PT low.Buildable[N], N any](label string, root *yaml.Node) (map[low.KeyReference[string]]low.ValueReference[PT], *yaml.Node, *yaml.Node, error) {
|
||||
_, labelNode, valueNode := utils.FindKeyNodeFull(label, root.Content)
|
||||
func ExtractMapFlat[PT low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (map[low.KeyReference[string]]low.ValueReference[PT], *yaml.Node, *yaml.Node, error) {
|
||||
var labelNode, valueNode *yaml.Node
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
valueNode = ref
|
||||
labelNode = rl
|
||||
}
|
||||
} else {
|
||||
_, labelNode, valueNode = utils.FindKeyNodeFull(label, root.Content)
|
||||
if valueNode != nil {
|
||||
if h, _, _ := utils.IsNodeRefValue(valueNode); h {
|
||||
ref := LocateRefNode(valueNode, idx)
|
||||
if ref != nil {
|
||||
valueNode = ref
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if valueNode != nil {
|
||||
var currentLabelNode *yaml.Node
|
||||
valueMap := make(map[low.KeyReference[string]]low.ValueReference[PT])
|
||||
@@ -134,6 +231,15 @@ func ExtractMapFlat[PT low.Buildable[N], N any](label string, root *yaml.Node) (
|
||||
currentLabelNode = en
|
||||
continue
|
||||
}
|
||||
|
||||
// check our valueNode isn't a reference still.
|
||||
if h, _, _ := utils.IsNodeRefValue(en); h {
|
||||
ref := LocateRefNode(en, idx)
|
||||
if ref != nil {
|
||||
en = ref
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(strings.ToLower(currentLabelNode.Value), "x-") {
|
||||
continue // yo, don't pay any attention to extensions, not here anyway.
|
||||
}
|
||||
@@ -142,7 +248,7 @@ func ExtractMapFlat[PT low.Buildable[N], N any](label string, root *yaml.Node) (
|
||||
if err != nil {
|
||||
return nil, labelNode, valueNode, err
|
||||
}
|
||||
berr := n.Build(en)
|
||||
berr := n.Build(en, idx)
|
||||
if berr != nil {
|
||||
return nil, labelNode, valueNode, berr
|
||||
}
|
||||
@@ -159,8 +265,19 @@ func ExtractMapFlat[PT low.Buildable[N], N any](label string, root *yaml.Node) (
|
||||
return nil, labelNode, valueNode, nil
|
||||
}
|
||||
|
||||
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)
|
||||
func ExtractMap[PT low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[PT], error) {
|
||||
var labelNode, valueNode *yaml.Node
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
ref := LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
valueNode = ref
|
||||
labelNode = rl
|
||||
}
|
||||
} else {
|
||||
_, labelNode, valueNode = utils.FindKeyNodeFull(label, root.Content)
|
||||
}
|
||||
|
||||
if valueNode != nil {
|
||||
var currentLabelNode *yaml.Node
|
||||
valueMap := make(map[low.KeyReference[string]]low.ValueReference[PT])
|
||||
@@ -177,7 +294,7 @@ func ExtractMap[PT low.Buildable[N], N any](label string, root *yaml.Node) (map[
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
berr := n.Build(en)
|
||||
berr := n.Build(en, idx)
|
||||
if berr != nil {
|
||||
return nil, berr
|
||||
}
|
||||
@@ -199,16 +316,13 @@ func ExtractMap[PT low.Buildable[N], N any](label string, root *yaml.Node) (map[
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func ExtractExtensions(root *yaml.Node) (map[low.KeyReference[string]]low.ValueReference[any], error) {
|
||||
func ExtractExtensions(root *yaml.Node) map[low.KeyReference[string]]low.ValueReference[any] {
|
||||
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
|
||||
}
|
||||
_ = ext.Value.Decode(&v)
|
||||
extensionMap[low.KeyReference[string]{
|
||||
Value: ext.Key.Value,
|
||||
KeyNode: ext.Key,
|
||||
@@ -243,15 +357,12 @@ func ExtractExtensions(root *yaml.Node) (map[low.KeyReference[string]]low.ValueR
|
||||
}
|
||||
if utils.IsNodeArray(ext.Value) {
|
||||
var v []interface{}
|
||||
err := ext.Value.Decode(&v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = ext.Value.Decode(&v)
|
||||
extensionMap[low.KeyReference[string]{
|
||||
Value: ext.Key.Value,
|
||||
KeyNode: ext.Key,
|
||||
}] = low.ValueReference[any]{Value: v, ValueNode: ext.Value}
|
||||
}
|
||||
}
|
||||
return extensionMap, nil
|
||||
return extensionMap
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -24,16 +25,11 @@ type Header struct {
|
||||
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
|
||||
func (h *Header) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
h.Extensions = ExtractExtensions(root)
|
||||
|
||||
// handle examples if set.
|
||||
exps, eErr := ExtractMap[*Example](ExamplesLabel, root)
|
||||
exps, eErr := ExtractMap[*Example](ExamplesLabel, root, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
@@ -42,7 +38,7 @@ func (h *Header) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle schema
|
||||
sch, sErr := ExtractSchema(root)
|
||||
sch, sErr := ExtractSchema(root, idx)
|
||||
if sErr != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -51,7 +47,7 @@ func (h *Header) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle content, if set.
|
||||
con, cErr := ExtractMap[*MediaType](ContentLabel, root)
|
||||
con, cErr := ExtractMap[*MediaType](ContentLabel, root, idx)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -20,12 +21,8 @@ func (l *Link) FindParameter(pName string) *low.ValueReference[string] {
|
||||
return FindItemInMap[string](pName, l.Parameters.Value)
|
||||
}
|
||||
|
||||
func (l *Link) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l.Extensions = extensionMap
|
||||
func (l *Link) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
l.Extensions = ExtractExtensions(root)
|
||||
|
||||
// extract parameters
|
||||
_, pl, pv := utils.FindKeyNodeFull(ParametersLabel, root.Content)
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -26,14 +27,8 @@ func (mt *MediaType) GetAllExamples() map[low.KeyReference[string]]low.ValueRefe
|
||||
return mt.Examples.Value
|
||||
}
|
||||
|
||||
func (mt *MediaType) Build(root *yaml.Node) error {
|
||||
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mt.Extensions = extensionMap
|
||||
func (mt *MediaType) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
mt.Extensions = ExtractExtensions(root)
|
||||
|
||||
// handle example if set.
|
||||
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||
@@ -42,7 +37,7 @@ func (mt *MediaType) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle schema
|
||||
sch, sErr := ExtractSchema(root)
|
||||
sch, sErr := ExtractSchema(root, idx)
|
||||
if sErr != nil {
|
||||
return nil
|
||||
}
|
||||
@@ -51,7 +46,7 @@ func (mt *MediaType) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle examples if set.
|
||||
exps, expsL, expsN, eErr := ExtractMapFlat[*Example](ExamplesLabel, root)
|
||||
exps, expsL, expsN, eErr := ExtractMapFlat[*Example](ExamplesLabel, root, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
@@ -64,9 +59,9 @@ func (mt *MediaType) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle encoding
|
||||
encs, encsL, encsN, encErr := ExtractMapFlat[*Encoding](EncodingLabel, root)
|
||||
encs, encsL, encsN, encErr := ExtractMapFlat[*Encoding](EncodingLabel, root, idx)
|
||||
if encErr != nil {
|
||||
return err
|
||||
return encErr
|
||||
}
|
||||
if encs != nil {
|
||||
mt.Encoding = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Encoding]]{
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -22,32 +23,28 @@ type OAuthFlows struct {
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
func (o *OAuthFlows) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Extensions = extensionMap
|
||||
func (o *OAuthFlows) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
o.Extensions = ExtractExtensions(root)
|
||||
|
||||
v, vErr := ExtractObject[*OAuthFlow](ImplicitLabel, root)
|
||||
v, vErr := ExtractObject[*OAuthFlow](ImplicitLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
o.Implicit = v
|
||||
|
||||
v, vErr = ExtractObject[*OAuthFlow](PasswordLabel, root)
|
||||
v, vErr = ExtractObject[*OAuthFlow](PasswordLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
o.Password = v
|
||||
|
||||
v, vErr = ExtractObject[*OAuthFlow](ClientCredentialsLabel, root)
|
||||
v, vErr = ExtractObject[*OAuthFlow](ClientCredentialsLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
o.ClientCredentials = v
|
||||
|
||||
v, vErr = ExtractObject[*OAuthFlow](AuthorizationCodeLabel, root)
|
||||
v, vErr = ExtractObject[*OAuthFlow](AuthorizationCodeLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
@@ -68,12 +65,8 @@ func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] {
|
||||
return FindItemInMap[string](scope, o.Scopes.Value)
|
||||
}
|
||||
|
||||
func (o *OAuthFlow) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Extensions = extensionMap
|
||||
func (o *OAuthFlow) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
o.Extensions = ExtractExtensions(root)
|
||||
|
||||
var currSec *yaml.Node
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -29,22 +30,18 @@ type Operation struct {
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
func (o *Operation) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Extensions = extensionMap
|
||||
func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
o.Extensions = ExtractExtensions(root)
|
||||
|
||||
// extract externalDocs
|
||||
extDocs, dErr := ExtractObject[*ExternalDoc](ExternalDocsLabel, root)
|
||||
extDocs, dErr := ExtractObject[*ExternalDoc](ExternalDocsLabel, root, idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
o.ExternalDocs = extDocs
|
||||
|
||||
// extract parameters
|
||||
params, ln, vn, pErr := ExtractArray[*Parameter](ParametersLabel, root)
|
||||
params, ln, vn, pErr := ExtractArray[*Parameter](ParametersLabel, root, idx)
|
||||
if pErr != nil {
|
||||
return pErr
|
||||
}
|
||||
@@ -57,21 +54,21 @@ func (o *Operation) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// extract request body
|
||||
rBody, rErr := ExtractObject[*RequestBody](RequestBodyLabel, root)
|
||||
rBody, rErr := ExtractObject[*RequestBody](RequestBodyLabel, root, idx)
|
||||
if rErr != nil {
|
||||
return rErr
|
||||
}
|
||||
o.RequestBody = rBody
|
||||
|
||||
// extract responses
|
||||
respBody, respErr := ExtractObject[*Responses](ResponsesLabel, root)
|
||||
respBody, respErr := ExtractObject[*Responses](ResponsesLabel, root, idx)
|
||||
if respErr != nil {
|
||||
return rErr
|
||||
}
|
||||
o.Responses = respBody
|
||||
|
||||
// extract callbacks
|
||||
callbacks, cbL, cbN, cbErr := ExtractMapFlat[*Callback](CallbacksLabel, root)
|
||||
callbacks, cbL, cbN, cbErr := ExtractMapFlat[*Callback](CallbacksLabel, root, idx)
|
||||
if cbErr != nil {
|
||||
return cbErr
|
||||
}
|
||||
@@ -84,14 +81,14 @@ func (o *Operation) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// extract security
|
||||
sec, sErr := ExtractObject[*SecurityRequirement](SecurityLabel, root)
|
||||
sec, sErr := ExtractObject[*SecurityRequirement](SecurityLabel, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
o.Security = sec
|
||||
|
||||
// extract servers
|
||||
servers, sl, sn, serErr := ExtractArray[*Server](ServersLabel, root)
|
||||
servers, sl, sn, serErr := ExtractArray[*Server](ServersLabel, root, idx)
|
||||
if serErr != nil {
|
||||
return serErr
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -36,14 +37,8 @@ func (p *Parameter) FindExample(eType string) *low.ValueReference[*Example] {
|
||||
return FindItemInMap[*Example](eType, p.Examples.Value)
|
||||
}
|
||||
|
||||
func (p *Parameter) Build(root *yaml.Node) error {
|
||||
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = extensionMap
|
||||
func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
p.Extensions = ExtractExtensions(root)
|
||||
|
||||
// handle example if set.
|
||||
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||
@@ -52,14 +47,16 @@ func (p *Parameter) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle schema
|
||||
sch, sErr := ExtractSchema(root)
|
||||
sch, sErr := ExtractSchema(root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
p.Schema = *sch
|
||||
if sch != nil {
|
||||
p.Schema = *sch
|
||||
}
|
||||
|
||||
// handle examples if set.
|
||||
exps, expsL, expsN, eErr := ExtractMapFlat[*Example](ExamplesLabel, root)
|
||||
exps, expsL, expsN, eErr := ExtractMapFlat[*Example](ExamplesLabel, root, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
@@ -72,7 +69,7 @@ func (p *Parameter) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle content, if set.
|
||||
con, cL, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root)
|
||||
con, cL, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root, idx)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -33,14 +35,8 @@ func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Paths) Build(root *yaml.Node) error {
|
||||
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = extensionMap
|
||||
func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
p.Extensions = ExtractExtensions(root)
|
||||
skip := false
|
||||
var currentNode *yaml.Node
|
||||
|
||||
@@ -60,11 +56,11 @@ func (p *Paths) Build(root *yaml.Node) error {
|
||||
continue
|
||||
}
|
||||
var path = PathItem{}
|
||||
err = BuildModel(pathNode, &path)
|
||||
err := BuildModel(pathNode, &path)
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
err = path.Build(pathNode)
|
||||
err = path.Build(pathNode, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -100,12 +96,8 @@ type PathItem struct {
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
func (p *PathItem) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Extensions = extensionMap
|
||||
func (p *PathItem) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
p.Extensions = ExtractExtensions(root)
|
||||
skip := false
|
||||
var currentNode *yaml.Node
|
||||
|
||||
@@ -114,6 +106,15 @@ func (p *PathItem) Build(root *yaml.Node) error {
|
||||
|
||||
var ops []low.NodeReference[*Operation]
|
||||
|
||||
if ok, _, _ := utils.IsNodeRefValue(root); ok {
|
||||
r := LocateRefNode(root, idx)
|
||||
if r != nil {
|
||||
root = r
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
for i, pathNode := range root.Content {
|
||||
if strings.HasPrefix(strings.ToLower(pathNode.Value), "x-") {
|
||||
skip = true
|
||||
@@ -161,18 +162,20 @@ func (p *PathItem) Build(root *yaml.Node) error {
|
||||
}
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
if len(ops) > 0 {
|
||||
//wg.Wait()
|
||||
}
|
||||
|
||||
// all operations have been superficially built,
|
||||
// now we need to build out the operation, we will do this asynchronously for speed.
|
||||
//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) {
|
||||
|
||||
// build out the operation.
|
||||
er := op.Value.Build(op.ValueNode)
|
||||
if err != nil {
|
||||
//build out the operation.
|
||||
er := op.Value.Build(op.ValueNode, idx)
|
||||
if er != nil {
|
||||
errCh <- er
|
||||
}
|
||||
ch <- true
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -16,18 +17,11 @@ func (rb *RequestBody) FindContent(cType string) *low.ValueReference[*MediaType]
|
||||
return FindItemInMap[*MediaType](cType, rb.Content.Value)
|
||||
}
|
||||
|
||||
func (rb *RequestBody) Build(root *yaml.Node) error {
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if extensionMap != nil {
|
||||
rb.Extensions = extensionMap
|
||||
}
|
||||
func (rb *RequestBody) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
rb.Extensions = ExtractExtensions(root)
|
||||
|
||||
// handle content, if set.
|
||||
con, cL, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root)
|
||||
con, cL, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root, idx)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -15,9 +16,9 @@ type Responses struct {
|
||||
Default low.NodeReference[*Response]
|
||||
}
|
||||
|
||||
func (r *Responses) Build(root *yaml.Node) error {
|
||||
func (r *Responses) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if utils.IsNodeMap(root) {
|
||||
codes, err := ExtractMapFlatNoLookup[*Response](root)
|
||||
codes, err := ExtractMapFlatNoLookup[*Response](root, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -52,15 +53,11 @@ func (r *Response) FindLink(hType string) *low.ValueReference[*Link] {
|
||||
return FindItemInMap[*Link](hType, r.Links.Value)
|
||||
}
|
||||
|
||||
func (r *Response) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Extensions = extensionMap
|
||||
func (r *Response) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
r.Extensions = ExtractExtensions(root)
|
||||
|
||||
// extract headers
|
||||
headers, lN, kN, err := ExtractMapFlat[*Header](HeadersLabel, root)
|
||||
headers, lN, kN, err := ExtractMapFlat[*Header](HeadersLabel, root, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -73,7 +70,7 @@ func (r *Response) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle content, if set.
|
||||
con, clN, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root)
|
||||
con, clN, cN, cErr := ExtractMapFlat[*MediaType](ContentLabel, root, idx)
|
||||
if cErr != nil {
|
||||
return cErr
|
||||
}
|
||||
@@ -86,7 +83,7 @@ func (r *Response) Build(root *yaml.Node) error {
|
||||
}
|
||||
|
||||
// handle links if set
|
||||
links, linkLabel, linkValue, lErr := ExtractMapFlat[*Link](LinksLabel, root)
|
||||
links, linkLabel, linkValue, lErr := ExtractMapFlat[*Link](LinksLabel, root, idx)
|
||||
if lErr != nil {
|
||||
return lErr
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strconv"
|
||||
@@ -61,20 +62,17 @@ func (s *Schema) FindProperty(name string) *low.ValueReference[*Schema] {
|
||||
return FindItemInMap[*Schema](name, s.Properties.Value)
|
||||
}
|
||||
|
||||
func (s *Schema) Build(root *yaml.Node) error {
|
||||
return s.BuildLevel(root, 0)
|
||||
func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
return s.BuildLevel(root, idx, 0)
|
||||
}
|
||||
|
||||
func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
func (s *Schema) BuildLevel(root *yaml.Node, idx *index.SpecIndex, level int) error {
|
||||
level++
|
||||
if level > 50 {
|
||||
if level > 10 {
|
||||
return nil // we're done, son! too fricken deep.
|
||||
}
|
||||
|
||||
err := s.extractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.extractExtensions(root)
|
||||
|
||||
// handle example if set.
|
||||
_, expLabel, expNode := utils.FindKeyNodeFull(ExampleLabel, root.Content)
|
||||
@@ -85,7 +83,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
_, addPLabel, addPNode := utils.FindKeyNodeFull(AdditionalPropertiesLabel, root.Content)
|
||||
if addPNode != nil {
|
||||
if utils.IsNodeMap(addPNode) {
|
||||
schema, serr := ExtractObjectRaw[*Schema](addPNode)
|
||||
schema, serr := ExtractObjectRaw[*Schema](addPNode, idx)
|
||||
if serr != nil {
|
||||
return serr
|
||||
}
|
||||
@@ -102,7 +100,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
_, discLabel, discNode := utils.FindKeyNodeFull(DiscriminatorLabel, root.Content)
|
||||
if discNode != nil {
|
||||
var discriminator Discriminator
|
||||
err = BuildModel(discNode, &discriminator)
|
||||
err := BuildModel(discNode, &discriminator)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -113,11 +111,11 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
_, extDocLabel, extDocNode := utils.FindKeyNodeFull(ExternalDocsLabel, root.Content)
|
||||
if extDocNode != nil {
|
||||
var exDoc ExternalDoc
|
||||
err = BuildModel(extDocNode, &exDoc)
|
||||
err := BuildModel(extDocNode, &exDoc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = exDoc.Build(extDocNode)
|
||||
err = exDoc.Build(extDocNode, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -128,7 +126,7 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
_, xmlLabel, xmlNode := utils.FindKeyNodeFull(XMLLabel, root.Content)
|
||||
if xmlNode != nil {
|
||||
var xml XML
|
||||
err = BuildModel(xmlNode, &xml)
|
||||
err := BuildModel(xmlNode, &xml)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -150,12 +148,21 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
currentProp = prop
|
||||
continue
|
||||
}
|
||||
|
||||
// check our prop isn't reference
|
||||
if h, _, _ := utils.IsNodeRefValue(prop); h {
|
||||
ref := LocateRefNode(prop, idx)
|
||||
if ref != nil {
|
||||
prop = ref
|
||||
}
|
||||
}
|
||||
|
||||
var property Schema
|
||||
err = BuildModel(prop, &property)
|
||||
err := BuildModel(prop, &property)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = property.BuildLevel(prop, level)
|
||||
err = property.BuildLevel(prop, idx, level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -179,11 +186,11 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
var allOf, anyOf, oneOf, not, items []low.NodeReference[*Schema]
|
||||
|
||||
// make this async at some point to speed things up.
|
||||
allOfLabel, allOfValue := buildSchema(&allOf, AllOfLabel, root, level, &errors)
|
||||
anyOfLabel, anyOfValue := buildSchema(&anyOf, AnyOfLabel, root, level, &errors)
|
||||
oneOfLabel, oneOfValue := buildSchema(&oneOf, OneOfLabel, root, level, &errors)
|
||||
notLabel, notValue := buildSchema(¬, NotLabel, root, level, &errors)
|
||||
itemsLabel, itemsValue := buildSchema(&items, ItemsLabel, root, level, &errors)
|
||||
allOfLabel, allOfValue := buildSchema(&allOf, AllOfLabel, root, level, &errors, idx)
|
||||
anyOfLabel, anyOfValue := buildSchema(&anyOf, AnyOfLabel, root, level, &errors, idx)
|
||||
oneOfLabel, oneOfValue := buildSchema(&oneOf, OneOfLabel, root, level, &errors, idx)
|
||||
notLabel, notValue := buildSchema(¬, NotLabel, root, level, &errors, idx)
|
||||
itemsLabel, itemsValue := buildSchema(&items, ItemsLabel, root, level, &errors, idx)
|
||||
|
||||
if len(errors) > 0 {
|
||||
// todo fix this
|
||||
@@ -228,16 +235,13 @@ func (s *Schema) BuildLevel(root *yaml.Node, level int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Schema) extractExtensions(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Extensions = extensionMap
|
||||
return err
|
||||
func (s *Schema) extractExtensions(root *yaml.Node) {
|
||||
s.Extensions = ExtractExtensions(root)
|
||||
}
|
||||
|
||||
func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNode *yaml.Node, level int, errors *[]error) (labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||
func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNode *yaml.Node, level int,
|
||||
errors *[]error, idx *index.SpecIndex) (labelNode *yaml.Node, valueNode *yaml.Node) {
|
||||
|
||||
_, labelNode, valueNode = utils.FindKeyNodeFull(attribute, rootNode.Content)
|
||||
//wg.Add(1)
|
||||
if valueNode != nil {
|
||||
@@ -248,7 +252,7 @@ func buildSchema(schemas *[]low.NodeReference[*Schema], attribute string, rootNo
|
||||
*errors = append(*errors, err)
|
||||
return nil
|
||||
}
|
||||
err = schema.BuildLevel(vn, level)
|
||||
err = schema.BuildLevel(vn, idx, level)
|
||||
if err != nil {
|
||||
*errors = append(*errors, err)
|
||||
return nil
|
||||
|
||||
@@ -111,7 +111,7 @@ additionalProperties: true `
|
||||
mbErr := BuildModel(&rootNode, &sch)
|
||||
assert.NoError(t, mbErr)
|
||||
|
||||
schErr := sch.Build(rootNode.Content[0])
|
||||
schErr := sch.Build(rootNode.Content[0], nil)
|
||||
assert.NoError(t, schErr)
|
||||
assert.Equal(t, "something object", sch.Description.Value)
|
||||
assert.True(t, sch.AdditionalProperties.Value.(bool))
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -28,14 +29,10 @@ type SecurityRequirement struct {
|
||||
Value []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]
|
||||
}
|
||||
|
||||
func (ss *SecurityScheme) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ss.Extensions = extensionMap
|
||||
func (ss *SecurityScheme) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
ss.Extensions = ExtractExtensions(root)
|
||||
|
||||
oa, oaErr := ExtractObject[*OAuthFlows](OAuthFlowsLabel, root)
|
||||
oa, oaErr := ExtractObject[*OAuthFlows](OAuthFlowsLabel, root, idx)
|
||||
if oaErr != nil {
|
||||
return oaErr
|
||||
}
|
||||
@@ -57,7 +54,7 @@ func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sr *SecurityRequirement) Build(root *yaml.Node) error {
|
||||
func (sr *SecurityRequirement) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if utils.IsNodeArray(root) {
|
||||
var requirements []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]
|
||||
for _, n := range root.Content {
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
@@ -17,7 +18,7 @@ type Server struct {
|
||||
Variables low.NodeReference[map[string]low.NodeReference[*ServerVariable]]
|
||||
}
|
||||
|
||||
func (s *Server) Build(root *yaml.Node) error {
|
||||
func (s *Server) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
kn, vars := utils.FindKeyNode(VariablesLabel, root.Content)
|
||||
if vars == nil {
|
||||
return nil
|
||||
|
||||
@@ -2,6 +2,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -17,16 +18,11 @@ type Tag struct {
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
func (t *Tag) Build(root *yaml.Node) error {
|
||||
// extract extensions
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.Extensions = extensionMap
|
||||
func (t *Tag) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
t.Extensions = ExtractExtensions(root)
|
||||
|
||||
// extract externalDocs
|
||||
extDocs, dErr := ExtractObject[*ExternalDoc](ExternalDocsLabel, root)
|
||||
extDocs, dErr := ExtractObject[*ExternalDoc](ExternalDocsLabel, root, idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
|
||||
@@ -15,10 +15,6 @@ type XML struct {
|
||||
}
|
||||
|
||||
func (x *XML) Build(root *yaml.Node) error {
|
||||
extensionMap, err := ExtractExtensions(root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
x.Extensions = extensionMap
|
||||
x.Extensions = ExtractExtensions(root)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package low
|
||||
|
||||
import "gopkg.in/yaml.v3"
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type HasNode interface {
|
||||
GetNode() *yaml.Node
|
||||
}
|
||||
|
||||
type Buildable[T any] interface {
|
||||
Build(node *yaml.Node) error
|
||||
Build(node *yaml.Node, idx *index.SpecIndex) error
|
||||
*T
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
localResolve int = 0
|
||||
httpResolve int = 1
|
||||
fileResolve int = 2
|
||||
LocalResolve int = 0
|
||||
HttpResolve int = 1
|
||||
FileResolve int = 2
|
||||
)
|
||||
|
||||
// Reference is a wrapper around *yaml.Node results to make things more manageable when performing
|
||||
@@ -72,7 +72,8 @@ type SpecIndex struct {
|
||||
responsesRefs map[string]*Reference // top level responses
|
||||
headersRefs map[string]*Reference // top level responses
|
||||
examplesRefs map[string]*Reference // top level examples
|
||||
linksRefs map[string]map[string][]*Reference // all links
|
||||
callbacksRefs map[string]map[string][]*Reference // all links
|
||||
linksRefs map[string]map[string][]*Reference // all callbacks
|
||||
operationTagsRefs map[string]map[string][]*Reference // tags found in operations
|
||||
operationDescriptionRefs map[string]map[string]*Reference // descriptions in operations.
|
||||
operationSummaryRefs map[string]map[string]*Reference // summaries in operations
|
||||
@@ -99,6 +100,7 @@ type SpecIndex struct {
|
||||
globalHeadersCount int // component headers
|
||||
globalExamplesCount int // component examples
|
||||
globalLinksCount int // component links
|
||||
globalCallbacksCount int // component callbacks
|
||||
globalCallbacks int // component callbacks.
|
||||
pathCount int // number of paths
|
||||
operationCount int // number of operations
|
||||
@@ -207,6 +209,7 @@ func NewSpecIndex(rootNode *yaml.Node) *SpecIndex {
|
||||
index.responsesRefs = make(map[string]*Reference)
|
||||
index.headersRefs = make(map[string]*Reference)
|
||||
index.examplesRefs = make(map[string]*Reference)
|
||||
index.callbacksRefs = make(map[string]map[string][]*Reference)
|
||||
index.linksRefs = make(map[string]map[string][]*Reference)
|
||||
index.callbackRefs = make(map[string]*Reference)
|
||||
index.externalSpecIndex = make(map[string]*SpecIndex)
|
||||
@@ -256,6 +259,7 @@ func NewSpecIndex(rootNode *yaml.Node) *SpecIndex {
|
||||
index.GetInlineUniqueParamCount,
|
||||
index.GetOperationTagsCount,
|
||||
index.GetGlobalLinksCount,
|
||||
index.GetGlobalCallbacksCount,
|
||||
}
|
||||
|
||||
wg.Add(len(countFuncs))
|
||||
@@ -872,13 +876,59 @@ func (index *SpecIndex) GetTotalTagsCount() int {
|
||||
return index.totalTagsCount
|
||||
}
|
||||
|
||||
// GetGlobalLinksCount for each response of each operation method, multiple links can be defined
|
||||
// GetGlobalCallbacksCount for each response of each operation method, multiple links can be defined
|
||||
func (index *SpecIndex) GetGlobalCallbacksCount() int {
|
||||
if index.root == nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
if index.globalCallbacksCount > 0 {
|
||||
return index.globalCallbacksCount
|
||||
}
|
||||
|
||||
index.pathRefsLock.Lock()
|
||||
for path, p := range index.pathRefs {
|
||||
for _, m := range p {
|
||||
|
||||
// look through method for callbacks
|
||||
callbacks, _ := yamlpath.NewPath("$..callbacks")
|
||||
res, _ := callbacks.Find(m.Node)
|
||||
|
||||
if len(res) > 0 {
|
||||
|
||||
for _, callback := range res[0].Content {
|
||||
if utils.IsNodeMap(callback) {
|
||||
|
||||
ref := &Reference{
|
||||
Definition: m.Name,
|
||||
Name: m.Name,
|
||||
Node: callback,
|
||||
}
|
||||
|
||||
if index.callbacksRefs[path] == nil {
|
||||
index.callbacksRefs[path] = make(map[string][]*Reference)
|
||||
}
|
||||
if len(index.callbacksRefs[path][m.Name]) > 0 {
|
||||
index.callbacksRefs[path][m.Name] = append(index.callbacksRefs[path][m.Name], ref)
|
||||
}
|
||||
index.callbacksRefs[path][m.Name] = []*Reference{ref}
|
||||
index.globalCallbacksCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
index.pathRefsLock.Unlock()
|
||||
return index.globalCallbacksCount
|
||||
}
|
||||
|
||||
// GetGlobalLinksCount for each response of each operation method, multiple callbacks can be defined
|
||||
func (index *SpecIndex) GetGlobalLinksCount() int {
|
||||
if index.root == nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
if index.globalLinksCount > 0 {
|
||||
if index.globalCallbacksCount > 0 {
|
||||
return index.globalLinksCount
|
||||
}
|
||||
|
||||
@@ -900,7 +950,6 @@ func (index *SpecIndex) GetGlobalLinksCount() int {
|
||||
Name: m.Name,
|
||||
Node: link,
|
||||
}
|
||||
|
||||
if index.linksRefs[path] == nil {
|
||||
index.linksRefs[path] = make(map[string][]*Reference)
|
||||
}
|
||||
@@ -1421,17 +1470,17 @@ func (index *SpecIndex) FindComponent(componentId string, parent *yaml.Node) *Re
|
||||
return index.lookupFileReference(id)
|
||||
}
|
||||
|
||||
switch determineReferenceResolveType(componentId) {
|
||||
case localResolve: // ideally, every single ref in every single spec is local. however, this is not the case.
|
||||
return index.findComponentInRoot(componentId)
|
||||
switch DetermineReferenceResolveType(componentId) {
|
||||
case LocalResolve: // ideally, every single ref in every single spec is local. however, this is not the case.
|
||||
return index.FindComponentInRoot(componentId)
|
||||
|
||||
case httpResolve:
|
||||
case HttpResolve:
|
||||
uri := strings.Split(componentId, "#")
|
||||
if len(uri) == 2 {
|
||||
return index.performExternalLookup(uri, componentId, remoteLookup, parent)
|
||||
}
|
||||
|
||||
case fileResolve:
|
||||
case FileResolve:
|
||||
uri := strings.Split(componentId, "#")
|
||||
if len(uri) == 2 {
|
||||
return index.performExternalLookup(uri, componentId, fileLookup, parent)
|
||||
@@ -1450,23 +1499,23 @@ func (index *SpecIndex) GetAllSummariesCount() int {
|
||||
return len(index.allSummaries)
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
func determineReferenceResolveType(ref string) int {
|
||||
func DetermineReferenceResolveType(ref string) int {
|
||||
if ref != "" && ref[0] == '#' {
|
||||
return localResolve
|
||||
return LocalResolve
|
||||
}
|
||||
if ref != "" && len(ref) >= 5 && (ref[:5] == "https" || ref[:5] == "http:") {
|
||||
return httpResolve
|
||||
return HttpResolve
|
||||
}
|
||||
if strings.Contains(ref, ".json") ||
|
||||
strings.Contains(ref, ".yaml") ||
|
||||
strings.Contains(ref, ".yml") {
|
||||
return fileResolve
|
||||
return FileResolve
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
/* private */
|
||||
|
||||
func (index *SpecIndex) extractDefinitionsAndSchemas(schemasNode *yaml.Node, pathPrefix string) {
|
||||
var name string
|
||||
for i, schema := range schemasNode.Content {
|
||||
@@ -1650,7 +1699,7 @@ func (index *SpecIndex) performExternalLookup(uri []string, componentId string,
|
||||
|
||||
} else {
|
||||
|
||||
foundRef := externalSpecIndex.findComponentInRoot(uri[1])
|
||||
foundRef := externalSpecIndex.FindComponentInRoot(uri[1])
|
||||
if foundRef != nil {
|
||||
foundNode = foundRef.Node
|
||||
}
|
||||
@@ -1670,7 +1719,7 @@ func (index *SpecIndex) performExternalLookup(uri []string, componentId string,
|
||||
return nil
|
||||
}
|
||||
|
||||
func (index *SpecIndex) findComponentInRoot(componentId string) *Reference {
|
||||
func (index *SpecIndex) FindComponentInRoot(componentId string) *Reference {
|
||||
|
||||
name, friendlySearch := utils.ConvertComponentIdIntoFriendlyPathSearch(componentId)
|
||||
|
||||
|
||||
@@ -348,7 +348,7 @@ func TestSpecIndex_TestEmptyBrokenReferences(t *testing.T) {
|
||||
assert.Equal(t, 2, index.GetGlobalTagsCount())
|
||||
assert.Equal(t, 3, index.GetTotalTagsCount())
|
||||
assert.Equal(t, 2, index.GetOperationTagsCount())
|
||||
assert.Equal(t, 2, index.GetGlobalLinksCount())
|
||||
assert.Equal(t, 4, index.GetGlobalLinksCount())
|
||||
assert.Equal(t, 0, index.GetComponentParameterCount())
|
||||
assert.Equal(t, 2, index.GetOperationsParameterCount())
|
||||
assert.Equal(t, 1, index.GetInlineDuplicateParamCount())
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/3.0"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/resolver"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"sync"
|
||||
)
|
||||
@@ -15,26 +14,27 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
||||
doc := v3.Document{Version: low.NodeReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||
|
||||
// build an index
|
||||
rsolvr := resolver.NewResolver(index.NewSpecIndex(info.RootNode))
|
||||
idx := index.NewSpecIndex(info.RootNode)
|
||||
//rsolvr := resolver.NewResolver()
|
||||
|
||||
// todo handle errors
|
||||
rsolvr.Resolve()
|
||||
//rsolvr.Resolve()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var errors []error
|
||||
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document,
|
||||
runFunc func(i *datamodel.SpecInfo, d *v3.Document) error,
|
||||
var runExtraction = func(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex,
|
||||
runFunc func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error,
|
||||
ers *[]error,
|
||||
wg *sync.WaitGroup) {
|
||||
|
||||
if er := runFunc(info, doc); er != nil {
|
||||
if er := runFunc(info, doc, idx); er != nil {
|
||||
*ers = append(*ers, er)
|
||||
}
|
||||
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document) error{
|
||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *v3.Document, idx *index.SpecIndex) error{
|
||||
extractInfo,
|
||||
extractServers,
|
||||
extractTags,
|
||||
@@ -45,7 +45,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
||||
}
|
||||
wg.Add(len(extractionFuncs))
|
||||
for _, f := range extractionFuncs {
|
||||
go runExtraction(info, &doc, f, &errors, &wg)
|
||||
go runExtraction(info, &doc, idx, f, &errors, &wg)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
@@ -56,7 +56,7 @@ func CreateDocument(info *datamodel.SpecInfo) (*v3.Document, error) {
|
||||
return &doc, nil
|
||||
}
|
||||
|
||||
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
func extractInfo(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(v3.InfoLabel, info.RootNode.Content)
|
||||
if vn != nil {
|
||||
ir := v3.Info{}
|
||||
@@ -71,8 +71,8 @@ func extractInfo(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractSecurity(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
sec, sErr := v3.ExtractObject[*v3.SecurityRequirement](v3.SecurityLabel, info.RootNode)
|
||||
func extractSecurity(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
sec, sErr := v3.ExtractObject[*v3.SecurityRequirement](v3.SecurityLabel, info.RootNode, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
@@ -80,8 +80,8 @@ func extractSecurity(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
extDocs, dErr := v3.ExtractObject[*v3.ExternalDoc](v3.ExternalDocsLabel, info.RootNode)
|
||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
extDocs, dErr := v3.ExtractObject[*v3.ExternalDoc](v3.ExternalDocsLabel, info.RootNode, idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
@@ -89,7 +89,7 @@ func extractExternalDocs(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractComponents(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
func extractComponents(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(v3.ComponentsLabel, info.RootNode.Content)
|
||||
if vn != nil {
|
||||
ir := v3.Components{}
|
||||
@@ -97,14 +97,14 @@ func extractComponents(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ir.Build(vn)
|
||||
err = ir.Build(vn, idx)
|
||||
nr := low.NodeReference[*v3.Components]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||
doc.Components = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
func extractServers(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(v3.ServersLabel, info.RootNode.Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
@@ -116,7 +116,7 @@ func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
srvr.Build(srvN)
|
||||
srvr.Build(srvN, idx)
|
||||
servers = append(servers, low.ValueReference[*v3.Server]{
|
||||
Value: &srvr,
|
||||
ValueNode: srvN,
|
||||
@@ -133,7 +133,7 @@ func extractServers(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
func extractTags(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(v3.TagsLabel, info.RootNode.Content)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
@@ -145,7 +145,7 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tag.Build(tagN)
|
||||
tag.Build(tagN, idx)
|
||||
tags = append(tags, low.ValueReference[*v3.Tag]{
|
||||
Value: &tag,
|
||||
ValueNode: tagN,
|
||||
@@ -162,11 +162,11 @@ func extractTags(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document) error {
|
||||
func extractPaths(info *datamodel.SpecInfo, doc *v3.Document, idx *index.SpecIndex) error {
|
||||
_, ln, vn := utils.FindKeyNodeFull(v3.PathsLabel, info.RootNode.Content)
|
||||
if vn != nil {
|
||||
ir := v3.Paths{}
|
||||
err := ir.Build(vn)
|
||||
err := ir.Build(vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -24,6 +24,17 @@ func BenchmarkCreateDocument(b *testing.B) {
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
||||
data, _ := ioutil.ReadFile("../test_specs/stripe.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := CreateDocument(info)
|
||||
if err != nil {
|
||||
panic("this should not error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDocument(t *testing.T) {
|
||||
assert.Equal(t, "3.0.1", doc.Version.Value)
|
||||
assert.Equal(t, "Burger Shop", doc.Info.Value.Title.Value)
|
||||
@@ -254,8 +265,9 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
|
||||
assert.NotNil(t, fries.Value)
|
||||
|
||||
assert.Len(t, fries.Value.Properties.Value, 3)
|
||||
p := fries.Value.FindProperty("favoriteDrink")
|
||||
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
|
||||
fries.Value.FindProperty("favoriteDrink").Value.Description.Value)
|
||||
p.Value.Description.Value)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,17 @@ func IsNodeBoolValue(node *yaml.Node) bool {
|
||||
return node.Tag == "!!bool"
|
||||
}
|
||||
|
||||
func IsNodeRefValue(node *yaml.Node) (bool, *yaml.Node, string) {
|
||||
for i, r := range node.Content {
|
||||
if i%2 == 0 {
|
||||
if r.Value == "$ref" {
|
||||
return true, r, node.Content[i+1].Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, nil, ""
|
||||
}
|
||||
|
||||
// FixContext will clean up a JSONpath string to be correctly traversable.
|
||||
func FixContext(context string) string {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user