mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 04:20:11 +00:00
An enormous amount of surgery on the low level model.
Every `Build()` method now requires a `context.Context`. This is so the rolodex knows where to resolve from when locating relative links. Without knowing where we are, there is no way to resolve anything. This new mechanism allows the model to recurse across as many files as required to locate references, without loosing track of where we are in the process. Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -65,7 +66,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Callback
|
var n v3.Callback
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewCallback(&n)
|
r := NewCallback(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -46,7 +47,7 @@ func TestComponents_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Components
|
var n v3.Components
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewComponents(&n)
|
r := NewComponents(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -5,16 +5,22 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
||||||
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var lowDoc *lowv3.Document
|
var lowDoc *lowv3.Document
|
||||||
@@ -22,7 +28,7 @@ var lowDoc *lowv3.Document
|
|||||||
func initTest() {
|
func initTest() {
|
||||||
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -382,9 +388,9 @@ func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
|||||||
func TestStripeAsDoc(t *testing.T) {
|
func TestStripeAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
}
|
}
|
||||||
@@ -402,7 +408,7 @@ func TestK8sAsDoc(t *testing.T) {
|
|||||||
func TestAsanaAsDoc(t *testing.T) {
|
func TestAsanaAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/asana.yaml")
|
data, _ := os.ReadFile("../../../test_specs/asana.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -412,10 +418,51 @@ func TestAsanaAsDoc(t *testing.T) {
|
|||||||
assert.Equal(t, 118, len(d.Paths.PathItems))
|
assert.Equal(t, 118, len(d.Paths.PathItems))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDigitalOceanAsDocViaCheckout(t *testing.T) {
|
||||||
|
|
||||||
|
// this is a full checkout of the digitalocean API repo.
|
||||||
|
tmp, _ := os.MkdirTemp("", "openapi")
|
||||||
|
cmd := exec.Command("git", "clone", "https://github.com/digitalocean/openapi", tmp)
|
||||||
|
defer os.RemoveAll(filepath.Join(tmp, "openapi"))
|
||||||
|
|
||||||
|
err := cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("cmd.Run() failed with %s\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, _ := filepath.Abs(filepath.Join(tmp, "specification", "DigitalOcean-public.v2.yaml"))
|
||||||
|
doLocal, _ := os.ReadFile(spec)
|
||||||
|
|
||||||
|
var rootNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal(doLocal, &rootNode)
|
||||||
|
|
||||||
|
basePath := filepath.Join(tmp, "specification")
|
||||||
|
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
config := datamodel.DocumentConfiguration{
|
||||||
|
AllowFileReferences: true,
|
||||||
|
AllowRemoteReferences: true,
|
||||||
|
BasePath: basePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
||||||
|
if err != nil {
|
||||||
|
er := utils.UnwrapErrors(err)
|
||||||
|
for e := range er {
|
||||||
|
fmt.Println(er[e])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d := NewDocument(lowDoc)
|
||||||
|
assert.NotNil(t, d)
|
||||||
|
assert.Equal(t, 183, len(d.Paths.PathItems))
|
||||||
|
}
|
||||||
|
|
||||||
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
|
|
||||||
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/82e1d558e15a59edc1d47d2c5544e7138f5b3cbf/specification")
|
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/82e1d558e15a59edc1d47d2c5544e7138f5b3cbf/specification")
|
||||||
config := datamodel.DocumentConfiguration{
|
config := datamodel.DocumentConfiguration{
|
||||||
@@ -424,12 +471,53 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
|||||||
BaseURL: baseURL,
|
BaseURL: baseURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("GITHUB_TOKEN") != "" {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 60,
|
||||||
|
}
|
||||||
|
config.RemoteURLHandler = func(url string) (*http.Response, error) {
|
||||||
|
request, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("GITHUB_TOKEN")))
|
||||||
|
return client.Do(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
||||||
|
assert.Len(t, utils.UnwrapErrors(err), 3) // there are 3 404's in this release of the API.
|
||||||
|
d := NewDocument(lowDoc)
|
||||||
|
assert.NotNil(t, d)
|
||||||
|
assert.Equal(t, 183, len(d.Paths.PathItems))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDigitalOceanAsDocFromMain(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
var err error
|
||||||
|
|
||||||
|
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/main/specification")
|
||||||
|
config := datamodel.DocumentConfiguration{
|
||||||
|
AllowFileReferences: true,
|
||||||
|
AllowRemoteReferences: true,
|
||||||
|
BaseURL: baseURL,
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getenv("GITHUB_TOKEN") != "" {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 60,
|
||||||
|
}
|
||||||
|
config.RemoteURLHandler = func(url string) (*http.Response, error) {
|
||||||
|
request, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("GITHUB_TOKEN")))
|
||||||
|
return client.Do(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for e := range err {
|
er := utils.UnwrapErrors(err)
|
||||||
fmt.Println(err[e])
|
for e := range er {
|
||||||
|
fmt.Printf("Reported Error: %s\n", er[e])
|
||||||
}
|
}
|
||||||
panic("broken something")
|
|
||||||
}
|
}
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
@@ -439,7 +527,7 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
|||||||
func TestPetstoreAsDoc(t *testing.T) {
|
func TestPetstoreAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -452,10 +540,10 @@ func TestPetstoreAsDoc(t *testing.T) {
|
|||||||
func TestCircularReferencesDoc(t *testing.T) {
|
func TestCircularReferencesDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lDoc, err := lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lDoc)
|
||||||
assert.Len(t, d.Components.Schemas, 9)
|
assert.Len(t, d.Components.Schemas, 9)
|
||||||
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
||||||
}
|
}
|
||||||
@@ -604,7 +692,7 @@ components:
|
|||||||
numPatties: 1`
|
numPatties: 1`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -657,7 +745,7 @@ components:
|
|||||||
required: true`
|
required: true`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -685,7 +773,7 @@ components:
|
|||||||
`
|
`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -20,7 +21,7 @@ func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
|||||||
// load the petstore spec
|
// load the petstore spec
|
||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -110,7 +111,7 @@ func TestMediaType_MarshalYAML(t *testing.T) {
|
|||||||
// load the petstore spec
|
// load the petstore spec
|
||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -161,7 +162,7 @@ func TestMediaType_Examples(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.MediaType
|
var n v3.MediaType
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewMediaType(&n)
|
r := NewMediaType(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -43,7 +44,7 @@ clientCredentials:
|
|||||||
|
|
||||||
var n v3.OAuthFlows
|
var n v3.OAuthFlows
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOAuthFlows(&n)
|
r := NewOAuthFlows(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ callbacks:
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ security: []`
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ func TestOperation_NoSecurity(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
@@ -19,17 +20,14 @@ func Example_createHighLevelOpenAPIDocument() {
|
|||||||
// Create a new *datamodel.SpecInfo from bytes.
|
// Create a new *datamodel.SpecInfo from bytes.
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
var err []error
|
var err error
|
||||||
|
|
||||||
// Create a new low-level Document, capture any errors thrown during creation.
|
// Create a new low-level Document, capture any errors thrown during creation.
|
||||||
lowDoc, err = lowv3.CreateDocument(info)
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||||
|
|
||||||
// Get upset if any errors were thrown.
|
// Get upset if any errors were thrown.
|
||||||
if len(err) > 0 {
|
for i := range utils.UnwrapErrors(err) {
|
||||||
for i := range err {
|
fmt.Printf("error: %v", i)
|
||||||
fmt.Printf("error: %e", err[i])
|
|
||||||
}
|
|
||||||
panic("something went wrong")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a high-level Document from the low-level one.
|
// Create a high-level Document from the low-level one.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ func TestPathItem(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.PathItem
|
var n v3.PathItem
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewPathItem(&n)
|
r := NewPathItem(&n)
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ trace:
|
|||||||
|
|
||||||
var n v3.PathItem
|
var n v3.PathItem
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewPathItem(&n)
|
r := NewPathItem(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ func TestPaths_MarshalYAML(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
high := NewPaths(&n)
|
high := NewPaths(&n)
|
||||||
@@ -89,7 +90,7 @@ func TestPaths_MarshalYAMLInline(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
high := NewPaths(&n)
|
high := NewPaths(&n)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ func TestNewResponses(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ func TestResponses_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ func TestResponses_MarshalYAMLInline(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -31,7 +32,7 @@ func TestSecurityScheme_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.SecurityScheme
|
var n v3.SecurityScheme
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewSecurityScheme(&n)
|
r := NewSecurityScheme(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -23,7 +24,7 @@ type Contact struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build is not implemented for Contact (there is nothing to build).
|
// Build is not implemented for Contact (there is nothing to build).
|
||||||
func (c *Contact) Build(_, _ *yaml.Node, _ *index.SpecIndex) error {
|
func (c *Contact) Build(_ context.Context, _, _ *yaml.Node, _ *index.SpecIndex) error {
|
||||||
c.Reference = new(low.Reference)
|
c.Reference = new(low.Reference)
|
||||||
// not implemented.
|
// not implemented.
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -60,7 +61,7 @@ func (ex *Example) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build extracts extensions and example value
|
// Build extracts extensions and example value
|
||||||
func (ex *Example) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ex *Example) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ex.Reference = new(low.Reference)
|
ex.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -33,7 +34,7 @@ func (ex *ExternalDoc) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions from the ExternalDoc instance.
|
// Build will extract extensions from the ExternalDoc instance.
|
||||||
func (ex *ExternalDoc) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ex *ExternalDoc) Build(_ context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ex.Reference = new(low.Reference)
|
ex.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
@@ -45,18 +46,18 @@ func (i *Info) GetExtensions() map[low.KeyReference[string]]low.ValueReference[a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract out the Contact and Info objects from the supplied root node.
|
// Build will extract out the Contact and Info objects from the supplied root node.
|
||||||
func (i *Info) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (i *Info) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
i.Reference = new(low.Reference)
|
i.Reference = new(low.Reference)
|
||||||
i.Extensions = low.ExtractExtensions(root)
|
i.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract contact
|
// extract contact
|
||||||
contact, _ := low.ExtractObject[*Contact](ContactLabel, root, idx)
|
contact, _ := low.ExtractObject[*Contact](ctx, ContactLabel, root, idx)
|
||||||
i.Contact = contact
|
i.Contact = contact
|
||||||
|
|
||||||
// extract license
|
// extract license
|
||||||
lic, _ := low.ExtractObject[*License](LicenseLabel, root, idx)
|
lic, _ := low.ExtractObject[*License](ctx, LicenseLabel, root, idx)
|
||||||
i.License = lic
|
i.License = lic
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -25,7 +26,7 @@ type License struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build out a license, complain if both a URL and identifier are present as they are mutually exclusive
|
// Build out a license, complain if both a URL and identifier are present as they are mutually exclusive
|
||||||
func (l *License) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (l *License) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
l.Reference = new(low.Reference)
|
l.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -490,13 +491,13 @@ func (s *Schema) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
// - UnevaluatedItems
|
// - UnevaluatedItems
|
||||||
// - UnevaluatedProperties
|
// - UnevaluatedProperties
|
||||||
// - Anchor
|
// - Anchor
|
||||||
func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
s.Index = idx
|
s.Index = idx
|
||||||
if h, _, _ := utils.IsNodeRefValue(root); h {
|
if h, _, _ := utils.IsNodeRefValue(root); h {
|
||||||
ref, err := low.LocateRefNode(root, idx)
|
ref, _, err := low.LocateRefNode(root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
root = ref
|
root = ref
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -704,7 +705,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if extDocNode != nil {
|
if extDocNode != nil {
|
||||||
var exDoc ExternalDoc
|
var exDoc ExternalDoc
|
||||||
_ = low.BuildModel(extDocNode, &exDoc)
|
_ = low.BuildModel(extDocNode, &exDoc)
|
||||||
_ = exDoc.Build(extDocLabel, extDocNode, idx) // throws no errors, can't check for one.
|
_ = exDoc.Build(ctx, extDocLabel, extDocNode, idx) // throws no errors, can't check for one.
|
||||||
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1069,7 +1070,7 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
isRef := false
|
isRef := false
|
||||||
refString := ""
|
refString := ""
|
||||||
if h, _, l := utils.IsNodeRefValue(prop); h {
|
if h, _, l := utils.IsNodeRefValue(prop); h {
|
||||||
ref, _ := low.LocateRefNode(prop, idx)
|
ref, _, _ := low.LocateRefNode(prop, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
isRef = true
|
isRef = true
|
||||||
prop = ref
|
prop = ref
|
||||||
@@ -1165,7 +1166,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(valueNode); h {
|
if h, _, refLocation = utils.IsNodeRefValue(valueNode); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(valueNode, idx)
|
ref, _, _ := low.LocateRefNode(valueNode, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
valueNode = ref
|
valueNode = ref
|
||||||
} else {
|
} else {
|
||||||
@@ -1196,7 +1197,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(vn); h {
|
if h, _, refLocation = utils.IsNodeRefValue(vn); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(vn, idx)
|
ref, _, _ := low.LocateRefNode(vn, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
vn = ref
|
vn = ref
|
||||||
} else {
|
} else {
|
||||||
@@ -1237,16 +1238,17 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
// ExtractSchema will return a pointer to a NodeReference that contains a *SchemaProxy if successful. The function
|
// ExtractSchema will return a pointer to a NodeReference that contains a *SchemaProxy if successful. The function
|
||||||
// will specifically look for a key node named 'schema' and extract the value mapped to that key. If the operation
|
// will specifically look for a key node named 'schema' and extract the value mapped to that key. If the operation
|
||||||
// fails then no NodeReference is returned and an error is returned instead.
|
// fails then no NodeReference is returned and an error is returned instead.
|
||||||
func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*SchemaProxy], error) {
|
func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*SchemaProxy], error) {
|
||||||
var schLabel, schNode *yaml.Node
|
var schLabel, schNode *yaml.Node
|
||||||
errStr := "schema build failed: reference '%s' cannot be found at line %d, col %d"
|
errStr := "schema build failed: reference '%s' cannot be found at line %d, col %d"
|
||||||
|
|
||||||
isRef := false
|
isRef := false
|
||||||
refLocation := ""
|
refLocation := ""
|
||||||
|
|
||||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||||
// locate reference in index.
|
// locate reference in index.
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(root, idx)
|
ref, _, _ := low.LocateRefNode(root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
schNode = ref
|
schNode = ref
|
||||||
schLabel = rl
|
schLabel = rl
|
||||||
@@ -1260,9 +1262,13 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
|||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(schNode); h {
|
if h, _, refLocation = utils.IsNodeRefValue(schNode); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(schNode, idx)
|
ref, foundIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, schNode, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
schNode = ref
|
schNode = ref
|
||||||
|
if foundIdx != nil {
|
||||||
|
//idx = foundIdx
|
||||||
|
}
|
||||||
|
ctx = nCtx
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf(errStr,
|
return nil, fmt.Errorf(errStr,
|
||||||
schNode.Content[1].Value, schNode.Content[1].Line, schNode.Content[1].Column)
|
schNode.Content[1].Value, schNode.Content[1].Line, schNode.Content[1].Column)
|
||||||
@@ -1273,7 +1279,7 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
|||||||
|
|
||||||
if schNode != nil {
|
if schNode != nil {
|
||||||
// check if schema has already been built.
|
// check if schema has already been built.
|
||||||
schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: idx, isReference: isRef, referenceLookup: refLocation}
|
schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: idx, ctx: ctx, isReference: isRef, referenceLookup: refLocation}
|
||||||
return &low.NodeReference[*SchemaProxy]{
|
return &low.NodeReference[*SchemaProxy]{
|
||||||
Value: schema, KeyNode: schLabel, ValueNode: schNode, ReferenceNode: isRef,
|
Value: schema, KeyNode: schLabel, ValueNode: schNode, ReferenceNode: isRef,
|
||||||
Reference: refLocation,
|
Reference: refLocation,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -51,14 +52,16 @@ type SchemaProxy struct {
|
|||||||
buildError error
|
buildError error
|
||||||
isReference bool // Is the schema underneath originally a $ref?
|
isReference bool // Is the schema underneath originally a $ref?
|
||||||
referenceLookup string // If the schema is a $ref, what's its name?
|
referenceLookup string // If the schema is a $ref, what's its name?
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will prepare the SchemaProxy for rendering, it does not build the Schema, only sets up internal state.
|
// Build will prepare the SchemaProxy for rendering, it does not build the Schema, only sets up internal state.
|
||||||
// Key maybe nil if absent.
|
// Key maybe nil if absent.
|
||||||
func (sp *SchemaProxy) Build(key, value *yaml.Node, idx *index.SpecIndex) error {
|
func (sp *SchemaProxy) Build(ctx context.Context, key, value *yaml.Node, idx *index.SpecIndex) error {
|
||||||
sp.kn = key
|
sp.kn = key
|
||||||
sp.vn = value
|
sp.vn = value
|
||||||
sp.idx = idx
|
sp.idx = idx
|
||||||
|
sp.ctx = ctx
|
||||||
if rf, _, r := utils.IsNodeRefValue(value); rf {
|
if rf, _, r := utils.IsNodeRefValue(value); rf {
|
||||||
sp.isReference = true
|
sp.isReference = true
|
||||||
sp.referenceLookup = r
|
sp.referenceLookup = r
|
||||||
@@ -83,7 +86,7 @@ func (sp *SchemaProxy) Schema() *Schema {
|
|||||||
}
|
}
|
||||||
schema := new(Schema)
|
schema := new(Schema)
|
||||||
utils.CheckForMergeNodes(sp.vn)
|
utils.CheckForMergeNodes(sp.vn)
|
||||||
err := schema.Build(sp.vn, sp.idx)
|
err := schema.Build(sp.ctx, sp.vn, sp.idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sp.buildError = err
|
sp.buildError = err
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -28,7 +29,7 @@ type SecurityRequirement struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract security requirements from the node (the structure is odd, to be honest)
|
// Build will extract security requirements from the node (the structure is odd, to be honest)
|
||||||
func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
func (s *SecurityRequirement) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -34,14 +35,14 @@ func (t *Tag) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and external docs for the Tag.
|
// Build will extract extensions and external docs for the Tag.
|
||||||
func (t *Tag) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (t *Tag) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
t.Reference = new(low.Reference)
|
t.Reference = new(low.Reference)
|
||||||
t.Extensions = low.ExtractExtensions(root)
|
t.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, err := low.ExtractObject[*ExternalDoc](ExternalDocsLabel, root, idx)
|
extDocs, err := low.ExtractObject[*ExternalDoc](ctx, ExternalDocsLabel, root, idx)
|
||||||
t.ExternalDocs = extDocs
|
t.ExternalDocs = extDocs
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -4,15 +4,14 @@
|
|||||||
package low
|
package low
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"strings"
|
||||||
"strings"
|
"testing"
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFindItemInMap(t *testing.T) {
|
func TestFindItemInMap(t *testing.T) {
|
||||||
@@ -1570,38 +1569,6 @@ func TestExtractMapFlat_Ref_Bad(t *testing.T) {
|
|||||||
assert.Len(t, things, 0)
|
assert.Len(t, things, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLocateRefNode_RemoteFile(t *testing.T) {
|
|
||||||
|
|
||||||
ymlFile := fmt.Sprintf(`components:
|
|
||||||
schemas:
|
|
||||||
hey:
|
|
||||||
$ref: '%s#/components/schemas/hey'`, "remote.yaml")
|
|
||||||
|
|
||||||
ymlRemote := `components:
|
|
||||||
schemas:
|
|
||||||
hey:
|
|
||||||
AlmostWork: 999`
|
|
||||||
|
|
||||||
_ = os.WriteFile("remote.yaml", []byte(ymlRemote), 0665)
|
|
||||||
defer os.Remove("remote.yaml")
|
|
||||||
|
|
||||||
ymlLocal := `$ref: '#/components/schemas/hey'`
|
|
||||||
|
|
||||||
var idxNode yaml.Node
|
|
||||||
mErr := yaml.Unmarshal([]byte(ymlFile), &idxNode) // an empty index.
|
|
||||||
assert.NoError(t, mErr)
|
|
||||||
idx := index.NewSpecIndexWithConfig(&idxNode, index.CreateOpenAPIIndexConfig())
|
|
||||||
|
|
||||||
var cNode yaml.Node
|
|
||||||
e := yaml.Unmarshal([]byte(ymlLocal), &cNode)
|
|
||||||
assert.NoError(t, e)
|
|
||||||
|
|
||||||
things, _, _, err := ExtractMap[*test_Good]("one", cNode.Content[0], idx)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, things, 1)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractExtensions(t *testing.T) {
|
func TestExtractExtensions(t *testing.T) {
|
||||||
|
|
||||||
yml := `x-bing: ding
|
yml := `x-bing: ding
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package low
|
package low
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
@@ -38,7 +39,7 @@ type IsReferenced interface {
|
|||||||
//
|
//
|
||||||
// Used by generic functions when automatically building out structs based on yaml.Node inputs.
|
// Used by generic functions when automatically building out structs based on yaml.Node inputs.
|
||||||
type Buildable[T any] interface {
|
type Buildable[T any] interface {
|
||||||
Build(key, value *yaml.Node, idx *index.SpecIndex) error
|
Build(ctx context.Context, key, value *yaml.Node, idx *index.SpecIndex) error
|
||||||
*T
|
*T
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +113,8 @@ type NodeReference[T any] struct {
|
|||||||
|
|
||||||
// If HasReference is true, then Reference contains the original $ref value.
|
// If HasReference is true, then Reference contains the original $ref value.
|
||||||
Reference string
|
Reference string
|
||||||
|
|
||||||
|
Context context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyReference is a low-level container for key nodes holding a Value of type T. A KeyNode is a pointer to the
|
// KeyReference is a low-level container for key nodes holding a Value of type T. A KeyNode is a pointer to the
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
@@ -71,7 +72,7 @@ func (s *SecurityDefinitions) FindSecurityDefinition(securityDef string) *low.Va
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all definitions into SchemaProxy instances.
|
// Build will extract all definitions into SchemaProxy instances.
|
||||||
func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (d *Definitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
@@ -81,7 +82,7 @@ func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*base.SchemaProxy], e chan error) {
|
r chan definitionResult[*base.SchemaProxy], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*base.SchemaProxy](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*base.SchemaProxy](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -133,7 +134,7 @@ func (d *Definitions) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all ParameterDefinitions into Parameter instances.
|
// Build will extract all ParameterDefinitions into Parameter instances.
|
||||||
func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (pd *ParameterDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*Parameter])
|
resultChan := make(chan definitionResult[*Parameter])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -141,7 +142,7 @@ func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex)
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*Parameter], e chan error) {
|
r chan definitionResult[*Parameter], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*Parameter](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*Parameter](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -182,7 +183,7 @@ type definitionResult[T any] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all ResponsesDefinitions into Response instances.
|
// Build will extract all ResponsesDefinitions into Response instances.
|
||||||
func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *ResponsesDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*Response])
|
resultChan := make(chan definitionResult[*Response])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -190,7 +191,7 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*Response], e chan error) {
|
r chan definitionResult[*Response], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*Response](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*Response](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -225,7 +226,7 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all SecurityDefinitions into SecurityScheme instances.
|
// Build will extract all SecurityDefinitions into SecurityScheme instances.
|
||||||
func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *SecurityDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*SecurityScheme])
|
resultChan := make(chan definitionResult[*SecurityScheme])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -234,7 +235,7 @@ func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) er
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*SecurityScheme], e chan error) {
|
r chan definitionResult[*SecurityScheme], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*SecurityScheme](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*SecurityScheme](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -27,7 +28,7 @@ func (e *Examples) FindExample(name string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
||||||
func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
func (e *Examples) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
var keyNode, currNode *yaml.Node
|
var keyNode, currNode *yaml.Node
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -51,11 +52,11 @@ func (h *Header) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will build out items, extensions and default value from the supplied node.
|
// Build will build out items, extensions and default value from the supplied node.
|
||||||
func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (h *Header) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
h.Extensions = low.ExtractExtensions(root)
|
h.Extensions = low.ExtractExtensions(root)
|
||||||
items, err := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, err := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -102,11 +103,11 @@ func (i *Items) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will build out items and default value.
|
// Build will build out items and default value.
|
||||||
func (i *Items) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (i *Items) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
i.Extensions = low.ExtractExtensions(root)
|
i.Extensions = low.ExtractExtensions(root)
|
||||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, iErr := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if iErr != nil {
|
if iErr != nil {
|
||||||
return iErr
|
return iErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -36,20 +37,20 @@ type Operation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract external docs, extensions, parameters, responses and security requirements.
|
// Build will extract external docs, extensions, parameters, responses and security requirements.
|
||||||
func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *Operation) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
o.Extensions = low.ExtractExtensions(root)
|
o.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, root, idx)
|
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, root, idx)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
return dErr
|
return dErr
|
||||||
}
|
}
|
||||||
o.ExternalDocs = extDocs
|
o.ExternalDocs = extDocs
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -62,14 +63,14 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract responses
|
// extract responses
|
||||||
respBody, respErr := low.ExtractObject[*Responses](ResponsesLabel, root, idx)
|
respBody, respErr := low.ExtractObject[*Responses](ctx, ResponsesLabel, root, idx)
|
||||||
if respErr != nil {
|
if respErr != nil {
|
||||||
return respErr
|
return respErr
|
||||||
}
|
}
|
||||||
o.Responses = respBody
|
o.Responses = respBody
|
||||||
|
|
||||||
// extract security
|
// extract security
|
||||||
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -94,18 +95,18 @@ func (p *Parameter) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract out extensions, schema, items and default value
|
// Build will extract out extensions, schema, items and default value
|
||||||
func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Parameter) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
if sch != nil {
|
if sch != nil {
|
||||||
p.Schema = *sch
|
p.Schema = *sch
|
||||||
}
|
}
|
||||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, iErr := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if iErr != nil {
|
if iErr != nil {
|
||||||
return iErr
|
return iErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -48,7 +49,7 @@ func (p *PathItem) GetExtensions() map[low.KeyReference[string]]low.ValueReferen
|
|||||||
|
|
||||||
// Build will extract extensions, parameters and operations for all methods. Every method is handled
|
// Build will extract extensions, parameters and operations for all methods. Every method is handled
|
||||||
// asynchronously, in order to keep things moving quickly for complex operations.
|
// asynchronously, in order to keep things moving quickly for complex operations.
|
||||||
func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *PathItem) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
@@ -61,7 +62,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var ops []low.NodeReference[*Operation]
|
var ops []low.NodeReference[*Operation]
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -158,7 +159,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
opErrorChan := make(chan error)
|
opErrorChan := make(chan 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) {
|
||||||
er := op.Value.Build(op.KeyNode, op.ValueNode, idx)
|
er := op.Value.Build(ctx, op.KeyNode, op.ValueNode, idx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
errCh <- er
|
errCh <- er
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -54,7 +55,7 @@ func (p *Paths) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and paths from node.
|
// Build will extract extensions and paths from node.
|
||||||
func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Paths) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
@@ -126,7 +127,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
cNode := value.currentNode
|
cNode := value.currentNode
|
||||||
path := new(PathItem)
|
path := new(PathItem)
|
||||||
_ = low.BuildModel(pNode, path)
|
_ = low.BuildModel(pNode, path)
|
||||||
err := path.Build(cNode, pNode, idx)
|
err := path.Build(ctx, cNode, pNode, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pathBuildResult{}, err
|
return pathBuildResult{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -43,11 +44,11 @@ func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract schema, extensions, examples and headers from node
|
// Build will extract schema, extensions, examples and headers from node
|
||||||
func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Response) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
s, err := base.ExtractSchema(root, idx)
|
s, err := base.ExtractSchema(ctx, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -56,14 +57,14 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract examples
|
// extract examples
|
||||||
examples, expErr := low.ExtractObject[*Examples](ExamplesLabel, root, idx)
|
examples, expErr := low.ExtractObject[*Examples](ctx, ExamplesLabel, root, idx)
|
||||||
if expErr != nil {
|
if expErr != nil {
|
||||||
return expErr
|
return expErr
|
||||||
}
|
}
|
||||||
r.Examples = examples
|
r.Examples = examples
|
||||||
|
|
||||||
//extract headers
|
//extract headers
|
||||||
headers, lN, kN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
|
headers, lN, kN, err := low.ExtractMap[*Header](ctx, HeadersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -27,13 +28,13 @@ func (r *Responses) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract default value and extensions from node.
|
// Build will extract default value and extensions from node.
|
||||||
func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Responses) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
if utils.IsNodeMap(root) {
|
if utils.IsNodeMap(root) {
|
||||||
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
|
codes, err := low.ExtractMapNoLookup[*Response](ctx, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -34,7 +35,7 @@ func (s *Scopes) FindScope(scope string) *low.ValueReference[string] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract scope values and extensions from node.
|
// Build will extract scope values and extensions from node.
|
||||||
func (s *Scopes) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *Scopes) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Extensions = low.ExtractExtensions(root)
|
s.Extensions = low.ExtractExtensions(root)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -38,12 +39,12 @@ func (ss *SecurityScheme) GetExtensions() map[low.KeyReference[string]]low.Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and scopes from the node.
|
// Build will extract extensions and scopes from the node.
|
||||||
func (ss *SecurityScheme) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ss *SecurityScheme) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ss.Extensions = low.ExtractExtensions(root)
|
ss.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
scopes, sErr := low.ExtractObject[*Scopes](ScopesLabel, root, idx)
|
scopes, sErr := low.ExtractObject[*Scopes](ctx, ScopesLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
@@ -20,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// processes a property of a Swagger document asynchronously using bool and error channels for signals.
|
// processes a property of a Swagger document asynchronously using bool and error channels for signals.
|
||||||
type documentFunction func(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error)
|
type documentFunction func(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error)
|
||||||
|
|
||||||
// Swagger represents a high-level Swagger / OpenAPI 2 document. An instance of Swagger is the root of the specification.
|
// Swagger represents a high-level Swagger / OpenAPI 2 document. An instance of Swagger is the root of the specification.
|
||||||
type Swagger struct {
|
type Swagger struct {
|
||||||
@@ -129,6 +130,9 @@ func CreateDocumentFromConfig(info *datamodel.SpecInfo,
|
|||||||
// CreateDocument will create a new Swagger document from the provided SpecInfo.
|
// CreateDocument will create a new Swagger document from the provided SpecInfo.
|
||||||
//
|
//
|
||||||
// Deprecated: Use CreateDocumentFromConfig instead.
|
// Deprecated: Use CreateDocumentFromConfig instead.
|
||||||
|
|
||||||
|
// TODO; DELETE ME
|
||||||
|
|
||||||
func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
|
func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
|
||||||
return createDocument(info, &datamodel.DocumentConfiguration{
|
return createDocument(info, &datamodel.DocumentConfiguration{
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -155,8 +159,10 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
// build out swagger scalar variables.
|
// build out swagger scalar variables.
|
||||||
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, err := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx)
|
extDocs, err := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, info.RootNode, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, err)
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
@@ -186,7 +192,7 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
doneChan := make(chan bool)
|
doneChan := make(chan bool)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
for i := range extractionFuncs {
|
for i := range extractionFuncs {
|
||||||
go extractionFuncs[i](info.RootNode.Content[0], &doc, idx, doneChan, errChan)
|
go extractionFuncs[i](ctx, info.RootNode.Content[0], &doc, idx, doneChan, errChan)
|
||||||
}
|
}
|
||||||
completedExtractions := 0
|
completedExtractions := 0
|
||||||
for completedExtractions < len(extractionFuncs) {
|
for completedExtractions < len(extractionFuncs) {
|
||||||
@@ -210,8 +216,8 @@ func (s *Swagger) GetExternalDocs() *low.NodeReference[any] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractInfo(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
info, err := low.ExtractObject[*base.Info](base.InfoLabel, root, idx)
|
info, err := low.ExtractObject[*base.Info](ctx, base.InfoLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -220,8 +226,8 @@ func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractPaths(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
paths, err := low.ExtractObject[*Paths](PathsLabel, root, idx)
|
paths, err := low.ExtractObject[*Paths](ctx, PathsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -229,8 +235,8 @@ func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<-
|
|||||||
doc.Paths = paths
|
doc.Paths = paths
|
||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
def, err := low.ExtractObject[*Definitions](DefinitionsLabel, root, idx)
|
def, err := low.ExtractObject[*Definitions](ctx, DefinitionsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -238,8 +244,8 @@ func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c c
|
|||||||
doc.Definitions = def
|
doc.Definitions = def
|
||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractParamDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
param, err := low.ExtractObject[*ParameterDefinitions](ParametersLabel, root, idx)
|
param, err := low.ExtractObject[*ParameterDefinitions](ctx, ParametersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -248,8 +254,8 @@ func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractResponsesDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ResponsesLabel, root, idx)
|
resp, err := low.ExtractObject[*ResponsesDefinitions](ctx, ResponsesLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -258,8 +264,8 @@ func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecI
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractSecurityDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
sec, err := low.ExtractObject[*SecurityDefinitions](SecurityDefinitionsLabel, root, idx)
|
sec, err := low.ExtractObject[*SecurityDefinitions](ctx, SecurityDefinitionsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -268,8 +274,8 @@ func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIn
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractTags(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
tags, ln, vn, err := low.ExtractArray[*base.Tag](base.TagsLabel, root, idx)
|
tags, ln, vn, err := low.ExtractArray[*base.Tag](ctx, base.TagsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -282,8 +288,8 @@ func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurity(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractSecurity(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
@@ -39,7 +40,7 @@ func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions, expressions and PathItem objects for Callback
|
// Build will extract extensions, expressions and PathItem objects for Callback
|
||||||
func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (cb *Callback) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
cb.Reference = new(low.Reference)
|
cb.Reference = new(low.Reference)
|
||||||
@@ -57,7 +58,7 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if strings.HasPrefix(currentCB.Value, "x-") {
|
if strings.HasPrefix(currentCB.Value, "x-") {
|
||||||
continue // ignore extension.
|
continue // ignore extension.
|
||||||
}
|
}
|
||||||
callback, eErr, _, rv := low.ExtractObjectRaw[*PathItem](currentCB, callbackNode, idx)
|
callback, eErr, _, rv := low.ExtractObjectRaw[*PathItem](ctx, currentCB, callbackNode, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -141,7 +142,7 @@ func (co *Components) FindCallback(callback string) *low.ValueReference[*Callbac
|
|||||||
|
|
||||||
// Build converts root YAML node containing components to low level model.
|
// Build converts root YAML node containing components to low level model.
|
||||||
// Process each component in parallel.
|
// Process each component in parallel.
|
||||||
func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (co *Components) Build(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
co.Reference = new(low.Reference)
|
co.Reference = new(low.Reference)
|
||||||
@@ -161,55 +162,55 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
schemas, err := extractComponentValues[*base.SchemaProxy](SchemasLabel, root, idx)
|
schemas, err := extractComponentValues[*base.SchemaProxy](ctx, SchemasLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Schemas = schemas
|
co.Schemas = schemas
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
parameters, err := extractComponentValues[*Parameter](ParametersLabel, root, idx)
|
parameters, err := extractComponentValues[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Parameters = parameters
|
co.Parameters = parameters
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
responses, err := extractComponentValues[*Response](ResponsesLabel, root, idx)
|
responses, err := extractComponentValues[*Response](ctx, ResponsesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Responses = responses
|
co.Responses = responses
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
examples, err := extractComponentValues[*base.Example](base.ExamplesLabel, root, idx)
|
examples, err := extractComponentValues[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Examples = examples
|
co.Examples = examples
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
requestBodies, err := extractComponentValues[*RequestBody](RequestBodiesLabel, root, idx)
|
requestBodies, err := extractComponentValues[*RequestBody](ctx, RequestBodiesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.RequestBodies = requestBodies
|
co.RequestBodies = requestBodies
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
headers, err := extractComponentValues[*Header](HeadersLabel, root, idx)
|
headers, err := extractComponentValues[*Header](ctx, HeadersLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Headers = headers
|
co.Headers = headers
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
securitySchemes, err := extractComponentValues[*SecurityScheme](SecuritySchemesLabel, root, idx)
|
securitySchemes, err := extractComponentValues[*SecurityScheme](ctx, SecuritySchemesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.SecuritySchemes = securitySchemes
|
co.SecuritySchemes = securitySchemes
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
links, err := extractComponentValues[*Link](LinksLabel, root, idx)
|
links, err := extractComponentValues[*Link](ctx, LinksLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Links = links
|
co.Links = links
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
callbacks, err := extractComponentValues[*Callback](CallbacksLabel, root, idx)
|
callbacks, err := extractComponentValues[*Callback](ctx, CallbacksLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Callbacks = callbacks
|
co.Callbacks = callbacks
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -222,7 +223,7 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// extractComponentValues converts all the YAML nodes of a component type to
|
// extractComponentValues converts all the YAML nodes of a component type to
|
||||||
// low level model.
|
// low level model.
|
||||||
// Process each node in parallel.
|
// Process each node in parallel.
|
||||||
func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]], error) {
|
func extractComponentValues[T low.Buildable[N], N any](ctx context.Context, label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]], error) {
|
||||||
var emptyResult low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]
|
var emptyResult low.NodeReference[map[low.KeyReference[string]]low.ValueReference[T]]
|
||||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
||||||
if nodeValue == nil {
|
if nodeValue == nil {
|
||||||
@@ -288,7 +289,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
// TODO: check circular crazy on this. It may explode
|
// TODO: check circular crazy on this. It may explode
|
||||||
var err error
|
var err error
|
||||||
if h, _, _ := utils.IsNodeRefValue(node); h && label != SchemasLabel {
|
if h, _, _ := utils.IsNodeRefValue(node); h && label != SchemasLabel {
|
||||||
node, err = low.LocateRefNode(node, idx)
|
node, _, err = low.LocateRefNode(node, idx)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return componentBuildResult[T]{}, err
|
return componentBuildResult[T]{}, err
|
||||||
@@ -296,7 +297,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
|
|
||||||
// build.
|
// build.
|
||||||
_ = low.BuildModel(node, n)
|
_ = low.BuildModel(node, n)
|
||||||
err = n.Build(currentLabel, node, idx)
|
err = n.Build(ctx, currentLabel, node, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return componentBuildResult[T]{}, err
|
return componentBuildResult[T]{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -39,28 +40,24 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
||||||
doc := Document{Version: version}
|
doc := Document{Version: version}
|
||||||
|
|
||||||
// get current working directory as a basePath
|
|
||||||
cwd, _ := os.Getwd()
|
|
||||||
if config.BasePath != "" {
|
|
||||||
cwd = config.BasePath
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: configure allowFileReferences and allowRemoteReferences stuff
|
// TODO: configure allowFileReferences and allowRemoteReferences stuff
|
||||||
|
|
||||||
// create an index config and shadow the document configuration.
|
// create an index config and shadow the document configuration.
|
||||||
idxConfig := index.CreateOpenAPIIndexConfig()
|
idxConfig := index.CreateOpenAPIIndexConfig()
|
||||||
idxConfig.SpecInfo = info
|
idxConfig.SpecInfo = info
|
||||||
idxConfig.BasePath = cwd
|
|
||||||
idxConfig.IgnoreArrayCircularReferences = config.IgnoreArrayCircularReferences
|
idxConfig.IgnoreArrayCircularReferences = config.IgnoreArrayCircularReferences
|
||||||
idxConfig.IgnorePolymorphicCircularReferences = config.IgnorePolymorphicCircularReferences
|
idxConfig.IgnorePolymorphicCircularReferences = config.IgnorePolymorphicCircularReferences
|
||||||
idxConfig.AvoidCircularReferenceCheck = config.SkipCircularReferenceCheck
|
idxConfig.AvoidCircularReferenceCheck = true
|
||||||
|
idxConfig.BaseURL = config.BaseURL
|
||||||
|
idxConfig.BasePath = config.BasePath
|
||||||
rolodex := index.NewRolodex(idxConfig)
|
rolodex := index.NewRolodex(idxConfig)
|
||||||
|
rolodex.SetRootNode(info.RootNode)
|
||||||
doc.Rolodex = rolodex
|
doc.Rolodex = rolodex
|
||||||
|
|
||||||
// If basePath is provided override it
|
// If basePath is provided, add a local filesystem to the rolodex.
|
||||||
if config.BasePath != "" {
|
if idxConfig.BasePath != "" {
|
||||||
var absError error
|
var absError error
|
||||||
|
var cwd string
|
||||||
cwd, absError = filepath.Abs(config.BasePath)
|
cwd, absError = filepath.Abs(config.BasePath)
|
||||||
if absError != nil {
|
if absError != nil {
|
||||||
return nil, absError
|
return nil, absError
|
||||||
@@ -77,13 +74,34 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Remote filesystem
|
// if base url is provided, add a remote filesystem to the rolodex.
|
||||||
|
if idxConfig.BaseURL != nil {
|
||||||
|
|
||||||
|
// create a remote filesystem
|
||||||
|
remoteFS, fsErr := index.NewRemoteFSWithConfig(idxConfig)
|
||||||
|
if fsErr != nil {
|
||||||
|
return nil, fsErr
|
||||||
|
}
|
||||||
|
if config.RemoteURLHandler != nil {
|
||||||
|
remoteFS.RemoteHandlerFunc = config.RemoteURLHandler
|
||||||
|
}
|
||||||
|
// add to the rolodex
|
||||||
|
rolodex.AddRemoteFS(config.BaseURL.String(), remoteFS)
|
||||||
|
}
|
||||||
|
|
||||||
// index the rolodex
|
// index the rolodex
|
||||||
err := rolodex.IndexTheRolodex()
|
|
||||||
var errs []error
|
var errs []error
|
||||||
if err != nil {
|
|
||||||
errs = append(errs, rolodex.GetCaughtErrors()...)
|
_ = rolodex.IndexTheRolodex()
|
||||||
|
|
||||||
|
if !config.SkipCircularReferenceCheck {
|
||||||
|
rolodex.CheckForCircularReferences()
|
||||||
|
}
|
||||||
|
|
||||||
|
roloErrs := rolodex.GetCaughtErrors()
|
||||||
|
|
||||||
|
if roloErrs != nil {
|
||||||
|
errs = append(errs, roloErrs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.Index = rolodex.GetRootIndex()
|
doc.Index = rolodex.GetRootIndex()
|
||||||
@@ -125,17 +143,17 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runExtraction := func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
runExtraction := func(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||||
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
runFunc func(ctx context.Context, i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||||
ers *[]error,
|
ers *[]error,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
) {
|
) {
|
||||||
if er := runFunc(info, doc, idx); er != nil {
|
if er := runFunc(ctx, info, doc, idx); er != nil {
|
||||||
*ers = append(*ers, er)
|
*ers = append(*ers, er)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
extractionFuncs := []func(ctx context.Context, i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
||||||
extractInfo,
|
extractInfo,
|
||||||
extractServers,
|
extractServers,
|
||||||
extractTags,
|
extractTags,
|
||||||
@@ -146,28 +164,30 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
extractWebhooks,
|
extractWebhooks,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
wg.Add(len(extractionFuncs))
|
wg.Add(len(extractionFuncs))
|
||||||
for _, f := range extractionFuncs {
|
for _, f := range extractionFuncs {
|
||||||
go runExtraction(info, &doc, rolodex.GetRootIndex(), f, &errs, &wg)
|
go runExtraction(ctx, info, &doc, rolodex.GetRootIndex(), f, &errs, &wg)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return &doc, errors.Join(errs...)
|
return &doc, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractInfo(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := base.Info{}
|
ir := base.Info{}
|
||||||
_ = low.BuildModel(vn, &ir)
|
_ = low.BuildModel(vn, &ir)
|
||||||
_ = ir.Build(ln, vn, idx)
|
_ = ir.Build(ctx, ln, vn, idx)
|
||||||
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||||
doc.Info = nr
|
doc.Info = nr
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractSecurity(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode.Content[0], idx)
|
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, info.RootNode.Content[0], idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -181,8 +201,8 @@ func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInd
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractExternalDocs(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
return dErr
|
return dErr
|
||||||
}
|
}
|
||||||
@@ -190,12 +210,12 @@ func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.Spe
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractComponents(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := Components{}
|
ir := Components{}
|
||||||
_ = low.BuildModel(vn, &ir)
|
_ = low.BuildModel(vn, &ir)
|
||||||
err := ir.Build(vn, idx)
|
err := ir.Build(ctx, vn, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -205,7 +225,7 @@ func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractServers(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -214,7 +234,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
|||||||
if utils.IsNodeMap(srvN) {
|
if utils.IsNodeMap(srvN) {
|
||||||
srvr := Server{}
|
srvr := Server{}
|
||||||
_ = low.BuildModel(srvN, &srvr)
|
_ = low.BuildModel(srvN, &srvr)
|
||||||
_ = srvr.Build(ln, srvN, idx)
|
_ = srvr.Build(ctx, ln, srvN, idx)
|
||||||
servers = append(servers, low.ValueReference[*Server]{
|
servers = append(servers, low.ValueReference[*Server]{
|
||||||
Value: &srvr,
|
Value: &srvr,
|
||||||
ValueNode: srvN,
|
ValueNode: srvN,
|
||||||
@@ -231,7 +251,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractTags(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -240,7 +260,7 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
if utils.IsNodeMap(tagN) {
|
if utils.IsNodeMap(tagN) {
|
||||||
tag := base.Tag{}
|
tag := base.Tag{}
|
||||||
_ = low.BuildModel(tagN, &tag)
|
_ = low.BuildModel(tagN, &tag)
|
||||||
if err := tag.Build(ln, tagN, idx); err != nil {
|
if err := tag.Build(ctx, ln, tagN, idx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tags = append(tags, low.ValueReference[*base.Tag]{
|
tags = append(tags, low.ValueReference[*base.Tag]{
|
||||||
@@ -259,11 +279,11 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractPaths(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := Paths{}
|
ir := Paths{}
|
||||||
err := ir.Build(ln, vn, idx)
|
err := ir.Build(ctx, ln, vn, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -273,8 +293,8 @@ func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractWebhooks(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
|
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](ctx, WebhooksLabel, info.RootNode, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,9 +147,8 @@ func TestCreateDocumentStripe(t *testing.T) {
|
|||||||
d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: false,
|
AllowFileReferences: false,
|
||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
BasePath: "/here",
|
|
||||||
})
|
})
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
|
|
||||||
assert.Equal(t, "3.0.0", d.Version.Value)
|
assert.Equal(t, "3.0.0", d.Version.Value)
|
||||||
assert.Equal(t, "Stripe API", d.Info.Value.Title.Value)
|
assert.Equal(t, "Stripe API", d.Info.Value.Title.Value)
|
||||||
@@ -206,7 +205,8 @@ func TestCreateDocument_WebHooks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
||||||
yml := `webhooks:
|
yml := `openapi: 3.0
|
||||||
|
webhooks:
|
||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
@@ -215,7 +215,7 @@ func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
|||||||
AllowFileReferences: false,
|
AllowFileReferences: false,
|
||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Servers(t *testing.T) {
|
func TestCreateDocument_Servers(t *testing.T) {
|
||||||
@@ -613,7 +613,7 @@ webhooks:
|
|||||||
AllowFileReferences: false,
|
AllowFileReferences: false,
|
||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Equal(t, "flat map build failed: reference cannot be found: reference '' at line 4, column 5 was not found",
|
assert.Equal(t, "flat map build failed: reference cannot be found: reference at line 4, column 5 is empty, it cannot be resolved",
|
||||||
err.Error())
|
err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,7 +630,7 @@ components:
|
|||||||
AllowFileReferences: false,
|
AllowFileReferences: false,
|
||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Equal(t, "reference '' at line 5, column 7 was not found", err.Error())
|
assert.Equal(t, "reference at line 5, column 7 is empty, it cannot be resolved", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Paths_Errors(t *testing.T) {
|
func TestCreateDocument_Paths_Errors(t *testing.T) {
|
||||||
@@ -661,7 +661,7 @@ tags:
|
|||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"object extraction failed: reference '' at line 3, column 5 was not found", err.Error())
|
"object extraction failed: reference at line 3, column 5 is empty, it cannot be resolved", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Security_Error(t *testing.T) {
|
func TestCreateDocument_Security_Error(t *testing.T) {
|
||||||
@@ -676,7 +676,7 @@ security:
|
|||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"array build failed: reference cannot be found: reference '' at line 3, column 3 was not found",
|
"array build failed: reference cannot be found: reference at line 3, column 3 is empty, it cannot be resolved",
|
||||||
err.Error())
|
err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -691,7 +691,7 @@ externalDocs:
|
|||||||
AllowFileReferences: false,
|
AllowFileReferences: false,
|
||||||
AllowRemoteReferences: false,
|
AllowRemoteReferences: false,
|
||||||
})
|
})
|
||||||
assert.Equal(t, "object extraction failed: reference '' at line 3, column 3 was not found", err.Error())
|
assert.Equal(t, "object extraction failed: reference at line 3, column 3 is empty, it cannot be resolved", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_YamlAnchor(t *testing.T) {
|
func TestCreateDocument_YamlAnchor(t *testing.T) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -58,11 +59,11 @@ func (en *Encoding) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all Header objects from supplied node.
|
// Build will extract all Header objects from supplied node.
|
||||||
func (en *Encoding) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (en *Encoding) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
en.Reference = new(low.Reference)
|
en.Reference = new(low.Reference)
|
||||||
headers, hL, hN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
|
headers, hL, hN, err := low.ExtractMap[*Header](ctx, HeadersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -95,7 +96,7 @@ func (h *Header) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions, examples, schema and content/media types from node.
|
// Build will extract extensions, examples, schema and content/media types from node.
|
||||||
func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (h *Header) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
h.Reference = new(low.Reference)
|
h.Reference = new(low.Reference)
|
||||||
@@ -108,7 +109,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle examples if set.
|
// handle examples if set.
|
||||||
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](base.ExamplesLabel, root, idx)
|
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
@@ -121,7 +122,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle schema
|
// handle schema
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
@@ -130,7 +131,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle content, if set.
|
// handle content, if set.
|
||||||
con, cL, cN, cErr := low.ExtractMap[*MediaType](ContentLabel, root, idx)
|
con, cL, cN, cErr := low.ExtractMap[*MediaType](ctx, ContentLabel, root, idx)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -53,13 +54,13 @@ func (l *Link) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and servers from the node.
|
// Build will extract extensions and servers from the node.
|
||||||
func (l *Link) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (l *Link) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
l.Reference = new(low.Reference)
|
l.Reference = new(low.Reference)
|
||||||
l.Extensions = low.ExtractExtensions(root)
|
l.Extensions = low.ExtractExtensions(root)
|
||||||
// extract server.
|
// extract server.
|
||||||
ser, sErr := low.ExtractObject[*Server](ServerLabel, root, idx)
|
ser, sErr := low.ExtractObject[*Server](ctx, ServerLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -54,7 +55,7 @@ func (mt *MediaType) GetAllExamples() map[low.KeyReference[string]]low.ValueRefe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract examples, extensions, schema and encoding from node.
|
// Build will extract examples, extensions, schema and encoding from node.
|
||||||
func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (mt *MediaType) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
mt.Reference = new(low.Reference)
|
mt.Reference = new(low.Reference)
|
||||||
@@ -83,7 +84,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//handle schema
|
//handle schema
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
@@ -92,7 +93,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle examples if set.
|
// handle examples if set.
|
||||||
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](base.ExamplesLabel, root, idx)
|
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle encoding
|
// handle encoding
|
||||||
encs, encsL, encsN, encErr := low.ExtractMap[*Encoding](EncodingLabel, root, idx)
|
encs, encsL, encsN, encErr := low.ExtractMap[*Encoding](ctx, EncodingLabel, root, idx)
|
||||||
if encErr != nil {
|
if encErr != nil {
|
||||||
return encErr
|
return encErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -36,31 +37,31 @@ func (o *OAuthFlows) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and all OAuthFlow types from the supplied node.
|
// Build will extract extensions and all OAuthFlow types from the supplied node.
|
||||||
func (o *OAuthFlows) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *OAuthFlows) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
o.Reference = new(low.Reference)
|
o.Reference = new(low.Reference)
|
||||||
o.Extensions = low.ExtractExtensions(root)
|
o.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
v, vErr := low.ExtractObject[*OAuthFlow](ImplicitLabel, root, idx)
|
v, vErr := low.ExtractObject[*OAuthFlow](ctx, ImplicitLabel, root, idx)
|
||||||
if vErr != nil {
|
if vErr != nil {
|
||||||
return vErr
|
return vErr
|
||||||
}
|
}
|
||||||
o.Implicit = v
|
o.Implicit = v
|
||||||
|
|
||||||
v, vErr = low.ExtractObject[*OAuthFlow](PasswordLabel, root, idx)
|
v, vErr = low.ExtractObject[*OAuthFlow](ctx, PasswordLabel, root, idx)
|
||||||
if vErr != nil {
|
if vErr != nil {
|
||||||
return vErr
|
return vErr
|
||||||
}
|
}
|
||||||
o.Password = v
|
o.Password = v
|
||||||
|
|
||||||
v, vErr = low.ExtractObject[*OAuthFlow](ClientCredentialsLabel, root, idx)
|
v, vErr = low.ExtractObject[*OAuthFlow](ctx, ClientCredentialsLabel, root, idx)
|
||||||
if vErr != nil {
|
if vErr != nil {
|
||||||
return vErr
|
return vErr
|
||||||
}
|
}
|
||||||
o.ClientCredentials = v
|
o.ClientCredentials = v
|
||||||
|
|
||||||
v, vErr = low.ExtractObject[*OAuthFlow](AuthorizationCodeLabel, root, idx)
|
v, vErr = low.ExtractObject[*OAuthFlow](ctx, AuthorizationCodeLabel, root, idx)
|
||||||
if vErr != nil {
|
if vErr != nil {
|
||||||
return vErr
|
return vErr
|
||||||
}
|
}
|
||||||
@@ -116,7 +117,7 @@ func (o *OAuthFlow) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions from the node.
|
// Build will extract extensions from the node.
|
||||||
func (o *OAuthFlow) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *OAuthFlow) Build(_ context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
o.Reference = new(low.Reference)
|
o.Reference = new(low.Reference)
|
||||||
o.Extensions = low.ExtractExtensions(root)
|
o.Extensions = low.ExtractExtensions(root)
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -55,21 +56,21 @@ func (o *Operation) FindSecurityRequirement(name string) []low.ValueReference[st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract external docs, parameters, request body, responses, callbacks, security and servers.
|
// Build will extract external docs, parameters, request body, responses, callbacks, security and servers.
|
||||||
func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *Operation) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
o.Reference = new(low.Reference)
|
o.Reference = new(low.Reference)
|
||||||
o.Extensions = low.ExtractExtensions(root)
|
o.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, root, idx)
|
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, root, idx)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
return dErr
|
return dErr
|
||||||
}
|
}
|
||||||
o.ExternalDocs = extDocs
|
o.ExternalDocs = extDocs
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -82,21 +83,21 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract request body
|
// extract request body
|
||||||
rBody, rErr := low.ExtractObject[*RequestBody](RequestBodyLabel, root, idx)
|
rBody, rErr := low.ExtractObject[*RequestBody](ctx, RequestBodyLabel, root, idx)
|
||||||
if rErr != nil {
|
if rErr != nil {
|
||||||
return rErr
|
return rErr
|
||||||
}
|
}
|
||||||
o.RequestBody = rBody
|
o.RequestBody = rBody
|
||||||
|
|
||||||
// extract responses
|
// extract responses
|
||||||
respBody, respErr := low.ExtractObject[*Responses](ResponsesLabel, root, idx)
|
respBody, respErr := low.ExtractObject[*Responses](ctx, ResponsesLabel, root, idx)
|
||||||
if respErr != nil {
|
if respErr != nil {
|
||||||
return respErr
|
return respErr
|
||||||
}
|
}
|
||||||
o.Responses = respBody
|
o.Responses = respBody
|
||||||
|
|
||||||
// extract callbacks
|
// extract callbacks
|
||||||
callbacks, cbL, cbN, cbErr := low.ExtractMap[*Callback](CallbacksLabel, root, idx)
|
callbacks, cbL, cbN, cbErr := low.ExtractMap[*Callback](ctx, CallbacksLabel, root, idx)
|
||||||
if cbErr != nil {
|
if cbErr != nil {
|
||||||
return cbErr
|
return cbErr
|
||||||
}
|
}
|
||||||
@@ -109,7 +110,7 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract security
|
// extract security
|
||||||
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
@@ -134,7 +135,7 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract servers
|
// extract servers
|
||||||
servers, sl, sn, serErr := low.ExtractArray[*Server](ServersLabel, root, idx)
|
servers, sl, sn, serErr := low.ExtractArray[*Server](ctx, ServersLabel, root, idx)
|
||||||
if serErr != nil {
|
if serErr != nil {
|
||||||
return serErr
|
return serErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -58,7 +59,7 @@ func (p *Parameter) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract examples, extensions and content/media types.
|
// Build will extract examples, extensions and content/media types.
|
||||||
func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Parameter) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Reference = new(low.Reference)
|
p.Reference = new(low.Reference)
|
||||||
@@ -71,7 +72,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle schema
|
// handle schema
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle examples if set.
|
// handle examples if set.
|
||||||
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](base.ExamplesLabel, root, idx)
|
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
@@ -93,7 +94,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle content, if set.
|
// handle content, if set.
|
||||||
con, cL, cN, cErr := low.ExtractMap[*MediaType](ContentLabel, root, idx)
|
con, cL, cN, cErr := low.ExtractMap[*MediaType](ctx, ContentLabel, root, idx)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -109,7 +110,7 @@ func (p *PathItem) GetExtensions() map[low.KeyReference[string]]low.ValueReferen
|
|||||||
|
|
||||||
// Build extracts extensions, parameters, servers and each http method defined.
|
// Build extracts extensions, parameters, servers and each http method defined.
|
||||||
// everything is extracted asynchronously for speed.
|
// everything is extracted asynchronously for speed.
|
||||||
func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *PathItem) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Reference = new(low.Reference)
|
p.Reference = new(low.Reference)
|
||||||
@@ -123,7 +124,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var ops []low.NodeReference[*Operation]
|
var ops []low.NodeReference[*Operation]
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -143,7 +144,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if utils.IsNodeMap(srvN) {
|
if utils.IsNodeMap(srvN) {
|
||||||
srvr := new(Server)
|
srvr := new(Server)
|
||||||
_ = low.BuildModel(srvN, srvr)
|
_ = low.BuildModel(srvN, srvr)
|
||||||
srvr.Build(ln, srvN, idx)
|
srvr.Build(ctx, ln, srvN, idx)
|
||||||
servers = append(servers, low.ValueReference[*Server]{
|
servers = append(servers, low.ValueReference[*Server]{
|
||||||
Value: srvr,
|
Value: srvr,
|
||||||
ValueNode: srvN,
|
ValueNode: srvN,
|
||||||
@@ -198,6 +199,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
continue // ignore everything else.
|
continue // ignore everything else.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundContext := ctx
|
||||||
var op Operation
|
var op Operation
|
||||||
opIsRef := false
|
opIsRef := false
|
||||||
var opRefVal string
|
var opRefVal string
|
||||||
@@ -213,12 +215,15 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
|
|
||||||
opIsRef = true
|
opIsRef = true
|
||||||
opRefVal = ref
|
opRefVal = ref
|
||||||
r, err := low.LocateRefNode(pathNode, idx)
|
r, newIdx, err, nCtx := low.LocateRefNodeWithContext(ctx, pathNode, idx)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
if r.Kind == yaml.DocumentNode {
|
if r.Kind == yaml.DocumentNode {
|
||||||
r = r.Content[0]
|
r = r.Content[0]
|
||||||
}
|
}
|
||||||
pathNode = r
|
pathNode = r
|
||||||
|
foundContext = nCtx
|
||||||
|
foundContext = context.WithValue(foundContext, "foundIndex", newIdx)
|
||||||
|
|
||||||
if r.Tag == "" {
|
if r.Tag == "" {
|
||||||
// If it's a node from file, tag is empty
|
// If it's a node from file, tag is empty
|
||||||
pathNode = r.Content[0]
|
pathNode = r.Content[0]
|
||||||
@@ -233,6 +238,8 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
return fmt.Errorf("path item build failed: cannot find reference: %s at line %d, col %d",
|
return fmt.Errorf("path item build failed: cannot find reference: %s at line %d, col %d",
|
||||||
pathNode.Content[1].Value, pathNode.Content[1].Line, pathNode.Content[1].Column)
|
pathNode.Content[1].Value, pathNode.Content[1].Line, pathNode.Content[1].Column)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
foundContext = context.WithValue(foundContext, "foundIndex", idx)
|
||||||
}
|
}
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
low.BuildModelAsync(pathNode, &op, &wg, &errors)
|
low.BuildModelAsync(pathNode, &op, &wg, &errors)
|
||||||
@@ -241,6 +248,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
Value: &op,
|
Value: &op,
|
||||||
KeyNode: currentNode,
|
KeyNode: currentNode,
|
||||||
ValueNode: pathNode,
|
ValueNode: pathNode,
|
||||||
|
Context: foundContext,
|
||||||
}
|
}
|
||||||
if opIsRef {
|
if opIsRef {
|
||||||
opRef.Reference = opRefVal
|
opRef.Reference = opRefVal
|
||||||
@@ -277,7 +285,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
ref = op.Reference
|
ref = op.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
err := op.Value.Build(op.KeyNode, op.ValueNode, idx)
|
err := op.Value.Build(op.Context, op.KeyNode, op.ValueNode, op.Context.Value("foundIndex").(*index.SpecIndex))
|
||||||
if ref != "" {
|
if ref != "" {
|
||||||
op.Value.Reference.Reference = ref
|
op.Value.Reference.Reference = ref
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -60,7 +61,7 @@ func (p *Paths) GetExtensions() map[low.KeyReference[string]]low.ValueReference[
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and all PathItems. This happens asynchronously for speed.
|
// Build will extract extensions and all PathItems. This happens asynchronously for speed.
|
||||||
func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Paths) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Reference = new(low.Reference)
|
p.Reference = new(low.Reference)
|
||||||
@@ -134,7 +135,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
cNode := value.currentNode
|
cNode := value.currentNode
|
||||||
|
|
||||||
if ok, _, _ := utils.IsNodeRefValue(pNode); ok {
|
if ok, _, _ := utils.IsNodeRefValue(pNode); ok {
|
||||||
r, err := low.LocateRefNode(pNode, idx)
|
r, _, err := low.LocateRefNode(pNode, idx)
|
||||||
if r != nil {
|
if r != nil {
|
||||||
pNode = r
|
pNode = r
|
||||||
if r.Tag == "" {
|
if r.Tag == "" {
|
||||||
@@ -156,9 +157,12 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
|
|
||||||
path := new(PathItem)
|
path := new(PathItem)
|
||||||
_ = low.BuildModel(pNode, path)
|
_ = low.BuildModel(pNode, path)
|
||||||
err := path.Build(cNode, pNode, idx)
|
err := path.Build(ctx, cNode, pNode, idx)
|
||||||
|
|
||||||
|
// don't fail the pipeline if there is an error, log it instead.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return buildResult{}, err
|
//return buildResult{}, err
|
||||||
|
idx.GetLogger().Error(fmt.Sprintf("error building path item '%s'", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return buildResult{
|
return buildResult{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -40,14 +41,14 @@ func (rb *RequestBody) FindContent(cType string) *low.ValueReference[*MediaType]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and MediaType objects from the node.
|
// Build will extract extensions and MediaType objects from the node.
|
||||||
func (rb *RequestBody) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (rb *RequestBody) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
rb.Reference = new(low.Reference)
|
rb.Reference = new(low.Reference)
|
||||||
rb.Extensions = low.ExtractExtensions(root)
|
rb.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// handle content, if set.
|
// handle content, if set.
|
||||||
con, cL, cN, cErr := low.ExtractMap[*MediaType](ContentLabel, root, idx)
|
con, cL, cN, cErr := low.ExtractMap[*MediaType](ctx, ContentLabel, root, idx)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -54,14 +55,14 @@ func (r *Response) FindLink(hType string) *low.ValueReference[*Link] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract headers, extensions, content and links from node.
|
// Build will extract headers, extensions, content and links from node.
|
||||||
func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Response) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
r.Reference = new(low.Reference)
|
r.Reference = new(low.Reference)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
//extract headers
|
//extract headers
|
||||||
headers, lN, kN, err := low.ExtractMapExtensions[*Header](HeadersLabel, root, idx, true)
|
headers, lN, kN, err := low.ExtractMapExtensions[*Header](ctx, HeadersLabel, root, idx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -73,7 +74,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
con, clN, cN, cErr := low.ExtractMap[*MediaType](ContentLabel, root, idx)
|
con, clN, cN, cErr := low.ExtractMap[*MediaType](ctx, ContentLabel, root, idx)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle links if set
|
// handle links if set
|
||||||
links, linkLabel, linkValue, lErr := low.ExtractMap[*Link](LinksLabel, root, idx)
|
links, linkLabel, linkValue, lErr := low.ExtractMap[*Link](ctx, LinksLabel, root, idx)
|
||||||
if lErr != nil {
|
if lErr != nil {
|
||||||
return lErr
|
return lErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -45,13 +46,13 @@ func (r *Responses) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract default response and all Response objects for each code
|
// Build will extract default response and all Response objects for each code
|
||||||
func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Responses) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
r.Reference = new(low.Reference)
|
r.Reference = new(low.Reference)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
if utils.IsNodeMap(root) {
|
if utils.IsNodeMap(root) {
|
||||||
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
|
codes, err := low.ExtractMapNoLookup[*Response](ctx, root, idx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -48,13 +49,13 @@ func (ss *SecurityScheme) GetExtensions() map[low.KeyReference[string]]low.Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract OAuthFlows and extensions from the node.
|
// Build will extract OAuthFlows and extensions from the node.
|
||||||
func (ss *SecurityScheme) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ss *SecurityScheme) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ss.Reference = new(low.Reference)
|
ss.Reference = new(low.Reference)
|
||||||
ss.Extensions = low.ExtractExtensions(root)
|
ss.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
oa, oaErr := low.ExtractObject[*OAuthFlows](OAuthFlowsLabel, root, idx)
|
oa, oaErr := low.ExtractObject[*OAuthFlows](ctx, OAuthFlowsLabel, root, idx)
|
||||||
if oaErr != nil {
|
if oaErr != nil {
|
||||||
return oaErr
|
return oaErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -34,7 +35,7 @@ func (s *Server) FindVariable(serverVar string) *low.ValueReference[*ServerVaria
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract server variables from the supplied node.
|
// Build will extract server variables from the supplied node.
|
||||||
func (s *Server) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *Server) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
Definition: definitionPath,
|
Definition: definitionPath,
|
||||||
Node: node.Content[i+1],
|
Node: node.Content[i+1],
|
||||||
Path: jsonPath,
|
Path: jsonPath,
|
||||||
|
Index: index,
|
||||||
}
|
}
|
||||||
|
|
||||||
isRef, _, _ := utils.IsNodeRefValue(node.Content[i+1])
|
isRef, _, _ := utils.IsNodeRefValue(node.Content[i+1])
|
||||||
@@ -120,6 +121,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
Definition: definitionPath,
|
Definition: definitionPath,
|
||||||
Node: prop,
|
Node: prop,
|
||||||
Path: jsonPath,
|
Path: jsonPath,
|
||||||
|
Index: index,
|
||||||
}
|
}
|
||||||
|
|
||||||
isRef, _, _ := utils.IsNodeRefValue(prop)
|
isRef, _, _ := utils.IsNodeRefValue(prop)
|
||||||
@@ -165,6 +167,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
Definition: definitionPath,
|
Definition: definitionPath,
|
||||||
Node: element,
|
Node: element,
|
||||||
Path: jsonPath,
|
Path: jsonPath,
|
||||||
|
Index: index,
|
||||||
}
|
}
|
||||||
|
|
||||||
isRef, _, _ := utils.IsNodeRefValue(element)
|
isRef, _, _ := utils.IsNodeRefValue(element)
|
||||||
@@ -341,6 +344,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
Name: name,
|
Name: name,
|
||||||
Node: node,
|
Node: node,
|
||||||
Path: p,
|
Path: p,
|
||||||
|
Index: index,
|
||||||
}
|
}
|
||||||
|
|
||||||
// add to raw sequenced refs
|
// add to raw sequenced refs
|
||||||
@@ -367,6 +371,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
|||||||
Name: ref.Name,
|
Name: ref.Name,
|
||||||
Node: &copiedNode,
|
Node: &copiedNode,
|
||||||
Path: p,
|
Path: p,
|
||||||
|
Index: index,
|
||||||
}
|
}
|
||||||
// protect this data using a copy, prevent the resolver from destroying things.
|
// protect this data using a copy, prevent the resolver from destroying things.
|
||||||
index.refsWithSiblings[value] = copied
|
index.refsWithSiblings[value] = copied
|
||||||
@@ -592,6 +597,11 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
|||||||
locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) {
|
locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) {
|
||||||
located := index.FindComponent(ref.FullDefinition, ref.Node)
|
located := index.FindComponent(ref.FullDefinition, ref.Node)
|
||||||
if located != nil {
|
if located != nil {
|
||||||
|
|
||||||
|
if located.Index == nil {
|
||||||
|
index.logger.Warn("located component has no index", "component", located.FullDefinition)
|
||||||
|
}
|
||||||
|
|
||||||
index.refLock.Lock()
|
index.refLock.Lock()
|
||||||
// have we already mapped this?
|
// have we already mapped this?
|
||||||
if index.allMappedRefs[ref.FullDefinition] == nil {
|
if index.allMappedRefs[ref.FullDefinition] == nil {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ func (index *SpecIndex) FindComponent(componentId string, parent *yaml.Node) *Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Reference {
|
func FindComponent(root *yaml.Node, componentId, absoluteFilePath string, index *SpecIndex) *Reference {
|
||||||
// check component for url encoding.
|
// check component for url encoding.
|
||||||
if strings.Contains(componentId, "%") {
|
if strings.Contains(componentId, "%") {
|
||||||
// decode the url.
|
// decode the url.
|
||||||
@@ -72,6 +72,12 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Refer
|
|||||||
|
|
||||||
fullDef := fmt.Sprintf("%s%s", absoluteFilePath, componentId)
|
fullDef := fmt.Sprintf("%s%s", absoluteFilePath, componentId)
|
||||||
|
|
||||||
|
// TODO: clean this shit up
|
||||||
|
|
||||||
|
newIndexWithUpdatedPath := *index
|
||||||
|
newIndexWithUpdatedPath.specAbsolutePath = absoluteFilePath
|
||||||
|
newIndexWithUpdatedPath.AbsoluteFile = absoluteFilePath
|
||||||
|
|
||||||
// extract properties
|
// extract properties
|
||||||
ref := &Reference{
|
ref := &Reference{
|
||||||
FullDefinition: fullDef,
|
FullDefinition: fullDef,
|
||||||
@@ -79,6 +85,8 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Refer
|
|||||||
Name: name,
|
Name: name,
|
||||||
Node: resNode,
|
Node: resNode,
|
||||||
Path: friendlySearch,
|
Path: friendlySearch,
|
||||||
|
RemoteLocation: absoluteFilePath,
|
||||||
|
Index: &newIndexWithUpdatedPath,
|
||||||
RequiredRefProperties: extractDefinitionRequiredRefProperties(resNode, map[string][]string{}, fullDef),
|
RequiredRefProperties: extractDefinitionRequiredRefProperties(resNode, map[string][]string{}, fullDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +97,7 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Refer
|
|||||||
|
|
||||||
func (index *SpecIndex) FindComponentInRoot(componentId string) *Reference {
|
func (index *SpecIndex) FindComponentInRoot(componentId string) *Reference {
|
||||||
if index.root != nil {
|
if index.root != nil {
|
||||||
return FindComponent(index.root, componentId, index.specAbsolutePath)
|
return FindComponent(index.root, componentId, index.specAbsolutePath, index)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -139,6 +147,9 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
|||||||
|
|
||||||
var parsedDocument *yaml.Node
|
var parsedDocument *yaml.Node
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
idx := index
|
||||||
|
|
||||||
if ext != "" {
|
if ext != "" {
|
||||||
|
|
||||||
// extract the document from the rolodex.
|
// extract the document from the rolodex.
|
||||||
@@ -153,6 +164,9 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
|||||||
index.logger.Error("rolodex file is empty!", "file", absoluteFileLocation)
|
index.logger.Error("rolodex file is empty!", "file", absoluteFileLocation)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if rFile.GetIndex() != nil {
|
||||||
|
idx = rFile.GetIndex()
|
||||||
|
}
|
||||||
|
|
||||||
parsedDocument, err = rFile.GetContentAsYAMLNode()
|
parsedDocument, err = rFile.GetContentAsYAMLNode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -184,6 +198,7 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
|||||||
FullDefinition: absoluteFileLocation,
|
FullDefinition: absoluteFileLocation,
|
||||||
Definition: fileName,
|
Definition: fileName,
|
||||||
Name: fileName,
|
Name: fileName,
|
||||||
|
Index: idx,
|
||||||
Node: parsedDocument,
|
Node: parsedDocument,
|
||||||
IsRemote: true,
|
IsRemote: true,
|
||||||
RemoteLocation: absoluteFileLocation,
|
RemoteLocation: absoluteFileLocation,
|
||||||
@@ -192,7 +207,7 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
|||||||
}
|
}
|
||||||
return foundRef
|
return foundRef
|
||||||
} else {
|
} else {
|
||||||
foundRef = FindComponent(parsedDocument, query, absoluteFileLocation)
|
foundRef = FindComponent(parsedDocument, query, absoluteFileLocation, index)
|
||||||
if foundRef != nil {
|
if foundRef != nil {
|
||||||
foundRef.IsRemote = true
|
foundRef.IsRemote = true
|
||||||
foundRef.RemoteLocation = absoluteFileLocation
|
foundRef.RemoteLocation = absoluteFileLocation
|
||||||
|
|||||||
@@ -61,9 +61,14 @@ func TestSpecIndex_CheckCircularIndex(t *testing.T) {
|
|||||||
index := rolo.GetRootIndex()
|
index := rolo.GetRootIndex()
|
||||||
|
|
||||||
assert.Nil(t, index.uri)
|
assert.Nil(t, index.uri)
|
||||||
assert.NotNil(t, index.SearchIndexForReference("second.yaml#/properties/property2"))
|
|
||||||
assert.NotNil(t, index.SearchIndexForReference("second.yaml"))
|
a, _ := index.SearchIndexForReference("second.yaml#/properties/property2")
|
||||||
assert.Nil(t, index.SearchIndexForReference("fourth.yaml"))
|
b, _ := index.SearchIndexForReference("second.yaml")
|
||||||
|
c, _ := index.SearchIndexForReference("fourth.yaml")
|
||||||
|
|
||||||
|
assert.NotNil(t, a)
|
||||||
|
assert.NotNil(t, b)
|
||||||
|
assert.Nil(t, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSpecIndex_performExternalLookup_invalidURL(t *testing.T) {
|
func TestSpecIndex_performExternalLookup_invalidURL(t *testing.T) {
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ type Reference struct {
|
|||||||
Circular bool
|
Circular bool
|
||||||
Seen bool
|
Seen bool
|
||||||
IsRemote bool
|
IsRemote bool
|
||||||
|
Index *SpecIndex // index that contains this reference.
|
||||||
RemoteLocation string
|
RemoteLocation string
|
||||||
Path string // this won't always be available.
|
Path string // this won't always be available.
|
||||||
RequiredRefProperties map[string][]string // definition names (eg, #/definitions/One) to a list of required properties on this definition which reference that definition
|
RequiredRefProperties map[string][]string // definition names (eg, #/definitions/One) to a list of required properties on this definition which reference that definition
|
||||||
@@ -166,6 +167,8 @@ func CreateClosedAPIIndexConfig() *SpecIndexConfig {
|
|||||||
// quick direct access to paths, operations, tags are all available. No need to walk the entire node tree in rules,
|
// quick direct access to paths, operations, tags are all available. No need to walk the entire node tree in rules,
|
||||||
// everything is pre-walked if you need it.
|
// everything is pre-walked if you need it.
|
||||||
type SpecIndex struct {
|
type SpecIndex struct {
|
||||||
|
specAbsolutePath string
|
||||||
|
AbsoluteFile string
|
||||||
rolodex *Rolodex // the rolodex is used to fetch remote and file based documents.
|
rolodex *Rolodex // the rolodex is used to fetch remote and file based documents.
|
||||||
allRefs map[string]*Reference // all (deduplicated) refs
|
allRefs map[string]*Reference // all (deduplicated) refs
|
||||||
rawSequencedRefs []*Reference // all raw references in sequence as they are scanned, not deduped.
|
rawSequencedRefs []*Reference // all raw references in sequence as they are scanned, not deduped.
|
||||||
@@ -261,7 +264,6 @@ type SpecIndex struct {
|
|||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
componentIndexChan chan bool
|
componentIndexChan chan bool
|
||||||
polyComponentIndexChan chan bool
|
polyComponentIndexChan chan bool
|
||||||
specAbsolutePath string
|
|
||||||
resolver *Resolver
|
resolver *Resolver
|
||||||
cache syncmap.Map
|
cache syncmap.Map
|
||||||
built bool
|
built bool
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
|||||||
if j.FullDefinition == r.FullDefinition {
|
if j.FullDefinition == r.FullDefinition {
|
||||||
|
|
||||||
var foundDup *Reference
|
var foundDup *Reference
|
||||||
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
foundRef, _ := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||||
if foundRef != nil {
|
if foundRef != nil {
|
||||||
foundDup = foundRef
|
foundDup = foundRef
|
||||||
}
|
}
|
||||||
@@ -307,7 +307,7 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
|||||||
|
|
||||||
if !skip {
|
if !skip {
|
||||||
var original *Reference
|
var original *Reference
|
||||||
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
foundRef, _ := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||||
if foundRef != nil {
|
if foundRef != nil {
|
||||||
original = foundRef
|
original = foundRef
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ func (resolver *Resolver) isInfiniteCircularDependency(ref *Reference, visitedDe
|
|||||||
}
|
}
|
||||||
|
|
||||||
for refDefinition := range ref.RequiredRefProperties {
|
for refDefinition := range ref.RequiredRefProperties {
|
||||||
r := resolver.specIndex.SearchIndexForReference(refDefinition)
|
r, _ := resolver.specIndex.SearchIndexForReference(refDefinition)
|
||||||
if initialRef != nil && initialRef.Definition == r.Definition {
|
if initialRef != nil && initialRef.Definition == r.Definition {
|
||||||
return true, visitedDefinitions
|
return true, visitedDefinitions
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,7 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
|||||||
IsRemote: true,
|
IsRemote: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
locatedRef = resolver.specIndex.SearchIndexForReferenceByReference(searchRef)
|
locatedRef, _ = resolver.specIndex.SearchIndexForReferenceByReference(searchRef)
|
||||||
|
|
||||||
if locatedRef == nil {
|
if locatedRef == nil {
|
||||||
_, path := utils.ConvertComponentIdIntoFriendlyPathSearch(value)
|
_, path := utils.ConvertComponentIdIntoFriendlyPathSearch(value)
|
||||||
|
|||||||
@@ -596,7 +596,7 @@ func TestResolver_ResolveComponents_MixedRef(t *testing.T) {
|
|||||||
resolver := index().GetResolver()
|
resolver := index().GetResolver()
|
||||||
|
|
||||||
assert.Len(t, resolver.GetCircularErrors(), 0)
|
assert.Len(t, resolver.GetCircularErrors(), 0)
|
||||||
assert.Equal(t, 3, resolver.GetIndexesVisited())
|
assert.Equal(t, 2, resolver.GetIndexesVisited())
|
||||||
|
|
||||||
// in v0.8.2 a new check was added when indexing, to prevent re-indexing the same file multiple times.
|
// in v0.8.2 a new check was added when indexing, to prevent re-indexing the same file multiple times.
|
||||||
assert.Equal(t, 6, resolver.GetRelativesSeen())
|
assert.Equal(t, 6, resolver.GetRelativesSeen())
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ func (l *LocalFile) Index(config *SpecIndexConfig) (*SpecIndex, error) {
|
|||||||
|
|
||||||
index := NewSpecIndexWithConfig(info.RootNode, config)
|
index := NewSpecIndexWithConfig(info.RootNode, config)
|
||||||
index.specAbsolutePath = l.fullPath
|
index.specAbsolutePath = l.fullPath
|
||||||
|
|
||||||
l.index = index
|
l.index = index
|
||||||
return index, nil
|
return index, nil
|
||||||
|
|
||||||
|
|||||||
@@ -176,13 +176,10 @@ const (
|
|||||||
|
|
||||||
func NewRemoteFSWithConfig(specIndexConfig *SpecIndexConfig) (*RemoteFS, error) {
|
func NewRemoteFSWithConfig(specIndexConfig *SpecIndexConfig) (*RemoteFS, error) {
|
||||||
remoteRootURL := specIndexConfig.BaseURL
|
remoteRootURL := specIndexConfig.BaseURL
|
||||||
|
|
||||||
// TODO: handle logging
|
|
||||||
|
|
||||||
log := specIndexConfig.Logger
|
log := specIndexConfig.Logger
|
||||||
if log == nil {
|
if log == nil {
|
||||||
log = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
log = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
Level: slog.LevelDebug,
|
Level: slog.LevelError,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +321,7 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
|||||||
// remove from processing
|
// remove from processing
|
||||||
i.ProcessingFiles.Delete(remoteParsedURL.Path)
|
i.ProcessingFiles.Delete(remoteParsedURL.Path)
|
||||||
|
|
||||||
i.logger.Error("Unable to fetch remote document",
|
i.logger.Error("unable to fetch remote document",
|
||||||
"file", remoteParsedURL.Path, "status", response.StatusCode, "resp", string(responseBytes))
|
"file", remoteParsedURL.Path, "status", response.StatusCode, "resp", string(responseBytes))
|
||||||
return nil, fmt.Errorf("unable to fetch remote document: %s", string(responseBytes))
|
return nil, fmt.Errorf("unable to fetch remote document: %s", string(responseBytes))
|
||||||
}
|
}
|
||||||
@@ -371,8 +368,6 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
|||||||
copiedCfg.SpecAbsolutePath = remoteParsedURL.String()
|
copiedCfg.SpecAbsolutePath = remoteParsedURL.String()
|
||||||
idx, idxError := remoteFile.Index(&copiedCfg)
|
idx, idxError := remoteFile.Index(&copiedCfg)
|
||||||
|
|
||||||
i.Files.Store(absolutePath, remoteFile)
|
|
||||||
|
|
||||||
if len(remoteFile.data) > 0 {
|
if len(remoteFile.data) > 0 {
|
||||||
i.logger.Debug("successfully loaded file", "file", absolutePath)
|
i.logger.Debug("successfully loaded file", "file", absolutePath)
|
||||||
}
|
}
|
||||||
@@ -390,6 +385,7 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
|||||||
|
|
||||||
// remove from processing
|
// remove from processing
|
||||||
i.ProcessingFiles.Delete(remoteParsedURL.Path)
|
i.ProcessingFiles.Delete(remoteParsedURL.Path)
|
||||||
|
i.Files.Store(absolutePath, remoteFile)
|
||||||
|
|
||||||
//if !i.remoteRunning {
|
//if !i.remoteRunning {
|
||||||
return remoteFile, errors.Join(i.remoteErrors...)
|
return remoteFile, errors.Join(i.remoteErrors...)
|
||||||
|
|||||||
@@ -4,130 +4,151 @@
|
|||||||
package index
|
package index
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"context"
|
||||||
"path/filepath"
|
"fmt"
|
||||||
"strings"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) *Reference {
|
type ContextKey string
|
||||||
|
|
||||||
if v, ok := index.cache.Load(fullRef); ok {
|
const CurrentPathKey ContextKey = "currentPath"
|
||||||
return v.(*Reference)
|
|
||||||
}
|
|
||||||
|
|
||||||
ref := fullRef.FullDefinition
|
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) (*Reference, *SpecIndex) {
|
||||||
refAlt := ref
|
r, idx, _ := index.SearchIndexForReferenceByReferenceWithContext(context.Background(), fullRef)
|
||||||
absPath := index.specAbsolutePath
|
return r, idx
|
||||||
if absPath == "" {
|
|
||||||
absPath = index.config.BasePath
|
|
||||||
}
|
|
||||||
var roloLookup string
|
|
||||||
uri := strings.Split(ref, "#/")
|
|
||||||
if len(uri) == 2 {
|
|
||||||
if uri[0] != "" {
|
|
||||||
if strings.HasPrefix(uri[0], "http") {
|
|
||||||
roloLookup = fullRef.FullDefinition
|
|
||||||
} else {
|
|
||||||
if filepath.IsAbs(uri[0]) {
|
|
||||||
roloLookup = uri[0]
|
|
||||||
} else {
|
|
||||||
if filepath.Ext(absPath) != "" {
|
|
||||||
absPath = filepath.Dir(absPath)
|
|
||||||
}
|
|
||||||
roloLookup, _ = filepath.Abs(filepath.Join(absPath, uri[0]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if filepath.Ext(uri[1]) != "" {
|
|
||||||
roloLookup = absPath
|
|
||||||
} else {
|
|
||||||
roloLookup = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
ref = fmt.Sprintf("#/%s", uri[1])
|
|
||||||
refAlt = fmt.Sprintf("%s#/%s", absPath, uri[1])
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if filepath.IsAbs(uri[0]) {
|
|
||||||
roloLookup = uri[0]
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if strings.HasPrefix(uri[0], "http") {
|
|
||||||
roloLookup = ref
|
|
||||||
} else {
|
|
||||||
if filepath.Ext(absPath) != "" {
|
|
||||||
absPath = filepath.Dir(absPath)
|
|
||||||
}
|
|
||||||
roloLookup, _ = filepath.Abs(filepath.Join(absPath, uri[0]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ref = uri[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := index.allMappedRefs[ref]; ok {
|
|
||||||
index.cache.Store(ref, r)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
if r, ok := index.allMappedRefs[refAlt]; ok {
|
|
||||||
index.cache.Store(refAlt, r)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the rolodex for the reference.
|
|
||||||
if roloLookup != "" {
|
|
||||||
rFile, err := index.rolodex.Open(roloLookup)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the index from the rolodex file.
|
|
||||||
idx := rFile.GetIndex()
|
|
||||||
if index.resolver != nil {
|
|
||||||
index.resolver.indexesVisited++
|
|
||||||
}
|
|
||||||
if idx != nil {
|
|
||||||
|
|
||||||
// check mapped refs.
|
|
||||||
if r, ok := idx.allMappedRefs[ref]; ok {
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
// build a collection of all the inline schemas and search them
|
|
||||||
// for the reference.
|
|
||||||
var d []*Reference
|
|
||||||
d = append(d, idx.allInlineSchemaDefinitions...)
|
|
||||||
d = append(d, idx.allRefSchemaDefinitions...)
|
|
||||||
d = append(d, idx.allInlineSchemaObjectDefinitions...)
|
|
||||||
for _, s := range d {
|
|
||||||
if s.Definition == ref {
|
|
||||||
index.cache.Store(ref, s)
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// does component exist in the root?
|
|
||||||
node, _ := rFile.GetContentAsYAMLNode()
|
|
||||||
if node != nil {
|
|
||||||
found := idx.FindComponent(ref, node)
|
|
||||||
if found != nil {
|
|
||||||
index.cache.Store(ref, found)
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("unable to locate reference: %s, within index: %s\n", ref, index.specAbsolutePath)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchIndexForReference searches the index for a reference, first looking through the mapped references
|
// SearchIndexForReference searches the index for a reference, first looking through the mapped references
|
||||||
// and then externalSpecIndex for a match. If no match is found, it will recursively search the child indexes
|
// and then externalSpecIndex for a match. If no match is found, it will recursively search the child indexes
|
||||||
// extracted when parsing the OpenAPI Spec.
|
// extracted when parsing the OpenAPI Spec.
|
||||||
func (index *SpecIndex) SearchIndexForReference(ref string) *Reference {
|
func (index *SpecIndex) SearchIndexForReference(ref string) (*Reference, *SpecIndex) {
|
||||||
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (index *SpecIndex) SearchIndexForReferenceWithContext(ctx context.Context, ref string) (*Reference, *SpecIndex, context.Context) {
|
||||||
|
return index.SearchIndexForReferenceByReferenceWithContext(ctx, &Reference{FullDefinition: ref})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (index *SpecIndex) SearchIndexForReferenceByReferenceWithContext(ctx context.Context, searchRef *Reference) (*Reference, *SpecIndex, context.Context) {
|
||||||
|
|
||||||
|
if v, ok := index.cache.Load(searchRef.FullDefinition); ok {
|
||||||
|
return v.(*Reference), index, context.WithValue(ctx, CurrentPathKey, v.(*Reference).RemoteLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
ref := searchRef.FullDefinition
|
||||||
|
refAlt := ref
|
||||||
|
absPath := index.specAbsolutePath
|
||||||
|
if absPath == "" {
|
||||||
|
absPath = index.config.BasePath
|
||||||
|
}
|
||||||
|
var roloLookup string
|
||||||
|
uri := strings.Split(ref, "#/")
|
||||||
|
if len(uri) == 2 {
|
||||||
|
if uri[0] != "" {
|
||||||
|
if strings.HasPrefix(uri[0], "http") {
|
||||||
|
roloLookup = searchRef.FullDefinition
|
||||||
|
} else {
|
||||||
|
if filepath.IsAbs(uri[0]) {
|
||||||
|
roloLookup = uri[0]
|
||||||
|
} else {
|
||||||
|
if filepath.Ext(absPath) != "" {
|
||||||
|
absPath = filepath.Dir(absPath)
|
||||||
|
}
|
||||||
|
roloLookup, _ = filepath.Abs(filepath.Join(absPath, uri[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if filepath.Ext(uri[1]) != "" {
|
||||||
|
roloLookup = absPath
|
||||||
|
} else {
|
||||||
|
roloLookup = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ref = fmt.Sprintf("#/%s", uri[1])
|
||||||
|
refAlt = fmt.Sprintf("%s#/%s", absPath, uri[1])
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if filepath.IsAbs(uri[0]) {
|
||||||
|
roloLookup = uri[0]
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if strings.HasPrefix(uri[0], "http") {
|
||||||
|
roloLookup = ref
|
||||||
|
} else {
|
||||||
|
if filepath.Ext(absPath) != "" {
|
||||||
|
absPath = filepath.Dir(absPath)
|
||||||
|
}
|
||||||
|
roloLookup, _ = filepath.Abs(filepath.Join(absPath, uri[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ref = uri[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if r, ok := index.allMappedRefs[ref]; ok {
|
||||||
|
index.cache.Store(ref, r)
|
||||||
|
return r, r.Index, context.WithValue(ctx, CurrentPathKey, r.RemoteLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
if r, ok := index.allMappedRefs[refAlt]; ok {
|
||||||
|
index.cache.Store(refAlt, r)
|
||||||
|
return r, r.Index, context.WithValue(ctx, CurrentPathKey, r.RemoteLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the rolodex for the reference.
|
||||||
|
if roloLookup != "" {
|
||||||
|
rFile, err := index.rolodex.Open(roloLookup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, index, ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract the index from the rolodex file.
|
||||||
|
if rFile != nil {
|
||||||
|
idx := rFile.GetIndex()
|
||||||
|
if index.resolver != nil {
|
||||||
|
index.resolver.indexesVisited++
|
||||||
|
}
|
||||||
|
if idx != nil {
|
||||||
|
|
||||||
|
// check mapped refs.
|
||||||
|
if r, ok := idx.allMappedRefs[ref]; ok {
|
||||||
|
index.cache.Store(ref, r)
|
||||||
|
idx.cache.Store(ref, r)
|
||||||
|
return r, r.Index, context.WithValue(ctx, CurrentPathKey, r.RemoteLocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build a collection of all the inline schemas and search them
|
||||||
|
// for the reference.
|
||||||
|
var d []*Reference
|
||||||
|
d = append(d, idx.allInlineSchemaDefinitions...)
|
||||||
|
d = append(d, idx.allRefSchemaDefinitions...)
|
||||||
|
d = append(d, idx.allInlineSchemaObjectDefinitions...)
|
||||||
|
for _, s := range d {
|
||||||
|
if s.FullDefinition == ref {
|
||||||
|
idx.cache.Store(ref, s)
|
||||||
|
index.cache.Store(ref, s)
|
||||||
|
return s, s.Index, context.WithValue(ctx, CurrentPathKey, s.RemoteLocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// does component exist in the root?
|
||||||
|
node, _ := rFile.GetContentAsYAMLNode()
|
||||||
|
if node != nil {
|
||||||
|
found := idx.FindComponent(ref, node)
|
||||||
|
if found != nil {
|
||||||
|
idx.cache.Store(ref, found)
|
||||||
|
index.cache.Store(ref, found)
|
||||||
|
return found, found.Index, context.WithValue(ctx, CurrentPathKey, found.RemoteLocation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index.logger.Error("unable to locate reference anywhere in the rolodex", "reference", ref)
|
||||||
|
return nil, index, ctx
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,6 @@ func TestSpecIndex_SearchIndexForReference(t *testing.T) {
|
|||||||
c := CreateOpenAPIIndexConfig()
|
c := CreateOpenAPIIndexConfig()
|
||||||
idx := NewSpecIndexWithConfig(&rootNode, c)
|
idx := NewSpecIndexWithConfig(&rootNode, c)
|
||||||
|
|
||||||
ref := idx.SearchIndexForReference("#/components/schemas/Pet")
|
ref, _ := idx.SearchIndexForReference("#/components/schemas/Pet")
|
||||||
assert.NotNil(t, ref)
|
assert.NotNil(t, ref)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,14 @@ func (index *SpecIndex) BuildIndex() {
|
|||||||
index.built = true
|
index.built = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (index *SpecIndex) GetSpecAbsolutePath() string {
|
||||||
|
return index.specAbsolutePath
|
||||||
|
}
|
||||||
|
|
||||||
|
func (index *SpecIndex) GetLogger() *slog.Logger {
|
||||||
|
return index.logger
|
||||||
|
}
|
||||||
|
|
||||||
// GetRootNode returns document root node.
|
// GetRootNode returns document root node.
|
||||||
func (index *SpecIndex) GetRootNode() *yaml.Node {
|
func (index *SpecIndex) GetRootNode() *yaml.Node {
|
||||||
return index.root
|
return index.root
|
||||||
|
|||||||
@@ -949,7 +949,7 @@ func TestSpecIndex_lookupFileReference_MultiRes(t *testing.T) {
|
|||||||
index := rolo.GetRootIndex()
|
index := rolo.GetRootIndex()
|
||||||
//index.seenRemoteSources = make(map[string]*yaml.Node)
|
//index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||||
absoluteRef, _ := filepath.Abs("embie.yaml#/naughty")
|
absoluteRef, _ := filepath.Abs("embie.yaml#/naughty")
|
||||||
fRef := index.SearchIndexForReference(absoluteRef)
|
fRef, _ := index.SearchIndexForReference(absoluteRef)
|
||||||
assert.NotNil(t, fRef)
|
assert.NotNil(t, fRef)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
|||||||
paramRef := index.allMappedRefs[paramRefName]
|
paramRef := index.allMappedRefs[paramRefName]
|
||||||
if paramRef == nil {
|
if paramRef == nil {
|
||||||
// could be in the rolodex
|
// could be in the rolodex
|
||||||
ref := index.SearchIndexForReference(paramRefName)
|
ref, _ := index.SearchIndexForReference(paramRefName)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
paramRef = ref
|
paramRef = ref
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user